dune-istl
2.1.1
|
00001 // -*- tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 00002 // vi: set et ts=8 sw=2 sts=2: 00003 #ifndef DUNE_MATRIX_UTILS_HH 00004 #define DUNE_MATRIX_UTILS_HH 00005 00006 #include<set> 00007 #include<vector> 00008 #include<limits> 00009 #include<dune/common/typetraits.hh> 00010 #include<dune/common/static_assert.hh> 00011 #include"istlexception.hh" 00012 00013 namespace Dune 00014 { 00015 00016 #ifndef DOYXGEN 00017 template<typename B, typename A> 00018 class BCRSMatrix; 00019 00020 template<typename K, int n, int m> 00021 class FieldMatrix; 00022 00023 template<class T, class A> 00024 class Matrix; 00025 #endif 00026 00036 namespace 00037 { 00038 00039 template<int i> 00040 struct NonZeroCounter 00041 { 00042 template<class M> 00043 static typename M::size_type count(const M& matrix) 00044 { 00045 typedef typename M::ConstRowIterator RowIterator; 00046 00047 RowIterator endRow = matrix.end(); 00048 typename M::size_type nonZeros = 0; 00049 00050 for(RowIterator row = matrix.begin(); row != endRow; ++row){ 00051 typedef typename M::ConstColIterator Entry; 00052 Entry endEntry = row->end(); 00053 for(Entry entry = row->begin(); entry != endEntry; ++entry){ 00054 nonZeros += NonZeroCounter<i-1>::count(*entry); 00055 } 00056 } 00057 return nonZeros; 00058 } 00059 }; 00060 00061 template<> 00062 struct NonZeroCounter<1> 00063 { 00064 template<class M> 00065 static typename M::size_type count(const M& matrix) 00066 { 00067 return matrix.N()*matrix.M(); 00068 } 00069 }; 00070 00071 } 00072 00077 template<class Matrix, std::size_t blocklevel, std::size_t l=blocklevel> 00078 struct CheckIfDiagonalPresent 00079 { 00084 static void check(const Matrix& mat) 00085 { 00086 #ifdef DUNE_ISTL_WITH_CHECKING 00087 typedef typename Matrix::ConstRowIterator Row; 00088 typedef typename Matrix::ConstColIterator Entry; 00089 for(Row row = mat.begin(); row!=mat.end(); ++row){ 00090 Entry diagonal = row->find(row.index()); 00091 if(diagonal==row->end()) 00092 DUNE_THROW(ISTLError, "Missing diagonal value in row "<<row.index() 00093 <<" at block recursion level "<<l-blocklevel); 00094 else 00095 CheckIfDiagonalPresent<typename Matrix::block_type,blocklevel-1,l>::check(*diagonal); 00096 } 00097 #endif 00098 } 00099 }; 00100 00101 template<class Matrix, std::size_t l> 00102 struct CheckIfDiagonalPresent<Matrix,0,l> 00103 { 00104 static void check(const Matrix& mat) 00105 { 00106 typedef typename Matrix::ConstRowIterator Row; 00107 for(Row row = mat.begin(); row!=mat.end(); ++row){ 00108 if(row->find(row.index())==row->end()) 00109 DUNE_THROW(ISTLError, "Missing diagonal value in row "<<row.index() 00110 <<" at block recursion level "<<l); 00111 } 00112 } 00113 }; 00114 00115 template<typename T1, typename T2, typename T3, typename T4, typename T5, 00116 typename T6, typename T7, typename T8, typename T9> 00117 class MultiTypeBlockMatrix; 00118 00119 template<typename T1, typename T2, typename T3, typename T4, typename T5, 00120 typename T6, typename T7, typename T8, typename T9, std::size_t blocklevel, std::size_t l> 00121 struct CheckIfDiagonalPresent<MultiTypeBlockMatrix<T1,T2,T3,T4,T5,T6,T7,T8,T9>, 00122 blocklevel,l> 00123 { 00124 typedef MultiTypeBlockMatrix<T1,T2,T3,T4,T5,T6,T7,T8,T9> Matrix; 00125 00130 static void check(const Matrix& mat) 00131 { 00132 #ifdef DUNE_ISTL_WITH_CHECKING 00133 // TODO Implement check 00134 #endif 00135 } 00136 }; 00137 00149 template<class M> 00150 inline int countNonZeros(const M& matrix) 00151 { 00152 return NonZeroCounter<M::blocklevel>::count(matrix); 00153 } 00154 /* 00155 template<class M> 00156 struct ProcessOnFieldsOfMatrix 00157 */ 00158 00160 namespace 00161 { 00162 struct CompPair{ 00163 template<class G,class M> 00164 bool operator()(const std::pair<G,M>& p1, const std::pair<G,M>& p2) 00165 { 00166 return p1.first<p2.first; 00167 } 00168 }; 00169 00170 } 00171 template<class M, class C> 00172 void printGlobalSparseMatrix(const M& mat, C& ooc, std::ostream& os) 00173 { 00174 typedef typename C::ParallelIndexSet::const_iterator IIter; 00175 typedef typename C::OwnerSet OwnerSet; 00176 typedef typename C::ParallelIndexSet::GlobalIndex GlobalIndex; 00177 00178 GlobalIndex gmax=0; 00179 00180 for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end(); 00181 idx!=eidx; ++idx) 00182 gmax=std::max(gmax,idx->global()); 00183 00184 gmax=ooc.communicator().max(gmax); 00185 ooc.buildGlobalLookup(); 00186 00187 for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end(); 00188 idx!=eidx; ++idx){ 00189 if(OwnerSet::contains(idx->local().attribute())) 00190 { 00191 typedef typename M::block_type Block; 00192 00193 std::set<std::pair<GlobalIndex,Block>,CompPair> entries; 00194 00195 // sort rows 00196 typedef typename M::ConstColIterator CIter; 00197 for(CIter c=mat[idx->local()].begin(), cend=mat[idx->local()].end(); 00198 c!=cend; ++c){ 00199 const typename C::ParallelIndexSet::IndexPair* pair 00200 =ooc.globalLookup().pair(c.index()); 00201 assert(pair); 00202 entries.insert(std::make_pair(pair->global(), *c)); 00203 } 00204 00205 //wait until its the rows turn. 00206 GlobalIndex rowidx = idx->global(); 00207 GlobalIndex cur=std::numeric_limits<GlobalIndex>::max(); 00208 while(cur!=rowidx) 00209 cur=ooc.communicator().min(rowidx); 00210 00211 // print rows 00212 typedef typename std::set<std::pair<GlobalIndex,Block>,CompPair>::iterator SIter; 00213 for(SIter s=entries.begin(), send=entries.end(); s!=send; ++s) 00214 os<<idx->global()<<" "<<s->first<<" "<<s->second<<std::endl; 00215 00216 00217 } 00218 } 00219 00220 ooc.freeGlobalLookup(); 00221 // Wait until everybody is finished 00222 GlobalIndex cur=std::numeric_limits<GlobalIndex>::max(); 00223 while(cur!=ooc.communicator().min(cur)); 00224 } 00225 00226 template<typename M> 00227 struct MatrixDimension 00228 { 00229 }; 00230 00231 00232 template<typename B, typename TA> 00233 struct MatrixDimension<BCRSMatrix<B,TA> > 00234 { 00235 typedef BCRSMatrix<B,TA> Matrix; 00236 typedef typename Matrix::block_type block_type; 00237 typedef typename Matrix::size_type size_type; 00238 00239 static size_type rowdim (const Matrix& A, size_type i) 00240 { 00241 const B* row = A.r[i].getptr(); 00242 if(row) 00243 return MatrixDimension<block_type>::rowdim(*row); 00244 else 00245 return 0; 00246 } 00247 00248 static size_type coldim (const Matrix& A, size_type c) 00249 { 00250 // find an entry in column j 00251 if (A.nnz>0) 00252 { 00253 for (size_type k=0; k<A.nnz; k++) { 00254 if (A.j[k]==c) { 00255 return MatrixDimension<block_type>::coldim(A.a[k]); 00256 } 00257 } 00258 } 00259 else 00260 { 00261 for (size_type i=0; i<A.N(); i++) 00262 { 00263 size_type* j = A.r[i].getindexptr(); 00264 B* a = A.r[i].getptr(); 00265 for (size_type k=0; k<A.r[i].getsize(); k++) 00266 if (j[k]==c) { 00267 return MatrixDimension<block_type>::coldim(a[k]); 00268 } 00269 } 00270 } 00271 00272 // not found 00273 return 0; 00274 } 00275 00276 static size_type rowdim (const Matrix& A){ 00277 size_type nn=0; 00278 for (size_type i=0; i<A.N(); i++) 00279 nn += rowdim(A,i); 00280 return nn; 00281 } 00282 00283 static size_type coldim (const Matrix& A){ 00284 typedef typename Matrix::ConstRowIterator ConstRowIterator; 00285 typedef typename Matrix::ConstColIterator ConstColIterator; 00286 00287 // The following code has a complexity of nnz, and 00288 // typically a very small constant. 00289 // 00290 std::vector<size_type> coldims(A.M(), 00291 std::numeric_limits<size_type>::max()); 00292 00293 for (ConstRowIterator row=A.begin(); row!=A.end(); ++row) 00294 for (ConstColIterator col=row->begin(); col!=row->end(); ++col) 00295 // only compute blocksizes we don't already have 00296 if (coldims[col.index()]==std::numeric_limits<size_type>::max()) 00297 coldims[col.index()] = MatrixDimension<block_type>::coldim(*col); 00298 00299 size_type sum = 0; 00300 for (typename std::vector<size_type>::iterator it=coldims.begin(); 00301 it!=coldims.end(); ++it) 00302 // skip rows for which no coldim could be determined 00303 if ((*it)>=0) 00304 sum += *it; 00305 00306 return sum; 00307 } 00308 }; 00309 00310 00311 template<typename B, int n, int m, typename TA> 00312 struct MatrixDimension<BCRSMatrix<FieldMatrix<B,n,m> ,TA> > 00313 { 00314 typedef BCRSMatrix<FieldMatrix<B,n,m> ,TA> Matrix; 00315 typedef typename Matrix::size_type size_type; 00316 00317 static size_type rowdim (const Matrix& A, size_type i) 00318 { 00319 return n; 00320 } 00321 00322 static size_type coldim (const Matrix& A, size_type c) 00323 { 00324 return m; 00325 } 00326 00327 static size_type rowdim (const Matrix& A) { 00328 return A.N()*n; 00329 } 00330 00331 static size_type coldim (const Matrix& A) { 00332 return A.M()*m; 00333 } 00334 }; 00335 00336 template<typename K, int n, int m> 00337 struct MatrixDimension<FieldMatrix<K,n,m> > 00338 { 00339 typedef FieldMatrix<K,n,m> Matrix; 00340 typedef typename Matrix::size_type size_type; 00341 00342 static size_type rowdim(const Matrix& A, size_type r) 00343 { 00344 return 1; 00345 } 00346 00347 static size_type coldim(const Matrix& A, size_type r) 00348 { 00349 return 1; 00350 } 00351 00352 static size_type rowdim(const Matrix& A) 00353 { 00354 return n; 00355 } 00356 00357 static size_type coldim(const Matrix& A) 00358 { 00359 return m; 00360 } 00361 }; 00362 00363 template<typename K, int n, int m, typename TA> 00364 struct MatrixDimension<Matrix<FieldMatrix<K,n,m>, TA> > 00365 { 00366 typedef Matrix<FieldMatrix<K,n,m>, TA> ThisMatrix; 00367 typedef typename ThisMatrix::size_type size_type; 00368 00369 static size_type rowdim(const ThisMatrix& A, size_type r) 00370 { 00371 return n; 00372 } 00373 00374 static size_type coldim(const ThisMatrix& A, size_type r) 00375 { 00376 return m; 00377 } 00378 00379 static size_type rowdim(const ThisMatrix& A) 00380 { 00381 return A.N()*n; 00382 } 00383 00384 static size_type coldim(const ThisMatrix& A) 00385 { 00386 return A.M()*m; 00387 } 00388 }; 00389 00390 } 00391 #endif