matrixutils.hh
Go to the documentation of this file.00001 #ifndef DUNE_MATRIX_UTILS_HH
00002 #define DUNE_MATRIX_UTILS_HH
00003
00004 #include<set>
00005 #include<limits>
00006 #include<dune/common/typetraits.hh>
00007 #include<dune/common/static_assert.hh>
00008 #include"istlexception.hh"
00009
00010 namespace Dune
00011 {
00021 namespace
00022 {
00023
00024 template<int i>
00025 struct NonZeroCounter
00026 {
00027 template<class M>
00028 static typename M::size_type count(const M& matrix)
00029 {
00030 typedef typename M::ConstRowIterator RowIterator;
00031
00032 RowIterator endRow = matrix.end();
00033 typename M::size_type nonZeros = 0;
00034
00035 for(RowIterator row = matrix.begin(); row != endRow; ++row){
00036 typedef typename M::ConstColIterator Entry;
00037 Entry endEntry = row->end();
00038 for(Entry entry = row->begin(); entry != endEntry; ++entry){
00039 nonZeros += NonZeroCounter<i-1>::count(*entry);
00040 }
00041 }
00042 return nonZeros;
00043 }
00044 };
00045
00046 template<>
00047 struct NonZeroCounter<1>
00048 {
00049 template<class M>
00050 static typename M::size_type count(const M& matrix)
00051 {
00052 return matrix.N()*matrix.M();
00053 }
00054 };
00055
00056 }
00057
00062 template<std::size_t blocklevel, std::size_t l=blocklevel>
00063 struct CheckIfDiagonalPresent
00064 {
00069 template<class Matrix>
00070 static void check(const Matrix& mat)
00071 {
00072 #ifdef DUNE_ISTL_WITH_CHECKING
00073 CheckIfDiagonalPresent<blocklevel-1,l>::check(mat);
00074 #endif
00075 }
00076 };
00077
00078 template<std::size_t l>
00079 struct CheckIfDiagonalPresent<0,l>
00080 {
00081 template<class Matrix>
00082 static void check(const Matrix& mat)
00083 {
00084 typedef typename Matrix::ConstRowIterator Row;
00085 for(Row row = mat.begin(); row!=mat.end(); ++row){
00086 if(row->find(row.index())==row->end())
00087 DUNE_THROW(ISTLError, "Missing diagonal value in row "<<row.index()
00088 <<" at block recursion level "<<l);
00089 }
00090 }
00091 };
00092
00104 template<class M>
00105 inline int countNonZeros(const M& matrix)
00106 {
00107 return NonZeroCounter<M::blocklevel>::count(matrix);
00108 }
00109
00110
00111
00112
00113
00115 namespace
00116 {
00117 struct CompPair{
00118 template<class G,class M>
00119 bool operator()(const std::pair<G,M>& p1, const std::pair<G,M>& p2)
00120 {
00121 return p1.first<p2.first;
00122 }
00123 };
00124
00125 }
00126 template<class M, class C>
00127 void printGlobalSparseMatrix(const M& mat, C& ooc, std::ostream& os)
00128 {
00129 typedef typename C::ParallelIndexSet::const_iterator IIter;
00130 typedef typename C::OwnerSet OwnerSet;
00131 typedef typename C::ParallelIndexSet::GlobalIndex GlobalIndex;
00132
00133 GlobalIndex gmax=0;
00134
00135 for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end();
00136 idx!=eidx; ++idx)
00137 gmax=std::max(gmax,idx->global());
00138
00139 gmax=ooc.communicator().max(gmax);
00140 ooc.buildGlobalLookup();
00141
00142 for(IIter idx=ooc.indexSet().begin(), eidx=ooc.indexSet().end();
00143 idx!=eidx; ++idx){
00144 if(OwnerSet::contains(idx->local().attribute()))
00145 {
00146 typedef typename M::block_type Block;
00147
00148 std::set<std::pair<GlobalIndex,Block>,CompPair> entries;
00149
00150
00151 typedef typename M::ConstColIterator CIter;
00152 for(CIter c=mat[idx->local()].begin(), cend=mat[idx->local()].end();
00153 c!=cend; ++c){
00154 const typename C::ParallelIndexSet::IndexPair* pair
00155 =ooc.globalLookup().pair(c.index());
00156 assert(pair);
00157 entries.insert(std::make_pair(pair->global(), *c));
00158 }
00159
00160
00161 GlobalIndex rowidx = idx->global();
00162 GlobalIndex cur=std::numeric_limits<GlobalIndex>::max();
00163 while(cur!=rowidx)
00164 cur=ooc.communicator().min(rowidx);
00165
00166
00167 typedef typename std::set<std::pair<GlobalIndex,Block>,CompPair>::iterator SIter;
00168 for(SIter s=entries.begin(), send=entries.end(); s!=send; ++s)
00169 os<<idx->global()<<" "<<s->first<<" "<<s->second<<std::endl;
00170
00171
00172 }
00173 }
00174
00175 ooc.freeGlobalLookup();
00176
00177 GlobalIndex cur=std::numeric_limits<GlobalIndex>::max();
00178 while(cur!=ooc.communicator().min(cur));
00179 }
00180
00181 }
00182 #endif