1#ifndef __ELLIPTIC_ESTIMATOR_HH__
2#define __ELLIPTIC_ESTIMATOR_HH__
5#include <dune/fem/quadrature/caching/twistutility.hh>
6#include <dune/fem/quadrature/cachingquadrature.hh>
7#include <dune/fem/quadrature/intersectionquadrature.hh>
8#include <dune/fem/operator/common/spaceoperatorif.hh>
9#include <dune/fem/operator/matrix/blockmatrix.hh>
10#include <dune/fem/space/discontinuousgalerkin.hh>
13#include "../estimators/estimatorinterface.hh"
14#include "../models/modelinterface.hh"
15#include "../common/geometry.hh"
16#include "../common/intersectiondatahandle.hh"
34 template<
class DiscreteFunctionSpace,
class Model, enum FunctionSpaceNorm Norm = H1Norm>
36 :
public DefaultEstimator<EllipticEstimator<DiscreteFunctionSpace, Model, Norm> >
39 typedef DefaultEstimator<ThisType> BaseType;
42 typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
43 typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType;
44 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
45 typedef typename GridPartType::GridType GridType;
46 typedef typename GridType::template Codim<0>::Entity ElementType;
48 typedef std::vector<RangeFieldType> ErrorIndicatorType;
50 typedef typename ErrorIndicatorType::const_iterator IteratorType;
56 typedef typename ModelType::OperatorPartsType OperatorPartsType;
58 typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
59 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
60 typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
61 typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
65 typedef typename BulkForcesFunctionType::LocalFunctionType BulkForcesLocalFunctionType;
67 typedef typename DirichletFunctionType::LocalFunctionType DirichletLocalFunctionType;
69 typedef typename NeumannFunctionType::LocalFunctionType NeumannLocalFunctionType;
76 typedef typename DiscreteFunctionSpaceType::IteratorType GridIteratorType;
77 typedef typename GridPartType::IndexSetType IndexSetType;
78 typedef typename IndexSetType::IndexType IndexType;
79 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
81 typedef typename IntersectionIteratorType::Intersection IntersectionType;
83 typedef typename ElementType::Geometry GeometryType;
84 static const int dimension = GridType::dimension;
86 typedef Dune::Fem::CachingQuadrature<GridPartType, 0> ElementQuadratureType;
87 typedef Dune::Fem::CachingQuadrature<GridPartType, 1> FaceQuadratureType;
92 typedef Dune::FieldMatrix<DomainFieldType,dimension,dimension> JacobianInverseType;
96 OperatorPartsType operatorParts_;
97 OperatorPartsType operatorPartsNeighbour_;
99 const DiscreteFunctionSpaceType &dfSpace_;
100 GridPartType &gridPart_;
101 const IndexSetType &indexSet_;
105 BulkForcesFunctionType bulkForcesFunction_;
106 NeumannFunctionType neumannFunction_;
107 NeumannIndicatorType neumannBndry_;
108 DirichletIndicatorType dirichletBndry_;
109 ErrorIndicatorType localIndicators_;
110 mutable std::vector<JacobianRangeType> outsideFaceFluxCache;
120 enum { bulk, jump, bdry, comm, numContributions };
121 RangeFieldType errorMin[numContributions];
122 RangeFieldType errorMax[numContributions];
134 typedef RangeType DataItemType;
135 typedef std::vector<DataItemType> IntersectionStorageType;
136 typedef std::map<IndexType, IntersectionStorageType> CommunicationStorageType;
137 typedef typename Fem::DFCommunicationOperation::Add OperationType;
147 class LocalIntersectionStorage
149 typedef std::vector<RangeFieldType> WeightStorageType;
151 LocalIntersectionStorage()
153 LocalIntersectionStorage(IndexType bulkEntityIndex,
size_t nop)
154 : bulkEntityIndex_(bulkEntityIndex), weights_(nop), h_(0)
156 IndexType bulkEntityIndex()
const {
return bulkEntityIndex_; }
157 IndexType& bulkEntityIndex() {
return bulkEntityIndex_; }
158 const RangeFieldType& operator[](
size_t idx)
const {
return weights_[idx]; }
159 RangeFieldType& operator[](
size_t idx) {
return weights_[idx]; }
160 size_t size()
const {
return weights_.size(); }
161 RangeFieldType&
hEstimate() {
return h_; }
162 const RangeFieldType&
hEstimate()
const {
return h_; }
164 IndexType bulkEntityIndex_;
165 WeightStorageType weights_;
168 typedef std::map<IndexType, LocalIntersectionStorage> LocalStorageType;
170 LocalStorageType localJumpStorage_;
171 CommunicationStorageType commJumpStorage_;
181 gridPart_(dfSpace_.gridPart()),
182 indexSet_(gridPart_.indexSet()),
183 grid_(gridPart_.grid()),
189 localIndicators_.resize(indexSet_.size(0));
193 template<
class DiscreteFunctionType>
194 RangeFieldType
estimate(
const DiscreteFunctionType& uh)
201 RangeFieldType hMax = 0.0;
204 const GridIteratorType end = dfSpace_.end();
205 for (GridIteratorType it = dfSpace_.begin(); it != end; ++it) {
213 RangeFieldType error = 0.0;
216 const IteratorType endEstimator = localIndicators_.end();
217 for (IteratorType it = localIndicators_.begin(); it != endEstimator; ++it) {
222 error = grid_.comm().sum(error);
224 grid_.comm().max(errorMax, numContributions);
225 grid_.comm().min(errorMin, numContributions);
227 if (Dune::Fem::Parameter::verbose()) {
229 std::cout <<
"Estimated " << (Norm == L2Norm ?
"L2" :
"H1") <<
"-Error: "
230 << std::sqrt(error) <<
" (squared: " << error <<
")" << std::endl;
231 const char *errorNames[numContributions] = {
"bulk",
"jump",
"bdry",
"comm" };
232 for (
int i = 0; i < numContributions; ++i) {
233 if (errorMax[i] == 0.0) {
236 std::cout <<
" " << errorNames[i] <<
"^2 min: " << errorMin[i] << std::endl;
237 std::cout <<
" " << errorNames[i] <<
"^2 max: " << errorMax[i] << std::endl;
239 std::cout <<
"hMax: " << hMax << std::endl;
241 return std::sqrt(error);
244 const RangeFieldType& operator[](
const size_t& idx)
const
246 return localIndicators_[idx];
249 const RangeFieldType& operator[](
const ElementType& entity)
const
251 return (*
this)[indexSet_.index(entity)];
256 return indexSet_.size(0);
259 IteratorType begin()
const {
260 return localIndicators_.begin();
263 IteratorType end()
const {
264 return localIndicators_.end();
267 GridType& grid()
const
272 const DiscreteFunctionSpaceType& space()
const
281 localIndicators_.resize(indexSet_.size(0));
282 const typename ErrorIndicatorType::iterator end = localIndicators_.end();
283 for (
typename ErrorIndicatorType::iterator it = localIndicators_.begin();
289 localJumpStorage_.clear();
290 commJumpStorage_.clear();
301 errorMax[comm] = 0.0;
305 template<
class DiscreteFunctionType>
306 void estimateLocal(
const ElementType &entity,
const DiscreteFunctionType& uh)
308 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
310 const typename ElementType::Geometry &geometry = entity.geometry();
311 const RangeFieldType h2 =
h2Estimate(geometry);
312 const RangeFieldType hFactor = Norm == L2Norm ? h2*h2 : h2;
313 const int index = indexSet_.index(entity);
314 const LocalFunctionType uLocal = uh.localFunction(entity);
315 const BulkForcesLocalFunctionType fLocal = bulkForcesFunction_.localFunction(entity);
317 ElementQuadratureType quad(entity, 2*(dfSpace_.order() + 1));
319 operatorParts_.setEntity(entity);
321 RangeFieldType localEstimate = 0.0;
322 const int numQuadraturePoints = quad.nop();
323 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
325 const typename ElementQuadratureType :: CoordinateType &x = quad.point(qp);
326 const RangeFieldType weight = quad.weight(qp) * geometry.integrationElement(x);
328 typename LocalFunctionType::RangeType values;
329 uLocal.evaluate(x, values);
331 typename LocalFunctionType::JacobianRangeType jacobian;
332 uLocal.jacobian(x, jacobian);
334 typename LocalFunctionType::HessianRangeType hessian;
335 uLocal.hessian(x, hessian);
338 RangeType el_res(0.);
339 if (Constituents::hasFlux) {
341 operatorParts_.fluxDivergence(entity, quad[qp], values, jacobian, hessian, tmp);
344 if (Constituents::hasSources) {
346 operatorParts_.source(entity, quad[qp], values, jacobian, tmp);
349 if (Constituents::hasBulkForces) {
351 fLocal.evaluate(x, tmp);
355 localEstimate += hFactor * weight * (el_res * el_res);
357 localIndicators_[index] += localEstimate;
359 errorMin[bulk] = std::min(errorMin[bulk], localEstimate);
360 errorMax[bulk] =
std::max(errorMax[bulk], localEstimate);
363 IntersectionIteratorType end = gridPart_.iend(entity);
364 for (IntersectionIteratorType it = gridPart_.ibegin(entity); it != end; ++it) {
366 const IntersectionType &intersection = *it;
371 }
else if (intersection.neighbor()) {
374 }
else if (intersection.boundary() && !dirichletBndry_.applies(intersection)) {
376 bool isRobin = operatorParts_.setIntersection(intersection);
379 neumannBndry_.applies(intersection),
386 template<
class DiscreteFunctionType>
388 const ElementType &inside,
389 const DiscreteFunctionType& uh,
390 const typename DiscreteFunctionType::LocalFunctionType &uInside)
392 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
395 const auto outside = intersection.outside();
397 const int insideIndex = indexSet_.index(inside);
398 const int outsideIndex = indexSet_.index(outside);
400 const bool isOutsideInterior = (outside.partitionType() == Dune::InteriorEntity);
401 if (!isOutsideInterior || (insideIndex < outsideIndex)) {
402 const LocalFunctionType uOutside = uh.localFunction(outside);
404 RangeFieldType error;
406 if (intersection.conforming())
407 error = estimateIntersection<true>(intersection, inside, uInside, outside, uOutside);
409 error = estimateIntersection<false>(intersection, inside, uInside, outside, uOutside);
412 const RangeFieldType h = 0.5 * (
hEstimate(inside.geometry()) +
hEstimate(outside.geometry()));
413 const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
415 localIndicators_[insideIndex] += error;
416 if (isOutsideInterior) {
417 localIndicators_[outsideIndex] += error;
421 errorMin[jump] = std::min(errorMin[jump], error);
422 errorMax[jump] =
std::max(errorMax[jump], error);
434 template<
bool conforming,
class LocalFunctionType>
436 const ElementType &inside,
437 const LocalFunctionType &uInside,
438 const ElementType &outside,
439 const LocalFunctionType &uOutside)
const
442 assert(intersection.conforming() == conforming);
445 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
446 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
448 const int quadOrder = 2 * (dfSpace_.order() - 1);
450 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
453 const Quadrature &quadInside = intersectionQuad.inside();
454 const Quadrature &quadOutside = intersectionQuad.outside();
456 const int numQuadraturePoints = quadInside.nop();
458 operatorPartsNeighbour_.setEntity(outside);
459 RangeFieldType error = 0.0;
460 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
461 DomainType integrationNormal
462 = intersection.integrationOuterNormal(quadInside.localPoint(qp));
463 const RangeFieldType integrationElement = integrationNormal.two_norm();
469 RangeType valueInside, valueOutside;
470 JacobianRangeType jacobianInside, jacobianOutside;
471 JacobianRangeType fluxInside, fluxOutside;
472 uInside.evaluate(quadInside[qp], valueInside);
473 uInside.jacobian(quadInside[qp], jacobianInside);
474 operatorParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
476 uOutside.evaluate(quadOutside[qp], valueOutside);
477 uOutside.jacobian(quadOutside[qp], jacobianOutside);
478 operatorPartsNeighbour_.flux(outside, quadOutside[qp], valueOutside, jacobianOutside,
482 JacobianRangeType& fluxJump(fluxInside);
483 fluxJump -= fluxOutside;
487 fluxJump.mv(integrationNormal, jump);
489 error += quadInside.weight(qp) * (jump * jump) / integrationElement;
499 if (commJumpStorage_.size() == 0) {
504 const bool verbose = Dune::Fem::Parameter::getValue<int>(
"fem.verboserank", -1) != -1;
508 gridPart_.communicate(dataHandle,
509 InteriorBorder_InteriorBorder_Interface,
510 ForwardCommunication);
516 auto commEnd = commJumpStorage_.end();
517 auto commIt = commJumpStorage_.begin();
518 auto localIt = localJumpStorage_.begin();
520 while (commIt != commEnd) {
521 assert(commIt->first == localIt->first);
523 const LocalIntersectionStorage& localData = localIt->second;
524 const IntersectionStorageType& commData = commIt->second;
526 const size_t numQuadraturePoints = localData.size();
527 assert(numQuadraturePoints+1 == commData.size());
530 RangeFieldType error = 0.0;
531 for (
unsigned qp = 0; qp < numQuadraturePoints; ++qp) {
532 error += localData[qp] * (commData[qp] * commData[qp]);
539 RangeFieldType h = 0.5 * commData[numQuadraturePoints][0];
540 RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
544 localIndicators_[localData.bulkEntityIndex()] += error;
546 errorMin[comm] = std::min(errorMin[comm], error);
547 errorMax[comm] =
std::max(errorMax[comm], error);
553 assert(localIt == localJumpStorage_.end());
556 size_t nFaces = commJumpStorage_.size();
557 nFaces = grid_.comm().sum(nFaces);
559 if (Dune::Fem::Parameter::verbose()) {
560 dwarn <<
"*** Processor Boundaries: "
561 << (RangeFieldType)nFaces/2.0
562 <<
" Faces ***" << std::endl;
579 template<
class LocalFunctionType>
581 const ElementType &inside,
582 const LocalFunctionType &uInside)
584 if (intersection.conforming()) {
585 estimateProcessorBoundary<true>(intersection, inside, uInside);
587 estimateProcessorBoundary<false>(intersection, inside, uInside);
595 template<
bool conforming,
class LocalFunctionType>
597 const ElementType &inside,
598 const LocalFunctionType &uInside)
601 assert(intersection.conforming() == conforming);
604 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
605 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
607 const int quadOrder = 2 * (dfSpace_.order() - 1);
609 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
612 const Quadrature &quadInside = intersectionQuad.inside();
613 const int numQuadraturePoints = quadInside.nop();
616 IndexType faceIndex = indexSet_.index(inside.template subEntity<1>(intersection.indexInInside()));
617 IndexType bulkIndex = indexSet_.index(inside);
623 IntersectionStorageType commData = IntersectionStorageType(numQuadraturePoints+1);
624 LocalIntersectionStorage localData = LocalIntersectionStorage(bulkIndex, numQuadraturePoints);
626 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
627 DomainType integrationNormal
628 = intersection.integrationOuterNormal(quadInside.localPoint(qp));
629 const RangeFieldType integrationElement = integrationNormal.two_norm();
630 integrationNormal /= integrationElement;
636 RangeType valueInside;
637 JacobianRangeType jacobianInside;
638 JacobianRangeType fluxInside;
639 uInside.evaluate(quadInside[qp], valueInside);
640 uInside.jacobian(quadInside[qp], jacobianInside);
641 operatorParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
645 fluxInside.mv(integrationNormal, commData[qp]);
648 localData[qp] = quadInside.weight(qp) * integrationElement;
650 localData.hEstimate() =
hEstimate(inside.geometry());
652 commData[numQuadraturePoints][0] = localData.hEstimate();
654 commJumpStorage_[faceIndex] = commData;
655 localJumpStorage_[faceIndex] = localData;
665 template<
class LocalFunctionType>
667 const ElementType &inside,
668 const LocalFunctionType &uLocal,
669 bool isNeumann,
bool isRobin)
671 assert(intersection.conforming() ==
true);
673 if (!isNeumann && !isRobin) {
678 const NeumannLocalFunctionType neumannLocal = neumannFunction_.localFunction(inside, intersection);
680 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType,
true > IntersectionQuadratureType;
681 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
685 int quadOrder = isRobin ? 2*dfSpace_.order() : 2*(dfSpace_.order() - 1);
688 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
690 const Quadrature &bndryQuad = intersectionQuad.inside();
691 const int numQuadraturePoints = bndryQuad.nop();
693 RangeFieldType error = 0.0;
695 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
696 const RangeFieldType weight = bndryQuad.weight(qp);
699 DomainType integrationNormal
700 = intersection.integrationOuterNormal(bndryQuad.localPoint(qp));
702 const RangeFieldType integrationElement = integrationNormal.two_norm();
703 integrationNormal /= integrationElement;
706 uLocal.evaluate(bndryQuad[qp], value);
707 JacobianRangeType jacobian;
708 uLocal.jacobian(bndryQuad[qp], jacobian);
710 JacobianRangeType flux;
711 operatorParts_.flux(inside, bndryQuad[qp], value, jacobian, flux);
714 flux.mv(integrationNormal, residual);
718 operatorParts_.robinFlux(intersection, bndryQuad[qp], integrationNormal, value, alphau);
724 neumannLocal.evaluate(bndryQuad[qp], gN);
728 error += weight * integrationElement * (residual * residual);
733 const int insideIndex = indexSet_.index(inside);
735 const RangeFieldType volume = inside.geometry().volume();
737 const RangeFieldType h = (dimension == 1 ? volume : std::pow(volume, 1.0 / (RangeFieldType)dimension));
738 const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
740 localIndicators_[insideIndex] += error;
743 errorMin[bdry] = std::min(errorMin[bdry], error);
744 errorMax[bdry] =
std::max(errorMax[bdry], error);
748 template<
class DiscreteFunctionSpace,
class Model, enum FunctionSpaceNorm Norm>
749 struct EstimatorTraits<EllipticEstimator<DiscreteFunctionSpace, Model, Norm> >
751 typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
753 std::vector<typename DiscreteFunctionSpaceType::RangeFieldType>::const_iterator
An standard residual estimator for elliptic problems.
Definition: ellipticestimator.hh:37
void estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const DiscreteFunctionType &uh, const typename DiscreteFunctionType::LocalFunctionType &uInside)
caclulate error on element boundary intersections
Definition: ellipticestimator.hh:387
RangeFieldType estimate(const DiscreteFunctionType &uh)
calculate estimator
Definition: ellipticestimator.hh:194
void estimateProcessorBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Compute the jump contribution to the estimator on process-boundaries.
Definition: ellipticestimator.hh:580
void estimateBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uLocal, bool isNeumann, bool isRobin)
calculate error over a boundary segment; yields zero for Dirichlet boundary values,...
Definition: ellipticestimator.hh:666
RangeFieldType estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside, const ElementType &outside, const LocalFunctionType &uOutside) const
caclulate error on element intersections
Definition: ellipticestimator.hh:435
void communicateJumpContributions()
Helper function in order to add the jump contributions on inter-process boundaries.
Definition: ellipticestimator.hh:497
void estimateLocal(const ElementType &entity, const DiscreteFunctionType &uh)
caclulate error on element
Definition: ellipticestimator.hh:306
void estimateProcessorBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Helper function for estimateProcessorBoundary() in order to distinguish between conforming and non-co...
Definition: ellipticestimator.hh:596
General intersection - intersection communication which communicates for each intersection a potentia...
Definition: intersectiondatahandle.hh:48
Interface class for second order elliptic models.
Definition: modelinterface.hh:192
NeumannBoundaryFunctionType neumannBoundaryFunction(const GridPartType &gridPart) const
Generate an instance of a class defining Neumann boundary values as a Fem grid-function.
Definition: modelinterface.hh:302
OperatorPartsType operatorParts() const
Return the integral kernels for the bilinear form.
Definition: modelinterface.hh:253
DirichletIndicatorType dirichletIndicator() const
Generate an object to identify parts of the boundary subject to Dirichlet boundary conditions.
Definition: modelinterface.hh:310
BulkForcesFunctionType bulkForcesFunction(const GridPartType &gridPart) const
Generate an instance of a class defining the bulk-forces the model is subject to.
Definition: modelinterface.hh:263
TraitsType::DirichletBoundaryFunctionType DirichletBoundaryFunctionType
A BoundarySupportedFunction which must be sub-ordinate to the DirichletIndicatorType.
Definition: modelinterface.hh:241
TraitsType::DirichletIndicatorType DirichletIndicatorType
A BoundarySupportedFunction which must be sub-ordinate to the DirichletIndicatorType.
Definition: modelinterface.hh:243
TraitsType::BulkForcesFunctionType BulkForcesFunctionType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:226
TraitsType::NeumannBoundaryFunctionType NeumannBoundaryFunctionType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:227
TraitsType::NeumannIndicatorType NeumannIndicatorType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:228
NeumannIndicatorType neumannIndicator() const
Generate an object to identify parts of the boundary subject to Neumann boundary conditions.
Definition: modelinterface.hh:318
bool isProcessorBoundary(const Intersection &intersection)
Retrun true if at the border to another computing note.
Definition: boundaryindicator.hh:134
Geometry::ctype h2Estimate(const Geometry &geometry)
Compute a rough estimate of the square of the diameter of the element's Geometry.
Definition: geometry.hh:18
Geometry::ctype hEstimate(const Geometry &geometry)
Compute a rough estimate of the diameter of the element's Geometry.
Definition: geometry.hh:39
LocalFunctionWrapper< LocalMaxAdapter< GridFunction1, GridFunction2 >, typename GridFunction1::GridPartType > max(const Fem::Function< typename GridFunction1::FunctionSpaceType, GridFunction1 > &f1, const Fem::Function< typename GridFunction2::FunctionSpaceType, GridFunction2 > &f2, const std::string &name="")
Pointwise maximum of two given functions.
Definition: maxfunction.hh:121
A helper class which identifies which components are provided by the given model.
Definition: modelinterface.hh:447