1#ifndef DUNE_ACFEM_DIRICHLETCONSTRAINTS_HH
2#define DUNE_ACFEM_DIRICHLETCONSTRAINTS_HH
4#include <dune/fem/function/common/scalarproducts.hh>
6#include "../../models/indicators/boundaryindicator.hh"
7#include "../../models/modeltraits.hh"
8#include "../../functions/functions.hh"
9#include "bulkblockconstraints.hh"
10#include "../../models/expressions.hh"
24 template<
class DiscreteFunctionSpace,
class BoundaryValues,
class Indicator =
void,
class SFINAE =
void>
25 class DirichletConstraints;
29 template<
class BoundaryValues,
class SFINAE =
void>
30 struct HasEmptySupport
34 template<
class BoundaryValues>
35 struct HasEmptySupport<
37 std::enable_if_t<(IsPDEModel<BoundaryValues>::value
38 && !EffectiveModelTraits<BoundaryValues>::template Exists<PDEModel::dirichlet>::value)> >
46 template<
class DiscreteFunctionSpace,
class Model>
47 class DirichletConstraints<DiscreteFunctionSpace, Model,
50 && IsPDEModel<Model>::value
51 && !HasEmptySupport<Model>::value> >
54 typedef DirichletConstraints
ThisType;
57 typedef typename BaseType::ConstraintsStorageType ConstraintsStorageType;
58 typedef typename BaseType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
59 typedef typename BaseType::GridPartType GridPartType;
60 typedef typename BaseType::EntityType EntityType;
62 using ModelType = EffectiveModel<Model>;
63 using ModelTraits = EffectiveModelTraits<ModelType>;
66 typedef typename DiscreteFunctionSpaceType::GridType
GridType;
70 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
73 typedef std::size_t GlobalKeyType;
75 DirichletConstraints(
const DiscreteFunctionSpaceType& space,
76 const ModelType& model)
81 using BaseType::jacobian;
82 using BaseType::constrain;
83 using BaseType::zeroConstrain;
84 using BaseType::communicate;
97 if (sequence_ == space_.sequence()) {
101 updateBoundaryValues();
105 sequence_ = space_.sequence();
109 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
114 const auto& mapper = space_.blockMapper();
115 const int maxNumDofs = mapper.maxNumDofs();
118 mask_.resize(mapper.size());
119 std::fill(mask_.begin(), mask_.end(), 0U);
123 if (!ModelTraits::template Exists<PDEModel::dirichlet>::value) {
129 std::vector<GlobalKeyType> blockDofIndices;
130 std::vector<bool> blockDofFaceMask;
131 blockDofIndices.reserve(maxNumDofs);
132 blockDofFaceMask.reserve(maxNumDofs);
133 auto uValues = temporaryLocalFunction(space_);
136 auto wLocal = values_.localFunction();
139 for (
const auto& entity : space_) {
140 for (
const auto& intersection : intersections(space_.gridPart(), entity)) {
143 if (intersection.neighbor() || !intersection.boundary()) {
148 const auto indicator = uLocal.classifyIntersection(intersection);
149 const auto& localMask = indicator.second;
151 if (!indicator.first || localMask.none()) {
155 const auto numConstrained = localMask.count();
158 const int numDofs = mapper.numDofs(entity);
161 blockDofIndices.resize(numDofs, GlobalKeyType(-1));
162 blockDofFaceMask.resize(numDofs,
false);
163 uValues.init(entity);
167 space_.blockMapper().map(entity, blockDofIndices);
171 const int face = intersection.indexInInside();
172 mapper.onSubEntity(entity, face, 1 , blockDofFaceMask);
175 space_.interpolation(entity)(uLocal, uValues);
177 for (
int localBlock = 0; localBlock < numDofs; ++localBlock) {
178 if (!blockDofFaceMask[localBlock]) {
181 auto& blockMask = mask_[blockDofIndices[localBlock]];
182 blockMask |= localMask;
183 auto numBlockConstrained = blockMask.count();
184 numConstrained_ += 2*numConstrained - numBlockConstrained;
185 int localDof = localBlock * localBlockSize;
186 for(
int l = 0; l < localBlockSize; ++l, ++localDof) {
187 wLocal[localDof] = uValues[localDof];
195 using BaseType::space_;
196 using BaseType::values_;
197 using BaseType::mask_;
198 using BaseType::sequence_;
199 using BaseType::numConstrained_;
206 template<
class DiscreteFunctionSpace,
class BoundaryValues,
class Indicator>
207 class DirichletConstraints<DiscreteFunctionSpace, BoundaryValues, Indicator,
208 std::enable_if_t<(IsWrappableByConstLocalFunction<BoundaryValues>::value
209 && IsBoundaryIndicator<Indicator>::value
210 && !IndicatorTraits<Indicator>::emptySupport
214 typedef DirichletConstraints
ThisType;
217 typedef typename BaseType::ConstraintsStorageType ConstraintsStorageType;
218 typedef typename BaseType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
219 typedef typename BaseType::GridPartType GridPartType;
220 typedef typename BaseType::EntityType EntityType;
222 using IndicatorType = Indicator;
223 typedef BoundaryValues BoundaryValuesFunctionType;
226 typedef typename DiscreteFunctionSpaceType::GridType
GridType;
230 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
233 typedef std::size_t GlobalKeyType;
235 DirichletConstraints(
const DiscreteFunctionSpaceType& space,
236 const BoundaryValuesFunctionType& boundaryValues,
237 const IndicatorType& indicator)
239 , boundaryValues_(boundaryValues)
240 , indicator_(indicator)
244 using BaseType::jacobian;
245 using BaseType::constrain;
246 using BaseType::zeroConstrain;
247 using BaseType::communicate;
260 if (sequence_ == space_.sequence()) {
264 updateBoundaryValues(boundaryValues_(), values_);
268 sequence_ = space_.sequence();
272 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
277 const auto& mapper = space_.blockMapper();
278 const int maxNumDofs = mapper.maxNumDofs();
281 mask_.resize(mapper.size());
282 std::fill(mask_.begin(), mask_.end(), 0U);
285 std::vector<GlobalKeyType> blockDofIndices;
286 std::vector<bool> blockDofFaceMask;
287 blockDofIndices.reserve(maxNumDofs);
288 blockDofFaceMask.reserve(maxNumDofs);
289 auto uValues = temporaryLocalFunction(space_);
290 auto uLocal = localFunction(u);
291 auto wLocal = localFunction(w);
294 for (
const auto& entity : space_) {
295 for (
const auto& intersection : intersections(space_.gridPart(), entity)) {
298 if (intersection.neighbor() || !intersection.boundary()) {
303 if (!indicator_.applies(intersection)) {
308 const int numDofs = mapper.numDofs(entity);
311 blockDofIndices.resize(numDofs, GlobalKeyType(-1));
312 blockDofFaceMask.resize(numDofs,
false);
313 uValues.init(entity);
314 uLocal.init(entity, intersection);
318 space_.blockMapper().map(entity, blockDofIndices);
322 const int face = intersection.indexInInside();
323 mapper.onSubEntity(entity, face, 1 , blockDofFaceMask);
326 space_.interpolation(entity)(uLocal, uValues);
328 for (
int localBlock = 0; localBlock < numDofs; ++localBlock) {
329 if (!blockDofFaceMask[localBlock]) {
332 if (!mask_[blockDofIndices[localBlock]].any()) {
334 mask_[blockDofIndices[localBlock]].set();
335 numConstrained_ += mask_[blockDofIndices[localBlock]].count();
337 int localDof = localBlock * localBlockSize;
338 for(
int l = 0; l < localBlockSize; ++l, ++localDof) {
339 wLocal[localDof] = uValues[localDof];
347 using BaseType::space_;
348 using BaseType::values_;
349 using BaseType::mask_;
350 using BaseType::sequence_;
351 using BaseType::numConstrained_;
353 const BoundaryValuesFunctionType boundaryValues_;
354 const IndicatorType indicator_;
359 template<
class DiscreteFunctionSpace,
class BoundaryValues,
class Indicator>
360 class DirichletConstraints<DiscreteFunctionSpace, BoundaryValues, Indicator,
361 std::enable_if_t<(HasEmptySupport<BoundaryValues>::value
362 || IndicatorTraits<Indicator>::emptySupport
366 typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
367 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
368 typedef typename DiscreteFunctionSpaceType::EntityType EntityType;
369 typedef BoundaryValues BoundaryValuesFunctionType;
372 DirichletConstraints(
const DiscreteFunctionSpaceType& space,
373 const BoundaryValuesFunctionType& boundaryValues)
376 template<
class DomainDiscreteFunction,
class RangeDiscreteFunction>
377 void operator()(
const DomainDiscreteFunction& arg, RangeDiscreteFunction& result)
const {}
379 template<
class DomainDiscreteFunction,
class JacobianOperator>
380 void jacobian(
const DomainDiscreteFunction& u, JacobianOperator& jOp)
const {}
382 template<
class DomainDiscreteFunction,
class JacobianOperator>
383 void applyToOperator(
const DomainDiscreteFunction& u, JacobianOperator& jOp)
const
386 template<
class DomainDiscreteFunction>
387 void constrain(DomainDiscreteFunction& w)
const {}
389 template<
class DomainDiscreteFunction>
390 void zeroConstrain(DomainDiscreteFunction& w)
const {}
392 size_t size()
const {
return 0; }
393 void reset()
const {}
394 void update()
const {}
395 void updateValues()
const {}
A default implementation for bulk block constraints.
Definition: bulkblockconstraints.hh:36
void updateBoundaryValues(const BoundaryValuesFunctionType &u, ConstraintsStorageType &w) const
Update the flag vector and interpolate the boundary values.
Definition: dirichletconstraints.hh:275
DiscreteFunctionSpaceType::GridType GridType
type of grid
Definition: dirichletconstraints.hh:226
void update() const
Rebuild everything in case the sequence number of the underlying space has changed,...
Definition: dirichletconstraints.hh:258
void update() const
Rebuild everything in case the sequence number of the underlying space has changed,...
Definition: dirichletconstraints.hh:95
void updateBoundaryValues() const
Update the flag vector and interpolate the boundary values.
Definition: dirichletconstraints.hh:112
DiscreteFunctionSpaceType::GridType GridType
type of grid
Definition: dirichletconstraints.hh:66
auto modelDirichletValues(Model &&model, const GridPart &gridPart, const std::string &name="")
Generate a representation of the Dirichlet values associated to the model as Fem::BindableGridFunctio...
Definition: modeldirichletvalues.hh:270
constexpr std::size_t size()
Gives the number of elements in tuple-likes and std::integer_sequence.
Definition: size.hh:73
BoolConstant< false > FalseType
Alias for std::false_type.
Definition: types.hh:110
BoolConstant< true > TrueType
Alias for std::true_type.
Definition: types.hh:107
BoundaryIndicator::Constant< false > EmptyBoundaryIndicator
A boundary indicator applying to no part of the boundary.
Definition: boundaryindicator.hh:373