dune-fem  2.4.1-rc
codimindexset.hh
Go to the documentation of this file.
1 #ifndef DUNE_FEM_CODIMINDEXSET_HH
2 #define DUNE_FEM_CODIMINDEXSET_HH
3 
4 #include <algorithm>
5 #include <set>
6 
7 //- Dune includes
9 
10 #include <dune/grid/utility/persistentcontainer.hh>
11 
12 #include <dune/grid/utility/persistentcontainervector.hh>
13 #include <dune/grid/utility/persistentcontainerwrapper.hh>
14 #include <dune/grid/utility/persistentcontainermap.hh>
15 
16 
17 namespace Dune
18 {
19 
20  namespace Fem
21  {
22 
23  //***********************************************************************
24  //
25  // Index Set for one codimension
26  // --CodimIndexSet
27  //
28  //***********************************************************************
29  template <class GridImp>
31  {
32  protected:
33  typedef GridImp GridType;
35 
36  private:
37  enum INDEXSTATE { UNUSED = 0, // unused indices
38  USED = 1, // used indices
39  NEW = 2 };// new indices
40 
41  // reference to grid
42  const GridType& grid_;
43 
44  public:
45  // type of exported index
46  typedef int IndexType ;
47 
48  // indices in this status have not been initialized
49  static IndexType invalidIndex() { return -1; }
50 
51  protected:
52  // array type for indices
55 
56  // use the imporved PersistentContainer
57  typedef PersistentContainer< GridType, IndexType > IndexContainerType;
58 
59  // the mapping of the global to leaf index
60  IndexContainerType leafIndex_;
61  IndexStateArrayType indexState_;
62 
63  // stack for holes
64  IndexArrayType holes_;
65 
66  // Array that only remeber the occuring
67  // holes (for compress of data)
68  IndexArrayType oldIdx_;
69  IndexArrayType newIdx_;
70 
71  // last size of set before compress (needed in parallel runs)
72  IndexType lastSize_;
73 
74  // codim for which index is provided
75  const int myCodim_;
76 
77  // actual number of holes
78  IndexType numberHoles_;
79 
80  public:
81 
83  CodimIndexSet (const GridType& grid,
84  const int codim,
85  const double memoryFactor = 1.1)
86  : grid_( grid )
87  , leafIndex_( grid, codim, invalidIndex() )
88  , indexState_( 0 )
89  , holes_(0)
90  , oldIdx_(0)
91  , newIdx_(0)
92  , lastSize_ (0)
93  , myCodim_( codim )
94  , numberHoles_(0)
95  {
96  setMemoryFactor(memoryFactor);
97  }
98 
100  void setMemoryFactor(const double memoryFactor)
101  {
102  indexState_.setMemoryFactor( memoryFactor );
103  holes_.setMemoryFactor(memoryFactor);
104  oldIdx_.setMemoryFactor(memoryFactor);
105  newIdx_.setMemoryFactor(memoryFactor);
106  }
107 
109  void resize () { leafIndex_.resize( invalidIndex() ); }
110 
112  void prepareCompress () {}
113 
114  public:
116  void clear()
117  {
118  // set all values to invalidIndex
119  leafIndex_.fill( invalidIndex() );
120  // free all indices
121  indexState_.resize( 0 );
122  }
123 
125  void resetUsed ()
126  {
127  std::fill( indexState_.begin(), indexState_.end(), UNUSED );
128  }
129 
130  bool consecutive ()
131  {
132  std::set< int > found ;
133  // Something's wrong here: This method _must_ always return true
134  typedef typename IndexContainerType::Iterator Iterator;
135  bool consecutive = true;
136  const Iterator end = leafIndex_.end();
137  for( Iterator it = leafIndex_.begin(); it != end; ++it )
138  {
139  if( *it != invalidIndex() )
140  {
141  if( found.find( *it ) != found.end() )
142  {
143  std::cout << "index " << *it << " exists twice " << std::endl;
144  }
145  assert( found.find( *it ) == found.end() );
146  found.insert( *it );
147  }
148  consecutive &= (*it < IndexType( indexState_.size() ));
149  }
150  return consecutive;
151  }
152 
154  void checkConsecutive () { assert( consecutive() ); }
155 
157  void clearHoles()
158  {
159  // set number of holes to zero
160  numberHoles_ = 0;
161  // remember actual size
162  lastSize_ = indexState_.size();
163  }
164 
167  bool compress ()
168  {
169  const int sizeOfVecs = indexState_.size();
170  holes_.resize( sizeOfVecs );
171 
172  // true if a least one dof must be copied
173  bool haveToCopy = false;
174 
175  // mark holes
176  int actHole = 0;
177  for( int index = 0; index < sizeOfVecs; ++index )
178  {
179  // create vector with all holes
180  if( indexState_[ index ] == UNUSED )
181  holes_[ actHole++ ] = index;
182  }
183 
184  // the new size is the actual size minus the holes
185  const int actSize = sizeOfVecs - actHole;
186 
187  // resize hole storing vectors
188  oldIdx_.resize(actHole);
189  newIdx_.resize(actHole);
190 
191  // only compress if number of holes > 0
192  if(actHole > 0)
193  {
194  // close holes
195  int holes = 0; // number of real holes
196  typedef typename IndexContainerType::Iterator Iterator;
197  const Iterator end = leafIndex_.end();
198  for( Iterator it = leafIndex_.begin(); it != end; ++it )
199  {
200  IndexType& index = *it;
201  if( index == invalidIndex() )
202  {
203  continue ;
204  }
205  else if( indexState_[ index ] == UNUSED )
206  {
207  index = invalidIndex();
208  continue ;
209  }
210 
211  // a index that is used but larger then actual size
212  // has to move to a hole
213  // if used index lies behind size, then index has to move
214  // to one of the holes
215  if( index >= actSize )
216  {
217  //std::cout << "Check index " << index << std::endl;
218  // serach next hole that is smaler than actual size
219  --actHole;
220  // if actHole < 0 then error, because we have index larger then
221  // actual size
222  assert(actHole >= 0);
223  while ( holes_[actHole] >= actSize )
224  {
225  --actHole;
226  if(actHole < 0) break;
227  }
228 
229  assert(actHole >= 0);
230 
231 #if HAVE_MPI
232  // only for none-ghost elements hole storage is applied
233  // this is because ghost indices might have in introduced
234  // after the resize was done.
235  if( indexState_[ index ] == USED )
236 #endif
237  {
238  // remember old and new index
239  oldIdx_[holes] = index;
240  newIdx_[holes] = holes_[actHole];
241  ++holes;
242  }
243 
244  index = holes_[actHole];
245 
246  // means that dof manager has to copy the mem
247  haveToCopy = true;
248  }
249  }
250 
251  // this call only sets the size of the vectors
252  oldIdx_.resize(holes);
253  newIdx_.resize(holes);
254 
255  // mark holes as new
256  // note: This needs to be done after reassignment, so that their
257  // original entry will still see them as UNUSED.
258  for( int hole = 0; hole < holes; ++hole )
259  indexState_[ newIdx_[ hole ] ] = NEW;
260 
261  } // end if actHole > 0
262 
263  // store number of actual holes
264  numberHoles_ = oldIdx_.size();
265 
266  // adjust size of container to correct value
267  leafIndex_.resize( invalidIndex() );
268 
269  // resize vector of index states
270  indexState_.resize( actSize );
271 
272 #ifndef NDEBUG
273  for( int i=0; i<actSize; ++i )
274  assert( indexState_[ i ] == USED ||
275  indexState_[ i ] == UNUSED ||
276  indexState_[ i ] == NEW );
277 
279 #endif
280  return haveToCopy;
281  }
282 
284  IndexType additionalSizeEstimate () const { return indexState_.size(); }
285 
287  IndexType size () const { return indexState_.size(); }
288 
290  IndexType realSize () const
291  {
292  return leafIndex_.size();
293  }
294 
296  //- --index
297  template <class EntityType>
298  IndexType index ( const EntityType& entity ) const
299  {
300  assert( myCodim_ == EntityType :: codimension );
301  assert( checkValidIndex( leafIndex_[ entity ] ) );
302  return leafIndex_[ entity ];
303  }
304 
306  template <class EntityType>
307  IndexType subIndex ( const EntityType& entity,
308  const int subNumber ) const
309  {
310  assert( 0 == EntityType :: codimension );
311  assert( checkValidIndex( leafIndex_( entity, subNumber ) ) );
312  return leafIndex_( entity, subNumber );
313  }
314 
316  template <class EntityType>
317  bool exists ( const EntityType& entity ) const
318  {
319  assert( myCodim_ == EntityType :: codimension );
320  const IndexType &index = leafIndex_[ entity ];
321  // if index is invalid (-1) it does not exist
322  if (index==invalidIndex()) return false;
323  assert( index < IndexType( indexState_.size() ) );
324  return (indexState_[ index ] != UNUSED);
325  }
326 
327  template <class EntityType>
328  bool exists ( const EntityType& entity ,
329  const int subNumber ) const
330  {
331  assert( 0 == EntityType :: codimension );
332  const IndexType &index = leafIndex_( entity, subNumber );
333  // if index is invalid (-1) it does not exist
334  if (index==invalidIndex()) return false;
335  assert( index < IndexType( indexState_.size() ) );
336  return (indexState_[ index ] != UNUSED);
337  }
338 
340  IndexType numberOfHoles () const
341  {
342  return numberHoles_;
343  }
344 
346  IndexType oldIndex (int elNum ) const
347  {
348  assert( numberHoles_ == IndexType(oldIdx_.size()) );
349  return oldIdx_[elNum];
350  }
351 
353  IndexType newIndex (int elNum) const
354  {
355  assert( numberHoles_ == IndexType(newIdx_.size()) );
356  return newIdx_[elNum];
357  }
358 
359  // insert element and create index for element number
360  template <class EntityType>
361  void insert (const EntityType& entity )
362  {
363  assert( myCodim_ == EntityType :: codimension );
364  insertIdx( leafIndex_[ entity ] );
365  }
366 
367  // insert element and create index for element number
368  template <class EntityType>
369  void insertSubEntity (const EntityType& entity,
370  const int subNumber)
371  {
372  assert( 0 == EntityType :: codimension );
373  insertIdx( leafIndex_( entity, subNumber ) );
374  }
375 
376  // insert element as ghost and create index for element number
377  template <class EntityType>
378  void insertGhost (const EntityType& entity )
379  {
380  assert( myCodim_ == EntityType :: codimension );
381  // insert index
382  IndexType &leafIdx = leafIndex_[ entity ];
383  insertIdx( leafIdx );
384 
385  // if index is also larger than lastSize
386  // mark as new to skip old-new index lists
387  if( leafIdx >= lastSize_ )
388  indexState_[ leafIdx ] = NEW;
389  }
390 
391  // insert element and create index for element number
392  template <class EntityType>
393  void markForRemoval( const EntityType& entity )
394  {
395  assert( myCodim_ == EntityType :: codimension );
396  const IndexType &index = leafIndex_[ entity ];
397  if( index != invalidIndex() )
398  indexState_[ index ] = UNUSED;
399  }
400 
401  // insert element as ghost and create index for element number
402  template <class EntityType>
403  bool validIndex (const EntityType& entity ) const
404  {
405  assert( myCodim_ == EntityType :: codimension );
406  return (leafIndex_[ entity ] >= 0);
407  }
408 
409  void print( std::ostream& out ) const
410  {
411  typedef typename IndexContainerType::ConstIterator Iterator;
412  const Iterator end = leafIndex_.end();
413  for( Iterator it = leafIndex_.begin(); it != end; ++it )
414  {
415  const IndexType &leafIdx = *it;
416  out << "idx: " << leafIdx << " stat: " << indexState_[ leafIdx ] << std::endl;
417  }
418  }
419 
420  protected:
421  // return true if the index idx is valid
422  bool checkValidIndex( const IndexType& idx ) const
423  {
424  assert( idx != invalidIndex() );
425  assert( idx < size() );
426  return (idx != invalidIndex() ) && ( idx < size() );
427  }
428 
429  // insert element and create index for element number
430  void insertIdx ( IndexType &index )
431  {
432  if( index == invalidIndex() )
433  {
434  index = indexState_.size();
435  indexState_.resize( index+1 );
436  }
437  assert( index < IndexType( indexState_.size() ) );
438  indexState_[ index ] = USED;
439  }
440 
441  public:
442  // write to stream
443  template <class StreamTraits>
445  {
446  // store current index set size
447  // don't write something like out << indexState_.size()
448  // since on read you then don't know exactly what
449  // type has been written, it must be the same types
450  const uint32_t indexSize = indexState_.size();
451  out << indexSize;
452 
453  // for consistency checking, write size as 64bit integer
454  const uint64_t mysize = leafIndex_.size();
455  out << mysize ;
456 
457  // backup indices
458  typedef typename IndexContainerType::ConstIterator ConstIterator;
459  const ConstIterator end = leafIndex_.end();
460  for( ConstIterator it = leafIndex_.begin(); it != end; ++it )
461  out << *it;
462 
463  return true;
464  }
465 
466  // read from stream
467  template <class StreamTraits>
469  {
470  // read current index set size
471  uint32_t size = 0;
472  in >> size;
473 
474  // mark all indices used
475  indexState_.resize( size );
476  std::fill( indexState_.begin(), indexState_.end(), USED );
477 
478  // for consistency checking
479  uint64_t storedSize = 0;
480  in >> storedSize ;
481 
482  uint64_t leafsize = leafIndex_.size();
483  // the stored size can be larger (visualization of parallel grids in serial)
484  if( storedSize < leafsize )
485  {
486  DUNE_THROW(InvalidStateException,"CodimIndexSet: size consistency check failed during restore!");
487  }
488 
489  // restore indices
490  typedef typename IndexContainerType::Iterator Iterator;
491  const Iterator end = leafIndex_.end();
492  uint64_t count = 0 ;
493  for( Iterator it = leafIndex_.begin(); it != end; ++it, ++count )
494  in >> *it;
495 
496  // also read indices that were stored but are not needed on read
497  if( count < storedSize )
498  {
499  IndexType value ;
500  const uint64_t leftOver = storedSize - count ;
501  for( uint64_t i = 0; i < leftOver; ++i )
502  in >> value ;
503  }
504 
505  return true;
506  }
507 
508  }; // end of CodimIndexSet
509 
510  } // namespace Fem
511 
512 } // namespace Dune
513 
514 #endif // #ifndef DUNE_FEM_CODIMINDEXSET_HH
IndexArrayType holes_
Definition: codimindexset.hh:64
void prepareCompress()
prepare for setup (nothing to do here)
Definition: codimindexset.hh:112
CodimIndexSet< GridType > ThisType
Definition: codimindexset.hh:34
IndexStateArrayType indexState_
Definition: codimindexset.hh:61
IndexType numberOfHoles() const
return number of holes
Definition: codimindexset.hh:340
void setMemoryFactor(const double memoryFactor)
set memory overestimation factor
Definition: codimindexset.hh:100
size_t size() const
return number of enties of array
Definition: arrays.hh:213
IndexType newIndex(int elNum) const
return new index, for dof manager only returns index
Definition: codimindexset.hh:353
void insertSubEntity(const EntityType &entity, const int subNumber)
Definition: codimindexset.hh:369
IndexType subIndex(const EntityType &entity, const int subNumber) const
return leaf index for given entity
Definition: codimindexset.hh:307
IndexArrayType oldIdx_
Definition: codimindexset.hh:68
bool checkValidIndex(const IndexType &idx) const
Definition: codimindexset.hh:422
static IndexType invalidIndex()
Definition: codimindexset.hh:49
void resize(size_t nsize)
Definition: arrays.hh:491
IndexType numberHoles_
Definition: codimindexset.hh:78
DofIteratorType begin()
iterator pointing to begin of array
Definition: arrays.hh:193
MutableArray< IndexType > IndexArrayType
Definition: codimindexset.hh:53
CodimIndexSet(const GridType &grid, const int codim, const double memoryFactor=1.1)
Constructor taking memory factor (default = 1.1)
Definition: codimindexset.hh:83
void print(std::ostream &out) const
Definition: codimindexset.hh:409
void clear()
clear set
Definition: codimindexset.hh:116
void insertIdx(IndexType &index)
Definition: codimindexset.hh:430
DofIteratorType end()
iterator pointing to end of array
Definition: arrays.hh:203
bool compress()
Definition: codimindexset.hh:167
Definition: coordinate.hh:4
bool read(InStreamInterface< StreamTraits > &in)
Definition: codimindexset.hh:468
GridImp GridType
Definition: codimindexset.hh:33
abstract interface for an input stream
Definition: streams.hh:177
IndexType size() const
return size of grid entities per level and codim
Definition: codimindexset.hh:287
IndexType oldIndex(int elNum) const
return old index, for dof manager only
Definition: codimindexset.hh:346
bool exists(const EntityType &entity) const
return state of index for given hierarchic number
Definition: codimindexset.hh:317
bool validIndex(const EntityType &entity) const
Definition: codimindexset.hh:403
IndexContainerType leafIndex_
Definition: codimindexset.hh:60
void setMemoryFactor(const double memFactor)
set memory factor
Definition: arrays.hh:465
void markForRemoval(const EntityType &entity)
Definition: codimindexset.hh:393
void clearHoles()
clear holes, i.e. set number of holes to zero
Definition: codimindexset.hh:157
void checkConsecutive()
set all entries to unused
Definition: codimindexset.hh:154
const int myCodim_
Definition: codimindexset.hh:75
bool consecutive()
Definition: codimindexset.hh:130
IndexType realSize() const
return size of grid entities per level and codim
Definition: codimindexset.hh:290
IndexType index(const EntityType &entity) const
return leaf index for given entity
Definition: codimindexset.hh:298
IndexType additionalSizeEstimate() const
return how much extra memory is needed for restriction
Definition: codimindexset.hh:284
Definition: codimindexset.hh:30
IndexType lastSize_
Definition: codimindexset.hh:72
int IndexType
Definition: codimindexset.hh:46
IndexArrayType newIdx_
Definition: codimindexset.hh:69
bool write(OutStreamInterface< StreamTraits > &out) const
Definition: codimindexset.hh:444
void insertGhost(const EntityType &entity)
Definition: codimindexset.hh:378
void insert(const EntityType &entity)
Definition: codimindexset.hh:361
MutableArray< INDEXSTATE > IndexStateArrayType
Definition: codimindexset.hh:54
void resize()
reallocate the vectors
Definition: codimindexset.hh:109
PersistentContainer< GridType, IndexType > IndexContainerType
Definition: codimindexset.hh:57
void resetUsed()
set all entries to unused
Definition: codimindexset.hh:125
abstract interface for an output stream
Definition: streams.hh:44
bool exists(const EntityType &entity, const int subNumber) const
Definition: codimindexset.hh:328