DUNE-ACFEM (unstable)

nitschedirichletmodel.hh
1 #ifndef __DUNE_ACFEM_MODELS_MODULES_NITSCHEDIRICHLETMODEL_HH__
2 #define __DUNE_ACFEM_MODELS_MODULES_NITSCHEDIRICHLETMODEL_HH__
3 
4 #include <dune/fem/function/localfunction/const.hh>
5 
6 #include "../../algorithms/modelparameters.hh"
7 #include "../indicators/boundaryindicator.hh"
8 #include "../modeltraits.hh"
9 #include "../expressions.hh"
10 
11 namespace Dune {
12 
13  namespace ACFem::PDEModel {
14 
15  using namespace Literals;
16 
29  namespace {
30 
31  template<class Model, class Penalty, bool linear, class LinArgs, class Args>
32  class RobinFluxProviderBase;
33 
34  template<class Model, class Penalty, bool linear, std::size_t... LinArgsIdx, std::size_t... ArgsIdx>
35  class RobinFluxProviderBase<Model, Penalty, linear,
36  IndexSequence<LinArgsIdx...>,
37  IndexSequence<ModelIntrospection::pointIndex, ModelIntrospection::normalIndex, ArgsIdx...> >
38  {
39  static constexpr std::size_t pointIndex = ModelIntrospection::pointIndex;
40  static constexpr std::size_t normalIndex = ModelIntrospection::normalIndex;
41  static constexpr std::size_t fluxTag = linear ? ModelIntrospection::linearizedFlux : ModelIntrospection::flux;
42  static constexpr std::size_t robinFluxTag = linear ? ModelIntrospection::linearizedRobinFlux : ModelIntrospection::robinFlux;
43  static constexpr std::size_t dirichletTag = linear ? ModelIntrospection::linearizedDirichlet : ModelIntrospection::dirichlet;
44 
45  RobinFluxProviderBase(const RobinFluxProviderBase&);
46  public:
47  RobinFluxProviderBase(const Model& m, const Penalty& p)
48  : flux_(m), robinFlux_(m), dirichlet_(m), p_(p)
49  {}
50 
51  template<class Quadrature>
52  auto robinMethod(const TupleElement<LinArgsIdx, PDEModel::AllArgs<Model> >&... linArgs,
53  const QuadraturePoint<Quadrature>& x,
54  const typename Model::DomainType& unitOuterNormal,
55  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
56  {
57  auto result = robinFlux_(linArgs..., x, unitOuterNormal, args...);
58  auto dirichlet = dirichlet_(linArgs..., x, args...);
59  const auto flux = flux_(linArgs..., x, args...);
60  const typename Model::RangeFieldType penalty = p_.evaluate(x);
61 
62 #if 0
63  flux.usmv(-1.0, unitOuterNormal, result);
64  result += (dirichlet *= penalty);
65 #else
66  result -= contractInner(flux, unitOuterNormal);
67  result += penalty * dirichlet;
68 #endif
69 
70  return result;
71  }
72 
73  const PDEModel::TaggedModelMethod<Model, fluxTag, SequenceMask<LinArgsIdx..., pointIndex, ArgsIdx...>::value> flux_;
74  const PDEModel::TaggedModelMethod<Model, robinFluxTag, SequenceMask<LinArgsIdx..., pointIndex, normalIndex, ArgsIdx...>::value> robinFlux_;
75  const PDEModel::TaggedModelMethod<Model, dirichletTag, SequenceMask<LinArgsIdx..., pointIndex, ArgsIdx...>::value> dirichlet_;
76  const Penalty& p_;
77  };
78 
79  template<class Model, class Penalty, bool linear, bool enable, class LinArgs, class Args>
80  class RobinFluxProvider;
81 
82  template<class Model, class Penalty, bool linear, class LinArgs, class Args>
83  class RobinFluxProvider<Model, Penalty, linear, false, LinArgs, Args>
84  {
85  public:
86  RobinFluxProvider(const Model& m, const Penalty& p)
87  {}
88  };
89 
90  template<class Model, class Penalty, std::size_t... ArgsIdx>
91  class RobinFluxProvider<Model, Penalty, false, true,
92  IndexSequence<>,
93  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
94  : RobinFluxProviderBase<Model, Penalty, false,
95  IndexSequence<>,
96  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
97  {
98  using BaseType = RobinFluxProviderBase<Model, Penalty, false,
99  IndexSequence<>,
100  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >;
101  using BaseType::robinMethod;
102  public:
103  RobinFluxProvider(const Model& m, const Penalty& p)
104  : BaseType(m, p)
105  {}
106 
107  template<class Quadrature>
108  auto
109  robinFlux(const QuadraturePoint<Quadrature>& x,
110  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
111  {
112  return robinMethod(x, args...);
113  }
114  };
115 
116  template<class Model, class Penalty, std::size_t... LinArgsIdx, std::size_t... ArgsIdx>
117  class RobinFluxProvider<Model, Penalty, true, true,
118  IndexSequence<LinArgsIdx...>,
119  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
120  : RobinFluxProviderBase<Model, Penalty, true,
121  IndexSequence<LinArgsIdx...>,
122  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
123  {
124  using BaseType = RobinFluxProviderBase<Model, Penalty, true,
125  IndexSequence<LinArgsIdx...>,
126  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >;
127  using BaseType::robinMethod;
128  public:
129  RobinFluxProvider(const Model& m, const Penalty& p)
130  : BaseType(m, p)
131  {}
132 
133  template<class Quadrature>
134  auto
135  linearizedRobinFlux(const TupleElement<LinArgsIdx, PDEModel::AllArgs<Model> >&... linArgs,
136  const QuadraturePoint<Quadrature>& x,
137  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
138  {
139  return robinMethod(linArgs..., x, args...);
140  }
141  };
142 
143  template<class Model, std::ptrdiff_t symmetry, bool linear, class LinArgs, class PointArgs, class Args>
144  class SingularFluxProviderBase;
145 
146  template<class Model, std::ptrdiff_t symmetry, bool linear, std::size_t... LinArgsIdx, std::size_t... PointIdx, std::size_t... ArgsIdx>
147  class SingularFluxProviderBase<Model, symmetry, linear,
148  IndexSequence<LinArgsIdx...>,
149  IndexSequence<PointIdx...>,
150  IndexSequence<ModelIntrospection::normalIndex, ArgsIdx...> >
151  {
152  static constexpr std::size_t pointIndex = ModelIntrospection::pointIndex;
153  static constexpr std::size_t normalIndex = ModelIntrospection::normalIndex;
154  static constexpr std::size_t jacobianIndex = ModelIntrospection::jacobianIndex;
155  static constexpr std::size_t fluxTag = linear ? ModelIntrospection::linearizedFlux : ModelIntrospection::flux;
156  static constexpr std::size_t singularFluxTag = linear ? ModelIntrospection::linearizedSingularFlux : ModelIntrospection::singularFlux;
157  static constexpr std::size_t dirichletTag = linear ? ModelIntrospection::linearizedDirichlet : ModelIntrospection::dirichlet;
158 
159  template<class Quadrature>
160  using AllArgs = PDEModel::AllArgs<Model, Quadrature>;
161 
162  protected:
163  SingularFluxProviderBase(const Model& m)
164  : flux_(m), singularFlux_(m), dirichlet_(m)
165  {}
166 
167  template<class Quadrature = PointWrapperQuadrature<typename Model::DomainType> >
168  auto singularFluxMethod(const TupleElement<LinArgsIdx, AllArgs<Quadrature> >&... linArgs,
169  const TupleElement<PointIdx, AllArgs<Quadrature> >&... xArg,
170  const typename Model::DomainType& unitOuterNormal,
171  const TupleElement<ArgsIdx, AllArgs<Quadrature> >&... args) const
172  {
173  using DomainRangeType = typename Model::DomainRangeType;
174  using DomainJacobianRangeType = typename Model::DomainJacobianRangeType;
175 
176  DomainJacobianRangeType result = singularFlux_(linArgs..., xArg..., unitOuterNormal, args...);
177  const auto dirichlet = dirichlet_(linArgs..., xArg..., args...);
178 
179  // we know that the first argument of args... must be the values.
180  DomainJacobianRangeType un;
181 
182  un = outer(dirichlet, unitOuterNormal);
183 
184  result -= flux_(linArgs..., xArg..., DomainRangeType(0), un) * symmetry;
185  if (!ModelTraits<Model>::template IsLinear<fluxTag>::value) {
186  result += flux_(linArgs..., xArg..., DomainRangeType(0), DomainJacobianRangeType(0)) * symmetry;
187  }
188 
189  return result;
190  }
191 
192  const PDEModel::TaggedModelMethod<Model, fluxTag, SequenceMask<LinArgsIdx..., PointIdx..., ArgsIdx...>::value> flux_;
193  const PDEModel::TaggedModelMethod<Model, singularFluxTag, SequenceMask<LinArgsIdx..., PointIdx..., normalIndex, ArgsIdx...>::value> singularFlux_;
194  const PDEModel::TaggedModelMethod<Model, dirichletTag, SequenceMask<LinArgsIdx..., PointIdx..., ArgsIdx...>::value> dirichlet_;
195  };
196 
197  template<class Model, std::ptrdiff_t symmetry, bool linear, bool enable, class LinArgs, class Args>
198  class SingularFluxProvider;
199 
200  template<class Model, std::ptrdiff_t symmetry, bool linear, class LinArgs, class Args>
201  class SingularFluxProvider<Model, symmetry, linear, false, LinArgs, Args>
202  {
203  public:
204  SingularFluxProvider(const Model& m)
205  {}
206  };
207 
208  template<class Model, std::ptrdiff_t symmetry, std::size_t... ArgsIdx>
209  class SingularFluxProvider<Model, symmetry, false, true,
210  IndexSequence<>,
211  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
212  : SingularFluxProviderBase<Model, symmetry, false,
213  IndexSequence<>,
214  IndexSequence<ModelIntrospection::pointIndex>,
215  IndexSequence<ArgsIdx...> >
216  {
217  using BaseType = SingularFluxProviderBase<Model, symmetry, false,
218  IndexSequence<>,
219  IndexSequence<ModelIntrospection::pointIndex>,
220  IndexSequence<ArgsIdx...> >;
221  using BaseType::singularFluxMethod;
222  public:
223  SingularFluxProvider(const Model& m)
224  : BaseType(m)
225  {}
226 
227  template<class Quadrature>
228  auto singularFlux(const QuadraturePoint<Quadrature>& x,
229  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
230  {
231  return BaseType::template singularFluxMethod<Quadrature>(x, args...);
232  }
233  };
234 
235  template<class Model, std::ptrdiff_t symmetry, std::size_t... LinArgsIdx, std::size_t... ArgsIdx>
236  class SingularFluxProvider<Model, symmetry, true, true,
237  IndexSequence<LinArgsIdx...>,
238  IndexSequence<ModelIntrospection::pointIndex, ArgsIdx...> >
239  : SingularFluxProviderBase<Model, symmetry, true,
240  IndexSequence<LinArgsIdx...>,
241  IndexSequence<ModelIntrospection::pointIndex>,
242  IndexSequence<ArgsIdx...> >
243  {
244  using BaseType = SingularFluxProviderBase<Model, symmetry, true,
245  IndexSequence<LinArgsIdx...>,
246  IndexSequence<ModelIntrospection::pointIndex>,
247  IndexSequence<ArgsIdx...> >;
248  using BaseType::singularFluxMethod;
249  public:
250 
251  SingularFluxProvider(const Model& m)
252  : BaseType(m)
253  {}
254 
255  template<class Quadrature>
256  auto linearizedSingularFlux(const TupleElement<LinArgsIdx, PDEModel::AllArgs<Model> >&... linArgs,
257  const QuadraturePoint<Quadrature>& x,
258  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
259  {
260  return BaseType::template singularFluxMethod<Quadrature>(linArgs..., x, args...);
261  }
262  };
263 
264  template<class Model, std::ptrdiff_t symmetry, std::size_t... ArgsIdx>
265  class SingularFluxProvider<Model, symmetry, false, true,
266  IndexSequence<>,
267  IndexSequence<ArgsIdx...> >
268  : SingularFluxProviderBase<Model, symmetry, false,
269  IndexSequence<>,
270  IndexSequence<>,
271  IndexSequence<ArgsIdx...> >
272  {
273  using BaseType = SingularFluxProviderBase<Model, symmetry, false,
274  IndexSequence<>,
275  IndexSequence<>,
276  IndexSequence<ArgsIdx...> >;
277  using BaseType::singularFluxMethod;
278  public:
279  SingularFluxProvider(const Model& m)
280  : BaseType(m)
281  {}
282 
283  auto singularFlux(const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
284  {
285  return singularFluxMethod(args...);
286  }
287  };
288 
289  template<class Model, std::ptrdiff_t symmetry, std::size_t... LinArgsIdx, std::size_t... ArgsIdx>
290  class SingularFluxProvider<Model, symmetry, true, true,
291  IndexSequence<LinArgsIdx...>,
292  IndexSequence<ArgsIdx...> >
293  : SingularFluxProviderBase<Model, symmetry, true,
294  IndexSequence<LinArgsIdx...>,
295  IndexSequence<>,
296  IndexSequence<ArgsIdx...> >
297  {
298  using BaseType = SingularFluxProviderBase<Model, symmetry, true,
299  IndexSequence<LinArgsIdx...>,
300  IndexSequence<>,
301  IndexSequence<ArgsIdx...> >;
302  using BaseType::singularFluxMethod;
303  public:
304 
305  SingularFluxProvider(const Model& m)
306  : BaseType(m)
307  {}
308 
309  auto linearizedSingularFlux(const TupleElement<LinArgsIdx, PDEModel::AllArgs<Model> >&... linArgs,
310  const TupleElement<ArgsIdx, PDEModel::AllArgs<Model> >&... args) const
311  {
312  return singularFluxMethod(linArgs..., args...);
313  }
314  };
315 
316  template<class Model>
317  using NeedRobinFlux = BoolConstant<ModelTraits<Model>::template HasMethod<ModelIntrospection::flux>::value
318  ||
319  ModelTraits<Model>::template HasMethod<ModelIntrospection::robinFlux>::value
320  ||
321  ModelTraits<Model>::template HasMethod<ModelIntrospection::dirichlet>::value>;
322  template<class Model>
323  using NeedLinearizedRobinFlux = BoolConstant<ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedFlux>::value
324  ||
325  ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedRobinFlux>::value
326  ||
327  ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedDirichlet>::value>;
328  template<class Model>
329  using RobinFluxSignature = ModelIntrospection::ArgumentMask<SequenceMask<ModelIntrospection::pointIndex, ModelIntrospection::normalIndex>::value
330  |
331  ModelMethodSignatureClosure<Model, ModelIntrospection::flux>::value
332  |
333  ModelMethodSignatureClosure<Model, ModelIntrospection::robinFlux>::value
334  |
335  ModelMethodSignatureClosure<Model, ModelIntrospection::dirichlet>::value>;
336  template<class Model>
337  using LinearizedRobinFluxSignature = ModelIntrospection::ArgumentMask<SequenceMask<ModelIntrospection::pointIndex, ModelIntrospection::normalIndex>::value
338  |
339  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedFlux>::value
340  |
341  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedRobinFlux>::value
342  |
343  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedDirichlet>::value>;
344 
345  template<class Model, class PenaltyFunction>
346  using RobinFluxMethod = RobinFluxProvider<Model, Fem::ConstLocalFunction<PenaltyFunction>,
347  false, NeedRobinFlux<Model>::value,
348  IndexSequence<>, MaskSequence<RobinFluxSignature<Model>::signature()> >;
349  template<class Model, class PenaltyFunction>
350  using LinearizedRobinFluxMethod = RobinFluxProvider<Model, Fem::ConstLocalFunction<PenaltyFunction>,
351  true, NeedLinearizedRobinFlux<Model>::value,
352  MaskSequence<LinearizedRobinFluxSignature<Model>::linearizationSignature()>,
353  MaskSequence<LinearizedRobinFluxSignature<Model>::signature()> >;
354 
355  template<class Model>
356  using NeedSingularFlux = BoolConstant<ModelTraits<Model>::template HasMethod<ModelIntrospection::flux>::value
357  ||
358  ModelTraits<Model>::template HasMethod<ModelIntrospection::singularFlux>::value
359  ||
360  ModelTraits<Model>::template HasMethod<ModelIntrospection::dirichlet>::value>;
361  template<class Model>
362  using NeedLinearizedSingularFlux = BoolConstant<ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedFlux>::value
363  ||
364  ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedSingularFlux>::value
365  ||
366  ModelTraits<Model>::template HasMethod<ModelIntrospection::linearizedDirichlet>::value>;
367  template<class Model>
368  using SingularFluxSignature = ModelIntrospection::ArgumentMask<SequenceMask<ModelIntrospection::normalIndex>::value
369  |
370  ModelMethodSignatureClosure<Model, ModelIntrospection::flux>::value
371  |
372  ModelMethodSignatureClosure<Model, ModelIntrospection::singularFlux>::value
373  |
374  ModelMethodSignatureClosure<Model, ModelIntrospection::dirichlet>::value>;
375  template<class Model>
376  using LinearizedSingularFluxSignature = ModelIntrospection::ArgumentMask<SequenceMask<ModelIntrospection::normalIndex>::value
377  |
378  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedFlux>::value
379  |
380  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedSingularFlux>::value
381  |
382  ModelMethodSignatureClosure<Model, ModelIntrospection::linearizedDirichlet>::value>;
383 
384  template<class Model, std::ptrdiff_t symmetry>
385  using SingularFluxMethod = SingularFluxProvider<Model, symmetry,
386  false, NeedSingularFlux<Model>::value && symmetry != 0,
387  IndexSequence<>, MaskSequence<SingularFluxSignature<Model>::signature()> >;
388  template<class Model, std::ptrdiff_t symmetry>
389  using LinearizedSingularFluxMethod = SingularFluxProvider<Model, symmetry,
390  true, NeedLinearizedSingularFlux<Model>::value && symmetry != 0,
391  MaskSequence<LinearizedSingularFluxSignature<Model>::linearizationSignature()>,
392  MaskSequence<LinearizedSingularFluxSignature<Model>::signature()> >;
393  }
394 
428  template<class Model, class PenaltyFunction, class Symmetrize = SkeletonSymmetrizeDefault<Model> >
430  : public ModelCrop<Model,
431  PDEModel::robinFlux,
432  PDEModel::linearizedRobinFlux,
433  PDEModel::singularFlux,
434  PDEModel::linearizedSingularFlux,
435  PDEModel::dirichlet,
436  PDEModel::linearizedDirichlet>
437  , public RobinFluxMethod<std::decay_t<Model>, PenaltyFunction>
438  , public LinearizedRobinFluxMethod<std::decay_t<Model>, PenaltyFunction>
439  , public SingularFluxMethod<std::decay_t<Model>, Symmetrize{}>
440  , public LinearizedSingularFluxMethod<std::decay_t<Model>, Symmetrize{}>
441  {
443  using TraitsType = ModelTraits<Model>;
444  using BaseType = ModelCrop<Model,
445  PDEModel::robinFlux,
446  PDEModel::linearizedRobinFlux,
447  PDEModel::singularFlux,
448  PDEModel::linearizedSingularFlux,
449  PDEModel::dirichlet,
450  PDEModel::linearizedDirichlet>;
451  using ModelDecay = std::decay_t<Model>;
452  using PenaltyDecay = std::decay_t<PenaltyFunction>;
453  using LocalPenalty = Fem::ConstLocalFunction<PenaltyDecay>;
454  static constexpr std::ptrdiff_t symmetry = Symmetrize{};
455  using RobinFluxBase = RobinFluxMethod<ModelDecay, PenaltyDecay>;
456  using LinearizedRobinFluxBase = LinearizedRobinFluxMethod<ModelDecay, PenaltyDecay>;
457  using SingularFluxBase = SingularFluxMethod<ModelDecay, symmetry>;
458  using LinearizedSingularFluxBase = LinearizedSingularFluxMethod<ModelDecay, symmetry>;
460 
462  "PenaltyFunction must provide a local function");
463  static_assert(std::is_convertible<typename PenaltyDecay::FunctionSpaceType::RangeFieldType,
464  typename ModelDecay::RangeFieldType>::value,
465  "PenaltyFunction should be convertible to model's RangeFieldType");
466  static_assert(IsSign<Symmetrize>::value,
467  "Symmetrize must be a sign.");
468 
469  public:
470  using ModelType = Model;
471  using typename BaseType::DomainType;
472  using typename BaseType::DomainRangeType;
473  using typename BaseType::DomainJacobianRangeType;
474  using typename BaseType::RangeType;
475  using typename BaseType::BoundaryConditionsType;
476 
477  using BaseType::model;
478 
479  template<class ModelArg, class FunctionArg,
480  std::enable_if_t<(std::is_constructible<BaseType, ModelArg>::value
481  && std::is_constructible<LocalPenalty, FunctionArg>::value
482  ), int> = 0>
483  NitscheDirichletBoundaryModel(ModelArg&& m, FunctionArg&& penalty,
484  const std::string& name = "")
485  : BaseType(m)
486  , RobinFluxBase(model(), localPenalty_)
487  , LinearizedRobinFluxBase(model(), localPenalty_)
488  , SingularFluxBase(model())
489  , LinearizedSingularFluxBase(model())
490  , localPenalty_(std::forward<FunctionArg>(penalty))
491  , name_(name == "" ? "NitscheDirichlet("+model().name()+")" : name)
492  {}
493 
495  : BaseType(other)
496  , RobinFluxBase(model(), localPenalty_)
497  , LinearizedRobinFluxBase(model(), localPenalty_)
498  , SingularFluxBase(model())
499  , LinearizedSingularFluxBase(model())
500  , localPenalty_(other.localPenalty_)
501  , name_(other.name_)
502  {}
503 
505  : BaseType(other)
506  , RobinFluxBase(model(), localPenalty_)
507  , LinearizedRobinFluxBase(model(), localPenalty_)
508  , SingularFluxBase(model())
509  , LinearizedSingularFluxBase(model())
510  , localPenalty_(std::move(other.localPenalty_))
511  , name_(std::move(other.name_))
512  {}
513 
514  std::string name() const
515  {
516  return name_;
517  }
518 
520  template<class Entity>
521  void bind(const Entity& entity)
522  {
523  BaseType::bind(entity);
524  localPenalty_.bind(entity);
525  }
526 
528  void unbind()
529  {
530  localPenalty_.unbind();
531  BaseType::unbind();
532  }
533 
535  template<class Intersection>
536  auto classifyBoundary(const Intersection& intersection)
537  {
538  // The resulting model has only Robin kind boundary conditions.
539  wrappedSupported_ = model().classifyBoundary(intersection);
540  supported_.first = wrappedSupported_.first;
541  return supported_;
542  }
543 
544  protected:
545  LocalPenalty localPenalty_;
546  BoundaryConditionsType wrappedSupported_;
547  BoundaryConditionsType supported_;
548  std::string name_;
549  };
550 
552 
561  template<class Model,
562  class PenaltyFunction,
563  class Symmetrize = SkeletonSymmetrizeDefault<Model>,
564  std::enable_if_t<(IsProperPDEModel<Model>::value
566  && !Expressions::IsPromotedTopLevel<PenaltyFunction>::value
569  ), int> = 0>
570  auto nitscheDirichletModel(const Model& m, const PenaltyFunction& p, Symmetrize = Symmetrize{})
571  {
572  return expressionClosure(
573  NitscheDirichletBoundaryModel<Model, PenaltyFunction, Symmetrize>(
574  m, p
575  )
576  );
577  }
578 
583  template<class Model,
584  class GridPart,
585  class Param = decltype(ModelParameters::nitscheDirichletPenalty()),
586  class Symmetrize = SkeletonSymmetrizeDefault<Model>,
587  std::enable_if_t<(IsPDEModel<Model>::value
588  && ModelMethodExists<Model, ModelIntrospection::dirichlet>::value
589  && IsTensor<Param>::value
590  && IsSign<Symmetrize>::value
591  ), int> = 0>
593  Model&& m,
594  const GridPart& gridPart,
595  Param&& p = ModelParameters::nitscheDirichletPenalty(),
596  Symmetrize = Symmetrize{})
597  {
598  return nitscheDirichletModel(std::forward<Model>(m), std::forward<Param>(p) * meshPenalty(gridPart), Symmetrize{});
599  }
600 
605  template<class Model, class... T,
606  std::enable_if_t<(IsProperPDEModel<Model>::value
607  && !ModelMethodExists<Model, ModelIntrospection::dirichlet>::value
608  ), int> = 0>
609  constexpr auto nitscheDirichletModel(Model&& m, T&&...)
610  {
611  return expressionClosure(std::forward<Model>(m));
612  }
613 
617  template<class GridFunction,
618  class Param,
619  class Indicator = EntireBoundaryIndicator,
620  class Symmetrize = Sign<1>,
623  && IsTensor<Param>::value
625  ), int> = 0>
626  auto
627  nitscheDirichletModel(GridFunction&& values,
628  Param&& p = ModelParameters::nitscheDirichletPenalty(),
629  Indicator&& where = Indicator(),
630  Symmetrize = Symmetrize{})
631  {
632  return nitscheDirichletModel(
633  dirichletBoundaryModel(std::forward<GridFunction>(values), std::forward<Indicator>(where)),
634  std::forward<Param>(p) * meshPenalty(values.gridPart()),
635  Symmetrize{});
636  }
637 
639 
641 
643 
644  } // namespace ACFem::PDEModel
645 
646  namespace ACFem {
647 
649 
650  template<class Model, class PenaltyFunction, class Symmetrize>
651  struct ExpressionTraits<PDEModel::NitscheDirichletBoundaryModel<Model, PenaltyFunction, Symmetrize> >
652  : ExpressionTraits<Model>
653  {
654  using ExpressionType = PDEModel::NitscheDirichletBoundaryModel<Model, PenaltyFunction, Symmetrize>;
655  using Definiteness = typename ExpressionTraits<Model>::Definiteness;
656  static constexpr bool isSymmetric = ExpressionTraits<Model>::isSymmetric && (Symmetrize{} == 1_f);
657  };
658 
659  }
660 
661 } //Namespace Dune
662 
663 #endif // __DUNE_ACFEM_MODELS_MODULES_NITSCHEDIRICHLETMODEL_HH__
This model constructs from a given other model weak Dirichlet conditions as first introduced by .
Definition: nitschedirichletmodel.hh:441
constexpr decltype(auto) expressionClosure(T &&t)
Do-nothing default implementation for pathologic cases.
Definition: interface.hh:93
decltype(operate(std::declval< OptOrF >(), std::declval< Rest >()...)) ExpressionType
Generate the type of an expression by calling operate().
Definition: optimizationbase.hh:256
std::is_base_of< Tag, std::decay_t< A > > HasTag
Evaluate to std::true_type if std::decay_t<A> is derived from Tag, otherwise to std::false_type.
Definition: tags.hh:176
auto meshPenalty(const GridPart &gridPart)
Create a penalty function diverging with the inverse element diameter towards infinity.
Definition: meshpenalty.hh:21
void bind(const Entity &entity)
Unbind from the previously bound entity.
Definition: nitschedirichletmodel.hh:521
constexpr auto dirichletBoundaryModel(T &&values, Indicator &&where, const std::string &name="")
Generate the zero model for the empty indicator.
Definition: dirichletmodel.hh:237
auto nitscheDirichletModel(GridFunction &&values, Param &&p=ModelParameters::nitscheDirichletPenalty(), Indicator &&where=Indicator(), Symmetrize=Symmetrize{})
Create a model supplying weak Dirichet conditions from a given grid-function.
Definition: nitschedirichletmodel.hh:627
void unbind()
Unbind from the previously bound entity.
Definition: nitschedirichletmodel.hh:528
auto classifyBoundary(const Intersection &intersection)
Bind to the given intersection and classify the components w.r.t.
Definition: nitschedirichletmodel.hh:536
std::tuple_element_t< N, std::decay_t< TupleLike > > TupleElement
Forward to std::tuple_element<N, std::decay_t<T> >
Definition: access.hh:125
IndexConstant< SequenceMaskHelper< I... >::value > SequenceMask
Generate a bit-mask from the given index-sequence.
Definition: mask.hh:78
auto outer(T1 &&t1, T2 &&t2)
Outer tensor product.
Definition: expressions.hh:138
constexpr auto contractInner(T1 &&t1, T2 &&t2, IndexConstant< N >=IndexConstant< N >{})
Contraction over the #N inner dimensions.
Definition: expressions.hh:118
Sequence< std::size_t, V... > IndexSequence
Sequence of std::size_t values.
Definition: types.hh:64
typename ModelTraits< Model >::template Exists< ModelIntrospection::CheckMethodTag< tag >::value > ModelMethodExists
Check for either non-linear or linearized method.
Definition: modeltraits.hh:906
BoundaryIndicator::Constant< true > EntireBoundaryIndicator
A boundary indicator applying to all parts of the boundary.
Definition: boundaryindicator.hh:376
ModelIntrospection::Traits< Model > ModelTraits
Traits class for models.
Definition: modeltraits.hh:898
TrueType if T is a BoundaryIndicator.
Definition: boundaryindicator.hh:49
A structure defining some basic default types and methods.
Definition: modelbase.hh:41
Definition: fractionconstant.hh:173
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)