DUNE-ACFEM (unstable)

modeldirichletvalues.hh
1#ifndef __DUNE_ACFEM_FUNCTIONS_MODULES_MODELDIRICHLETVALUES_HH__
2#define __DUNE_ACFEM_FUNCTIONS_MODULES_MODELDIRICHLETVALUES_HH__
3
4#include <dune/fem/function/localfunction/bindable.hh>
5#include "../../models/modelfacade.hh"
6#include "../../models/modelboundaryindicators.hh"
7
8#include "zero.hh"
9
10namespace Dune {
11
12 namespace ACFem {
13
14 namespace GridFunction {
15
27 template<class Model, class GridPart>
29 : public Fem::BindableGridFunction<GridPart, typename ModelTraits<Model>::RangeType>
30 {
31 static_assert(IsPDEModel<Model>::value,
32 "Model better would be a proper PDE-model ...");
33 using BaseType = Fem::BindableGridFunction<GridPart, typename ModelTraits<Model>::RangeType>;
34 public:
35 using GridPartType = GridPart;
36 using ModelType = std::decay_t<Model>;
37 using ModelTraits = ModelIntrospection::Traits<Model>;
38 using typename BaseType::EntityType;
39 using typename BaseType::RangeFieldType;
40 using RealType = typename Dune::FieldTraits<RangeFieldType>::real_type;
41 using typename BaseType::DomainType;
42 using typename BaseType::RangeType;
43 using typename BaseType::JacobianRangeType;
44 using HessianRangeType = typename ModelType::HessianRangeType; // NOT from BaseType
45 static constexpr std::size_t dimRange = ModelType::dimRange;
46 static constexpr std::size_t dimDomain = ModelType::dimDomain;
47 static constexpr std::size_t dirichlet = ModelIntrospection::dirichlet;
48 static constexpr std::size_t linearizedDirichlet = ModelIntrospection::linearizedDirichlet;
49 static constexpr bool precomputeJacobian =
50 ModelTraits::template IsPiecewiseConstant<linearizedDirichlet>::value
51 &&
52 ModelTraits::template IsAffineLinear<dirichlet>::value;
53 using DirichletJacobianRangeType = FieldMatrix<RangeFieldType, dimRange, dimRange>;
54
64 ModelDirichletValues(Model&& model,
65 const GridPartType& gridPart,
66 const std::string& name = "")
67 : BaseType(gridPart)
68 , model_(model)
69 , dirichlet_(model_)
70 , linearizedDirichlet_(model_)
71 , name_(name == "" ? "Dirichlet("+model_.name()+")" : name)
72 , tolerance_(Fem::Parameter::getValue<RealType>("acfem.dirichlet.newton.tolerance", 2.0*std::numeric_limits<RangeFieldType>::epsilon()))
73 , maxIter_(Fem::Parameter::getValue<RealType>("acfem.dirichlet.newton.iterationLimit", 100))
74 {}
75
77 : BaseType(other)
78 , model_(other.model_)
79 , dirichlet_(model_)
80 , linearizedDirichlet_(model_)
81 , name_(other.name_)
82 , tolerance_(other.tolerance_)
83 , maxIter_(other.maxIter_)
84 {}
85
87 : BaseType(other)
88 , model_(std::move(other.model_))
89 , dirichlet_(model_)
90 , linearizedDirichlet_(model_)
91 , name_(std::move(other.name_))
92 , tolerance_(other.tolerance_)
93 , maxIter_(other.maxIter_)
94 {}
95
96 using BaseType::entity;
97 using BaseType::gridPart;
98
99 const std::string& name() const { return name_; }
100
101 // New Bindable interface
102 void bind(const EntityType& entity)
103 {
104 BaseType::bind(entity);
105 model_.bind(BaseType::entity());
106 }
107
108 // New Bindable interface
109 void unbind()
110 {
111 model_.unbind();
112 BaseType::unbind();
113 }
114
116 template<class Intersection>
117 auto classifyIntersection(const Intersection& intersection)
118 {
119 auto supported = model_.classifyBoundary(intersection);
120 if constexpr (precomputeJacobian) {
121 // FIXME: will be wrong when working on a manifold
122 jacobian_ = computeJacobian(RangeType(), quadraturePoint(DomainType()));
123 }
124 return supported;
125 }
126
127 int order() const
128 {
129 return std::numeric_limits<int>::max();
130 }
131
134 template<class Point,
135 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
136 auto evaluate(Point& x) const
137 {
138 /*
139 G(u) = u*|u|^2 - g
140 G'(u)v = 2 (uv) u + |u|^2 v,
141
142 G(u) = alpha u - g
143 G'(u)v = alpha v
144 */
145
146 // Some start value. In case of non-convergence one could try
147 // to modify it ...
148 auto values = RangeType(0.5);
149
150 for (int k = 0; k <= maxIter_; ++k) {
151
152 assert(k < maxIter_); // rather throw or something
153
154 auto G = dirichlet_(x, values);
155
156 RangeType d;
157 if constexpr (precomputeJacobian) {
158 jacobian_.solve(d, G);
159 } else {
160 computeJacobian(values, x).solve(d, G);
161 }
162
163#if 0
164 static_assert(ModelTraits::template IsAffineLinear<dirichlet>::value,
165 "non-linear Dirichlet values");
166#endif
167
168 if constexpr (ModelTraits::template IsAffineLinear<dirichlet>::value) {
169 values -= d;
170 break;
171 }
172
173 if (d.two_norm2() < tolerance_ * tolerance_) {
174 break;
175 }
176
177 values -= d;
178
179 }
180 return values;
181 }
182
184 template<class Point,
185 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
186 void evaluate(const Point& point, RangeType& result) const
187 {
188 result = evaluate(point);
189 }
190
192 template<class Point,
193 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
194 auto jacobian(const Point& x) const
195 {
196#if !__DUNE_ACFEM_MAKE_CHECK__
197 static_assert(sizeof(Point) != 0, "It does not make sense to differentiate Dirichlet values.");
198#endif
199 return JacobianRangeType(0);
200 }
201
203 template<class Point,
204 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
205 void jacobian(const Point& x, JacobianRangeType& result) const
206 {
207#if !__DUNE_ACFEM_MAKE_CHECK__
208 static_assert(sizeof(Point) != 0, "It does not make sense to differentiate Dirichlet values.");
209#endif
210 result = jacobian(x);
211 }
212
213 // hessian of local function
214 template<class Point,
215 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
216 auto hessian(const Point& x) const
217 {
218#if !__DUNE_ACFEM_MAKE_CHECK__
219 static_assert(sizeof(Point) != 0, "It does not make sense to differentiate Dirichlet values.");
220#endif
221 return HessianRangeType(0);
222 }
223
224 // hessian of local function
225 template<class Point,
226 std::enable_if_t<(IsQuadraturePoint<Point>::value || IsFieldVector<Point>::value), int> = 0>
227 void hessian(const Point& x, HessianRangeType& ret) const
228 {
229#if !__DUNE_ACFEM_MAKE_CHECK__
230 static_assert(sizeof(Point) != 0, "It does not make sense to differentiate Dirichlet values.");
231#endif
232 ret = hessian(x);
233 }
234
235 const ModelType& model() const { return model_; }
236 ModelType& model() { return model_; }
237
238 protected:
239 template<class Quadrature>
240 auto computeJacobian(const RangeType& values, const QuadraturePoint<Quadrature>& x) const
241 {
242 DirichletJacobianRangeType jacobian;
243
244 forLoop<dimRange>([&](auto j) {
245 using J = decltype(j);
246 auto ej = kroneckerDelta<J::value>(IndexSequence<dimRange>{});
247 auto tmp = linearizedDirichlet_(values, x, ej);
248 for (unsigned i = 0; i < dimRange; ++i) {
249 jacobian[i][J::value] = tmp[i];
250 }
251 });
252 return jacobian;
253 }
254
255 protected:
256 Model model_;
257 ModelClosureMethod<ModelType, dirichlet> dirichlet_;
258 ModelClosureMethod<ModelType, linearizedDirichlet> linearizedDirichlet_;
259 std::string name_;
260 RealType tolerance_;
261 int maxIter_;
262 DirichletJacobianRangeType jacobian_;
263 };
264
268 template<class Model, class GridPart,
269 std::enable_if_t<EffectiveModelTraits<Model>::template Exists<PDEModel::dirichlet>::value, int> = 0>
270 auto modelDirichletValues(Model&& model,
271 const GridPart& gridPart,
272 const std::string& name = "")
273 {
274 static_assert(IsPDEModel<Model>::value, "Model better would be a proper PDE-model ...");
275 return ModelDirichletValues<Model, GridPart>(std::forward<Model>(model), gridPart, name);
276 }
277
281 template<class Model, class GridPart,
282 std::enable_if_t<!EffectiveModelTraits<Model>::template Exists<PDEModel::dirichlet>::value, int> = 0>
283 auto modelDirichletValues(Model&& model,
284 const GridPart& gridPart,
285 const std::string& name = "")
286 {
287 static_assert(IsPDEModel<Model>::value, "Model better would be a proper PDE-model ...");
288 return GridFunction::zeros<typename std::decay_t<Model>::FunctionSpaceType>(gridPart);
289 }
290
292
294
295 } // NS GridFunction::
296
298
299 } // ACFem::
300
301} // Dune::
302
303#endif // __DUNE_ACFEM_FUNCTIONS_MODULES_MODELDIRICHLETVALUES_HH__
An adapter class which takes any ACFem-PDE model and extracts its Dirichlet values as a BoundarySuppo...
Definition: modeldirichletvalues.hh:30
auto classifyIntersection(const Intersection &intersection)
Bind to the given intersection and classify the components w.r.t.
Definition: modeldirichletvalues.hh:117
auto evaluate(Point &x) const
evaluate local function evaluate local function
Definition: modeldirichletvalues.hh:136
auto jacobian(const Point &x) const
jacobian of local function
Definition: modeldirichletvalues.hh:194
ModelDirichletValues(Model &&model, const GridPartType &gridPart, const std::string &name="")
Extract the Dirichlet values from the given model.
Definition: modeldirichletvalues.hh:64
void evaluate(const Point &point, RangeType &result) const
evaluate local function
Definition: modeldirichletvalues.hh:186
void jacobian(const Point &x, JacobianRangeType &result) const
jacobian of local function
Definition: modeldirichletvalues.hh:205
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
ModelIntrospection::template IsModel< Model > IsPDEModel
std::true_type if Model is derived from ModelBase.
Definition: modeltraits.hh:894
STL namespace.
Definition: quadraturepoint.hh:29
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)