40#ifndef DUNE_DIRICHLETCONSTRAINTS_HH
41#define DUNE_DIRICHLETCONSTRAINTS_HH
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>
55class HasLocalFunction;
58template <
class Model,
class DiscreteFunctionSpace,
bool useIdentity >
59class DirichletConstraints
62 enum Operation { set = 0, sub = 1, add = 2 };
63 typedef Model ModelType;
65 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
66 typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
67 typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
68 typedef typename DiscreteFunctionSpaceType::HessianRangeType HessianRangeType;
71 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
73 typedef typename DiscreteFunctionSpaceType :: GridType GridType;
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;
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;
95 const ModelType& impl_;
96 const EntityType& entity_;
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 Po
int>
107 void evaluate(
const Point& x, RangeType& ret )
const
108 { impl_.dirichlet(bndId_,Dune::Fem::coordinate(x),ret); }
109 template <
class Po
int>
110 void jacobian(
const Point& x, JacobianRangeType& ret )
const
114 DirichletConstraints( ModelType &model,
const DiscreteFunctionSpaceType& space )
119 hasDirichletDofs_( false ),
130 template <
class DiscreteFunctionType >
133 updateDirichletDofs();
136 if( hasDirichletDofs_ )
141 ConstDofIteratorType uIt = u.
dbegin();
142 DofIteratorType wIt = w.
dbegin();
145 const unsigned int blocks = space_.blockMapper().size();
146 for(
unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
148 for(
int l = 0; l < localBlockSize ; ++ l, ++ wIt, ++ uIt )
150 if( dirichletBlocks_[ blockDof ][l] )
153 assert( uIt != u.
dend() );
154 assert( wIt != w.
dend() );
168 template <
class DiscreteFunctionType >
171 updateDirichletDofs();
174 if( hasDirichletDofs_ )
178 DofIteratorType wIt = w.
dbegin();
181 const unsigned int blocks = space_.blockMapper().size();
182 for(
unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
184 for(
int l = 0; l < localBlockSize ; ++ l, ++ wIt )
186 if( dirichletBlocks_[ blockDof ][l] )
189 assert( wIt != w.
dend() );
203 template <
class DiscreteFunctionType >
206 if (op != Operation::set)
209 return (*
this)(u,w,op);
212 updateDirichletDofs();
214 if( hasDirichletDofs_ )
216 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
217 typedef typename IteratorType :: Entity EntityType;
219 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
220 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
221 for(
const EntityType &entity : space_ )
226 auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
228 auto iGuard = bindGuard( interpolation, entity );
231 dirichletDofTreatment( interpolation, wLocal );
236 typename = std::enable_if_t< std::is_base_of<Dune::Fem::HasLocalFunction, GridFunctionType>::value > >
237 void operator ()(
const GridFunctionType &u,
240 updateDirichletDofs();
242 if( hasDirichletDofs_ )
244 Dune::Fem::ConstLocalFunction< GridFunctionType > uLocal( u );
245 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
246 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
248 for(
const auto &entity : space_ )
250 auto guard = Dune::Fem::bindGuard( std::tie(uLocal,wLocal), entity );
252 auto iGuard = bindGuard( interpolation, entity );
255 if (op == Operation::sub || op == Operation::add)
257 dirichletDofTreatment( interpolation, uLocal, wLocal, op );
270 template <
class LinearOperator>
271 void applyToOperator( LinearOperator& linearOperator )
const
273 updateDirichletDofs();
275 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
276 typedef typename IteratorType :: Entity EntityType;
279 if( hasDirichletDofs_ )
281 typedef typename DiscreteFunctionSpaceType :: BlockMapperType BlockMapperType;
284 std::vector<std::size_t> globalBlockDofs;
285 std::vector<std::size_t> globalDofs;
288 std::set<std::size_t> unitRows;
289 std::set<std::size_t> auxRows;
291 const auto& space = space_;
295 const IteratorType end = space_.end();
296 for( IteratorType it = space_.begin(); it != end; ++it )
298 const EntityType &entity = *it;
301 const int localBlocks = space.blockMapper().numDofs( entity );
304 globalBlockDofs.resize(localBlocks);
306 space.blockMapper().map( entity, globalBlockDofs );
309 globalDofs.resize(localBlocks * localBlockSize);
310 mapper.map( entity, globalDofs );
315 for(
int localBlockDof = 0 ; localBlockDof < localBlocks; ++ localBlockDof )
317 int global = globalBlockDofs[localBlockDof];
321 std::set<std::size_t>& rows = useIdentity ? unitRows : auxRows;
322 for(
int l = 0; l < localBlockSize; ++ l, ++ localDof )
324 if( dirichletBlocks_[global][l] )
327 rows.insert( globalDofs[ localDof ] );
334 linearOperator.setUnitRows( unitRows, auxRows );
338 const DirichletBlockVector &dirichletBlocks()
const
340 updateDirichletDofs();
341 return dirichletBlocks_;
346 template<
class LocalInterpolationType,
class LocalFunctionType >
347 void dirichletDofTreatment(
const LocalInterpolationType& interpolation, LocalFunctionType &wLocal)
const
350 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
353 const int localBlocks = space_.blockMapper().numDofs( entity );
356 std::vector<std::size_t> globalBlockDofs(localBlocks);
357 space_.blockMapper().map( entity, globalBlockDofs );
358 std::vector<typename LocalFunctionType::RangeFieldType> values( localBlocks*localBlockSize );
363 for(
int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
366 int global = globalBlockDofs[localBlock];
367 for(
int l = 0; l < localBlockSize ; ++ l, ++localDof )
369 if( dirichletBlocks_[ global ][l] )
371 interpolation( BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), values );
373 assert( (
unsigned int)localDof < wLocal.size() );
374 wLocal[ localDof ] = values[ localDof ];
380 template<
class LocalInterpolationType,
class Gr
idLocalFunctionType,
class LocalFunctionType >
381 void dirichletDofTreatment(
const LocalInterpolationType& interpolation,
382 const GridLocalFunctionType &uLocal,
383 LocalFunctionType &wLocal, Operation op )
const
386 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
389 const int localBlocks = space_.blockMapper().numDofs( entity );
391 typedef typename DiscreteFunctionSpaceType::BlockMapperType::GlobalKeyType GlobalKeyType;
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 );
399 if constexpr ( useIdentity )
400 interpolation( uLocal, values );
405 for(
int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
408 int global = globalBlockDofs[localBlock];
409 for(
int l = 0; l < localBlockSize ; ++ l, ++localDof )
411 if( dirichletBlocks_[ global ][l] )
413 if (op == Operation::sub)
415 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
416 values[ localDof ] -= valuesModel[ localDof ];
418 else if (op == Operation::add)
420 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
421 values[ localDof ] += valuesModel[ localDof ];
424 assert( (
unsigned int)localDof < wLocal.size() );
425 wLocal[ localDof ] = values[ localDof ];
433 void updateDirichletDofs()
const
435 if( sequence_ != space_.sequence() )
438 if( ! model_.hasDirichletBoundary() )
440 hasDirichletDofs_ = false ;
445 const int blocks = space_.blockMapper().size() ;
446 dirichletBlocks_.resize( blocks );
447 for(
int i=0; i<blocks; ++i )
448 dirichletBlocks_[ i ].fill(0);
450 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
451 typedef typename IteratorType :: Entity EntityType;
453 bool hasDirichletBoundary =
false;
454 const IteratorType end = space_.end();
455 for( IteratorType it = space_.begin(); it != end; ++it )
457 const EntityType &entity = *it;
459 if( entity.hasBoundaryIntersections() )
461 hasDirichletBoundary |= searchEntityDirichletDofs( entity, model_ );
466 sequence_ = space_.sequence();
467 if( space_.gridPart().comm().size() > 1 )
471 DirichletBuilder handle( *
this, space_ , space_.blockMapper() );
472 space_.gridPart().communicate
476 catch(
const Exception &e )
478 std::cerr << e << std::endl;
479 std::cerr <<
"Exception thrown in: " << __FILE__ <<
" line:" << __LINE__ << std::endl;
482 hasDirichletDofs_ = space_.gridPart().grid().comm().max( hasDirichletBoundary );
486 hasDirichletDofs_ = hasDirichletBoundary;
492 template<
class EntityType >
493 bool searchEntityDirichletDofs(
const EntityType &entity, ModelType& model )
const
495 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
497 typedef typename GridPartType :: IntersectionIteratorType
498 IntersectionIteratorType;
500 const GridPartType &gridPart = space_.gridPart();
503 bool hasDirichletBoundary =
false;
506 std::vector<size_t> globalBlockDofs(space_.blockMapper().numDofs(entity));
507 space_.blockMapper().map(entity,globalBlockDofs);
509 std::vector<char> subEntityFilter(space_.blockMapper().numDofs(entity));
511 IntersectionIteratorType it = gridPart.ibegin( entity );
512 const IntersectionIteratorType endit = gridPart.iend( entity );
513 for( ; it != endit; ++it )
515 typedef typename IntersectionIteratorType :: Intersection IntersectionType;
516 const IntersectionType& intersection = *it;
519 if( intersection.boundary() )
522 DirichletBlock block;
524 std::array<int,dimRange> dblock;
526 model.init(intersection);
527 const bool isDirichletIntersection = model.isDirichletIntersection( intersection, dblock );
528 if (isDirichletIntersection)
531 const int face = intersection.indexInInside();
532 space_.blockMapper().onSubEntity(entity,face,1,subEntityFilter);
533 for(
unsigned int i=0;i<globalBlockDofs.size();++i)
535 assert( i < subEntityFilter.size());
536 if ( subEntityFilter[i]==0)
continue;
538 for(
int k = 0; k < localBlockSize; ++k)
540 int comp = subEntityFilter[i]-1+k;
541 assert( comp < dimRange );
542 dirichletBlocks_[ globalBlockDofs[ i ] ][k] = dblock[comp];
545 hasDirichletBoundary = true ;
551 return hasDirichletBoundary;
555 const DiscreteFunctionSpaceType& space_;
556 mutable DirichletBlockVector dirichletBlocks_;
557 mutable bool hasDirichletDofs_ ;
558 mutable int sequence_ ;
560 class DirichletBuilder;
563template <
class Model,
class Space,
bool useIdentity >
564class DirichletConstraints< Model,Space, useIdentity > :: DirichletBuilder
565 :
public CommDataHandleIF< DirichletBuilder, int >
569 typedef typename SpaceType::BlockMapperType MapperType;
571 enum { nCodim = SpaceType :: GridType :: dimension + 1 };
574 typedef int DataType;
579 typedef DirichletConstraints< Model,Space, useIdentity > DirichletType;
580 const DirichletType &dirichlet_;
583 const MapperType &mapper_;
585 static const int blockSize = SpaceType::localBlockSize;
588 DirichletBuilder(
const DirichletType &dirichlet,
590 const MapperType &mapper )
591 : myRank_( space.gridPart().comm().rank() ),
592 mySize_( space.gridPart().comm().
size() ),
593 dirichlet_( dirichlet ),
598 bool contains (
int dim,
int codim )
const
600 return mapper_.contains( codim );
603 bool fixedSize (
int dim,
int codim )
const
609 template<
class MessageBuffer,
class Entity >
610 inline void gather ( MessageBuffer &buffer,
611 const Entity &entity )
const
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 )
619 int global = globalBlockDofs[localBlock];
620 for (
int r=0;r<blockSize;++r)
621 if (dirichlet_.dirichletBlocks_[ global ][r] )
632 template<
class MessageBuffer,
class EntityType >
633 inline void scatter ( MessageBuffer &buffer,
634 const EntityType &entity,
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 )
644 int global = globalBlockDofs[localBlock];
645 for (
int r=0;r<blockSize;++r)
649 if ( !dirichlet_.dirichletBlocks_[ global ][r] && val == 1)
650 dirichlet_.dirichletBlocks_[ global ][r] =
true;
655 template<
class Entity >
656 size_t size (
const Entity &entity )
const
658 return blockSize * mapper_.numEntityDofs( entity );
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
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