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 bool valid()
const {
return true; }
105 const EntityType& entity()
const {
return entity_; }
106 const int order ()
const {
return order_; }
107 template <
class Po
int>
108 void evaluate(
const Point& x, RangeType& ret )
const
109 { impl_.dirichlet(bndId_,Dune::Fem::coordinate(x),ret); }
110 template <
class Po
int>
111 void jacobian(
const Point& x, JacobianRangeType& ret )
const
115 DirichletConstraints( ModelType &model,
const DiscreteFunctionSpaceType& space )
120 hasDirichletDofs_( false ),
131 template <
class DiscreteFunctionType >
134 updateDirichletDofs();
137 if( hasDirichletDofs_ )
142 ConstDofIteratorType uIt = u.
dbegin();
143 DofIteratorType wIt = w.
dbegin();
146 const unsigned int blocks = space_.blockMapper().size();
147 for(
unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
149 for(
int l = 0; l < localBlockSize ; ++ l, ++ wIt, ++ uIt )
151 if( dirichletBlocks_[ blockDof ][l] )
154 assert( uIt != u.
dend() );
155 assert( wIt != w.
dend() );
169 template <
class DiscreteFunctionType >
172 updateDirichletDofs();
175 if( hasDirichletDofs_ )
179 DofIteratorType wIt = w.
dbegin();
182 const unsigned int blocks = space_.blockMapper().size();
183 for(
unsigned int blockDof = 0; blockDof < blocks ; ++ blockDof )
185 for(
int l = 0; l < localBlockSize ; ++ l, ++ wIt )
187 if( dirichletBlocks_[ blockDof ][l] )
190 assert( wIt != w.
dend() );
204 template <
class DiscreteFunctionType >
207 if (op != Operation::set)
210 return (*
this)(u,w,op);
213 updateDirichletDofs();
215 if( hasDirichletDofs_ )
217 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
218 typedef typename IteratorType :: Entity EntityType;
220 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
221 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
222 for(
const EntityType &entity : space_ )
227 auto wGuard = Dune::Fem::bindGuard( wLocal, entity );
229 auto iGuard = bindGuard( interpolation, entity );
232 dirichletDofTreatment( interpolation, wLocal );
237 typename = std::enable_if_t< std::is_base_of<Dune::Fem::HasLocalFunction, GridFunctionType>::value > >
238 void operator ()(
const GridFunctionType &u,
241 updateDirichletDofs();
243 if( hasDirichletDofs_ )
245 Dune::Fem::ConstLocalFunction< GridFunctionType > uLocal( u );
246 Dune::Fem::SetSelectedLocalContribution< DiscreteFunctionType > wLocal( w );
247 Dune::Fem::LocalInterpolation< DiscreteFunctionSpaceType > interpolation( space_ );
249 for(
const auto &entity : space_ )
251 auto guard = Dune::Fem::bindGuard( std::tie(uLocal,wLocal), entity );
253 auto iGuard = bindGuard( interpolation, entity );
256 if (op == Operation::sub || op == Operation::add)
258 dirichletDofTreatment( interpolation, uLocal, wLocal, op );
271 template <
class LinearOperator>
272 void applyToOperator( LinearOperator& linearOperator )
const
274 updateDirichletDofs();
276 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
277 typedef typename IteratorType :: Entity EntityType;
280 if( hasDirichletDofs_ )
282 typedef typename DiscreteFunctionSpaceType :: BlockMapperType BlockMapperType;
285 std::vector<std::size_t> globalBlockDofs;
286 std::vector<std::size_t> globalDofs;
289 std::set<std::size_t> unitRows;
290 std::set<std::size_t> auxRows;
292 const auto& space = space_;
296 const IteratorType end = space_.end();
297 for( IteratorType it = space_.begin(); it != end; ++it )
299 const EntityType &entity = *it;
302 const int localBlocks = space.blockMapper().numDofs( entity );
305 globalBlockDofs.resize(localBlocks);
307 space.blockMapper().map( entity, globalBlockDofs );
310 globalDofs.resize(localBlocks * localBlockSize);
311 mapper.map( entity, globalDofs );
316 for(
int localBlockDof = 0 ; localBlockDof < localBlocks; ++ localBlockDof )
318 int global = globalBlockDofs[localBlockDof];
322 std::set<std::size_t>& rows = useIdentity ? unitRows : auxRows;
323 for(
int l = 0; l < localBlockSize; ++ l, ++ localDof )
325 if( dirichletBlocks_[global][l] )
328 rows.insert( globalDofs[ localDof ] );
335 linearOperator.setUnitRows( unitRows, auxRows );
339 const DirichletBlockVector &dirichletBlocks()
const
341 updateDirichletDofs();
342 return dirichletBlocks_;
347 template<
class LocalInterpolationType,
class LocalFunctionType >
348 void dirichletDofTreatment(
const LocalInterpolationType& interpolation, LocalFunctionType &wLocal)
const
351 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
354 const int localBlocks = space_.blockMapper().numDofs( entity );
357 std::vector<std::size_t> globalBlockDofs(localBlocks);
358 space_.blockMapper().map( entity, globalBlockDofs );
359 std::vector<typename LocalFunctionType::RangeFieldType> values( localBlocks*localBlockSize );
364 for(
int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
367 int global = globalBlockDofs[localBlock];
368 for(
int l = 0; l < localBlockSize ; ++ l, ++localDof )
370 if( dirichletBlocks_[ global ][l] )
372 interpolation( BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), values );
374 assert( (
unsigned int)localDof < wLocal.size() );
375 wLocal[ localDof ] = values[ localDof ];
381 template<
class LocalInterpolationType,
class Gr
idLocalFunctionType,
class LocalFunctionType >
382 void dirichletDofTreatment(
const LocalInterpolationType& interpolation,
383 const GridLocalFunctionType &uLocal,
384 LocalFunctionType &wLocal, Operation op )
const
387 const typename LocalFunctionType::EntityType &entity = wLocal.entity();
390 const int localBlocks = space_.blockMapper().numDofs( entity );
392 typedef typename DiscreteFunctionSpaceType::BlockMapperType::GlobalKeyType GlobalKeyType;
395 std::vector< GlobalKeyType > globalBlockDofs(localBlocks);
396 space_.blockMapper().map(entity,globalBlockDofs);
397 std::vector<double> values( localBlocks*localBlockSize,0 );
398 std::vector<double> valuesModel( localBlocks*localBlockSize );
400 if constexpr ( useIdentity )
401 interpolation( uLocal, values );
406 for(
int localBlock = 0 ; localBlock < localBlocks; ++ localBlock )
409 int global = globalBlockDofs[localBlock];
410 for(
int l = 0; l < localBlockSize ; ++ l, ++localDof )
412 if( dirichletBlocks_[ global ][l] )
414 if (op == Operation::sub)
416 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
417 values[ localDof ] -= valuesModel[ localDof ];
419 else if (op == Operation::add)
421 interpolation(BoundaryWrapper(model_, entity, wLocal.order(), dirichletBlocks_[global][l]), valuesModel);
422 values[ localDof ] += valuesModel[ localDof ];
425 assert( (
unsigned int)localDof < wLocal.size() );
426 wLocal[ localDof ] = values[ localDof ];
434 void updateDirichletDofs()
const
436 if( sequence_ != space_.sequence() )
439 if( ! model_.hasDirichletBoundary() )
441 hasDirichletDofs_ = false ;
446 const int blocks = space_.blockMapper().size() ;
447 dirichletBlocks_.resize( blocks );
448 for(
int i=0; i<blocks; ++i )
449 dirichletBlocks_[ i ].fill(0);
451 typedef typename DiscreteFunctionSpaceType :: IteratorType IteratorType;
452 typedef typename IteratorType :: Entity EntityType;
454 bool hasDirichletBoundary =
false;
455 const IteratorType end = space_.end();
456 for( IteratorType it = space_.begin(); it != end; ++it )
458 const EntityType &entity = *it;
460 if( entity.hasBoundaryIntersections() )
462 hasDirichletBoundary |= searchEntityDirichletDofs( entity, model_ );
467 sequence_ = space_.sequence();
468 if( space_.gridPart().comm().size() > 1 )
472 DirichletBuilder handle( *
this, space_ , space_.blockMapper() );
473 space_.gridPart().communicate
477 catch(
const Exception &e )
479 std::cerr << e << std::endl;
480 std::cerr <<
"Exception thrown in: " << __FILE__ <<
" line:" << __LINE__ << std::endl;
483 hasDirichletDofs_ = space_.gridPart().grid().comm().max( hasDirichletBoundary );
487 hasDirichletDofs_ = hasDirichletBoundary;
493 template<
class EntityType >
494 bool searchEntityDirichletDofs(
const EntityType &entity, ModelType& model )
const
496 typedef typename DiscreteFunctionSpaceType :: GridPartType GridPartType;
498 typedef typename GridPartType :: IntersectionIteratorType
499 IntersectionIteratorType;
501 const GridPartType &gridPart = space_.gridPart();
504 bool hasDirichletBoundary =
false;
507 std::vector<size_t> globalBlockDofs(space_.blockMapper().numDofs(entity));
508 space_.blockMapper().map(entity,globalBlockDofs);
510 std::vector<char> subEntityFilter(space_.blockMapper().numDofs(entity));
512 IntersectionIteratorType it = gridPart.ibegin( entity );
513 const IntersectionIteratorType endit = gridPart.iend( entity );
514 for( ; it != endit; ++it )
516 typedef typename IntersectionIteratorType :: Intersection IntersectionType;
517 const IntersectionType& intersection = *it;
520 if( intersection.boundary() )
523 DirichletBlock block;
525 std::array<int,dimRange> dblock;
527 model.init(intersection);
528 const bool isDirichletIntersection = model.isDirichletIntersection( intersection, dblock );
529 if (isDirichletIntersection)
532 const int face = intersection.indexInInside();
533 space_.blockMapper().onSubEntity(entity,face,1,subEntityFilter);
534 for(
unsigned int i=0;i<globalBlockDofs.size();++i)
536 assert( i < subEntityFilter.size());
537 if ( subEntityFilter[i]==0)
continue;
539 for(
int k = 0; k < localBlockSize; ++k)
541 int comp = subEntityFilter[i]-1+k;
542 assert( comp < dimRange );
543 dirichletBlocks_[ globalBlockDofs[ i ] ][k] = dblock[comp];
546 hasDirichletBoundary = true ;
552 return hasDirichletBoundary;
556 const DiscreteFunctionSpaceType& space_;
557 mutable DirichletBlockVector dirichletBlocks_;
558 mutable bool hasDirichletDofs_ ;
559 mutable int sequence_ ;
561 class DirichletBuilder;
564template <
class Model,
class Space,
bool useIdentity >
565class DirichletConstraints< Model,Space, useIdentity > :: DirichletBuilder
566 :
public CommDataHandleIF< DirichletBuilder, int >
570 typedef typename SpaceType::BlockMapperType MapperType;
572 enum { nCodim = SpaceType :: GridType :: dimension + 1 };
575 typedef int DataType;
580 typedef DirichletConstraints< Model,Space, useIdentity > DirichletType;
581 const DirichletType &dirichlet_;
584 const MapperType &mapper_;
586 static const int blockSize = SpaceType::localBlockSize;
589 DirichletBuilder(
const DirichletType &dirichlet,
591 const MapperType &mapper )
592 : myRank_( space.gridPart().comm().rank() ),
593 mySize_( space.gridPart().comm().
size() ),
594 dirichlet_( dirichlet ),
599 bool contains (
int dim,
int codim )
const
601 return mapper_.contains( codim );
604 bool fixedSize (
int dim,
int codim )
const
610 template<
class MessageBuffer,
class Entity >
611 inline void gather ( MessageBuffer &buffer,
612 const Entity &entity )
const
614 unsigned int localBlocks = mapper_.numEntityDofs( entity );
615 std::vector<std::size_t> globalBlockDofs(localBlocks);
616 mapper_.mapEntityDofs( entity, globalBlockDofs );
617 assert(
size(entity) == globalBlockDofs.size()*blockSize );
618 for(
unsigned int localBlock = 0 ; localBlock < globalBlockDofs.size(); ++ localBlock )
620 int global = globalBlockDofs[localBlock];
621 for (
int r=0;r<blockSize;++r)
622 if (dirichlet_.dirichletBlocks_[ global ][r] )
633 template<
class MessageBuffer,
class EntityType >
634 inline void scatter ( MessageBuffer &buffer,
635 const EntityType &entity,
638 unsigned int localBlocks = mapper_.numEntityDofs( entity );
639 std::vector<std::size_t> globalBlockDofs(localBlocks);
640 mapper_.mapEntityDofs( entity, globalBlockDofs );
641 assert( n == globalBlockDofs.size()*blockSize );
642 assert( n ==
size(entity) );
643 for(
unsigned int localBlock = 0 ; localBlock < globalBlockDofs.size(); ++ localBlock )
645 int global = globalBlockDofs[localBlock];
646 for (
int r=0;r<blockSize;++r)
650 if ( !dirichlet_.dirichletBlocks_[ global ][r] && val == 1)
651 dirichlet_.dirichletBlocks_[ global ][r] =
true;
656 template<
class Entity >
657 size_t size (
const Entity &entity )
const
659 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:357
#define DUNE_THROW(E,...)
Definition: exceptions.hh:314
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