dune-grid
2.1.1
|
00001 #ifndef DUNE_PERSISTENTCONTAINER_HH 00002 #define DUNE_PERSISTENTCONTAINER_HH 00003 00004 #include <cassert> 00005 #include <map> 00006 #include <vector> 00007 00008 #include <dune/common/misc.hh> 00009 #include <dune/common/forloop.hh> 00010 #include <dune/grid/common/capabilities.hh> 00011 00012 namespace Dune 00013 { 00042 template < class Grid, class Data, class Allocator=std::allocator<Data> > 00043 class PersistentContainer; 00044 00048 template <class Grid, class Index, class Vector> 00049 class PersistentContainerVector 00050 { 00051 public: 00052 typedef typename Vector::value_type Data; 00053 typedef Grid GridType; 00054 protected: 00055 const int codim_; 00056 const Index& index_; 00057 const double overEstimate_; 00058 Vector data_; 00059 00060 public: 00062 typedef typename GridType :: template Codim< 0 > :: Entity ElementType; 00063 00065 typedef typename Vector :: iterator Iterator ; 00067 typedef typename Vector :: const_iterator ConstIterator ; 00068 00070 // store data on entities of given codim using index to store data in vector. 00071 // The overEstimate parameter can be used to allocate more memory than 00072 // required to store the data. 00073 PersistentContainerVector( const GridType& grid, const int codim, 00074 const Index& index, 00075 const double overEstimate, 00076 const typename Vector::allocator_type &allocator) 00077 : codim_( codim ) 00078 , index_( index ) 00079 , overEstimate_( overEstimate ) // this is not yet the right approach - will be revised 00080 , data_(int(index.size(0)*overEstimate), Data(), allocator) 00081 { 00082 data_.resize(index.size(0)); 00083 } 00084 00086 PersistentContainerVector( const PersistentContainerVector& other ) 00087 : codim_( other.codim_ ) 00088 , index_( other.index_ ) 00089 , overEstimate_( other.overEstimate_ ) 00090 , data_( other.data_ ) 00091 {} 00092 00094 const Index& index() 00095 { 00096 return index_; 00097 } 00098 00100 template <class Entity> 00101 Data& operator [] (const Entity& entity ) 00102 { 00103 assert( Entity :: codimension == codim_ ); 00104 assert( (typename Index::IndexType) index_.index( entity ) < (typename Index::IndexType) data_.size() ); 00105 return data_[ index_.index( entity ) ]; 00106 } 00107 00109 template <class Entity> 00110 const Data& operator [] (const Entity& entity ) const 00111 { 00112 assert( Entity :: codimension == codim_ ); 00113 assert( (typename Index::IndexType) index_.index( entity ) < (typename Index::IndexType) data_.size() ); 00114 return data_[ index_.index( entity ) ]; 00115 } 00116 00118 Data& operator () (const ElementType& element, const int subEntity ) 00119 { 00120 assert( (typename Index::IndexType) index_.subIndex( element, subEntity, codim_ ) < (typename Index::IndexType) data_.size() ); 00121 return data_[ index_.subIndex( element, subEntity, codim_ ) ]; 00122 } 00123 00125 const Data& operator () (const ElementType& element, const int subEntity ) const 00126 { 00127 assert( (typename Index::IndexType) index_.subIndex( element, subEntity, codim_ ) < (typename Index::IndexType) data_.size() ); 00128 return data_[ index_.subIndex( element, subEntity, codim_ ) ]; 00129 } 00130 00132 Iterator begin() 00133 { 00134 return data_.begin(); 00135 } 00136 00138 ConstIterator begin() const 00139 { 00140 return data_.begin(); 00141 } 00142 00144 Iterator end() 00145 { 00146 return data_.end(); 00147 } 00148 00150 ConstIterator end() const 00151 { 00152 return data_.end(); 00153 } 00154 00156 size_t size() const { return data_.size(); } 00157 00159 void reserve( ) // need a better name 00160 { 00161 if( (typename Index::IndexType) index_.size( codim_ ) > (typename Index::IndexType) data_.size() ) 00162 update( ); 00163 } 00164 00166 void clear( ) 00167 { 00168 const size_t newSize = index_.size( codim_ ); 00169 data_.resize( newSize ); 00170 data_.clear(); 00171 } 00172 00174 void update( ) 00175 { // this could be more sophisticated (although std::vector is not stupid and 00176 // overestimated on its own... 00177 const size_t newSize = index_.size( codim_ ); 00178 if (newSize < data_.capacity()) 00179 data_.resize(newSize); 00180 else 00181 { 00182 data_.reserve(newSize*overEstimate_); 00183 data_.resize(newSize); 00184 } 00185 } 00186 }; 00187 00191 template <class Grid, class Id, class Map> 00192 class PersistentContainerMap 00193 { 00194 typedef PersistentContainerMap< Grid, Id, Map > ThisType; 00195 00196 protected: 00197 typedef typename Map :: mapped_type Data; 00198 typedef typename Id :: IdType IdType; 00199 typedef Grid GridType; 00200 const GridType& grid_; 00201 const int codim_; 00202 const Id& id_; 00203 mutable Map data_; 00204 00205 typedef typename Map :: iterator iterator ; 00206 typedef typename Map :: const_iterator const_iterator ; 00207 00208 template <class D, class IteratorType > 00209 struct DataExtractor ; 00210 00211 // Data type for iterator 00212 template <class D> 00213 struct DataExtractor< D, iterator > 00214 { 00215 typedef D Type ; 00216 }; 00217 00218 // Data type for const iterator 00219 template <class D> 00220 struct DataExtractor< D, const_iterator > 00221 { 00222 typedef const D Type ; 00223 }; 00224 00225 template <class IteratorType> 00226 class MyIterator 00227 { 00228 IteratorType it_; 00229 public: 00230 // get correct data type (const or non-const) 00231 typedef typename DataExtractor<Data, IteratorType> :: Type value_type ; 00232 00233 MyIterator(const IteratorType& it) : it_( it ) {} 00234 MyIterator(const MyIterator& other) : it_( other.it_ ) {} 00235 00236 bool operator == (const MyIterator& other) const { return it_ == other.it_; } 00237 bool operator != (const MyIterator& other) const { return it_ != other.it_; } 00238 00239 MyIterator& operator ++ () 00240 { 00241 ++it_; 00242 return *this; 00243 } 00244 value_type& operator * () { return (*it_).second; } 00245 value_type* operator -> () { return &((*it_).second); } 00246 MyIterator& operator = (const MyIterator& other) 00247 { 00248 it_ = other.it_; 00249 return *this; 00250 } 00251 }; 00252 00253 template< int codim , bool gridHasCodim > 00254 struct AdaptCodimBase 00255 { 00256 static void apply ( ThisType &container, const Data& value , const int myCodim) 00257 { 00258 if( codim == myCodim ) 00259 container.template adaptCodim< codim > ( value ); 00260 } 00261 }; 00262 00263 template< int codim > 00264 struct AdaptCodimBase< codim, false > 00265 { 00266 static void apply ( ThisType &container, const Data& value , const int myCodim) 00267 { 00268 } 00269 }; 00270 00271 template< int codim > 00272 struct AdaptCodim 00273 : public AdaptCodimBase< codim, Capabilities :: hasEntity < GridType, codim > :: v > 00274 { 00275 }; 00276 00277 public: 00278 typedef typename GridType :: template Codim< 0 > :: Entity ElementType; 00279 typedef MyIterator< iterator > Iterator; 00280 typedef MyIterator< const_iterator > ConstIterator; 00281 00283 // 00284 // Container is to be used to store data on entities of given codim using id to store data in map. 00285 PersistentContainerMap( const GridType& grid, const int codim, const Id& id, 00286 const typename Map::key_compare& comp, 00287 const typename Map::allocator_type &allocator ) 00288 : grid_( grid ) 00289 , codim_( codim ) 00290 , id_( id ) 00291 , data_(comp,allocator) 00292 { 00293 } 00295 // unordered_map the constructor taking only an allocator is not available that is 00296 // why this constructor is added) 00297 // 00298 // Container is to be used to store data on entities of given codim using id to store data in map. 00299 PersistentContainerMap( const GridType& grid, const int codim, const Id& id) 00300 : grid_( grid ) 00301 , codim_( codim ) 00302 , id_( id ) 00303 , data_() 00304 { 00305 } 00306 00308 PersistentContainerMap( const PersistentContainerMap& other ) 00309 : grid_( other.grid_ ) 00310 , codim_( other.codim_ ) 00311 , id_( other.id_ ) 00312 , data_( other.data_ ) 00313 {} 00314 00316 template <class Entity> 00317 Data& operator [] (const Entity& entity ) 00318 { 00319 assert( Entity :: codimension == codim_ ); 00320 return data_[ id_.id( entity ) ]; 00321 } 00322 00324 template <class Entity> 00325 const Data& operator [] (const Entity& entity ) const 00326 { 00327 assert( Entity :: codimension == codim_ ); 00328 return data_[ id_.id( entity ) ]; 00329 } 00330 00332 Data& operator () (const ElementType& element, const int subEntity ) 00333 { 00334 return data_[ id_.subId( element, subEntity, codim_ ) ]; 00335 } 00336 00338 const Data& operator () (const ElementType& element, const int subEntity ) const 00339 { 00340 return data_[ id_.subId( element, subEntity, codim_ ) ]; 00341 } 00342 00344 Iterator begin() 00345 { 00346 return Iterator( data_.begin() ); 00347 } 00348 00350 ConstIterator begin() const 00351 { 00352 return ConstIterator( data_.begin() ); 00353 } 00354 00356 Iterator end() 00357 { 00358 return Iterator( data_.end() ); 00359 } 00360 00362 ConstIterator end() const 00363 { 00364 return ConstIterator( data_.end() ); 00365 } 00366 00368 size_t size() const { return data_.size(); } 00369 00371 void reserve() 00372 { 00373 } 00374 00376 void clear( ) 00377 { 00378 data_.clear(); 00379 } 00380 00382 void update( ) 00383 { // this version could be implemented differently by only compressing 00384 update( Data() ); 00385 } 00386 protected: 00388 void update( const Data& value ) 00389 { 00390 // loop over all codimensions (needed to make codim_ static) 00391 ForLoop< AdaptCodim, 0, GridType :: dimension > :: apply( *this, value, codim_ ); 00392 } 00393 00394 template <int codim> 00395 void adaptCodim( const Data& value ) 00396 { 00397 assert( codim_ == codim ); 00398 // create empty map and swap it with current map (no need to copy twice) 00399 Map oldData; 00400 std::swap( oldData, data_ ); 00401 00402 const iterator olddataend = oldData.end(); 00403 typedef typename GridType :: template Codim< codim > :: LevelIterator LevelIterator ; 00404 typedef typename LevelIterator :: Entity Entity; 00405 for(int l = 0; l <= grid_.maxLevel(); ++ l) 00406 { 00407 const LevelIterator endit = grid_.template lend< codim > ( l ); 00408 for( LevelIterator it = grid_.template lbegin< codim > ( l ); it != endit; ++ it ) 00409 { 00410 const Entity& entity = * it ; 00411 const IdType id = id_.id( entity ); 00412 Data& data = data_[ id ]; 00413 iterator entry = oldData.find( id ); 00414 if( entry != olddataend ) 00415 data = (*entry).second; 00416 } 00417 } 00418 } 00419 }; 00420 00421 // PersistentContainer (default is to use PersistentContainerMap) 00422 // ------------------- 00423 template < class Grid, class Data, class Allocator> 00424 class PersistentContainer 00425 : public PersistentContainerMap< Grid, typename Grid::Traits::LocalIdSet, 00426 std::map<const typename Grid::Traits::LocalIdSet::IdType, Data, 00427 std::less<const typename Grid::Traits::LocalIdSet::IdType>, Allocator> > 00428 { 00429 public: 00430 typedef Grid GridType; 00431 protected: 00432 typedef typename Grid::Traits::LocalIdSet IdSet; 00433 typedef typename IdSet::IdType IdType; 00434 typedef std::map<const IdType, Data, std::less<const IdType>, Allocator> Map; 00435 typedef PersistentContainerMap< Grid, IdSet, Map > BaseType; 00436 00437 public: 00440 PersistentContainer ( const GridType &grid, const int codim, const Allocator &allocator=Allocator() ) 00441 : BaseType( grid, codim, grid.localIdSet(), std::less<const IdType>(), allocator ) 00442 {} 00443 }; 00444 00445 #if 0 // the following implementation can be used for a grid providing a hash for the id type 00446 #include <unordered_map> 00447 template < class MyGrid, class Data, class Allocator > 00448 class PersistentContainer 00449 : public PersistentContainerMap< MyGrid, typename MyGrid::Traits::LocalIdSet, 00450 std::unordered_map<const typename MyGrid::Traits::LocalIdSet::IdType, Data, 00451 std::hash<typename MyGrid::Traits::LocalIdSet::IdType>, 00452 std::equal_to<const typename MyGrid::Traits::LocalIdSet::IdType>, Allocator> > 00453 { 00454 typedef MyGrid GridType; 00455 typedef typename GridType::Traits::LocalIdSet IdSet; 00456 typedef typename IdSet::IdType IdType; 00457 typedef std::unordered_map<const IdType, Data, std::hash<IdType>, std::equal_to<const IdType>, Allocator> Map; 00458 typedef PersistentContainerMap< GridType, IdSet, Map > BaseType; 00459 00460 public: 00466 PersistentContainer ( const GridType &grid, const int codim, const Allocator &allocator=Allocator() ) 00467 : BaseType( grid, codim, grid.localIdSet() ) 00468 {} 00469 }; 00470 #endif 00471 } // end namespace Dune 00472 00473 #endif // end DUNE_PERSISTENTCONTAINER_HH