DUNE-ACFEM (unstable)

dirichletconstraints.hh
1#ifndef DUNE_ACFEM_DIRICHLETCONSTRAINTS_HH
2#define DUNE_ACFEM_DIRICHLETCONSTRAINTS_HH
3
4#include <dune/fem/function/common/scalarproducts.hh>
5
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"
11
12namespace Dune {
13
14 namespace ACFem {
15
24 template<class DiscreteFunctionSpace, class BoundaryValues, class Indicator = void, class SFINAE = void>
25 class DirichletConstraints;
26
27 namespace {
28
29 template<class BoundaryValues, class SFINAE = void>
30 struct HasEmptySupport
31 : FalseType
32 {};
33
34 template<class BoundaryValues>
35 struct HasEmptySupport<
36 BoundaryValues,
37 std::enable_if_t<(IsPDEModel<BoundaryValues>::value
38 && !EffectiveModelTraits<BoundaryValues>::template Exists<PDEModel::dirichlet>::value)> >
39 : TrueType
40 {};
41
42 }
43
46 template<class DiscreteFunctionSpace, class Model>
47 class DirichletConstraints<DiscreteFunctionSpace, Model,
48 void,
49 std::enable_if_t<true
50 && IsPDEModel<Model>::value
51 && !HasEmptySupport<Model>::value> >
52 : public BulkBlockConstraints<DiscreteFunctionSpace>
53 {
54 typedef DirichletConstraints ThisType;
56 public:
57 typedef typename BaseType::ConstraintsStorageType ConstraintsStorageType;
58 typedef typename BaseType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
59 typedef typename BaseType::GridPartType GridPartType;
60 typedef typename BaseType::EntityType EntityType;
61
62 using ModelType = EffectiveModel<Model>;
63 using ModelTraits = EffectiveModelTraits<ModelType>;
64
66 typedef typename DiscreteFunctionSpaceType::GridType GridType;
67
68 // types for boundary treatment
69 // ----------------------------
70 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
71
72 //typedef typename BlockMapperType::GlobalKeyType GlobalKeyType;
73 typedef std::size_t GlobalKeyType;
74
75 DirichletConstraints(const DiscreteFunctionSpaceType& space,
76 const ModelType& model)
77 : BaseType(space), model_(model)
78 {}
79
80 using BaseType::size;
81 using BaseType::jacobian;
82 using BaseType::constrain;
83 using BaseType::zeroConstrain;
84 using BaseType::communicate;
85
86 //using BaseType::operator();
87 // template<class DomainDiscreteFunction, class RangeDiscreteFunction>
88 //void operator()(const DomainDiscreteFunction& arg, RangeDiscreteFunctionType& result) const {
89 //BaseType::operator()(arg, result);
90 //}
91
95 void update() const
96 {
97 if (sequence_ == space_.sequence()) {
98 return;
99 }
100
101 updateBoundaryValues();
102
103 communicate();
104
105 sequence_ = space_.sequence();
106 }
107
108 protected:
109 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
110
113 {
114 const auto& mapper = space_.blockMapper();
115 const int maxNumDofs = mapper.maxNumDofs();
116
117 // resize flag vector with number of blocks and reset flags
118 mask_.resize(mapper.size());
119 std::fill(mask_.begin(), mask_.end(), 0U);
120 values_.clear();
121
122 // only start search if Dirichlet boundary is present
123 if (!ModelTraits::template Exists<PDEModel::dirichlet>::value) {
124 numConstrained_ = 0;
125 return;
126 }
127
128 // pre-allocate local objects
129 std::vector<GlobalKeyType> blockDofIndices;
130 std::vector<bool> blockDofFaceMask;
131 blockDofIndices.reserve(maxNumDofs);
132 blockDofFaceMask.reserve(maxNumDofs);
133 auto uValues = temporaryLocalFunction(space_);
134 auto model = model_;
135 auto uLocal = modelDirichletValues(model, space_.gridPart());
136 auto wLocal = values_.localFunction();
137
138 numConstrained_ = 0;
139 for (const auto& entity : space_) {
140 for (const auto& intersection : intersections(space_.gridPart(), entity)) {
141
142 // if intersection is with boundary, adjust data
143 if (intersection.neighbor() || !intersection.boundary()) {
144 continue;
145 }
146
147 uLocal.bind(entity); // need to bind to intersection.inside()
148 const auto indicator = uLocal.classifyIntersection(intersection);
149 const auto& localMask = indicator.second;
150
151 if (!indicator.first || localMask.none()) {
152 continue;
153 }
154
155 const auto numConstrained = localMask.count();
156
157 // actual number of DoFs
158 const int numDofs = mapper.numDofs(entity);
159
160 // init local stuff
161 blockDofIndices.resize(numDofs, GlobalKeyType(-1));
162 blockDofFaceMask.resize(numDofs, false);
163 uValues.init(entity);
164 wLocal.init(entity);
165
166 // get local -> global mapping
167 space_.blockMapper().map(entity, blockDofIndices);
168
169 // get mask of affected (block)-DoFs
170 // get face number of boundary intersection
171 const int face = intersection.indexInInside();
172 mapper.onSubEntity(entity, face, 1 /* codim */, blockDofFaceMask);
173
174 // call "natural" interpolation for _ALL_ DoFs
175 space_.interpolation(entity)(uLocal, uValues);
176
177 for (int localBlock = 0; localBlock < numDofs; ++localBlock) {
178 if (!blockDofFaceMask[localBlock]) {
179 continue;
180 }
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];
188 }
189 } // block-dof loop
190 } // intersection loop
191 } // mesh-loop
192 } // method
193
194 protected:
195 using BaseType::space_;
196 using BaseType::values_;
197 using BaseType::mask_;
198 using BaseType::sequence_;
199 using BaseType::numConstrained_;
200 ModelType model_;
201 };
202
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
211 )> >
212 : public BulkBlockConstraints<DiscreteFunctionSpace>
213 {
214 typedef DirichletConstraints ThisType;
216 public:
217 typedef typename BaseType::ConstraintsStorageType ConstraintsStorageType;
218 typedef typename BaseType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
219 typedef typename BaseType::GridPartType GridPartType;
220 typedef typename BaseType::EntityType EntityType;
221
222 using IndicatorType = Indicator;
223 typedef BoundaryValues BoundaryValuesFunctionType;
224
226 typedef typename DiscreteFunctionSpaceType::GridType GridType;
227
228 // types for boundary treatment
229 // ----------------------------
230 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
231
232 //typedef typename BlockMapperType::GlobalKeyType GlobalKeyType;
233 typedef std::size_t GlobalKeyType;
234
235 DirichletConstraints(const DiscreteFunctionSpaceType& space,
236 const BoundaryValuesFunctionType& boundaryValues,
237 const IndicatorType& indicator)
238 : BaseType(space)
239 , boundaryValues_(boundaryValues)
240 , indicator_(indicator)
241 {}
242
243 using BaseType::size;
244 using BaseType::jacobian;
245 using BaseType::constrain;
246 using BaseType::zeroConstrain;
247 using BaseType::communicate;
248
249 //using BaseType::operator();
250 // template<class DomainDiscreteFunction, class RangeDiscreteFunction>
251 //void operator()(const DomainDiscreteFunction& arg, RangeDiscreteFunctionType& result) const {
252 //BaseType::operator()(arg, result);
253 //}
254
258 void update() const
259 {
260 if (sequence_ == space_.sequence()) {
261 return;
262 }
263
264 updateBoundaryValues(boundaryValues_(), values_);
265
266 communicate();
267
268 sequence_ = space_.sequence();
269 }
270
271 protected:
272 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
273
275 void updateBoundaryValues(const BoundaryValuesFunctionType& u, ConstraintsStorageType& w) const
276 {
277 const auto& mapper = space_.blockMapper();
278 const int maxNumDofs = mapper.maxNumDofs();
279
280 // resize flag vector with number of blocks and reset flags
281 mask_.resize(mapper.size());
282 std::fill(mask_.begin(), mask_.end(), 0U);
283
284 // pre-allocate local objects
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);
292
293 numConstrained_ = 0;
294 for (const auto& entity : space_) {
295 for (const auto& intersection : intersections(space_.gridPart(), entity)) {
296
297 // if intersection is with boundary, adjust data
298 if (intersection.neighbor() || !intersection.boundary()) {
299 continue;
300 }
301
302 // Check whether this segment belongs to a Dirichlet boundary ...
303 if (!indicator_.applies(intersection)) {
304 continue; // Nope
305 }
306
307 // actual number of DoFs
308 const int numDofs = mapper.numDofs(entity);
309
310 // init local stuff
311 blockDofIndices.resize(numDofs, GlobalKeyType(-1));
312 blockDofFaceMask.resize(numDofs, false);
313 uValues.init(entity);
314 uLocal.init(entity, intersection);
315 wLocal.init(entity);
316
317 // get local -> global mapping
318 space_.blockMapper().map(entity, blockDofIndices);
319
320 // get mask of affected (block)-DoFs
321 // get face number of boundary intersection
322 const int face = intersection.indexInInside();
323 mapper.onSubEntity(entity, face, 1 /* codim */, blockDofFaceMask);
324
325 // call "natural" interpolation for _ALL_ DoFs
326 space_.interpolation(entity)(uLocal, uValues);
327
328 for (int localBlock = 0; localBlock < numDofs; ++localBlock) {
329 if (!blockDofFaceMask[localBlock]) {
330 continue;
331 }
332 if (!mask_[blockDofIndices[localBlock]].any()) {
333 // FIXME: comonent wise
334 mask_[blockDofIndices[localBlock]].set();
335 numConstrained_ += mask_[blockDofIndices[localBlock]].count();
336 }
337 int localDof = localBlock * localBlockSize;
338 for(int l = 0; l < localBlockSize; ++l, ++localDof) {
339 wLocal[localDof] = uValues[localDof];
340 }
341 }
342 } // intersection loop
343 } // mesh-loop
344 } // method
345
346 protected:
347 using BaseType::space_;
348 using BaseType::values_;
349 using BaseType::mask_;
350 using BaseType::sequence_;
351 using BaseType::numConstrained_;
352
353 const BoundaryValuesFunctionType boundaryValues_;
354 const IndicatorType indicator_;
355 };
356
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
363 )> >
364 {
365 public:
366 typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
367 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
368 typedef typename DiscreteFunctionSpaceType::EntityType EntityType;
369 typedef BoundaryValues BoundaryValuesFunctionType;
370 typedef EmptyBoundaryIndicator IndicatorType;
371
372 DirichletConstraints(const DiscreteFunctionSpaceType& space,
373 const BoundaryValuesFunctionType& boundaryValues)
374 {}
375
376 template<class DomainDiscreteFunction, class RangeDiscreteFunction>
377 void operator()(const DomainDiscreteFunction& arg, RangeDiscreteFunction& result) const {}
378
379 template<class DomainDiscreteFunction, class JacobianOperator>
380 void jacobian(const DomainDiscreteFunction& u, JacobianOperator& jOp) const {}
381
382 template<class DomainDiscreteFunction, class JacobianOperator>
383 void applyToOperator(const DomainDiscreteFunction& u, JacobianOperator& jOp) const
384 {}
385
386 template<class DomainDiscreteFunction>
387 void constrain(DomainDiscreteFunction& w) const {}
388
389 template<class DomainDiscreteFunction>
390 void zeroConstrain(DomainDiscreteFunction& w) const {}
391
392 size_t size() const { return 0; }
393 void reset() const {}
394 void update() const {}
395 void updateValues() const {}
396 };
397
399
401
402 } // ACFem::
403
404} // Dune::
405#endif
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
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
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
STL namespace.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 27, 23:30, 2024)