DUNE-ACFEM (2.5.1)

bulkblockconstraints.hh
1#ifndef _DUNE_ACFEM_BULK_BLOCKCONSTRAINTS_HH_
2#define _DUNE_ACFEM_BULK_BLOCKCONSTRAINTS_HH_
3
4#include "blockconstraintsoperator.hh"
5#include "../../common/functor.hh"
6#include <dune/fem/misc/mpimanager.hh>
7
8namespace Dune {
9
10 namespace ACFem {
11
20 template<class JacobianOperator, class Traits>
21 class BulkBlockConstraints;
22
23 template<class JacobianOperator, class Traits>
24 class LocalBulkBlockConstraints;
25
26 template<class JacobianOperator>
27 struct BulkBlockConstraintsDefaultTraits
28 : public
29 BlockConstraintsDefaultStorageTraits<
30 BulkBlockConstraints<JacobianOperator,
31 BulkBlockConstraintsDefaultTraits<JacobianOperator> >,
32 LocalBulkBlockConstraints<JacobianOperator,
33 BulkBlockConstraintsDefaultTraits<JacobianOperator> > >
34 {};
35
48 template<class JacobianOperator, class Traits = BulkBlockConstraintsDefaultTraits<JacobianOperator> >
50 : public DifferentiableBlockConstraintsOperatorInterface<JacobianOperator, Traits>
51 {
53 typedef
56 public:
57 typedef Traits TraitsType;
58 typedef typename TraitsType::GlobalOperatorType GlobalOperatorType;
59 typedef JacobianOperator JacobianOperatorType;
60 typedef typename JacobianOperatorType::DomainFunctionType DiscreteFunctionType;
61 typedef typename TraitsType::LocalOperatorType LocalOperatorType;
62
63 typedef typename TraitsType::LocalObjectWrapperType LocalObjectWrapperType;
64 typedef typename TraitsType::LocalObjectType LocalObjectType;
65 typedef typename TraitsType::LocalObjectFactoryType LocalObjectFactoryType;
66 typedef typename TraitsType::LocalObjectStorageType LocalObjectStorageType;
67
68 typedef LocalBulkBlockConstraints<JacobianOperatorType, TraitsType> LocalBaseObjectType;
69
70 friend LocalObjectType; // not necessarily identical to LocalBulkBlockConstraints
71 friend LocalBaseObjectType;
72
73 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
74 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
75 typedef typename DiscreteFunctionSpaceType::EntityType EntityType;
76 protected:
77 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
78 typedef Dune::Fem::SlaveDofs<DiscreteFunctionSpaceType, BlockMapperType> SlaveDofsType;
79 typedef typename SlaveDofsType::SingletonKey SlaveDofsKeyType;
80 typedef Dune::Fem::SingletonList<SlaveDofsKeyType, SlaveDofsType> SlaveDofsProviderType;
81 typedef typename BlockMapperType::GlobalKeyType GlobalKeyType;
82
83 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
84 public:
85
87 BulkBlockConstraints(const DiscreteFunctionType& values, const std::vector<unsigned>& mask)
88 : space_(values.space()),
89 localObjectFactory_(*static_cast<GlobalOperatorType *>(this)),
90 localObjectStorage_(localObjectFactory_),
91 affineOffset_(values),
92 constrainedDofsMask_(mask),
93 slaveDofMask_(space_.blockMapper().size(), false),
94 numSlaveDofs_(space_.slaveDofs().size()-1),
95 numConstrained_(std::count_if(constrainedDofsMask_.begin(), constrainedDofsMask_.end(),
96 [](const unsigned& value) { return value > 0; })),
97 sequence_(space_.sequence())
98 {}
99
101 BulkBlockConstraints(const DiscreteFunctionSpaceType& space)
102 : space_(space),
103 localObjectFactory_(*static_cast<GlobalOperatorType *>(this)),
104 localObjectStorage_(localObjectFactory_),
105 affineOffset_("Constraint Values", space_),
106 constrainedDofsMask_(space_.blockMapper().size(), 0),
107 slaveDofMask_(space_.blockMapper().size(), false),
108 numSlaveDofs_(space_.slaveDofs().size()-1),
109 numConstrained_(0),
110 sequence_(-1)
111 {}
112
118 void rebuild() const
119 {
120 if (sequence_ != space_.sequence()) {
121 rebuildSlaveDofs();
122 }
123
124 constrainedDofsMask_.resize(space_.blockMapper().size(), 0);
125
126 numConstrained_ =
127 std::count_if(constrainedDofsMask_.begin(), constrainedDofsMask_.end(),
128 [](const unsigned& value) { return value > 0; });
129
130 sequence_ = space_.sequence();
131 }
132
133 protected:
134 void rebuildSlaveDofs() const
135 {
136 const auto& slaveDofs = space_.slaveDofs();
137 numSlaveDofs_ = slaveDofs.size() - 1;
138
139 slaveDofMask_.resize(space_.blockMapper().size());
140 slaveDofMask_.clear();
141 for (unsigned i = 0; i < numSlaveDofs_; ++i) {
142 slaveDofMask_[slaveDofs[i]] = true;
143 }
144 }
145
146 bool isSlaveDof(GlobalKeyType index) const
147 {
148 assert(Fem::MPIManager::size() > 1 || numSlaveDofs_ == 0);
149 return numSlaveDofs_ > 0 && slaveDofMask_[index];
150 }
151 public:
163 void operator()(const DiscreteFunctionType &u, DiscreteFunctionType &w) const
164 {
165 BaseType::rebuild(); // Update if out of sequence_ number
166
167 if (size() == 0) {
168 return;
169 }
170
171 auto uIt = u.dbegin();
172 auto wIt = w.dbegin();
173 auto offsetIt = affineOffset_.dbegin();
174 auto maskIt = constrainedDofsMask_.begin();
175 auto maskEnd = constrainedDofsMask_.end();
176 while (maskIt != maskEnd) {
177 if (*maskIt) {
178 for (int l = 0; l < localBlockSize; ++l, ++wIt, ++offsetIt, ++uIt) {
179 *wIt = *uIt - *offsetIt;
180 }
181 } else {
182 for (int l = 0; l < localBlockSize; ++l, ++wIt, ++offsetIt, ++uIt);
183 }
184 ++maskIt;
185 }
186 }
187
194 void jacobian(const DiscreteFunctionType& u, JacobianOperatorType& jOp) const
195 {
196 BaseType::rebuild(); // Update if out of sequence_ number
197
198 if (size() == 0) {
199 return;
200 }
201
202 const auto end = space_.end();
203 for (auto it = space_.begin(); it != end; ++it) {
204 auto localConstraints = localOperator(*it);
205 auto jOpLocal = jOp.localMatrix(*it, *it);
206
207 localConstraints.jacobian(u.localFunction(*it), jOpLocal);
208 }
209
210 jOp.communicate();
211 }
212
224 void constrain(DiscreteFunctionType& w) const
225 {
226 BaseType::rebuild(); // Update if out of sequence_ number
227
228 if (size() == 0) {
229 // nothing to do.
230 return;
231 }
232
233 auto wIt = w.dbegin();
234 auto offsetIt = affineOffset_.dbegin();
235 auto maskIt = constrainedDofsMask_.begin();
236 auto maskEnd = constrainedDofsMask_.end();
237 while (maskIt != maskEnd) {
238 if (*maskIt) {
239 for (int l = 0; l < localBlockSize; ++l, ++wIt, ++offsetIt) {
240 *wIt = *offsetIt;
241 }
242 } else {
243 for (int l = 0; l < localBlockSize; ++l, ++wIt, ++offsetIt);
244 }
245 ++maskIt;
246 }
247 }
248
250 void zeroConstrain(DiscreteFunctionType& w) const
251 {
253
254 if (size() == 0) {
255 return;
256 }
257
258 auto wIt = w.dbegin();
259 auto maskIt = constrainedDofsMask_.begin();
260 auto maskEnd = constrainedDofsMask_.end();
261 while (maskIt != maskEnd) {
262 if (*maskIt) {
263 for (int l = 0; l < localBlockSize; ++l, ++wIt) {
264 *wIt = 0;
265 }
266 } else {
267 for (int l = 0; l < localBlockSize; ++l, ++wIt);
268 }
269 ++maskIt;
270 }
271 }
272
273 size_t size() const {
274 return numConstrained_;
275 }
276
277 LocalOperatorType localOperator(const EntityType& entity) const
278 {
279 return LocalOperatorType(entity, localObjectStorage_);
280 }
281
282 LocalOperatorType localOperator() const
283 {
284 return LocalOperatorType(localObjectStorage_);
285 }
286
287 protected:
288 const DiscreteFunctionSpaceType& space_;
289 mutable LocalObjectFactoryType localObjectFactory_;
290 mutable LocalObjectStorageType localObjectStorage_;
291 mutable DiscreteFunctionType affineOffset_;
292 mutable std::vector<unsigned> constrainedDofsMask_;
293 mutable std::vector<bool> slaveDofMask_;
294 mutable std::size_t numSlaveDofs_;
295 mutable unsigned numConstrained_;
296 mutable int sequence_;
297 };
298
299 template<class JacobianOperator, class Traits>
300 class LocalBulkBlockConstraints
301 {
302 protected:
303 typedef Traits TraitsType;
305 typedef JacobianOperator JacobianOperatorType;
306 typedef typename JacobianOperatorType::RangeFunctionType DiscreteFunctionType;
307 typedef typename DiscreteFunctionType::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
308 typedef typename DiscreteFunctionSpaceType::BlockMapperType BlockMapperType;
309 typedef typename BlockMapperType::GlobalKeyType GlobalKeyType;
310
311 friend typename OperatorType::LocalObjectFactoryType;
312
313 LocalBulkBlockConstraints(const OperatorType& op)
314 : entity_(0),
315 operator_(op),
316 numberOfLocalBlocks_(0),
317 constrainedDofs_(operator_.space_.blockMapper().maxNumDofs()),
318 slaveDofs_(operator_.space_.blockMapper().maxNumDofs())
319 {}
320
321 public:
322 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
323 typedef typename DiscreteFunctionSpaceType::EntityType EntityType;
324
325 enum { localBlockSize = DiscreteFunctionSpaceType::localBlockSize };
326
327 void init(const EntityType& entity)
328 {
329 entity_ = &entity;
330 numberOfLocalBlocks_ = operator_.space_.blockMapper().numDofs(*entity_);
331
332#if 1
333 // ... this way :::
334 operator_.space_.blockMapper().mapEach(
335 *entity_,
336 makeTupleFunctor(ExtractFunctor<std::vector<unsigned>, std::vector<unsigned> >(constrainedDofs_, operator_.constrainedDofsMask_),
337 ExtractFunctor<std::vector<bool>, std::vector<bool> >(slaveDofs_, operator_.slaveDofMask_)));
338#else
339 // ... likewise ...
340 operator_.space_.blockMapper().mapEach(
341 *entity_,
342 makePairFunctor(ExtractFunctor<std::vector<unsigned>, std::vector<unsigned> >(constrainedDofs_, operator_.constrainedDofsMask_),
343 ExtractFunctor<std::vector<bool>, std::vector<bool> >(slaveDofs_, operator_.slaveDofMask_)));
344#endif
345 numConstrained_ = std::count_if(constrainedDofs_.begin(), constrainedDofs_.end(),
346 [](const unsigned& value) { return value > 0; });
347 }
348
349 bool unconstrained() const
350 {
351 return numConstrained_ == 0;
352 }
353
354 bool totallyConstrained() const
355 {
356 return numConstrained_ == numberOfLocalBlocks_;
357 }
358
359 size_t numConstrained() const
360 {
361 return numConstrained_;
362 }
363
364 void operator()(const LocalFunctionType& u, LocalFunctionType& w) const
365 {
366 if (unconstrained()) {
367 return;
368 }
369
370 LocalFunctionType localOffset(operator_.affineOffset_.localFunction(*entity_));
371
372 int localDof = 0;
373 for (int localBlockDof = 0; localBlockDof < numberOfLocalBlocks_; ++localBlockDof) {
374 if (constrainedDofs_[localBlockDof]) {
375 if (slaveDofs_[localBlockDof]) {
376 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
377 w[localDof] = 0;
378 }
379 } else {
380 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
381 w[localDof] = u[localDof] - localOffset[localDof];
382 }
383 }
384 } else {
385 // Do nothing, operation is restricted to masked-out DOFs
386 localDof += localBlockSize;
387 }
388 }
389 }
390
391 template<class LocalMatrix>
392 void jacobian(const LocalFunctionType& u /* unused */, LocalMatrix& jOpLocal) const
393 {
394 if (unconstrained()) {
395 return;
396 }
397
398 int localDof = 0;
399 for (int localBlockDof = 0; localBlockDof < numberOfLocalBlocks_; ++localBlockDof) {
400 unsigned constraintFactor = constrainedDofs_[localBlockDof]; // 0: unconstrained, > 0: number of elements sharing this DOF.
401 if (constraintFactor > 0) {
402 double value = slaveDofs_[localBlockDof] ? 0.0 : 1.0 / (double)constraintFactor;
403 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
404 jOpLocal.clearRow(localDof); // indexed by non-block-DoF
405 jOpLocal.set(localDof, localDof, value);
406 }
407 } else {
408 localDof += localBlockSize;
409 }
410 }
411 }
412
413 void constrain(LocalFunctionType& w) const
414 {
415 if (unconstrained()) {
416 return;
417 }
418
419 LocalFunctionType localOffset(operator_.affineOffset_.localFunction(*entity_));
420
421 int localDof = 0;
422 for (int localBlockDof = 0; localBlockDof < numberOfLocalBlocks_; ++localBlockDof) {
423 if (constrainedDofs_[localBlockDof]) {
424 if (slaveDofs_[localBlockDof]) {
425 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
426 w[localDof] = 0;
427 }
428 } else {
429 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
430 w[localDof] = localOffset[localDof];
431 }
432 }
433 } else {
434 // Do nothing, operation is restricted to masked-out DOFs
435 localDof += localBlockSize;
436 }
437 }
438 }
439
440 void zeroConstrain(LocalFunctionType& w) const
441 {
442 if (unconstrained()) {
443 return;
444 }
445
446 int localDof = 0;
447 for (int localBlockDof = 0; localBlockDof < numberOfLocalBlocks_; ++localBlockDof) {
448 if (constrainedDofs_[localBlockDof]) {
449 for (int l = 0; l < localBlockSize; ++l, ++localDof) {
450 w[localDof] = 0;
451 }
452 } else {
453 // Do nothing, operation is restricted to masked-out DOFs
454 localDof += localBlockSize;
455 }
456 }
457 }
458
459 protected:
460 const EntityType* entity_;
461 const OperatorType& operator_;
462 int numberOfLocalBlocks_;
463 std::vector<unsigned> constrainedDofs_;
464 std::vector<bool> slaveDofs_;
465 int numConstrained_;
466 };
467
469
471
472 } // ACFem::
473
474} // Dune::
475
476
477#endif // _DUNE_ACFEM_EMPTY_BLOCKCONSTRAINTS_HH_
A default implementation for bulk block constraints.
Definition: bulkblockconstraints.hh:51
void operator()(const DiscreteFunctionType &u, DiscreteFunctionType &w) const
Apply the operator to the given argument.
Definition: bulkblockconstraints.hh:163
void zeroConstrain(DiscreteFunctionType &w) const
Unconditionally set the values of all masked DoFs to zero.
Definition: bulkblockconstraints.hh:250
BulkBlockConstraints(const DiscreteFunctionSpaceType &space)
Construct an empty operator.
Definition: bulkblockconstraints.hh:101
BulkBlockConstraints(const DiscreteFunctionType &values, const std::vector< unsigned > &mask)
Explicitly set the constraints to defined values.
Definition: bulkblockconstraints.hh:87
void rebuild() const
An update method which has to be called initially or after mesh-adaptation, or for time-dependent con...
Definition: bulkblockconstraints.hh:118
void constrain(DiscreteFunctionType &w) const
The solution operator; unconditionally install the given constraints into the argument.
Definition: bulkblockconstraints.hh:224
void jacobian(const DiscreteFunctionType &u, JacobianOperatorType &jOp) const
The Jacobian of the operator.
Definition: bulkblockconstraints.hh:194
Interface class for a differentiable block-constraints-operator.
Definition: blockconstraintsoperator.hh:182
void rebuild() const
An update method which has to be called initially or after mesh-adaptation, or for time-dependent con...
Definition: blockconstraintsoperator.hh:98
Define a factory for a "local object" which has a constructor which accepts a single argument,...
Definition: localobjectstorage.hh:21
Local object stack which (hopefully) efficiently caches local objects.
Definition: localobjectstorage.hh:50
TupleFunctor< Types... > makeTupleFunctor(Types &&... args)
Combine several functors into one.
Definition: functor.hh:142
PairFunctor< FunctorOne, FunctorTwo > makePairFunctor(FunctorOne &&func1, FunctorTwo &&func2)
Combine two functors into one.
Definition: functor.hh:87
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Aug 13, 22:30, 2024)