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