KASKADE 7 development version
fem/hierarchicErrorEstimator.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2/* */
3/* This file is part of the library KASKADE 7 */
4/* https://www.zib.de/research/projects/kaskade7-finite-element-toolbox */
5/* */
6/* Copyright (C) 2002-2016 Zuse Institute Berlin */
7/* */
8/* KASKADE 7 is distributed under the terms of the ZIB Academic License. */
9/* see $KASKADE/academic.txt */
10/* */
11/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
12
13#ifndef HIEARARCHIC_ERROR_ESTIMATOR_HH
14#define HIEARARCHIC_ERROR_ESTIMATOR_HH
15
16#include "fem/variables.hh"
26namespace Kaskade
27{
34 namespace HierarchicErrorEstimatorDetail {
35
45 template <class Functional>
46 struct DefaultD2
47 {
48 template <int row, int col>
49 class D2: public Functional::template D2<row,col>
50 {
51 typedef typename Functional::template D2<row,col> d2;
52
53 public:
54 static bool const present = d2::present && d2::symmetric;
55 static bool const lumped = true;
56 };
57 };
58
59 template <class Functional>
60 struct LumpSymmetricD2
61 {
62 template <int row, int col>
63 class D2: public Functional::template D2<row,col>
64 {
65 public:
66 static constexpr bool lumped = Functional::template D2<row,col>::symmetric;
67 };
68 };
69
79 template <class Functional>
80 struct TakeAllD2
81 {
82 template <int row, int col>
83 class D2: public Functional::template D2<row,col> {};
84 };
85
86
87 } // End of namespace HierarchicErrorEstimatorDetail
88
148 template <class LinearFunctional,
149 class ExtensionAnsatzVariables,
150 class ExtensionTestVariables=ExtensionAnsatzVariables,
151 class D2BlockInfo = HierarchicErrorEstimatorDetail::DefaultD2<LinearFunctional> >
153 {
155 typedef typename LinearFunctional::AnsatzVars FEAnsatzVars;
156 typedef typename ExtensionAnsatzVariables::Grid Grid;
157 typedef typename Grid::template Codim<0>::Entity Cell;
158
159 public:
160 static ProblemType const type = LinearFunctional::type;
161 typedef typename LinearFunctional::Scalar Scalar;
162 typedef ExtensionAnsatzVariables AnsatzVars;
163 typedef ExtensionTestVariables TestVars;
164
165 typedef typename FEAnsatzVars::VariableSet FESolution;
166
170 class DomainCache
171 {
172 public:
173 DomainCache(LinearFunctional const& lf, FESolution const& ul_, int flags):
174 ul(ul_), dc(lf.createDomainCache(flags))
175 {}
176
177 void moveTo(Cell const& e) { dc.moveTo(e); }
178
179 template <class Position, class Evaluators>
180 void evaluateAt(Position const& x, Evaluators const& evaluators)
181 {
182 dc.evaluateAt(x,evaluators);
183 ulEval = evaluateVariables(ul,evaluators,valueMethod);
184 ulGradEval = evaluateVariables(ul,evaluators,derivativeMethod);
185 }
186
187 Scalar d0() const { return dc.d0(); }
188
189 template <int row, int dim>
191 d1(VariationalArg<Scalar,dim> const& arg) const
192 {
194
195 boost::fusion::for_each(typename FEAnsatzVars::Variables(),
196 addLowerOrderD2<row,dim>(dc,ulEval,ulGradEval,arg,result));
197
198 return result;
199 }
200
201 template<int row, int col, int dim>
203 AnsatzVars::template Components<col>::m>
204 d2(VariationalArg<Scalar,dim> const& arg1, VariationalArg<Scalar,dim> const& arg2) const
205 {
206 return dc.template d2<row,col>(arg1,arg2);
207 }
208
209 private:
210 FESolution const& ul;
211 typename LinearFunctional::DomainCache dc;
214
215 template <int row, int dim>
216 struct addLowerOrderD2
217 {
218 addLowerOrderD2(typename LinearFunctional::DomainCache const& dc_,
221 VariationalArg<Scalar,dim> const& arg_,
222 Dune::FieldVector<Scalar,TestVars::template Components<row>::m>& result_):
223 dc(dc_), ulEval(ulEval_), ulGradEval(ulGradEval_), arg(arg_), result(result_)
224 {}
225
226 template <class VarDescription>
227 void operator()(VarDescription const& vd) const {
228 int const col = VarDescription::id;
229 bool const mirror = row<col && LinearFunctional::type==VariationalFunctional;
230 bool const original = row>=col || LinearFunctional::type==WeakFormulation;
231
232
233 // Check whether this block is present in the first
234 // place. Note that it is important to use D2 from
235 // LinearFunctional instead of our own, because for the error
236 // estimation matrix we may deliberately drop blocks!
237 //
238 // If we have a symmetric problem, we only access subdiagonal
239 // blocks and mirror them to the upper triangular part.
240 if (! ( (original && LinearFunctional::template D2<row,col>::present) ||
241 (mirror && LinearFunctional::template D2<col,row>::present) ) )
242 return;
243
244
245 typedef typename SpaceType<typename FEAnsatzVars::Spaces,
246 VarDescription::spaceIndex>::type FEColSpace;
247
249 // Step through components of variable
250 for (int c=0; c<VarDescription::m; ++c) {
251 int off = c*FEColSpace::sfComponents;
252
253 // Fill variational arg with values from that
254 // component. Handle vectorial shape functions correctly.
255 for (int i=0; i<FEColSpace::sfComponents; ++i) {
256 uArg.value[i] = boost::fusion::at_c<col>(ulEval)[off+i];
257
258 for (int j=0; j<dim; ++j)
259 {
260 uArg.derivative[i][j] = boost::fusion::at_c<col>(ulGradEval)[off+i][j];
261 }
262 }
263
264 // Compute local matrix. Note that since we're working
265 // currently on the c-th component, only the c-th column is
266 // used.
267 if (original && LinearFunctional::template D2<row,col>::present) {
269 AnsatzVars::template Components<col>::m>
270 d2 = dc.template d2<row,col>(arg,uArg);
271
272 for (int i=0; i<TestVars::template Components<row>::m; ++i)
273 {
274 result[i] += d2[i][c];
275 }
276 }
277
278 // Apply transposed mirror-blocks if available.
279 if (mirror && LinearFunctional::template D2<col,row>::present) {
281 TestVars::template Components<row>::m>
282 d2 = dc.template d2<col,row>(uArg,arg);
283
284 for (int i=0; i<TestVars::template Components<row>::m; ++i)
285 {
286 result[i] += d2[c][i];
287 }
288 }
289 }
290 }
291
292 private:
293 typename LinearFunctional::DomainCache const& dc;
298 };
299 };
300
301 class BoundaryCache
302 {
303 public:
304 typedef typename Grid::LeafIntersectionIterator FaceIterator;
305
306 BoundaryCache(LinearFunctional const& lf, FESolution const& ul_, int flags):
307 ul(ul_), bc(lf.createBoundaryCache(flags))
308 {}
309
310 void moveTo(FaceIterator const& entity) { bc.moveTo(entity); }
311
312 template <class Evaluators>
313 void evaluateAt(Dune::FieldVector<typename Grid::ctype,Grid::dimension-1> const& x, Evaluators const& evaluators)
314 {
315 bc.evaluateAt(x,evaluators);
316 ulEval = evaluateVariables(ul,evaluators,valueMethod);
317 }
318
319 Scalar d0() const { return bc.d0(); }
320
321 template<int row, int dim>
323 d1 (VariationalArg<Scalar,dim> const& arg) const
324 {
326 boost::fusion::for_each(typename FEAnsatzVars::Variables(),
327 addLowerOrderD2<row,dim>(bc,ulEval,arg,result));
328 return result;
329 }
330
331 template<int row, int col, int dim>
333 d2 (VariationalArg<Scalar,dim> const &arg1, VariationalArg<Scalar,dim> const &arg2) const
334 {
335 return bc.template d2<row,col>(arg1,arg2);
336 }
337
338 private:
339 FESolution const& ul;
340 typename LinearFunctional::BoundaryCache bc;
342
343 template <int row, int dim>
344 struct addLowerOrderD2
345 {
346 addLowerOrderD2(typename LinearFunctional::BoundaryCache const& bc_,
348 VariationalArg<Scalar,dim> const& arg_,
349 Dune::FieldVector<Scalar,TestVars::template Components<row>::m>& result_):
350 bc(bc_), ulEval(ulEval_), arg(arg_), result(result_)
351 {}
352
353 template <class VarDescription>
354 void operator()(VarDescription const& vd) const {
355 int const col = VarDescription::id;
356 bool const mirror = row<col && LinearFunctional::type==VariationalFunctional;
357 bool const original = row>=col || LinearFunctional::type==WeakFormulation;
358
359 // Check whether this block is present in the first
360 // place. Note that it is important to use D2 from
361 // LinearFunctional instead of our own, because for the error
362 // estimation matrix we may deliberately drop blocks!
363 //
364 // If we have a symmetric problem, we only access subdiagonal
365 // blocks and mirror them to the upper triangular part.
366 if (! ( (original && LinearFunctional::template D2<row,col>::present) ||
367 (mirror && LinearFunctional::template D2<col,row>::present) ) )
368 return;
369
370 typedef typename SpaceType<typename FEAnsatzVars::Spaces,
371 VarDescription::spaceIndex>::type FEColSpace;
372
373 VariationalArg<Scalar,dim> uArg;
374 // Step through components of variable
375 for (int c=0; c<VarDescription::m; ++c) {
376 int off = c*FEColSpace::sfComponents;
377
378 // Fill variational arg with values from that
379 // component. Handle vectorial shape functions correctly.
380 for (int i=0; i<FEColSpace::sfComponents; ++i)
381 uArg.value[i] = boost::fusion::at_c<col>(ulEval)[off+i];
382
383 // Compute local matrix. Note that since we're working
384 // currently on the c-th component, only the c-th column is
385 // used.
386 if (original && LinearFunctional::template D2<row,col>::present) {
388 AnsatzVars::template Components<col>::m>
389 d2 = bc.template d2<row,col>(arg,uArg);
390
391 for (int i=0; i<TestVars::template Components<row>::m; ++i)
392 result[i] += d2[i][c];
393 }
394
395 // Apply transposed mirror-blocks if available.
396 if (mirror && LinearFunctional::template D2<col,row>::present) {
398 TestVars::template Components<row>::m>
399 d2 = bc.template d2<col,row>(uArg,arg);
400
401 for (int i=0; i<TestVars::template Components<row>::m; ++i)
402 result[i] += d2[c][i];
403 }
404 }
405 }
406
407 private:
408 typename LinearFunctional::BoundaryCache const& bc;
410 VariationalArg<Scalar,dim> const& arg;
412 };
413 };
414
415 template <int row>
416 struct D1: public LinearFunctional::template D1<row>
417 {};
418
419 template <int row, int col>
420 struct D2: public D2BlockInfo::template D2<row,col> {
421 // Make sure that we only claim availability of blocks we can actually provide...
422 static bool const present = D2BlockInfo::template D2<row,col>::present && LinearFunctional::template D2<row,col>::present;
423 };
424
437 HierarchicErrorEstimator(LinearFunctional const& lf_, FESolution const& ul_): lf(lf_), ul(ul_) {}
438
439
440 DomainCache createDomainCache(int flags) const
441 {
442 return DomainCache(lf,ul,flags);
443 }
444
445 BoundaryCache createBoundaryCache(int flags) const
446 {
447 return BoundaryCache(lf,ul,flags);
448 }
449
450 int integrationOrder(Cell const& cell, int shapeFunctionOrder, bool boundary) const
451 {
452 return lf.integrationOrder(cell,shapeFunctionOrder,boundary);
453 }
454
455
456 private:
457 LinearFunctional lf;
458 FESolution const& ul;
459 };
460
461 //---------------------------------------------------------------------
462
463 template <class ExtensionVariables, class LinearFunctional>
464 HierarchicErrorEstimator<LinearFunctional,ExtensionVariables>
465 hierarchicErrorEstimator(LinearFunctional const& lf, typename LinearFunctional::AnsatzVars::VariableSet const& u)
466 {
468 }
469
470
474} // namespace Kaskade
475#endif
Defines assembly of hierarchically extended problems for defining DLY style error estimators.
HierarchicErrorEstimator(LinearFunctional const &lf_, FESolution const &ul_)
DomainCache createDomainCache(int flags) const
int integrationOrder(Cell const &cell, int shapeFunctionOrder, bool boundary) const
BoundaryCache createBoundaryCache(int flags) const
HierarchicErrorEstimator< LinearFunctional, ExtensionVariables > hierarchicErrorEstimator(LinearFunctional const &lf, typename LinearFunctional::AnsatzVars::VariableSet const &u)
typename boost::fusion::result_of::as_vector< typename boost::fusion::result_of::transform< Spaces, GetEvaluatorTypes >::type >::type Evaluators
the heterogeneous sequence type of Evaluators for the given spaces
ProblemType
A type for describing the nature of a PDE problem.
@ VariationalFunctional
decltype(evaluateVariables(std::declval< VariableSet >(), std::declval< typename VariableSet::Descriptions::Evaluators >(), std::declval< Method >())) EvaluateVariables
The type of evaluated variables as returned by evaluateVariables.
Definition: variables.hh:1008
constexpr auto valueMethod
Helper method for evaluating whole variable sets.
Definition: variables.hh:1018
auto evaluateVariables(VariableSet const &vars, typename VariableSet::Descriptions::Evaluators const &eval, Method const &method=Method())
A function evaulating all functions in a variable set using the provided method.
Definition: variables.hh:988
constexpr auto derivativeMethod
Helper method for evaluating whole variable sets.
Definition: variables.hh:1027
Functional::Scalar d1(Assembler &assembler, Functional const &f, typename Functional::AnsatzVars::VariableSet &x, typename Functional::Scalar tolerance=1e-6, typename Functional::Scalar increment=1e-12, bool toFile=false, std::string const &filename=std::string("d1error"))
Functional::Scalar d2(Assembler &assembler, Functional const &f, typename Functional::AnsatzVars::VariableSet const &x, typename Functional::Scalar increment=1e-12, typename Functional::Scalar tolerance=1e-6, bool toFile=false, std::string const &savefilename=std::string("d2error"))
Helper class for specifying the number of components of a variable.
Definition: variables.hh:100
Extracts the type of FE space with given index from set of spaces.
static int const m
number of component of this variable
Definition: variables.hh:80
A class that stores values, gradients, and Hessians of evaluated shape functions.
Dune::FieldMatrix< Scalar, components, dim > derivative
The shape function's spatial derivative, a components x dim matrix.
ValueType value
The shape function's value, a vector of dimension components
Variables and their descriptions.