matrixutils.hh

Go to the documentation of this file.
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

Generated on Fri Apr 29 2011 with Doxygen (ver 1.7.1) [doxygen-log,error-log].