DUNE-FEM (unstable)

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