DUNE-FEM (unstable)

tuplemapper.hh
1#ifndef DUNE_FEM_SPACE_COMBINEDSPACE_TUPLEMAPPER_HH
2#define DUNE_FEM_SPACE_COMBINEDSPACE_TUPLEMAPPER_HH
3
4#include <array>
5#include <tuple>
6#include <utility>
7
8#include <dune/common/hybridutilities.hh>
9
10#include <dune/fem/common/utility.hh>
11#include <dune/fem/space/common/adaptationmanager.hh>
12#include <dune/fem/space/common/dofmanager.hh>
13#include <dune/fem/space/mapper/dofmapper.hh>
14#include <dune/fem/space/mapper/nonblockmapper.hh>
15#include <dune/fem/misc/functor.hh>
16
17namespace Dune
18{
19
20 namespace Fem
21 {
22
23 // Internal forward declaration
24 // ----------------------------
25 template< class GridPart, class ... Mapper >
26 class TupleMapper;
27
28
29#ifndef DOXYGEN
30
31 namespace __TupleMapper
32 {
33
34 // Traits
35 // ------
36
37 template< class GridPart, class ... Mapper >
38 struct Traits
39 {
40 static_assert( Std::are_all_same< typename Mapper::ElementType ... >::value,
41 "TupleMapper needs common ElementType" );
42
43 typedef typename std::tuple_element< 0, std::tuple< Mapper ... > >::type FirstMapperType;
44 typedef typename FirstMapperType::ElementType ElementType;
45 typedef typename FirstMapperType::SizeType SizeType;
46 typedef typename FirstMapperType::GlobalKeyType GlobalKeyType;
47
48 typedef TupleMapper< GridPart, Mapper ... > DofMapperType;
49 };
50
51 // CombinedIndex
52 // -------------
53
54 template< class Index, class Int, Int i >
55 struct CombinedIndex
56 {
57 constexpr CombinedIndex ( Index index, Index offset ) : index_( index ), offset_( offset ) {}
58
59 static constexpr Int component () { return i; }
60
61 constexpr operator Index () const { return index_ + offset_; }
62
63 constexpr Index index () const { return index_; }
64
65 constexpr Index offset () const { return offset_; }
66
67 private:
68 Index index_, offset_;
69 };
70
71
72 // DofMapper
73 // ---------
74
75 template< class T, template< class > class Base = Dune::Fem::DofMapper >
76 class DofMapper;
77
78 template< class GridPart, class ... Mapper, template< class > class Base >
79 class DofMapper< Traits< GridPart, Mapper ... >, Base >
80 : public Base< Traits< GridPart, Mapper ... > >
81 {
82 typedef Base< Traits< GridPart, Mapper ... > > BaseType;
83
84 // FunctorWrapper
85 // --------------
86
87 template< class Functor, int i >
88 struct FunctorWrapper
89 {
90 FunctorWrapper ( Functor functor, int localOffset, int globalOffset )
91 : functor_( functor ),
92 localOffset_( localOffset ),
93 globalOffset_( globalOffset )
94 {}
95
96 template< class GlobalKey >
97 void operator() ( int localDof, const GlobalKey &globalKey ) const
98 {
99 functor_( localDof + localOffset_, CombinedIndex< GlobalKey, int, i >( globalKey, globalOffset_ ) );
100 }
101
102 template< class GlobalKey >
103 void operator() ( const GlobalKey &globalKey ) const
104 {
105 functor_( CombinedIndex< GlobalKey, int, i >( globalKey, globalOffset_ ) );
106 }
107
108 private:
109 Functor functor_;
110 const int localOffset_;
111 const int globalOffset_;
112 };
113
114 protected:
115 // size of the Mapper Tuple
116 static const int mapperTupleSize = sizeof ... ( Mapper );
117
118 typedef std::array< typename BaseType::SizeType, mapperTupleSize + 1 > OffsetType;
119
120 public:
121 typedef typename BaseType::ElementType ElementType;
122 typedef typename BaseType::SizeType SizeType;
123 typedef typename BaseType::Traits::GlobalKeyType GlobalKeyType;
124
125 typedef GridPart GridPartType;
126
127 DofMapper ( GridPartType &gridPart, Mapper & ... mapper )
128 : gridPart_( gridPart ),
129 mapperTuple_( mapper ... )
130 {
131 computeOffset();
132 }
133
134 DofMapper ( GridPartType &gridPart, Mapper && ... mapper )
135 : gridPart_( gridPart ),
136 mapperTuple_( std::move( mapper ) ... )
137 {
138 computeOffset();
139 }
140
141 SizeType size () const { return size( std::index_sequence_for< Mapper ... >() ); }
142
143 bool contains ( const int codim ) const { return contains( codim, std::index_sequence_for< Mapper ... >() ); }
144
145 bool fixedDataSize ( int codim ) const { return fixedDataSize( codim, std::index_sequence_for< Mapper ... >() ); }
146
147 template< class Functor >
148 void mapEach ( const ElementType &element, Functor f ) const
149 {
150 OffsetType localOffset;
151 localOffset[ 0 ] = 0;
152 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
153 [ & ]( auto i )
154 {
155 FunctorWrapper< Functor, i > wrappedFunctor( f, localOffset[ i ], globalOffset_[ i ] );
156 std::get< i >( mapperTuple_ ).mapEach( element, wrappedFunctor );
157 localOffset[ i + 1 ] = localOffset[ i ] + std::get< i >( mapperTuple_ ).numDofs( element );
158 } );
159 }
160
161 template< class Entity, class Functor >
162 void mapEachEntityDof ( const Entity &entity, Functor f ) const
163 {
164 OffsetType localOffset;
165 localOffset[ 0 ] = 0;
166 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
167 [ & ]( auto i )
168 {
169 FunctorWrapper< Functor, i > wrappedFunctor( f, localOffset[ i ], globalOffset_[ i ] );
170 std::get< i >( mapperTuple_ ).mapEachEntityDof( entity, wrappedFunctor );
171 localOffset[ i + 1 ] = localOffset[ i ] + std::get< i >( mapperTuple_ ).numEntityDofs( entity );
172 } );
173 }
174
175 [[deprecated("Use onSubEntity method with char vector instead")]]
176 void onSubEntity ( const ElementType &element, int i, int c, std::vector< bool > &indices ) const
177 {
178 std::vector< char > _idx;
179 onSubEntity(element, i, c, _idx);
180 indices.resize( _idx.size() );
181 for (std::size_t i=0; i<_idx.size();++i)
182 _idx[i] = indices[i] > 0;
183 }
184 // this method returns which local dofs are attached to the given subentity.
185 // indices[locDofNr] =
186 // 0 : not attached, not equal to 0 : attached
187 // (so this method can still be used in the way the deprecated method was).
188 // New: In case the dof can be associated to a component of the
189 // space, the value returned is that component+1. In other
190 // cases (normal velocity for RT for example) the value is -1).
191 // So indices[i] is in [-1,dimRange+1]
192 void onSubEntity ( const ElementType &element, int i, int c, std::vector< char > &indices ) const
193 {
194 indices.resize( numDofs( element ) );
195 OffsetType localOffset;
196 localOffset[ 0 ] = 0;
197 int rangeOffset = 0;
198 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
199 [ & ]( auto t )
200 {
201 std::vector< char > subIndices;
202 std::get< t >( mapperTuple_ ).onSubEntity( element, i,c, subIndices );
203 auto localSize = std::get< t >( mapperTuple_ ).numDofs( element );
204 assert( subIndices.size() == localSize );
205 assert( localOffset[ t ] + localSize <= indices.size() );
206 for (std::size_t d=0;d<subIndices.size();++d)
207 {
208 indices[ localOffset[t] + d ] = subIndices[d]==0? 0 : subIndices[d] + rangeOffset;
209 }
210 // std::copy( subIndices.begin(), subIndices.end(), indices.begin() + localOffset[ t ] );
211 /*
212 std::cout << "\t space<" << t << ">:";
213 for (std::size_t d=0;d<localSize;++d)
214 std::cout << " " << subIndices[d];
215 std::cout << " ->";
216 for (std::size_t d=0;d<indices.size();++d)
217 std::cout << " " << indices[d];
218 std::cout << std::endl;
219 */
220 // FIXME: here we need 'dimRange' of the subspace to cover
221 // cases where a space is vector valued by has blockSize=1
222 // like RT. Otherwise we will get for RTxRT something like
223 // [1,0,0,1, 2,0,0,2] instead of [1,0,0,1, 3,0,0,3]
224 rangeOffset += std::get< t >( mapperTuple_ ).blockSize;
225 localOffset[ t + 1 ] = localOffset[ t ] + localSize;
226 } );
227 /*
228 std::cout << "element (" << i << "," << c << "):";
229 for (std::size_t d=0;d<indices.size();++d)
230 std::cout << " " << indices[d];
231 std::cout << std::endl;
232 */
233 // DUNE_THROW( NotImplemented, "Method onSubEntity(...) not yet implemented for TupleMapper" );
234 }
235
236 int maxNumDofs () const { return maxNumDofs( std::index_sequence_for< Mapper ... >() ); }
237
238 SizeType numDofs ( const ElementType &element ) const { return numDofs( element, std::index_sequence_for< Mapper ... >() ); }
239
240 template< class Entity >
241 SizeType numEntityDofs ( const Entity &entity ) const { return numEntityDofs( entity, std::index_sequence_for< Mapper ... >() ); }
242
243 void map ( const ElementType &element, std::vector< SizeType > &indices ) const
244 {
245 indices.resize( numDofs( element ) );
246 mapEach( element, AssignFunctor< std::vector< SizeType > >( indices ) );
247 }
248 template< class Entity >
249 void mapEntityDofs ( const Entity &entity, std::vector< SizeType > &indices ) const
250 {
251 indices.resize( numEntityDofs( entity ) );
252 mapEachEntityDof( entity, AssignFunctor< std::vector< SizeType > >( indices ) );
253 }
254
255 static constexpr bool consecutive () noexcept { return false; }
256
257 SizeType numBlocks () const
258 {
259 DUNE_THROW( NotImplemented, "Method numBlocks() called on non-adaptive block mapper" );
260 }
261
262 SizeType numberOfHoles ( int ) const
263 {
264 DUNE_THROW( NotImplemented, "Method numberOfHoles() called on non-adaptive block mapper" );
265 }
266
267 GlobalKeyType oldIndex ( int hole, int ) const
268 {
269 DUNE_THROW( NotImplemented, "Method oldIndex() called on non-adaptive block mapper" );
270 }
271
272 GlobalKeyType newIndex ( int hole, int ) const
273 {
274 DUNE_THROW( NotImplemented, "Method newIndex() called on non-adaptive block mapper" );
275 }
276
277 SizeType oldOffSet ( int ) const
278 {
279 DUNE_THROW( NotImplemented, "Method oldOffSet() called on non-adaptive block mapper" );
280 }
281
282 SizeType offSet ( int ) const
283 {
284 DUNE_THROW( NotImplemented, "Method offSet() called on non-adaptive block mapper" );
285 }
286
287 void update()
288 {
289 // compute update for each mapper (if any)
290 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
291 [ & ](auto i){ std::get< i >( mapperTuple_ ).update(); } );
292
293 computeOffset();
294 }
295
296 /*** NonInterface Methods ***/
297
298 SizeType offset ( int i ) const { return globalOffset_[ i ]; }
299
300 template< int i >
301 SizeType subSize () const { return std::get< i >( mapperTuple_ ).size(); }
302
303 protected:
304 template< std::size_t ... i >
305 SizeType size ( std::index_sequence< i ... > ) const
306 {
307 return Std::sum( std::get< i >( mapperTuple_ ).size() ... );
308 }
309
310 template< std::size_t ... i >
311 bool fixedDataSize ( const int codim, std::index_sequence< i ... > ) const
312 {
313 return Std::And( std::get< i >( mapperTuple_ ).fixedDataSize( codim ) ... );
314 }
315
316 template< std::size_t ... i >
317 bool contains ( const int codim, std::index_sequence< i ... > ) const
318 {
319 return Std::Or( std::get< i >( mapperTuple_ ).contains( codim ) ... );
320 }
321
322 template< std::size_t ... i >
323 int maxNumDofs ( std::index_sequence< i ... > ) const
324 {
325 return Std::sum( std::get< i >( mapperTuple_ ).maxNumDofs() ... );
326 }
327
328 template< std::size_t ... i >
329 SizeType numDofs ( const ElementType &element, std::index_sequence< i ... > ) const
330 {
331 return Std::sum( std::get< i >( mapperTuple_ ).numDofs( element ) ... );
332 }
333
334 template< class Entity, std::size_t ... i >
335 SizeType numEntityDofs ( const Entity &entity, std::index_sequence< i ... > ) const
336 {
337 return Std::sum( std::get< i >( mapperTuple_ ).numEntityDofs( entity ) ... );
338 }
339
340 void computeOffset ()
341 {
342 globalOffset_[ 0 ] = 0;
343 // compute new offsets
344 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
345 [ & ]( auto i ){ globalOffset_[ i + 1 ] = globalOffset_[ i ] + std::get< i >( mapperTuple_ ).size(); } );
346 }
347
348 GridPartType &gridPart_;
349 std::tuple< Mapper ... > mapperTuple_;
350 OffsetType globalOffset_;
351 };
352
353
354
355 // AdaptiveDofMapper
356 // -----------------
357
358 template< class T >
359 class AdaptiveDofMapper;
360
361 template< class GridPart, class ... Mapper >
362 class AdaptiveDofMapper< Traits< GridPart, Mapper ... > >
363 : public DofMapper< Traits< GridPart, Mapper ... >, Dune::Fem::AdaptiveDofMapper >
364 {
365 typedef DofMapper< Traits< GridPart, Mapper ... >, Dune::Fem::AdaptiveDofMapper > BaseType;
366
367 protected:
368 typedef typename GridPart :: GridType GridType;
369 typedef AdaptationMethod< GridType > AdaptationMethodType;
370
371 typedef typename BaseType::OffsetType OffsetType;
372
373 using BaseType::mapperTupleSize;
374 using BaseType::mapperTuple_;
375 using BaseType::gridPart_;
376 using BaseType::globalOffset_;
377
378 public:
379 typedef typename BaseType::ElementType ElementType;
380 typedef typename BaseType::SizeType SizeType;
381 typedef typename BaseType::GlobalKeyType GlobalKeyType;
382 typedef GridPart GridPartType;
383
384 AdaptiveDofMapper ( GridPartType &gridPart, Mapper & ... mapper )
385 : BaseType( gridPart, mapper ... ),
386 numBlocks_( computeNumBlocks() ),
387 isCallBackAdapt_( AdaptationMethodType( gridPart.grid() ).isCallBackAdaptation() ),
388 needsFullUpdate_(true)
389 {
390 oldGlobalOffset_ = globalOffset_;
392 }
393
394 AdaptiveDofMapper ( GridPartType &gridPart, Mapper && ... mapper )
395 : BaseType( gridPart, std::move( mapper ) ... ),
396 numBlocks_( computeNumBlocks() ),
397 isCallBackAdapt_( AdaptationMethodType( gridPart.grid() ).isCallBackAdaptation() ),
398 needsFullUpdate_(true)
399 {
400 oldGlobalOffset_ = globalOffset_;
402 }
403
404 ~AdaptiveDofMapper () { DofManager< typename GridPartType::GridType >::instance( gridPart_.grid() ).removeIndexSet( *this ); }
405
406 AdaptiveDofMapper ( const AdaptiveDofMapper & ) = delete;
407 AdaptiveDofMapper ( AdaptiveDofMapper && ) = delete;
408
409 static constexpr bool consecutive () noexcept { return true; }
410
411 SizeType numBlocks () const { return numBlocks( std::index_sequence_for< Mapper ... >() ); }
412
413 SizeType numberOfHoles ( const int block ) const
414 {
415 SizeType nHoles = 0;
416 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
417 [ & ]( auto i )
418 {
419 const int localBlock = computeBlock( i, block );
420 if( localBlock >= 0 )
421 {
422 nHoles = std::get< i >( this->mapperTuple_ ).numberOfHoles( localBlock );
423 return;
424 }
425 } );
426 return nHoles;
427 }
428
429 GlobalKeyType oldIndex ( const int hole, const int block ) const
430 {
431 SizeType oIndex = 0;
432 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
433 [ & ]( auto i )
434 {
435 const int localBlock = computeBlock( i, block );
436 if( localBlock >= 0 )
437 {
438 oIndex = std::get< i >( this->mapperTuple_ ).oldIndex( hole, localBlock ) + globalOffset_[ i ];
439 return;
440 }
441 } );
442 return oIndex;
443 }
444
445 GlobalKeyType newIndex ( const int hole, const int block ) const
446 {
447 SizeType nIndex = 0;
448 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
449 [ & ]( auto i )
450 {
451 const int localBlock = computeBlock( i, block );
452 if( localBlock >= 0 )
453 {
454 nIndex = std::get< i >( this->mapperTuple_ ).newIndex( hole, localBlock ) + globalOffset_[ i ];
455 return ;
456 }
457 } );
458 return nIndex;
459 }
460
461 SizeType oldOffSet ( int block ) const
462 {
463 SizeType oOffset = 0;
464 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
465 [ & ]( auto i )
466 {
467 const int localBlock = computeBlock( i, block );
468 if( localBlock >= 0 )
469 {
470 oOffset = std::get< i >( this->mapperTuple_ ).oldOffSet( localBlock ) + oldGlobalOffset_[ i ];
471 return ;
472 }
473 } );
474 return oOffset;
475 }
476
477 SizeType offSet ( int block ) const
478 {
479 SizeType offset = 0;
480 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
481 [ & ]( auto i )
482 {
483 const int localBlock = computeBlock( i, block );
484 if( localBlock >= 0 )
485 {
486 offset = std::get< i >( this->mapperTuple_ ).offSet( localBlock ) + globalOffset_[ i ];
487 return ;
488 }
489 } );
490 return offset;
491 }
492
493 void resize () { update(); }
494
495 bool compress ()
496 {
497 update();
498 // after this step for both methods we need the full update
499 needsFullUpdate_ = true;
500 return true;
501 }
502
503 void backup () const {}
504
505 void restore () { compress(); }
506
507 template< class IOStream >
508 void read ( IOStream &in ) { compress(); }
509
510 template< class IOStream >
511 void write ( IOStream &out ) const {}
512
513 template< class Entity >
514 void insertEntity ( const Entity & )
515 {
516 if( needsFullUpdate_ )
517 {
518 // update also offsets in this case
519 update();
520 }
521 else
522 {
523 // call BaseType::update to avoid changing oldGlobalOffSet_
524 // do not use this->update here!
525 BaseType::update();
526 }
527 }
528
529 template< class Entity >
530 void removeEntity ( const Entity & ) {}
531
532 void update ()
533 {
534 // store previous offset
535 oldGlobalOffset_ = globalOffset_;
536
537 // in callback we always need the full update, otherwise set to false here
538 needsFullUpdate_ = isCallBackAdapt_ ;
539
540 // update component mappers and compute offsets
541 BaseType::update();
542 }
543
544 protected:
545 int computeBlock( const int i, const unsigned int block ) const
546 {
547 if( block >= blocks_[ i ] && block < blocks_[ i + 1 ] )
548 return block - blocks_[ i ];
549 else
550 return -1;
551 }
552
553 void printOffSet( const OffsetType& offset, const std::string& name ) const
554 {
555 for( const auto& off : offset )
556 {
557 std::cout << name << " = " << off << std::endl;
558 }
559 }
560
561 template< std::size_t ... i >
562 SizeType numBlocks ( std::index_sequence< i ... > ) const
563 {
564 return Std::sum( std::get< i >( mapperTuple_ ).numBlocks() ... );
565 }
566
567 SizeType computeNumBlocks ()
568 {
569 // compute blocks (only needs to be done once)
570 // length of blocks_ is mapperTupleSize + 1
571 blocks_[ 0 ] = 0;
572 Hybrid::forEach( std::make_index_sequence< mapperTupleSize >{},
573 [ & ]( auto i ){ blocks_[ i + 1 ] = blocks_[ i ] + std::get< i >( mapperTuple_ ).numBlocks(); } );
574
575 // last block number determines overall block numbers
576 return blocks_.back();
577 }
578
579
580 OffsetType oldGlobalOffset_;
581 OffsetType blocks_;
582
583 const SizeType numBlocks_;
584 const bool isCallBackAdapt_;
585 bool needsFullUpdate_;
586 };
587
588
589
590 // Implementation
591 // --------------
592
593 template< class GridPart, class ... Mapper >
594 struct Implementation
595 {
596 typedef typename std::conditional<
597 Std::And( Capabilities::isAdaptiveDofMapper< Mapper >::v ... ),
598 AdaptiveDofMapper< Traits< GridPart, Mapper ... > >,
599 DofMapper< Traits< GridPart, Mapper ... > > >::type Type;
600 };
601
602
603 } // namespace __TupleMapper
604
605#endif // #ifndef DOXYGEN
606
607
608 // TupleMapper
609 // -----------
610
621 template< class GridPart, class ... Mapper >
623 : public __TupleMapper::template Implementation< GridPart, Mapper ... >::Type
624 {
625 typedef typename __TupleMapper::template Implementation< GridPart, Mapper ... >::Type BaseType;
626
627 public:
628 TupleMapper ( GridPart &gridPart, Mapper & ... mapper ) : BaseType( gridPart, mapper ... ) {}
629 TupleMapper ( GridPart &gridPart, Mapper && ... mapper ) : BaseType( gridPart, std::move( mapper ) ... ) {}
630 };
631
632 // Capabilities
633 // ------------
634
635 namespace Capabilities
636 {
637 template< class GridPart, class ... Mapper >
638 struct isAdaptiveDofMapper< TupleMapper< GridPart, Mapper ... > >
639 {
640 static const bool v = Std::And( isAdaptiveDofMapper< Mapper >::v ... );
641 };
642
643 template< class GridPart, class ... Mapper >
644 struct isConsecutiveIndexSet< __TupleMapper::AdaptiveDofMapper< __TupleMapper::Traits< GridPart, Mapper ... > > >
645 {
646 static const bool v = true;
647 };
648
649 } // namespace Capabilities
650
651 } // namespace Fem
652
653} // namespace Dune
654
655#endif // #ifndef DUNE_FEM_SPACE_COMBINEDSPACE_TUPLEMAPPER_HH
Extended interface for adaptive DoF mappers.
Definition: dofmapper.hh:219
Interface for calculating the size of a function space for a grid on a specified level....
Definition: dofmapper.hh:43
mapper allocating one DoF per subentity of a given codimension
Definition: tuplemapper.hh:624
Mapper interface.
Definition: mapper.hh:110
void removeIndexSet(const IndexSetType &iset)
removed index set from dof manager's list of index sets
Definition: dofmanager.hh:1331
static ThisType & instance(const GridType &grid)
obtain a reference to the DofManager for a given grid
Definition: dofmanager.hh:1251
void addIndexSet(const IndexSetType &iset)
add index set to dof manager's list of index sets
Definition: dofmanager.hh:1296
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
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
constexpr std::bool_constant<((II==value)||...)> contains(std::integer_sequence< T, II... >, std::integral_constant< T, value >)
Checks whether or not a given sequence contains a value.
Definition: integersequence.hh:137
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 27, 22:29, 2024)