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