1 #ifndef DUNE_ALUGRID_DEFAULTINDEXSETS_HH
2 #define DUNE_ALUGRID_DEFAULTINDEXSETS_HH
3 
4 #include <type_traits>
5 #include <memory>
6 #include <vector>
7 
8 #include <dune/common/version.hh>
9 
10 #include <dune/grid/common/grid.hh>
11 #include <dune/grid/common/adaptcallback.hh>
12 #include <dune/grid/utility/persistentcontainer.hh>
13 
14 #include <dune/alugrid/common/alugrid_assert.hh>
15 
16 /** @file
17  @author Robert Kloefkorn
18  @brief Provides default index set implementations for Level- and
19  LeafIndexsets used by ALUGrid.
20 */
21 
22 namespace Dune
23 {
24 
25   //! LevelIterator tpyes for all codims and partition types
26   template <class GridImp>
27   struct DefaultLevelIteratorTypes
28   {
29     //! The types
30     template<int cd>
31     struct Codim
32     {
33       template<PartitionIteratorType pitype>
34       struct Partition
35       {
36         typedef typename GridImp::Traits::template Codim<cd>::template Partition<pitype>::LevelIterator Iterator;
37       };
38     };
39   };
40 
41   //! LeafIterator tpyes for all codims and partition types
42   template <class GridImp>
43   struct DefaultLeafIteratorTypes
44   {
45     //! The types of the iterator
46     template<int cd>
47     struct Codim
48     {
49       template<PartitionIteratorType pitype>
50       struct Partition
51       {
52         typedef typename GridImp::Traits::template Codim<cd>::
53           template Partition<pitype>::LeafIterator  Iterator;
54       };
55     };
56   };
57 
58 
59 
60   /*! \brief
61     DefaultIndexSet creates an index set by using the grids persistent container
62     an a given pair of iterators
63    */
64   template < class GridImp, class IteratorImp >
65   class DefaultIndexSet :
66     public IndexSet< GridImp, DefaultIndexSet <GridImp, IteratorImp>,
67                      unsigned int, std::vector< GeometryType > >
68   {
69     typedef GridImp GridType;
70     enum { dim = GridType::dimension };
71 
72   public:
73     enum { ncodim = GridType::dimension + 1 };
74 
75     //! type of index
76     typedef unsigned int IndexType;
77     //! type of geometry types
78     typedef std::vector< GeometryType > Types;
79 
80   private:
81     //! type of iterator to generate index set
82     typedef IteratorImp IteratorType ;
83 
84   public:
85     struct Index
86     {
87       int index_;
IndexDune::DefaultIndexSet::Index88       Index() : index_( -1 ) {}
indexDune::DefaultIndexSet::Index89       int index() const { return index_; }
setDune::DefaultIndexSet::Index90       void set( const int index ) { index_ = index; }
91     };
92 
93     typedef PersistentContainer< GridType, Index > PersistentContainerType ;
94     typedef std::vector< std::unique_ptr< PersistentContainerType > > PersistentContainerVectorType;
95 
96   private:
97     typedef DefaultIndexSet<GridType, IteratorType > ThisType;
98 
99     template< int codim >
100     struct InsertEntityLoop
101     {
102       // determine next codim with a sealing of the grid's dimension
103       static const int nextCodim = codim == dim ? dim : codim + 1;
104 
applyDune::DefaultIndexSet::InsertEntityLoop105       static void apply ( const typename GridType::template Codim< 0 >::Entity &entity,
106                           PersistentContainerVectorType &indexContainer,
107                           std::vector< int > &sizes )
108       {
109         PersistentContainerType &codimContainer = *(indexContainer[ codim ]);
110         if( codim == 0 )
111         {
112           Index &idx = codimContainer[ entity ];
113           if( idx.index() < 0 )
114             idx.set( sizes[ codim ]++ );
115         }
116         else
117         {
118           const int subEntities = entity.subEntities( codim );
119           for( int i = 0; i < subEntities; ++i )
120           {
121             Index &idx = codimContainer( entity, i );
122             if( idx.index() < 0 )
123               idx.set( sizes[ codim ]++ );
124           }
125         }
126 
127         if( codim < dim )
128         {
129           // call next codim, dim will end this loop
130           InsertEntityLoop< nextCodim >::apply( entity, indexContainer, sizes );
131         }
132       }
133     };
134 
135     template <class EntityType, int codim>
136     struct EntitySpec
137     {
subIndexDune::DefaultIndexSet::EntitySpec138       static IndexType subIndex( const PersistentContainerType& indexContainer,
139                                  const EntityType & e,
140                                  int i )
141       {
142         // if the codimension equals that of the entity simply return the index
143         if( codim == EntityType::codimension )
144           return indexContainer[ e ].index();
145 
146         DUNE_THROW(NotImplemented,"subIndex for entities with codimension > 0 is not implemented");
147         return IndexType(-1);
148       }
149     };
150 
151     template <class EntityType>
152     struct EntitySpec<EntityType,0>
153     {
subIndexDune::DefaultIndexSet::EntitySpec154       static IndexType subIndex( const PersistentContainerType& indexContainer,
155                                  const EntityType & e,
156                                  int i )
157       {
158         alugrid_assert ( indexContainer( e, i ).index() >= 0 );
159         return indexContainer( e, i ).index();
160       }
161     };
162 
163     // no copying
164     DefaultIndexSet( const DefaultIndexSet& org ) = delete;
165 
166   public:
167     //! import default implementation of subIndex<cc>
168     //! \todo remove after next release
169     using IndexSet<GridType, DefaultIndexSet>::subIndex;
170 
171     //! create index set by using the given begin and end iterator
172     //! for the given level (level == -1 means leaf level)
DefaultIndexSet(const GridType & grid,const IteratorType & begin,const IteratorType & end,const int level=-1)173     DefaultIndexSet( const GridType& grid ,
174                      const IteratorType& begin,
175                      const IteratorType& end,
176                      const int level = -1 )
177     : grid_(grid),
178       indexContainers_( ncodim ),
179       size_( ncodim, -1 ),
180       level_(level)
181     {
182       for( int codim=0; codim < ncodim; ++codim )
183       {
184         indexContainers_[ codim ].reset( new PersistentContainerType( grid, codim ) );
185       }
186 
187       calcNewIndex (begin, end);
188     }
189 
indexContainer(const size_t codim) const190     const PersistentContainerType& indexContainer( const size_t codim ) const
191     {
192       alugrid_assert ( codim < indexContainers_.size() );
193       alugrid_assert ( indexContainers_[ codim ] );
194       return *( indexContainers_[ codim ] );
195     }
196 
indexContainer(const size_t codim)197     PersistentContainerType& indexContainer( const size_t codim )
198     {
199       alugrid_assert ( codim < indexContainers_.size() );
200       alugrid_assert ( indexContainers_[ codim ] );
201       return *( indexContainers_[ codim ] );
202     }
203 
204     //! return LevelIndex of given entity
205     template<class EntityType>
index(const EntityType & en) const206     IndexType index (const EntityType & en) const
207     {
208       enum { cd = EntityType::codimension };
209       // this must not be true for vertices
210       // therefore only check other codims
211 #ifdef ALUGRIDDEBUG
212       const int codim = cd;
213       alugrid_assert ( (codim == dim) ? (1) : ( level_ < 0 ) || (level_ == en.level() ));
214       alugrid_assert ( indexContainer( codim )[ en ].index() >= 0 );
215 #endif
216       return indexContainer( cd )[ en ].index();
217     }
218 
219     //! return LevelIndex of given entity
220     template<int cd>
index(const typename GridImp::template Codim<cd>::Entity & en) const221     IndexType index (const typename GridImp::template Codim<cd>::Entity& en) const
222     {
223       // this must not be true for vertices
224       // therefore only check other codims
225 #ifdef ALUGRIDDEBUG
226       const int codim = cd;
227       //const bool isLeaf = (codim == 0) ? en.isLeaf() : true ;
228 
229       alugrid_assert ( (codim == dim) ? (true) : ( level_ < 0 ) || (level_ == en.level() ));
230       alugrid_assert ( indexContainer( cd )[ en ].index() >= 0 );
231 #endif
232       return indexContainer( cd )[ en ].index();
233     }
234 
235     //! return subIndex (LevelIndex) for a given Entity of codim = 0 and a
236     //! given SubEntity codim and number of SubEntity
237     template< int cc >
subIndex(const typename std::remove_const<GridImp>::type::Traits::template Codim<cc>::Entity & e,int i,unsigned int codim) const238     IndexType subIndex ( const typename std::remove_const< GridImp >::type::Traits::template Codim< cc >::Entity &e,
239                          int i, unsigned int codim ) const
240     {
241       alugrid_assert ( (codim != 0) || (level_ < 0) || ( level_ == e.level() ) );
242       typedef typename std::remove_const< GridImp >::type::Traits::template Codim< cc >::Entity Entity;
243       return EntitySpec< Entity, cc >::subIndex( indexContainer( codim ), e, i );
244     }
245 
246     //! returns true if this set provides an index for given entity
247     template<class EntityType>
contains(const EntityType & en) const248     bool contains (const EntityType& en) const
249     {
250       enum { cd = EntityType::codimension };
251       return (indexContainer( cd )[ en ].index() >= 0 );
252     }
253 
254     //! return size of IndexSet for a given level and codim
size(int codim) const255     IndexType size ( int codim ) const
256     {
257       alugrid_assert ( codim >= 0 && codim <= GridType::dimension );
258       return size_[ codim ];
259     }
260 
261     //! return size of IndexSet for a given level and codim
262     //! this method is to be revised
size(GeometryType type) const263     IndexType size ( GeometryType type ) const
264     {
265       if( typeNotValid(type) ) return 0;
266       return size_[GridType::dimension-type.dim()];
267     }
268 
269     //! do calculation of the index set, has to be called when grid was
270     //! changed or if index set is created
calcNewIndex(const IteratorType & begin,const IteratorType & end)271     void calcNewIndex ( const IteratorType &begin, const IteratorType &end )
272     {
273       // resize arrays to new size
274       // and set size to zero
275       for( int cd = 0; cd < ncodim; ++cd )
276       {
277         indexContainer( cd ).resize( Index() );
278         indexContainer( cd ).fill( Index() );
279         size_[ cd ] = 0;
280       }
281 
282       // grid walk to setup index set
283       for( IteratorType it = begin; it != end; ++it )
284       {
285         const typename IteratorType::Entity &entity = *it;
286         alugrid_assert ( ( level_ < 0 ) ? entity.isLeaf() : (entity.level() == level_) );
287         InsertEntityLoop< 0 >::apply( entity, indexContainers_, size_ );
288       }
289 
290       // remember the number of entity on level and cd = 0
291       for(int cd=0; cd<ncodim; ++cd)
292       {
293 #ifdef ALUGRIDDEBUG
294         const int gridSize = ( level_ < 0 ) ? grid_.size( cd ) : grid_.size( level_, cd);
295         const int mySize = size_[cd];
296         if( mySize > gridSize )
297         {
298           std::cout << "DefaultIndexSet[ " << level_ << " ]: " << mySize << " s | g " << gridSize << std::endl;
299         }
300         // this assertion currently fails for 3d conforming
301         // alugrid_assert ( ( grid_.conformingRefinement() && dim == 3 && level_ >= 0 ) ? true : (mySize <= gridSize) );
302 #endif
303       }
304     }
305 
306     //! deliver all geometry types used in this grid
geomTypes(int codim) const307     const std::vector<GeometryType>& geomTypes (int codim) const
308     {
309       return grid_.geomTypes( codim );
310     }
311 
312     //! deliver all geometry types used in this grid
types(const int codim) const313     Types types( const int codim ) const
314     {
315       return geomTypes( codim );
316     }
317 
318     //! returns true if this set provides an index for given entity
containsIndex(const int cd,const int idx) const319     bool containsIndex ( const int cd, const int idx ) const
320     {
321       alugrid_assert ( (typename PersistentContainerType::Size)idx < indexContainer( cd ).size() );
322       return ((indexContainer( cd ).begin() + idx)->index() >= 0);
323     }
324 
325   private:
326     // return whether set has this type stored or not
typeNotValid(const GeometryType & type) const327     bool typeNotValid (const GeometryType & type) const
328     {
329       int codim = GridType::dimension - type.dim();
330       const std::vector<GeometryType> & geomT = geomTypes(codim);
331       for(size_t i=0; i<geomT.size(); ++i) if(geomT[i] == type) return false;
332       return true;
333     }
334 
335     // grid this index set belongs to
336     const GridType& grid_;
337 
338     //! vector with PersistentContainer for each codim
339     PersistentContainerVectorType indexContainers_;
340 
341     // number of entitys of each level an codim
342     std::vector< int > size_;
343 
344     // the level for which this index set is created
345     const int level_;
346   };
347 
348 
349   /*! \brief
350     DefaultBoundarySegmentIndexSet creates an index set for the macro boundary segments
351    */
352   template <class Grid>
353   class DefaultBoundarySegmentIndexSet
354   {
355   public:
356     //! type of index
357     typedef int IndexType;
358 
359   public:
360     struct Index
361     {
362       IndexType index_;
IndexDune::DefaultBoundarySegmentIndexSet::Index363       Index() : index_( -1 ) {}
indexDune::DefaultBoundarySegmentIndexSet::Index364       int index() const { return index_; }
setDune::DefaultBoundarySegmentIndexSet::Index365       void set( const int index ) { index_ = index; }
366     };
367 
368     //! type of geometry types
369     typedef std::vector< Index > SegmentIndexVectorType;
370   protected:
371     SegmentIndexVectorType segmentIndex_;
372     int numSegments_;
373 
374   public:
DefaultBoundarySegmentIndexSet()375     DefaultBoundarySegmentIndexSet()
376       : segmentIndex_(),
377         numSegments_( -1 )
378     {
379     }
380 
381     //! return LevelIndex of given entity
index(const int segmentId) const382     IndexType index ( const int segmentId ) const
383     {
384       alugrid_assert( valid() );
385       alugrid_assert( segmentId < int(segmentIndex_.size() ) );
386       alugrid_assert( segmentIndex_[ segmentId ].index() >= 0 );
387       return segmentIndex_[ segmentId ].index();
388     }
389 
size() const390     IndexType size() const
391     {
392       alugrid_assert( valid() );
393       return numSegments_;
394     }
395 
396     //! do calculation of the index set, has to be called when grid was
397     //! changed or if index set is created
398     template <class GridViewType>
update(const GridViewType & gridView)399     void update( const GridViewType& gridView )
400     {
401       numSegments_ = 0 ;
402       segmentIndex_.clear();
403 
404       const auto end = gridView.template end<0, Interior_Partition> ();
405       for( auto it = gridView.template begin<0, Interior_Partition> (); it != end; ++ it )
406       {
407         const auto& entity = *it;
408         const auto endi = gridView.iend( entity );
409         for( auto i = gridView.ibegin( entity ); i != endi; ++i )
410         {
411           const auto& intersection = *i;
412           if( intersection.boundary() )
413           {
414             const int id = intersection.impl().segmentId();
415             if( int(segmentIndex_.size()) <= id )
416               segmentIndex_.resize( id+1 );
417             if( segmentIndex_[ id ].index() < 0 )
418               segmentIndex_[ id ].set( numSegments_ ++ );
419           }
420         }
421       }
422 
423       // if segment index is consecutive use identity
424       if( numSegments_ == int(segmentIndex_.size()) )
425       {
426         for( int i=0; i<numSegments_; ++ i )
427         {
428           segmentIndex_[ i ].set( i );
429         }
430       }
431     }
432 
valid() const433     bool valid () const { return numSegments_ >= 0; }
invalidate()434     void invalidate () { numSegments_ = -1; }
435   };
436 
437 } // namespace Dune
438 
439 #endif // #ifndef DUNE_ALUGRID_DEFAULTINDEXSETS_HH
440