utility/persistentcontainer.hh

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

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