DUNE-FEM (unstable)

dirichletconstraints.hh
1/**************************************************************************
2
3 The dune-fem module is a module of DUNE (see www.dune-project.org).
4 It is based on the dune-grid interface library
5 extending the grid interface by a number of discretization algorithms
6 for solving non-linear systems of partial differential equations.
7
8 Copyright (C) 2003 - 2015 Robert Kloefkorn
9 Copyright (C) 2003 - 2010 Mario Ohlberger
10 Copyright (C) 2004 - 2015 Andreas Dedner
11 Copyright (C) 2005 Adrian Burri
12 Copyright (C) 2005 - 2015 Mirko Kraenkel
13 Copyright (C) 2006 - 2015 Christoph Gersbacher
14 Copyright (C) 2006 - 2015 Martin Nolte
15 Copyright (C) 2011 - 2015 Tobias Malkmus
16 Copyright (C) 2012 - 2015 Stefan Girke
17 Copyright (C) 2013 - 2015 Claus-Justus Heine
18 Copyright (C) 2013 - 2014 Janick Gerstenberger
19 Copyright (C) 2013 Sven Kaulman
20 Copyright (C) 2013 Tom Ranner
21 Copyright (C) 2015 Marco Agnese
22 Copyright (C) 2015 Martin Alkaemper
23
24
25 The dune-fem module is free software; you can redistribute it and/or
26 modify it under the terms of the GNU General Public License as
27 published by the Free Software Foundation; either version 2 of
28 the License, or (at your option) any later version.
29
30 The dune-fem module is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
34
35 You should have received a copy of the GNU General Public License along
36 with this program; if not, write to the Free Software Foundation, Inc.,
37 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
38
39**************************************************************************/
40#ifndef DUNE_DIRICHLETCONSTRAINTS_HH
41#define DUNE_DIRICHLETCONSTRAINTS_HH
42
43#include <dune/fem/function/common/scalarproducts.hh>
44#include <dune/fem/function/localfunction/const.hh>
45#include <dune/fem/operator/common/temporarylocalmatrix.hh>
46#include <dune/fem/common/bindguard.hh>
47#include <dune/fem/common/coordinate.hh>
48#include <dune/fem/common/localcontribution.hh>
49#include <dune/fem/space/common/localinterpolation.hh>
50#include <dune/fem/space/mapper/nonblockmapper.hh>
51
52namespace Dune {
53
54namespace Fem {
55class HasLocalFunction;
56}
57
58template < class Model, class DiscreteFunctionSpace, bool useIdentity >
59class DirichletConstraints
60{
61public:
62 enum Operation { set = 0, sub = 1, add = 2 };
63 typedef Model ModelType;
64 typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
65 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
66 typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
67 typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
68 typedef typename DiscreteFunctionSpaceType::HessianRangeType HessianRangeType;
69
71 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
73 typedef typename DiscreteFunctionSpaceType :: GridType GridType;
74
75 // types for boundary treatment
76 // ----------------------------
77 static const int localBlockSize = DiscreteFunctionSpaceType :: localBlockSize ;
78 static const int dimRange = DiscreteFunctionSpaceType::FunctionSpaceType::dimRange;
79 static_assert( localBlockSize <= dimRange,
80 "local block size of the space must be less than or equal to the dimension of the range of the function space.");
81 typedef std::array<int,localBlockSize> DirichletBlock;
82 typedef std::vector< DirichletBlock > DirichletBlockVector;
83
84 class BoundaryWrapper
85 {
86 public:
87 typedef typename DiscreteFunctionSpaceType::EntityType EntityType;
89 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
90 typedef typename DiscreteFunctionSpace::RangeType RangeType;
91 typedef typename DiscreteFunctionSpace::JacobianRangeType JacobianRangeType;
92 typedef typename DiscreteFunctionSpace::HessianRangeType HessianRangeType;
93
94 private:
95 const ModelType& impl_;
96 const EntityType& entity_;
97 const int order_;
98 int bndId_;
99
100 public:
101 static const int dimRange = RangeType::dimension;
102 BoundaryWrapper( const ModelType& impl, const EntityType& entity, const int order, int bndId )
103 : impl_( impl ), entity_(entity), order_(order), bndId_(bndId) {}
104 const EntityType& entity() const { return entity_; }
105 const int order () const { return order_; }
106 template <class Point>
107 void evaluate( const Point& x, RangeType& ret ) const
108 { impl_.dirichlet(bndId_,Dune::Fem::coordinate(x),ret); }
109 template <class Point>
110 void jacobian( const Point& x, JacobianRangeType& ret ) const
111 { DUNE_THROW(Dune::NotImplemented,"rhs jacobian not implemented"); }
112 };
113
114 DirichletConstraints( ModelType &model, const DiscreteFunctionSpaceType& space )
115 : model_(model),
116 space_( space ),
117 dirichletBlocks_(),
118 // mark DoFs on the Dirichlet boundary
119 hasDirichletDofs_( false ),
120 sequence_( -1 )
121 {}
122
130 template < class DiscreteFunctionType >
131 void operator ()( const DiscreteFunctionType& u, DiscreteFunctionType& w ) const
132 {
133 updateDirichletDofs();
134
135 // if Dirichlet Dofs have been found, treat them
136 if( hasDirichletDofs_ )
137 {
138 typedef typename DiscreteFunctionType :: DofIteratorType DofIteratorType ;
139 typedef typename DiscreteFunctionType :: ConstDofIteratorType ConstDofIteratorType ;
140
141 ConstDofIteratorType uIt = u.dbegin();
142 DofIteratorType wIt = w.dbegin();
143
144 // loop over all blocks
145 const unsigned int blocks = space_.blockMapper().size();
146 for( unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
147 {
148 for( int l = 0; l < localBlockSize ; ++ l, ++ wIt, ++ uIt )
149 {
150 if( dirichletBlocks_[ blockDof ][l] )
151 {
152 // copy dofs of the block
153 assert( uIt != u.dend() );
154 assert( wIt != w.dend() );
155 (*wIt) = (*uIt);
156 }
157 }
158 }
159 }
160 }
168 template < class DiscreteFunctionType >
169 void operator ()( const typename DiscreteFunctionType::RangeType& value, DiscreteFunctionType& w ) const
170 {
171 updateDirichletDofs();
172
173 // if Dirichlet Dofs have been found, treat them
174 if( hasDirichletDofs_ )
175 {
176 typedef typename DiscreteFunctionType :: DofIteratorType DofIteratorType ;
177
178 DofIteratorType wIt = w.dbegin();
179
180 // loop over all blocks
181 const unsigned int blocks = space_.blockMapper().size();
182 for( unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
183 {
184 for( int l = 0; l < localBlockSize ; ++ l, ++ wIt )
185 {
186 if( dirichletBlocks_[ blockDof ][l] )
187 {
188 // copy dofs of the block
189 assert( wIt != w.dend() );
190 (*wIt) = value[l];
191 }
192 }
193 }
194 }
195 }
196
203 template < class DiscreteFunctionType >
204 void operator ()( DiscreteFunctionType& w, Operation op=Operation::set ) const
205 {
206 if (op != Operation::set)
207 {
209 return (*this)(u,w,op);
210 }
211
212 updateDirichletDofs();
213
214 if( hasDirichletDofs_ )
215 {
216 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
217 typedef typename IteratorType :: Entity EntityType;
218
219 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
220 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
221 for( const EntityType &entity : space_ )
222 {
223 model_.init(entity);
224
225 // bind local contribution to entity
226 auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
227 // bind interpolation to entity
228 auto iGuard = bindGuard( interpolation, entity );
229
230 // interpolate dirichlet dofs
231 dirichletDofTreatment( interpolation, wLocal );
232 }
233 }
234 }
235 template < class GridFunctionType, class DiscreteFunctionType,
236 typename = std::enable_if_t< std::is_base_of<Dune::Fem::HasLocalFunction, GridFunctionType>::value > >
237 void operator ()( const GridFunctionType &u,
238 DiscreteFunctionType& w, Operation op=Operation::set ) const
239 {
240 updateDirichletDofs();
241
242 if( hasDirichletDofs_ )
243 {
244 Dune::Fem::ConstLocalFunction< GridFunctionType > uLocal( u );
245 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
246 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
247
248 for( const auto &entity : space_ )
249 {
250 auto guard = Dune::Fem::bindGuard( std::tie(uLocal,wLocal), entity );
251 // bind interpolation to entity
252 auto iGuard = bindGuard( interpolation, entity );
253
254 // interpolate dirichlet dofs
255 if (op == Operation::sub || op == Operation::add)
256 model_.init(entity);
257 dirichletDofTreatment( interpolation, uLocal, wLocal, op );
258 }
259 }
260 }
261
270 template <class LinearOperator>
271 void applyToOperator( LinearOperator& linearOperator ) const
272 {
273 updateDirichletDofs();
274
275 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
276 typedef typename IteratorType :: Entity EntityType;
277
278 // if Dirichlet Dofs have been found, treat them
279 if( hasDirichletDofs_ )
280 {
281 typedef typename DiscreteFunctionSpaceType :: BlockMapperType BlockMapperType;
283
284 std::vector<std::size_t> globalBlockDofs;
285 std::vector<std::size_t> globalDofs;
286
287 // storage for unit rows and auxiliary rows, should be unique and sorted
288 std::set<std::size_t> unitRows;
289 std::set<std::size_t> auxRows;
290
291 const auto& space = space_; // linearOperator.rangeSpace();
292 // get auxiliary dof structure (for parallel runs) /*@LST0S@*/
293 //const auto &auxiliaryDofs = space.auxiliaryDofs();
294
295 const IteratorType end = space_.end();
296 for( IteratorType it = space_.begin(); it != end; ++it )
297 {
298 const EntityType &entity = *it;
299
300 // get number of basis functions
301 const int localBlocks = space.blockMapper().numDofs( entity );
302
303 // map local to global dofs
304 globalBlockDofs.resize(localBlocks);
305 // obtain all DofBlocks for this element
306 space.blockMapper().map( entity, globalBlockDofs );
307
308 // obtain all non-blocked dofs
309 globalDofs.resize(localBlocks * localBlockSize);
310 mapper.map( entity, globalDofs );
311
312 // counter for all local dofs (i.e. localBlockDof * localBlockSize + ... )
313 int localDof = 0;
314 // iterate over face dofs and set unit row
315 for( int localBlockDof = 0 ; localBlockDof < localBlocks; ++ localBlockDof )
316 {
317 int global = globalBlockDofs[localBlockDof];
318 // all diagonals were set to one anyway independent of auxDof or not
319 // so don't need this distinction anymore
320 // std::set<std::size_t>& rows = auxiliaryDofs.contains( global ) ? auxRows : unitRows;
321 std::set<std::size_t>& rows = useIdentity ? unitRows : auxRows;
322 for( int l = 0; l < localBlockSize; ++ l, ++ localDof )
323 {
324 if( dirichletBlocks_[global][l] )
325 {
326 // push non-blocked dof
327 rows.insert( globalDofs[ localDof ] );
328 }
329 }
330 }
331 } // end for elements
332
333 // set unit and auxiliary rows at once
334 linearOperator.setUnitRows( unitRows, auxRows );
335 }
336 }
337
338 const DirichletBlockVector &dirichletBlocks() const
339 {
340 updateDirichletDofs();
341 return dirichletBlocks_;
342 }
343
344protected:
346 template< class LocalInterpolationType, class LocalFunctionType >
347 void dirichletDofTreatment( const LocalInterpolationType& interpolation, LocalFunctionType &wLocal) const
348 {
349 // get entity
350 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
351
352 // get number of Lagrange Points
353 const int localBlocks = space_.blockMapper().numDofs( entity );
354
355 // map local to global BlockDofs
356 std::vector<std::size_t> globalBlockDofs(localBlocks);
357 space_.blockMapper().map( entity, globalBlockDofs );
358 std::vector<typename LocalFunctionType::RangeFieldType> values( localBlocks*localBlockSize );
359
360 int localDof = 0;
361
362 // iterate over face dofs and set unit row
363 for( int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
364 {
365 // store result to dof vector
366 int global = globalBlockDofs[localBlock];
367 for( int l = 0; l < localBlockSize ; ++ l, ++localDof )
368 {
369 if( dirichletBlocks_[ global ][l] )
370 {
371 interpolation( BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), values );
372 // store result
373 assert( (unsigned int)localDof < wLocal.size() );
374 wLocal[ localDof ] = values[ localDof ];
375 }
376 }
377 }
378 }
379
380 template< class LocalInterpolationType, class GridLocalFunctionType, class LocalFunctionType >
381 void dirichletDofTreatment( const LocalInterpolationType& interpolation,
382 const GridLocalFunctionType &uLocal,
383 LocalFunctionType &wLocal, Operation op ) const
384 {
385 // get entity
386 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
387
388 // get number of Lagrange Points
389 const int localBlocks = space_.blockMapper().numDofs( entity );
390
391 typedef typename DiscreteFunctionSpaceType::BlockMapperType::GlobalKeyType GlobalKeyType;
392
393 // map local to global BlockDofs
394 std::vector< GlobalKeyType > globalBlockDofs(localBlocks);
395 space_.blockMapper().map(entity,globalBlockDofs);
396 std::vector<double> values( localBlocks*localBlockSize,0 );
397 std::vector<double> valuesModel( localBlocks*localBlockSize );
398
399 if constexpr ( useIdentity )
400 interpolation( uLocal, values );
401
402 int localDof = 0;
403
404 // iterate over face dofs and set unit row
405 for( int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
406 {
407 // store result to dof vector
408 int global = globalBlockDofs[localBlock];
409 for( int l = 0; l < localBlockSize ; ++ l, ++localDof )
410 {
411 if( dirichletBlocks_[ global ][l] )
412 {
413 if (op == Operation::sub)
414 {
415 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
416 values[ localDof ] -= valuesModel[ localDof ];
417 }
418 else if (op == Operation::add)
419 {
420 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
421 values[ localDof ] += valuesModel[ localDof ];
422 }
423 // store result
424 assert( (unsigned int)localDof < wLocal.size() );
425 wLocal[ localDof ] = values[ localDof ];
426 }
427 }
428 }
429 }
430
431protected:
432 // detect all DoFs on the Dirichlet boundary
433 void updateDirichletDofs() const
434 {
435 if( sequence_ != space_.sequence() )
436 {
437 // only start search if Dirichlet boundary is present
438 if( ! model_.hasDirichletBoundary() )
439 {
440 hasDirichletDofs_ = false ;
441 return ;
442 }
443
444 // resize flag vector with number of blocks and reset flags
445 const int blocks = space_.blockMapper().size() ;
446 dirichletBlocks_.resize( blocks );
447 for( int i=0; i<blocks; ++i )
448 dirichletBlocks_[ i ].fill(0);
449
450 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
451 typedef typename IteratorType :: Entity EntityType;
452
453 bool hasDirichletBoundary = false;
454 const IteratorType end = space_.end();
455 for( IteratorType it = space_.begin(); it != end; ++it )
456 {
457 const EntityType &entity = *it;
458 // if entity has boundary intersections
459 if( entity.hasBoundaryIntersections() )
460 {
461 hasDirichletBoundary |= searchEntityDirichletDofs( entity, model_ );
462 }
463 }
464
465 // update sequence number
466 sequence_ = space_.sequence();
467 if( space_.gridPart().comm().size() > 1 )
468 {
469 try
470 {
471 DirichletBuilder handle( *this, space_ , space_.blockMapper() );
472 space_.gridPart().communicate
473 ( handle, GridPartType::indexSetInterfaceType, ForwardCommunication );
474 }
475 // catch possible exceptions here to have a clue where it happend
476 catch( const Exception &e )
477 {
478 std::cerr << e << std::endl;
479 std::cerr << "Exception thrown in: " << __FILE__ << " line:" << __LINE__ << std::endl;
480 abort();
481 }
482 hasDirichletDofs_ = space_.gridPart().grid().comm().max( hasDirichletBoundary );
483 }
484 else
485 {
486 hasDirichletDofs_ = hasDirichletBoundary;
487 }
488 }
489 }
490
491 // detect all DoFs on the Dirichlet boundary of the given entity
492 template< class EntityType >
493 bool searchEntityDirichletDofs( const EntityType &entity, ModelType& model ) const
494 {
495 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
496
497 typedef typename GridPartType :: IntersectionIteratorType
498 IntersectionIteratorType;
499
500 const GridPartType &gridPart = space_.gridPart();
501
502 // default is false
503 bool hasDirichletBoundary = false;
504
505 //map local to global BlockDofs
506 std::vector<size_t> globalBlockDofs(space_.blockMapper().numDofs(entity));
507 space_.blockMapper().map(entity,globalBlockDofs);
508
509 std::vector<char> subEntityFilter(space_.blockMapper().numDofs(entity));
510
511 IntersectionIteratorType it = gridPart.ibegin( entity );
512 const IntersectionIteratorType endit = gridPart.iend( entity );
513 for( ; it != endit; ++it )
514 {
515 typedef typename IntersectionIteratorType :: Intersection IntersectionType;
516 const IntersectionType& intersection = *it;
517
518 // if intersection is with boundary, adjust data
519 if( intersection.boundary() )
520 {
521 // get dirichlet information from model
522 DirichletBlock block;
523 block.fill(0);
524 std::array<int,dimRange> dblock;
525
526 model.init(intersection);
527 const bool isDirichletIntersection = model.isDirichletIntersection( intersection, dblock );
528 if (isDirichletIntersection)
529 {
530 // get face number of boundary intersection
531 const int face = intersection.indexInInside();
532 space_.blockMapper().onSubEntity(entity,face,1,subEntityFilter);
533 for( unsigned int i=0;i<globalBlockDofs.size();++i)
534 {
535 assert( i < subEntityFilter.size());
536 if ( subEntityFilter[i]==0) continue;
537 // mark global DoF number
538 for(int k = 0; k < localBlockSize; ++k)
539 {
540 int comp = subEntityFilter[i]-1+k;
541 assert( comp < dimRange );
542 dirichletBlocks_[ globalBlockDofs[ i ] ][k] = dblock[comp];
543 }
544 // we have Dirichlet values
545 hasDirichletBoundary = true ;
546 }
547 }
548 }
549 }
550
551 return hasDirichletBoundary;
552 }
553
554 ModelType &model_;
555 const DiscreteFunctionSpaceType& space_;
556 mutable DirichletBlockVector dirichletBlocks_;
557 mutable bool hasDirichletDofs_ ;
558 mutable int sequence_ ;
559
560 class DirichletBuilder;
561};
562
563template < class Model, class Space, bool useIdentity >
564class DirichletConstraints< Model,Space, useIdentity > :: DirichletBuilder
565 : public CommDataHandleIF< DirichletBuilder, int >
566{
567public:
568 typedef Space SpaceType;
569 typedef typename SpaceType::BlockMapperType MapperType;
570
571 enum { nCodim = SpaceType :: GridType :: dimension + 1 };
572
573public:
574 typedef int DataType;
575
576 const int myRank_;
577 const int mySize_;
578
579 typedef DirichletConstraints< Model,Space, useIdentity > DirichletType;
580 const DirichletType &dirichlet_;
581
582 const SpaceType &space_;
583 const MapperType &mapper_;
584
585 static const int blockSize = SpaceType::localBlockSize;
586
587public:
588 DirichletBuilder( const DirichletType &dirichlet,
589 const SpaceType &space,
590 const MapperType &mapper )
591 : myRank_( space.gridPart().comm().rank() ),
592 mySize_( space.gridPart().comm().size() ),
593 dirichlet_( dirichlet ),
594 space_( space ),
595 mapper_( mapper )
596 {
597 }
598 bool contains ( int dim, int codim ) const
599 {
600 return mapper_.contains( codim );
601 }
602
603 bool fixedSize ( int dim, int codim ) const
604 {
605 return false;
606 }
607
609 template< class MessageBuffer, class Entity >
610 inline void gather ( MessageBuffer &buffer,
611 const Entity &entity ) const
612 {
613 unsigned int localBlocks = mapper_.numEntityDofs( entity );
614 std::vector<std::size_t> globalBlockDofs(localBlocks);
615 mapper_.mapEntityDofs( entity, globalBlockDofs );
616 assert( size(entity) == globalBlockDofs.size()*blockSize );
617 for( unsigned int localBlock = 0 ; localBlock < globalBlockDofs.size(); ++ localBlock )
618 {
619 int global = globalBlockDofs[localBlock];
620 for (int r=0;r<blockSize;++r)
621 if (dirichlet_.dirichletBlocks_[ global ][r] )
622 buffer.write( 1 );
623 else
624 buffer.write( 0 );
625 }
626 }
627
632 template< class MessageBuffer, class EntityType >
633 inline void scatter ( MessageBuffer &buffer,
634 const EntityType &entity,
635 size_t n )
636 {
637 unsigned int localBlocks = mapper_.numEntityDofs( entity );
638 std::vector<std::size_t> globalBlockDofs(localBlocks);
639 mapper_.mapEntityDofs( entity, globalBlockDofs );
640 assert( n == globalBlockDofs.size()*blockSize );
641 assert( n == size(entity) );
642 for( unsigned int localBlock = 0 ; localBlock < globalBlockDofs.size(); ++ localBlock )
643 {
644 int global = globalBlockDofs[localBlock];
645 for (int r=0;r<blockSize;++r)
646 {
647 int val;
648 buffer.read(val);
649 if ( !dirichlet_.dirichletBlocks_[ global ][r] && val == 1)
650 dirichlet_.dirichletBlocks_[ global ][r] = true;
651 }
652 }
653 }
655 template< class Entity >
656 size_t size ( const Entity &entity ) const
657 {
658 return blockSize * mapper_.numEntityDofs( entity );
659 }
660};
661
662} // end namespace Dune
663#endif
discrete function space
Traits::ConstDofIteratorType ConstDofIteratorType
type of the const dof iterator
Definition: discretefunction.hh:628
ConstDofIteratorType dbegin() const
Obtain the constant iterator pointing to the first dof.
Definition: discretefunction.hh:761
ConstDofIteratorType dend() const
Obtain the constant iterator pointing to the last dof.
Definition: discretefunction.hh:773
DiscreteFunctionSpaceType::RangeType RangeType
type of range vector
Definition: discretefunction.hh:614
Traits::DofIteratorType DofIteratorType
type of the dof iterator
Definition: discretefunction.hh:626
Traits::FunctionSpaceType FunctionSpaceType
type of function space
Definition: discretefunctionspace.hh:194
A vector valued function space.
Definition: functionspace.hh:60
Definition: nonblockmapper.hh:284
forward declaration
Definition: discretefunction.hh:51
Default exception for dummy implementations.
Definition: exceptions.hh:263
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
@ ForwardCommunication
communicate as given in InterfaceType
Definition: gridenums.hh:171
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
std::size_t fixedSize
The number of data items per index if it is fixed, 0 otherwise.
Definition: variablesizecommunicator.hh:264
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 21, 23:30, 2024)