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 
12 namespace 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 
112  void updateBoundaryValues() const
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 29, 22:29, 2024)