1#ifndef __PARABOLIC_ESTIMATOR_HH__
2#define __PARABOLIC_ESTIMATOR_HH__
7#include <dune/fem/quadrature/caching/twistutility.hh>
8#include <dune/fem/quadrature/cachingquadrature.hh>
9#include <dune/fem/quadrature/intersectionquadrature.hh>
10#include <dune/fem/operator/common/spaceoperatorif.hh>
11#include <dune/fem/operator/matrix/blockmatrix.hh>
12#include <dune/fem/space/discontinuousgalerkin.hh>
15#include "../tensors/tensor.hh"
16#include "../functions/functions.hh"
17#include "../common/entitystorage.hh"
18#include "../common/geometry.hh"
19#include "../common/intersectionclassification.hh"
20#include "../common/intersectiondatahandle.hh"
21#include "../common/functionspacenorm.hh"
22#include "../models/expressions.hh"
23#include "../models/modelfacade.hh"
63 template<
class OldSolutionFunction,
class TimeProvider,
class ImplicitModel,
class ExplicitModel,
64 enum FunctionSpaceNorm Norm = L2Norm>
66 :
public EntityStorage<typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType,
67 typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType::ctype>
70 using BaseType = EntityStorage<
typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType,
71 typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType::ctype>;
74 typedef typename OldSolutionFunction::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
75 typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType;
76 typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
77 typedef typename GridPartType::GridType GridType;
78 typedef typename GridType::template Codim<0>::Entity ElementType;
80 typedef std::vector<RangeFieldType> ErrorIndicatorType;
82 typedef typename ErrorIndicatorType::const_iterator IteratorType;
85 using TimeProviderType = TimeProvider;
87 using ImplicitModelType = EffectiveModel<ImplicitModel>;
88 using ImplicitTraits = EffectiveModelTraits<ImplicitModel>;
90 using ExplicitModelType = EffectiveModel<ExplicitModel>;
91 using ExplicitTraits = EffectiveModelTraits<ExplicitModel>;
94 typedef typename ImplicitModelType::BoundaryConditionsType BoundaryConditionsType;
96 typedef OldSolutionFunction OldSolutionFunctionType;
98 typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
99 typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
100 typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
101 typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
102 typedef typename DiscreteFunctionSpaceType::HessianRangeType HessianRangeType;
105 typedef typename DiscreteFunctionSpaceType::IteratorType GridIteratorType;
106 typedef typename GridPartType::IndexSetType IndexSetType;
107 typedef typename IndexSetType::IndexType IndexType;
108 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
110 typedef typename IntersectionIteratorType::Intersection IntersectionType;
113 typedef typename ElementType::Geometry GeometryType;
114 static const int dimension = GridType::dimension;
116 typedef Dune::Fem::CachingQuadrature<GridPartType, 0> ElementQuadratureType;
117 typedef Dune::Fem::CachingQuadrature<GridPartType, 1> FaceQuadratureType;
122 typedef Dune::FieldMatrix<DomainFieldType,dimension,dimension> JacobianInverseType;
125 const TimeProviderType& timeProvider_;
129 const OldSolutionFunctionType& oldSolution_;
131 const DiscreteFunctionSpaceType &dfSpace_;
132 GridPartType &gridPart_;
133 const IndexSetType &indexSet_;
137 RangeFieldType timeIndicator_;
139 mutable std::vector<JacobianRangeType> outsideFaceFluxCache;
149 enum { bulk, jump, bdry, comm, numContributions };
150 RangeFieldType errorMin[numContributions];
151 RangeFieldType errorMax[numContributions];
163 typedef RangeType DataItemType;
164 typedef std::vector<DataItemType> IntersectionStorageType;
165 typedef std::map<IndexType, IntersectionStorageType> CommunicationStorageType;
166 typedef typename Fem::DFCommunicationOperation::Add OperationType;
176 class LocalIntersectionStorage
178 typedef std::vector<RangeFieldType> WeightStorageType;
180 LocalIntersectionStorage()
182 LocalIntersectionStorage(IndexType bulkEntityIndex,
size_t nop)
183 : bulkEntityIndex_(bulkEntityIndex), weights_(nop), h_(0)
185 IndexType bulkEntityIndex()
const {
return bulkEntityIndex_; }
186 IndexType& bulkEntityIndex() {
return bulkEntityIndex_; }
187 const RangeFieldType& operator[](
size_t idx)
const {
return weights_[idx]; }
188 RangeFieldType& operator[](
size_t idx) {
return weights_[idx]; }
189 size_t size()
const {
return weights_.size(); }
190 RangeFieldType&
hEstimate() {
return h_; }
191 const RangeFieldType&
hEstimate()
const {
return h_; }
193 IndexType bulkEntityIndex_;
194 WeightStorageType weights_;
197 typedef std::map<IndexType, LocalIntersectionStorage> LocalStorageType;
199 LocalStorageType localJumpStorage_;
200 CommunicationStorageType commJumpStorage_;
205 const ImplicitModelType& implicitModel,
206 const ExplicitModelType& explicitModel,
207 const OldSolutionFunctionType& oldSolution)
208 : BaseType(oldSolution.space().gridPart()),
209 timeProvider_(timeProvider),
210 implicitModel_(implicitModel),
211 implicitModelNeighbour_(implicitModel_),
212 explicitModel_(explicitModel),
213 oldSolution_(oldSolution),
214 dfSpace_(oldSolution_.space()),
215 gridPart_(dfSpace_.gridPart()),
216 indexSet_(gridPart_.indexSet()),
217 grid_(gridPart_.grid()),
223 template<
class DiscreteFunctionType>
224 RangeFieldType
estimate(
const DiscreteFunctionType& uh)
230 const GridIteratorType end = dfSpace_.end();
231 for (GridIteratorType it = dfSpace_.begin(); it != end; ++it) {
235 RangeFieldType error = 0.0;
238 error = std::accumulate(this->storage_.begin(), this->storage_.end(), error);
241 RangeFieldType commarray[] = { error, timeIndicator_ };
242 grid_.comm().sum(commarray, 2);
243 error = commarray[0];
244 timeIndicator_ = commarray[1];
246 if (Dune::Fem::Parameter::verbose()) {
248 std::cout <<
"Estimated " << (Norm == L2Norm ?
"L2" :
"H1") <<
"-Error: " << std::sqrt(error) << std::endl;
251 timeIndicator_ = std::sqrt(timeIndicator_);
253 return std::sqrt(error);
256 RangeFieldType timeEstimate()
const {
257 return timeIndicator_;
260 const DiscreteFunctionSpaceType& space()
const
273 localJumpStorage_.clear();
274 commJumpStorage_.clear();
280 errorMin[comm] = std::numeric_limits<RangeFieldType>::max();
285 errorMax[comm] = 0.0;
289 template<
class DiscreteFunctionType>
290 void estimateLocal(
const ElementType &entity,
const DiscreteFunctionType& uh)
292 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
293 typedef typename OldSolutionFunctionType::LocalFunctionType ExplicitLocalFunctionType;
295 const typename ElementType::Geometry &geometry = entity.geometry();
297 const RangeFieldType volume = geometry.volume();
298 const RangeFieldType h2 = (dimension == 2 ? volume :
std::pow(volume, 2.0 / (RangeFieldType)dimension));
299 const RangeFieldType hFactor = Norm == L2Norm ? h2 * h2 : h2;
300 const int index = indexSet_.index(entity);
301 const LocalFunctionType uLocal = uh.localFunction(entity);
302 const ExplicitLocalFunctionType uOldLocal = oldSolution_.localFunction(entity);
304 implicitModel_.
bind(entity);
305 explicitModel_.
bind(entity);
307 ElementQuadratureType quad(entity, 2*(dfSpace_.order() + 1));
309 const int numQuadraturePoints = quad.nop();
310 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
311 const typename ElementQuadratureType::CoordinateType &x = quad.point(qp);
312 const RangeFieldType weight = quad.weight(qp) * geometry.integrationElement(x);
315 uLocal.evaluate(x, values);
317 JacobianRangeType jacobian;
318 uLocal.jacobian(x, jacobian);
320 HessianRangeType hessian;
321 uLocal.hessian(x, hessian);
324 RangeType el_res = 0;
325 if (ImplicitTraits::template Exists<PDEModel::flux>::value) {
326 el_res += implicitModel_.
fluxDivergence(quad[qp], values, jacobian, hessian);
328 if (ImplicitTraits::template Exists<PDEModel::source>::value) {
329 el_res += implicitModel_.
source(quad[qp], values, jacobian);
334 uOldLocal.evaluate(x, oldValues);
336 JacobianRangeType oldJacobian;
337 uOldLocal.jacobian(x, oldJacobian);
339 HessianRangeType oldHessian;
340 uOldLocal.hessian(x, oldHessian);
343 if (ExplicitTraits::template Exists<PDEModel::flux>::value) {
344 el_res += explicitModel_.
fluxDivergence(quad[qp], values, jacobian, hessian);
346 if (ExplicitTraits::template Exists<PDEModel::source>::value) {
347 el_res += explicitModel_.
source(quad[qp], values, jacobian);
350 this->storage_[index] += hFactor * weight * (el_res * el_res);
354 RangeType deltaU = values;
357 timeIndicator_ += weight * (deltaU * deltaU);
361 const auto end = gridPart_.iend(entity);
362 for (
auto it = gridPart_.ibegin(entity); it != end; ++it) {
363 const auto& intersection = *it;
368 }
else if (intersection.neighbor()) {
371 }
else if (intersection.boundary()) {
374 assert(!active.first || active.second.all() || active.second.none());
376 if (!active.second.all()) {
384 template<
class DiscreteFunctionType>
386 const ElementType &inside,
387 const DiscreteFunctionType& uh,
388 const typename DiscreteFunctionType::LocalFunctionType &uInside)
390 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
393 const auto outside = intersection.outside();
395 const int insideIndex = indexSet_.index(inside);
396 const int outsideIndex = indexSet_.index(outside);
398 const bool isOutsideInterior = (outside.partitionType() == Dune::InteriorEntity);
399 if (!isOutsideInterior || (insideIndex < outsideIndex)) {
400 const LocalFunctionType uOutside = uh.localFunction(outside);
402 RangeFieldType error;
404 if (intersection.conforming())
405 error = estimateIntersection<true>(intersection, inside, uInside, outside, uOutside);
407 error = estimateIntersection<false>(intersection, inside, uInside, outside, uOutside);
410 const RangeFieldType volume
411 = 0.5 * (inside.geometry().volume() + outside.geometry().volume());
412 const RangeFieldType h = (dimension == 1 ? volume :
std::pow(volume, 1.0 / (RangeFieldType)dimension));
413 const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
414 this->storage_[insideIndex] += hFactor * error;
415 if (isOutsideInterior) {
416 this->storage_[outsideIndex] += hFactor * error;
423 template<
bool conforming,
class LocalFunctionType>
425 const ElementType &inside,
426 const LocalFunctionType &uInside,
427 const ElementType &outside,
428 const LocalFunctionType &uOutside)
431 assert(intersection.conforming() == conforming);
434 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
435 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
437 const int quadOrder = 2 * (dfSpace_.order() - 1);
439 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
442 const Quadrature &quadInside = intersectionQuad.inside();
443 const Quadrature &quadOutside = intersectionQuad.outside();
445 const int numQuadraturePoints = quadInside.nop();
447 implicitModelNeighbour_.
bind(outside);
449 RangeFieldType error = 0.0;
450 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
451 DomainType integrationNormal
452 = intersection.integrationOuterNormal(quadInside.localPoint(qp));
453 const RangeFieldType integrationElement = integrationNormal.two_norm();
459 RangeType valueInside;
460 JacobianRangeType jacobianInside;
461 uInside.evaluate(quadInside[qp], valueInside);
462 uInside.jacobian(quadInside[qp], jacobianInside);
463 decltype(
auto) fluxInside = implicitModel_.
flux(quadInside[qp], valueInside, jacobianInside);
465 RangeType valueOutside;
466 JacobianRangeType jacobianOutside;
467 uOutside.evaluate(quadOutside[qp], valueOutside);
468 uOutside.jacobian(quadOutside[qp], jacobianOutside);
469 decltype(
auto) fluxOutside = implicitModelNeighbour_.
flux(quadOutside[qp], valueOutside, jacobianOutside);
472 auto jump =
contractInner(fluxInside - fluxOutside, integrationNormal);
474 error += quadInside.weight(qp) * (jump * jump) / integrationElement;
484 if (commJumpStorage_.size() == 0) {
489 const bool verbose = Dune::Fem::Parameter::getValue<int>(
"fem.verboserank", 0) != -1;
493 gridPart_.communicate(dataHandle,
494 InteriorBorder_InteriorBorder_Interface,
495 ForwardCommunication);
501 auto commEnd = commJumpStorage_.end();
502 auto localEnd = localJumpStorage_.end();
503 auto commIt = commJumpStorage_.begin();
504 auto localIt = localJumpStorage_.begin();
506 while (commIt != commEnd) {
507 assert(commIt->first == localIt->first);
509 const LocalIntersectionStorage& localData = localIt->second;
510 const IntersectionStorageType& commData = commIt->second;
512 const size_t numQuadraturePoints = localData.size();
513 assert(numQuadraturePoints+1 == commData.size());
516 RangeFieldType error = 0.0;
517 for (
unsigned qp = 0; qp < numQuadraturePoints; ++qp) {
518 error += localData[qp] * (commData[qp] * commData[qp]);
523 RangeFieldType h = localData.hEstimate() + commData[numQuadraturePoints][0];
524 RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
528 this->storage_[localData.bulkEntityIndex()] += error;
530 errorMin[comm] = std::min(errorMin[comm], error);
531 errorMax[comm] = std::max(errorMax[comm], error);
537 assert(localIt == localEnd);
540 size_t nFaces = commJumpStorage_.size();
541 nFaces = grid_.comm().sum(nFaces);
543 if (Dune::Fem::Parameter::verbose()) {
544 dwarn <<
"*** Processor Boundaries: "
545 << (RangeFieldType)nFaces/2.0
546 <<
" Faces ***" << std::endl;
563 template<
class LocalFunctionType>
565 const ElementType &inside,
566 const LocalFunctionType &uInside)
568 if (intersection.conforming()) {
569 estimateProcessBoundary<true>(intersection, inside, uInside);
571 estimateProcessBoundary<false>(intersection, inside, uInside);
579 template<
bool conforming,
class LocalFunctionType>
581 const ElementType &inside,
582 const LocalFunctionType &uInside)
585 assert(intersection.conforming() == conforming);
588 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
589 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
591 const int quadOrder = 2 * (dfSpace_.order() - 1);
593 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
596 const Quadrature &quadInside = intersectionQuad.inside();
597 const int numQuadraturePoints = quadInside.nop();
600 IndexType faceIndex = indexSet_.index(inside.template subEntity<1>(intersection.indexInInside()));
601 IndexType bulkIndex = indexSet_.index(inside);
607 IntersectionStorageType commData = IntersectionStorageType(numQuadraturePoints+1);
608 LocalIntersectionStorage localData = LocalIntersectionStorage(bulkIndex, numQuadraturePoints);
610 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
611 auto normal = intersection.integrationOuterNormal(quadInside.localPoint(qp));
612 const auto integrationElement = normal.two_norm();
613 normal /= integrationElement;
619 RangeType valueInside;
620 JacobianRangeType jacobianInside;
621 uInside.evaluate(quadInside[qp], valueInside);
622 uInside.jacobian(quadInside[qp], jacobianInside);
623 auto fluxInside = implicitModel_.
flux(quadInside[qp], valueInside, jacobianInside);
629 localData[qp] = quadInside.weight(qp) * integrationElement;
631 localData.hEstimate() =
hEstimate(inside.geometry());
633 commData[numQuadraturePoints][0] = localData.hEstimate();
635 commJumpStorage_[faceIndex] = commData;
636 localJumpStorage_[faceIndex] = localData;
646 template<
class LocalFunctionType>
648 const ElementType &inside,
649 const LocalFunctionType &uLocal,
650 const BoundaryConditionsType& active)
652 if (!ImplicitTraits::template Exists<PDEModel::flux>::value
654 !ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
658 assert(intersection.conforming() ==
true);
660 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType,
true > IntersectionQuadratureType;
661 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
665 const auto quadOrder = 2*dfSpace_.order();
668 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
670 const Quadrature &bndryQuad = intersectionQuad.inside();
671 const int numQuadraturePoints = bndryQuad.nop();
673 RangeFieldType error = 0.0;
675 for (
int qp = 0; qp < numQuadraturePoints; ++qp) {
676 const RangeFieldType weight = bndryQuad.weight(qp);
679 DomainType normal = intersection.integrationOuterNormal(bndryQuad.localPoint(qp));
680 const auto integrationElement = normal.two_norm();
681 normal /= integrationElement;
684 uLocal.evaluate(bndryQuad[qp], value);
686 JacobianRangeType jacobian;
687 if (ImplicitTraits::template Exists<PDEModel::flux>::value
689 ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
690 uLocal.jacobian(bndryQuad[qp], jacobian);
693 RangeType residual(0);
694 if (ImplicitTraits::template Exists<PDEModel::flux>::value) {
699 if (ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
701 residual += implicitModel_.
robinFlux(bndryQuad[qp], normal, value, jacobian);
705 error += weight * integrationElement * (residual * residual);
710 const int insideIndex = indexSet_.index(inside);
712 const RangeFieldType volume = inside.geometry().volume();
714 const RangeFieldType h = (dimension == 1 ? volume :
std::pow(volume, 1.0 / (RangeFieldType)dimension));
715 const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
716 this->storage_[insideIndex] += hFactor * error;
General intersection - intersection communication which communicates for each intersection a potentia...
Definition: intersectiondatahandle.hh:50
A class defining the "closure" type of all supported model-method and method-call-signatures.
Definition: modelfacade.hh:72
auto flux(const QuadraturePoint< Quadrature > &x, const DomainRangeType &value, const DomainJacobianRangeType &jacobian) const
Evaluate in local coordinates.
Definition: modelfacade.hh:236
auto source(const QuadraturePoint< Quadrature > &x, const DomainRangeType &value, const DomainJacobianRangeType &jacobian) const
The zero-order term as function of local coordinates.
Definition: modelfacade.hh:287
auto robinFlux(const QuadraturePoint< Quadrature > &x, const DomainType &unitOuterNormal, const DomainRangeType &value, const DomainJacobianRangeType &jacobian) const
The non-linearized Robin-type flux term.
Definition: modelfacade.hh:344
void bind(const Entity &entity)
Bind to the given entity.
Definition: modelfacade.hh:154
BoundaryConditionsType classifyBoundary(const Intersection &intersection)
Bind to the given intersection and classify the components w.r.t.
Definition: modelfacade.hh:206
auto fluxDivergence(const QuadraturePoint< Quadrature > &x, const DomainRangeType &value, const DomainJacobianRangeType &jacobian, const DomainHessianRangeType &hessian) const
Compute the point-wise value of the flux-part of the operator, meaning the part of the differential o...
Definition: modelfacade.hh:455
Residual estimator for the heat equation.
Definition: parabolicestimator.hh:68
void estimateLocal(const ElementType &entity, const DiscreteFunctionType &uh)
caclulate error on element
Definition: parabolicestimator.hh:290
void estimateBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uLocal, const BoundaryConditionsType &active)
caclulate error over a boundary segment; yields zero for Dirichlet boundary values,...
Definition: parabolicestimator.hh:647
void estimateProcessBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Compute the jump contribution to the estimator on process-boundaries.
Definition: parabolicestimator.hh:564
void estimateProcessBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Helper function for estimateProcessBoundary() in order to distinguish between conforming and non-conf...
Definition: parabolicestimator.hh:580
void communicateJumpContributions()
Helper function in order to add the jump contributions on inter-process boundaries.
Definition: parabolicestimator.hh:482
void estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const DiscreteFunctionType &uh, const typename DiscreteFunctionType::LocalFunctionType &uInside)
caclulate error on element boundary intersections
Definition: parabolicestimator.hh:385
RangeFieldType estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside, const ElementType &outside, const LocalFunctionType &uOutside)
caclulate error on element intersections
Definition: parabolicestimator.hh:424
RangeFieldType estimate(const DiscreteFunctionType &uh)
calculate estimator
Definition: parabolicestimator.hh:224
Geometry::ctype hEstimate(const Geometry &geometry)
Compute a rough estimate of the diameter of the element's Geometry.
Definition: geometry.hh:41
bool isProcessorBoundary(const Intersection &intersection)
Retrun true if at the border to another computing note.
Definition: intersectionclassification.hh:35
constexpr std::size_t size()
Gives the number of elements in tuple-likes and std::integer_sequence.
Definition: size.hh:73
constexpr auto contractInner(T1 &&t1, T2 &&t2, IndexConstant< N >=IndexConstant< N >{})
Contraction over the #N inner dimensions.
Definition: expressions.hh:118
auto pow(T1 &&t1, T2 &&t2)
Power operations with scalar exponents are promoted to component-wise power operations by multiplying...
Definition: expressions.hh:525