1 #ifndef DUNE_FEM_NONBLOCKMAPPER_HH
2 #define DUNE_FEM_NONBLOCKMAPPER_HH
3 
4 #include <vector>
5 
6 #include <dune/fem/gridpart/common/indexset.hh>
7 #include <dune/fem/misc/functor.hh>
8 #include <dune/fem/space/mapper/dofmapper.hh>
9 
10 namespace Dune
11 {
12 
13   namespace Fem
14   {
15 
16     // Internal Forward Declarations
17     // -----------------------------
18 
19     template< class BlockMapper, int blockSize >
20     class NonBlockMapper;
21 
22 
23     namespace __NonBlockMapper
24     {
25 
26       // Traits
27       // ------
28 
29       template< class BlockMapper, int bS >
30       struct Traits
31       {
32         typedef NonBlockMapper< BlockMapper, bS > DofMapperType;
33 
34         typedef BlockMapper BlockMapperType;
35         typedef typename BlockMapper::ElementType ElementType;
36         typedef typename BlockMapper::SizeType SizeType;
37         typedef typename BlockMapper::GlobalKeyType GlobalKeyType;
38 
39         static const int blockSize = bS;
40       };
41 
42 
43       // DofMapper
44       // ---------
45 
46       template< class T, template< class > class Base = Dune::Fem::DofMapper >
47       class DofMapper
48         : public Base< T >
49       {
50         typedef Base< T > BaseType;
51 
52         template< class, template< class > class >
53         friend class DofMapper;
54 
55       public:
56         typedef typename BaseType::Traits Traits;
57 
58         typedef typename Traits::BlockMapperType BlockMapperType;
59         static const int blockSize = Traits::blockSize;
60 
61         typedef typename Traits::ElementType ElementType;
62         typedef typename Traits::SizeType SizeType;
63         typedef typename Traits::GlobalKeyType GlobalKeyType;
64 
65       private:
66         template< class Functor >
67         struct BlockFunctor
68         {
BlockFunctorDune::Fem::__NonBlockMapper::DofMapper::BlockFunctor69           explicit BlockFunctor ( Functor functor )
70             : functor_( functor )
71           {}
72 
73           template< class GlobalKey >
operator ()Dune::Fem::__NonBlockMapper::DofMapper::BlockFunctor74           void operator() ( int localBlock, const GlobalKey globalKey ) const
75           {
76             int localDof = blockSize*localBlock;
77             SizeType globalDof = blockSize*globalKey;
78             const int localEnd = localDof + blockSize;
79             while( localDof != localEnd )
80               functor_( localDof++, globalDof++ );
81           }
82 
83         private:
84           Functor functor_;
85         };
86 
87       public:
DofMapper(BlockMapperType & blockMapper)88         DofMapper ( BlockMapperType &blockMapper )
89           : blockMapper_( blockMapper )
90         {}
91 
size() const92         SizeType size () const { return blockSize * blockMapper_.size(); }
93 
contains(const int codim) const94         bool contains ( const int codim ) const { return blockMapper_.contains( codim ); }
95 
fixedDataSize(int codim) const96         bool fixedDataSize ( int codim ) const { return blockMapper_.fixedDataSize( codim ); }
97 
98         template< class Functor >
mapEach(const ElementType & element,Functor f) const99         void mapEach ( const ElementType &element, Functor f ) const
100         {
101           blockMapper_.mapEach( element, BlockFunctor< Functor >( std::forward< Functor >( f ) ) );
102         }
103 
map(const ElementType & element,std::vector<GlobalKeyType> & indices) const104         void map ( const ElementType &element, std::vector< GlobalKeyType > &indices ) const
105         {
106           indices.resize( numDofs( element ) );
107           mapEach( element, [ &indices ] ( int local, GlobalKeyType global ) { indices[ local ] = global; } );
108         }
109 
onSubEntity(const ElementType & element,int i,int c,std::vector<bool> & indices) const110         void onSubEntity ( const ElementType &element, int i, int c, std::vector< bool > &indices ) const
111         {
112           const SizeType numDofs = blockMapper_.numDofs( element );
113           blockMapper_.onSubEntity( element, i, c, indices );
114           indices.resize( blockSize * numDofs );
115           for( SizeType i = numDofs; i > 0; )
116           {
117             for( int j = 0; j < blockSize; ++j )
118               indices[ i*blockSize + j ] = indices[ i ];
119           }
120         }
121 
122         template< class Entity, class Functor >
mapEachEntityDof(const Entity & entity,Functor f) const123         void mapEachEntityDof ( const Entity &entity, Functor f ) const
124         {
125           blockMapper_.mapEachEntityDof( entity, BlockFunctor< Functor >( std::forward< Functor >( f ) ) );
126         }
127 
128         template< class Entity >
mapEntityDofs(const Entity & entity,std::vector<GlobalKeyType> & indices) const129         void mapEntityDofs ( const Entity &entity, std::vector< GlobalKeyType > &indices ) const
130         {
131           indices.resize( numEntityDofs( entity ) );
132           mapEachEntityDof( entity, [ &indices ] ( int local, GlobalKeyType global ) { indices[ local ] = global; } );
133         }
134 
maxNumDofs() const135         int maxNumDofs () const { return blockSize * blockMapper_.maxNumDofs(); }
136 
numDofs(const ElementType & element) const137         SizeType numDofs ( const ElementType &element ) const { return blockSize * blockMapper_.numDofs( element ); }
138 
139         template< class Entity >
numEntityDofs(const Entity & entity) const140         SizeType numEntityDofs ( const Entity &entity ) const { return blockSize * blockMapper_.numEntityDofs( entity ); }
141 
consecutive()142         static constexpr bool consecutive () noexcept { return false; }
143 
numBlocks() const144         SizeType numBlocks () const
145         {
146           DUNE_THROW( NotImplemented, "Method numBlocks() called on non-adaptive block mapper" );
147         }
148 
numberOfHoles(int) const149         SizeType numberOfHoles ( int ) const
150         {
151           DUNE_THROW( NotImplemented, "Method numberOfHoles() called on non-adaptive block mapper" );
152         }
153 
oldIndex(int hole,int) const154         GlobalKeyType oldIndex ( int hole, int ) const
155         {
156           DUNE_THROW( NotImplemented, "Method oldIndex() called on non-adaptive block mapper" );
157         }
158 
newIndex(int hole,int) const159         GlobalKeyType newIndex ( int hole, int ) const
160         {
161           DUNE_THROW( NotImplemented, "Method newIndex() called on non-adaptive block mapper" );
162         }
163 
oldOffSet(int) const164         SizeType oldOffSet ( int ) const
165         {
166           DUNE_THROW( NotImplemented, "Method oldOffSet() called on non-adaptive block mapper" );
167         }
168 
offSet(int) const169         SizeType offSet ( int ) const
170         {
171           DUNE_THROW( NotImplemented, "Method offSet() called on non-adaptive block mapper" );
172         }
173 
blockMapper() const174         const BlockMapperType &blockMapper () const { return blockMapper_; }
175 
update()176         void update () { blockMapper_.update(); }
177 
178       private:
179         BlockMapperType &blockMapper_;
180       };
181 
182 
183       // AdaptiveDofMapper
184       // -----------------
185 
186       template< class T >
187       class AdaptiveDofMapper
188         : public DofMapper< T, Dune::Fem::AdaptiveDofMapper >
189       {
190         typedef DofMapper< T, Dune::Fem::AdaptiveDofMapper > BaseType;
191 
192         template< class >
193         friend class AdaptiveDofMapper;
194 
195       public:
196         typedef typename BaseType::Traits Traits;
197 
198         typedef typename Traits::BlockMapperType BlockMapperType;
199 
200         static const int blockSize = Traits::blockSize;
201 
202         using BaseType::blockMapper;
203 
204         typedef typename Traits::ElementType ElementType;
205         typedef typename Traits::SizeType SizeType;
206         typedef typename Traits::GlobalKeyType GlobalKeyType;
207 
AdaptiveDofMapper(BlockMapperType & blockMapper)208         AdaptiveDofMapper ( BlockMapperType &blockMapper )
209           : BaseType( blockMapper )
210         {}
211 
consecutive() const212         bool consecutive () const { return blockMapper().consecutive(); }
213 
numBlocks() const214         SizeType numBlocks () const { return blockMapper().numBlocks(); }
215 
numberOfHoles(const int block) const216         SizeType numberOfHoles ( const int block ) const { return blockSize * blockMapper().numberOfHoles( block ); }
217 
oldIndex(const int hole,const int block) const218         GlobalKeyType oldIndex ( const int hole, const int block ) const
219         {
220           const int i = hole % blockSize;
221           const int blockHole = hole / blockSize;
222           return blockMapper().oldIndex( blockHole, block ) * blockSize + i;
223         }
224 
newIndex(const int hole,const int block) const225         GlobalKeyType newIndex ( const int hole, const int block ) const
226         {
227           const int i = hole % blockSize;
228           const int blockHole = hole / blockSize;
229           return blockMapper().newIndex( blockHole, block ) * blockSize + i;
230         }
231 
oldOffSet(const int block) const232         SizeType oldOffSet ( const int block ) const { return blockMapper().oldOffSet( block ) * blockSize; }
233 
offSet(const int block) const234         SizeType offSet ( const int block ) const { return blockMapper().offSet( block ) * blockSize; }
235       };
236 
237 
238 
239       // Implementation
240       // --------------
241 
242       template< class BlockMapper, int blockSize, bool adaptive = Capabilities::isAdaptiveDofMapper< BlockMapper >::v >
243       class Implementation
244       {
245         typedef __NonBlockMapper::Traits< BlockMapper, blockSize > Traits;
246 
247       public:
248         typedef typename std::conditional< adaptive,
249                                            AdaptiveDofMapper< Traits >,
250                                            DofMapper< Traits > >::type Type;
251       };
252 
253     } // namespace __NonBlockMapper
254 
255 
256     // NonBlockMapper
257     // --------------
258 
259     /**Flatten the index-space of a given BlockMapper. */
260     template< class BlockMapper, int blockSize >
261     class NonBlockMapper
262       : public __NonBlockMapper::template Implementation< BlockMapper, blockSize >::Type
263     {
264       typedef typename __NonBlockMapper::template Implementation< BlockMapper, blockSize >::Type BaseType;
265 
266     public:
267 
NonBlockMapper(BlockMapper & blockMapper)268       NonBlockMapper ( BlockMapper &blockMapper )
269         : BaseType( blockMapper )
270       {}
271     };
272 
273 
274     // NonBlockMapper for NonBlockMapper
275     // ---------------------------------
276 
277     template< class BlockMapper, int innerBlockSize, int outerBlockSize >
278     class NonBlockMapper< NonBlockMapper< BlockMapper, innerBlockSize >, outerBlockSize >
279       : public NonBlockMapper< BlockMapper, innerBlockSize *outerBlockSize >
280     {
281       typedef NonBlockMapper< NonBlockMapper< BlockMapper, innerBlockSize >, outerBlockSize > ThisType;
282       typedef NonBlockMapper< BlockMapper, innerBlockSize *outerBlockSize > BaseType;
283 
284     public:
NonBlockMapper(const NonBlockMapper<BlockMapper,innerBlockSize> & blockMapper)285       explicit NonBlockMapper ( const NonBlockMapper< BlockMapper, innerBlockSize > &blockMapper )
286         : BaseType( blockMapper.blockMapper_ )
287       {}
288     };
289 
290 
291     // Capabilities
292     // ------------
293 
294     namespace Capabilities
295     {
296       template< class BlockMapper, int blockSize >
297       struct isAdaptiveDofMapper< NonBlockMapper< BlockMapper, blockSize > >
298       {
299         static const bool v = isAdaptiveDofMapper< BlockMapper >::v;
300       };
301 
302       template< class BlockMapper, int blockSize >
303       struct isConsecutiveIndexSet< __NonBlockMapper::AdaptiveDofMapper< __NonBlockMapper::Traits< BlockMapper, blockSize > > >
304       {
305         static const bool v = isConsecutiveIndexSet< BlockMapper >::v;
306       };
307 
308     } // namespace Capabilities
309 
310   } // namespace Fem
311 
312 } // namespace Dune
313 
314 #endif // #ifndef DUNE_FEM_NONBLOCKMAPPER_HH
315