00001 #ifndef DUNE_SIZECACHE_HH
00002 #define DUNE_SIZECACHE_HH
00003
00004 #include <cassert>
00005 #include <vector>
00006
00007 #include <dune/common/geometrytype.hh>
00008
00009 #include <dune/grid/common/gridenums.hh>
00010
00017 namespace Dune {
00018
00020 template <class GridImp>
00021 class SingleTypeSizeCache
00022 {
00023 typedef SingleTypeSizeCache<GridImp> ThisType;
00025 enum { dim = GridImp::dimension };
00026
00028 enum { nCodim = GridImp::dimension+1 };
00029
00030 typedef GridImp GridType;
00031
00032
00033 mutable std::vector<int> levelSizes_[nCodim];
00034
00035
00036 mutable int leafSizes_[nCodim];
00037
00038
00039 mutable std::vector<int> ghostLevelSizes_[nCodim];
00040
00041
00042 mutable int ghostLeafSizes_[nCodim];
00043
00044
00045 const GridType & grid_;
00046
00047
00048 const bool isSimplex_;
00049
00050 const bool isCube_;
00051
00052 bool notWorry_;
00053
00054
00055 template <class SzCacheType ,PartitionIteratorType pitype, int codim >
00056 struct CountLevelEntities
00057 {
00058 static inline int count (const SzCacheType & sc, int level, int cd)
00059 {
00060 if( cd == codim )
00061 {
00062 return sc.template countLevelEntities<pitype,codim> (level);
00063 }
00064 else
00065 return CountLevelEntities < SzCacheType, pitype, codim-1> :: count (sc,level,cd);
00066 }
00067 };
00068
00069
00070 template <class SzCacheType,PartitionIteratorType pitype>
00071 struct CountLevelEntities<SzCacheType,pitype,0>
00072 {
00073 static inline int count (const SzCacheType & sc, int level, int cd)
00074 {
00075 enum { codim = 0 };
00076 assert( cd == codim );
00077 return sc.template countLevelEntities<pitype,codim> (level);
00078 }
00079 };
00080
00081
00082
00083 template <class SzCacheType , PartitionIteratorType pitype, int codim >
00084 struct CountLeafEntities
00085 {
00086 static inline int count (const SzCacheType & sc, int cd)
00087 {
00088 if( cd == codim )
00089 {
00090 return sc.template countLeafEntities<pitype,codim> ();
00091 }
00092 else
00093 return CountLeafEntities < SzCacheType, pitype, codim-1> :: count (sc,cd);
00094 }
00095 };
00096
00097
00098 template <class SzCacheType,PartitionIteratorType pitype>
00099 struct CountLeafEntities<SzCacheType,pitype,0>
00100 {
00101 static inline int count (const SzCacheType & sc, int cd)
00102 {
00103 enum { codim = 0 };
00104 assert( cd == codim );
00105 return sc.template countLeafEntities<pitype,codim> ();
00106 }
00107 };
00108
00109
00110
00111 SingleTypeSizeCache (const SingleTypeSizeCache & );
00112 public:
00113 SingleTypeSizeCache (const GridType & grid,
00114 const bool isSimplex , const bool isCube, bool notWorry = false )
00115 : grid_(grid) , isSimplex_(isSimplex) , isCube_(isCube), notWorry_ ( notWorry )
00116 {
00117 assert( isSimplex_ != isCube_ );
00118 for(int i=0; i<nCodim; i++)
00119 {
00120 leafSizes_[i] = -1;
00121 ghostLeafSizes_[i] = -1;
00122 }
00123
00124 int numMxl = grid_.maxLevel()+1;
00125 for(int i=0; i<nCodim; i++)
00126 {
00127 std::vector<int> & vec = levelSizes_[i];
00128 vec.resize(numMxl);
00129 for(int level = 0; level<numMxl; level++) vec[level] = -1;
00130
00131 std::vector<int> & ghVec = ghostLevelSizes_[i];
00132 ghVec.resize(numMxl);
00133 for(int level = 0; level<numMxl; level++) ghVec[level] = -1;
00134 }
00135 }
00136
00137
00138
00139
00144 int size (int level, int codim) const
00145 {
00146 assert( codim >= 0 );
00147 assert( codim < nCodim );
00148 assert( level >= 0 );
00149 if( level >= (int) levelSizes_[codim].size() ) return 0;
00150
00151 if( levelSizes_[codim][level] < 0)
00152 levelSizes_[codim][level] = CountLevelEntities<ThisType,All_Partition,dim>::count(*this,level,codim);
00153 return levelSizes_[codim][level];
00154 }
00155
00157 int size (int level, int codim, GeometryType type) const
00158 {
00159
00160 if( (isSimplex_) && (isSimplex_ != type.isSimplex()) ) return 0;
00161
00162 if( (isCube_) && (isCube_ != type.isCube() ) ) return 0;
00163 return size(level,codim);
00164 }
00165
00166
00167
00168
00170 int size (int codim) const
00171 {
00172 assert( codim >= 0 );
00173 assert( codim < nCodim );
00174 if( leafSizes_[codim] < 0)
00175 leafSizes_[codim] = CountLeafEntities<ThisType,All_Partition,dim>::count(*this,codim);
00176 return leafSizes_[codim];
00177 };
00178
00180 int size (int codim, GeometryType type) const
00181 {
00182
00183 if( (isSimplex_) && (isSimplex_ != type.isSimplex()) ) return 0;
00184
00185 if( (isCube_) && (isCube_ != type.isCube() ) ) return 0;
00186 return size(codim);
00187 }
00188
00190 int ghostSize (int codim) const {
00191 if( ghostLeafSizes_[codim] < 0)
00192 ghostLeafSizes_[codim] = CountLeafEntities<ThisType,Ghost_Partition,dim>::count(*this,codim);
00193 return ghostLeafSizes_[codim];
00194 }
00195
00197 int ghostSize (int level, int codim) const
00198 {
00199
00200 if( level >= (int) ghostLevelSizes_[codim].size() ) return 0;
00201
00202 if( ghostLevelSizes_[codim][level] < 0)
00203 ghostLevelSizes_[codim][level] = CountLevelEntities<ThisType,Ghost_Partition,dim>::count(*this,level,codim);
00204 return ghostLevelSizes_[codim][level];
00205 }
00206
00207 private:
00208 template <PartitionIteratorType pitype, int codim>
00209 int countLevelEntities(int level) const
00210 {
00211 typedef typename GridType::template Codim<codim> :: template Partition<pitype> :: LevelIterator LevelIterator;
00212 LevelIterator it = grid_.template lbegin<codim,pitype> (level);
00213 LevelIterator end = grid_.template lend<codim,pitype> (level);
00214
00215 GeometryType type (((isSimplex_) ? GeometryType::simplex : GeometryType::cube ),dim-codim);
00216 assert( ((dim-codim) > 1) ? (type.isCube() == isCube_) : 1);
00217 if( notWorry_ ) return countElements(it,end,type);
00218 return countElements(it,end);
00219 }
00220
00221 template <PartitionIteratorType pitype, int codim>
00222 int countLeafEntities() const
00223 {
00224
00225 typedef typename GridType::template Codim<codim> :: template Partition<pitype> :: LeafIterator LeafIterator;
00226 LeafIterator it = grid_.template leafbegin<codim,pitype> ();
00227 LeafIterator end = grid_.template leafend<codim,pitype> ();
00228 GeometryType type (((isSimplex_) ? GeometryType::simplex : GeometryType::cube ),dim-codim);
00229 assert( ((dim-codim) > 1) ? (type.isCube() == isCube_) : 1);
00230 if( notWorry_ ) return countElements(it,end,type);
00231 return countElements(it,end);
00232 }
00233
00234
00235 template <class IteratorType>
00236 int countElements(IteratorType & it, const IteratorType & end ,
00237 const GeometryType & type ) const
00238 {
00239 int count = 0;
00240 if((type.isSimplex()) || (type.isCube()))
00241 {
00242 for( ; it != end; ++it )
00243 {
00244 if(it->type() == type)
00245 ++ count ;
00246 }
00247 }
00248 return count;
00249 }
00250
00251
00252 template <class IteratorType>
00253 int countElements(IteratorType & it, const IteratorType & end) const
00254 {
00255 int count = 0;
00256 for( ; it != end; ++it )
00257 {
00258 ++ count ;
00259 }
00260 return count;
00261 }
00262 };
00263
00265 template <class GridImp>
00266 class SizeCache
00267 {
00268 typedef SizeCache<GridImp> ThisType;
00269 typedef GridImp GridType;
00270
00271 SingleTypeSizeCache<GridType> simplexSize_;
00272 SingleTypeSizeCache<GridType> cubeSize_;
00273
00274 public:
00275 SizeCache (const GridType & grid) : simplexSize_(grid,true,false), cubeSize_(grid,false,true)
00276 {
00277
00278
00279 const std::vector<GeometryType> & geomTypes = grid.geomTypes(0);
00280 int found = 0;
00281 int others = 0;
00282 for(unsigned int i=0; i<geomTypes.size(); i++)
00283 {
00284 if( (geomTypes[i].isSimplex()) ||
00285 (geomTypes[i].isCube() ) )
00286 found++;
00287 else
00288 others++;
00289 }
00290
00291
00292 assert( !others );
00293
00294
00295 assert( found > 0 );
00296 }
00297
00298
00299
00300
00305 int size (int level, int codim) const
00306 {
00307 return (simplexSize_.size(level,codim) + cubeSize_(level,codim));
00308 }
00309
00311 int size (int level, int codim, GeometryType type) const
00312 {
00313 if( type.isSimplex()) return simplexSize_.size(level,codim);
00314 if( type.isCube() ) return cubeSize_(level,codim);
00315 return 0;
00316 }
00317
00318
00319
00320
00322 int size (int codim) const
00323 {
00324 return (simplexSize_.size(codim) + cubeSize_(codim));
00325 };
00326
00328 int size (int codim, GeometryType type) const
00329 {
00330 if( type.isSimplex() ) return simplexSize_.size(codim);
00331 if( type.isCube() ) return cubeSize_(codim);
00332 return 0;
00333 }
00334
00336 int ghostSize (int codim) const
00337 {
00338 return simplexSize_.ghostSize(codim) + cubeSize_.ghostSize(codim);
00339 }
00340
00342 int ghostSize (int level, int codim) const
00343 {
00344 return simplexSize_.ghostSize(level,codim) + cubeSize_.ghostSize(level,codim);
00345 }
00346 };
00347
00348
00349 }
00350 #endif