DUNE-ACFEM (unstable)

parabolicestimator.hh
1#ifndef __PARABOLIC_ESTIMATOR_HH__
2#define __PARABOLIC_ESTIMATOR_HH__
3
4#include <numeric>
5
6//- Dune-fem includes
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>
13
14// Local includes
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"
24
25namespace Dune {
26
27 namespace ACFem {
28
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>
68 {
70 using BaseType = EntityStorage<typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType,
71 typename OldSolutionFunction::DiscreteFunctionSpaceType::GridPartType::ctype>;
72 public:
73 // Interface types
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;
79 protected:
80 typedef std::vector<RangeFieldType> ErrorIndicatorType;
81 public:
82 typedef typename ErrorIndicatorType::const_iterator IteratorType;
83
84 protected:
85 using TimeProviderType = TimeProvider;
86
87 using ImplicitModelType = EffectiveModel<ImplicitModel>;
88 using ImplicitTraits = EffectiveModelTraits<ImplicitModel>;
90 using ExplicitModelType = EffectiveModel<ExplicitModel>;
91 using ExplicitTraits = EffectiveModelTraits<ExplicitModel>;
93
94 typedef typename ImplicitModelType::BoundaryConditionsType BoundaryConditionsType;
95
96 typedef OldSolutionFunction OldSolutionFunctionType;
97
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;
103
104 //typedef typename GridPartType::GridType GridType;
105 typedef typename DiscreteFunctionSpaceType::IteratorType GridIteratorType;
106 typedef typename GridPartType::IndexSetType IndexSetType;
107 typedef typename IndexSetType::IndexType IndexType;
108 typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
109
110 typedef typename IntersectionIteratorType::Intersection IntersectionType;
111
112 //typedef typename GridType::template Codim<0>::Entity ElementType; see above
113 typedef typename ElementType::Geometry GeometryType;
114 static const int dimension = GridType::dimension;
115
116 typedef Dune::Fem::CachingQuadrature<GridPartType, 0> ElementQuadratureType;
117 typedef Dune::Fem::CachingQuadrature<GridPartType, 1> FaceQuadratureType;
118
119 //typedef Dune::Fem::ElementQuadrature<GridPartType, 0> ElementQuadratureType;
120 //typedef Dune::Fem::ElementQuadrature<GridPartType, 1> FaceQuadratureType;
121
122 typedef Dune::FieldMatrix<DomainFieldType,dimension,dimension> JacobianInverseType;
123
124 protected:
125 const TimeProviderType& timeProvider_;
126 ImplicitModelClosure implicitModel_;
127 ImplicitModelClosure implicitModelNeighbour_;
128 ExplicitModelClosure explicitModel_;
129 const OldSolutionFunctionType& oldSolution_;
130
131 const DiscreteFunctionSpaceType &dfSpace_;
132 GridPartType &gridPart_;
133 const IndexSetType &indexSet_;
134 GridType &grid_;
135
136 private:
137 RangeFieldType timeIndicator_;
138
139 mutable std::vector<JacobianRangeType> outsideFaceFluxCache;
140
149 enum { bulk, jump, bdry, comm, numContributions };
150 RangeFieldType errorMin[numContributions];
151 RangeFieldType errorMax[numContributions];
152
163 typedef RangeType DataItemType;
164 typedef std::vector<DataItemType> IntersectionStorageType;
165 typedef std::map<IndexType, IntersectionStorageType> CommunicationStorageType;
166 typedef typename Fem::DFCommunicationOperation::Add OperationType;
168
176 class LocalIntersectionStorage
177 {
178 typedef std::vector<RangeFieldType> WeightStorageType;
179 public:
180 LocalIntersectionStorage()
181 {}
182 LocalIntersectionStorage(IndexType bulkEntityIndex, size_t nop)
183 : bulkEntityIndex_(bulkEntityIndex), weights_(nop), h_(0)
184 {}
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_; }
192 private:
193 IndexType bulkEntityIndex_;
194 WeightStorageType weights_;
195 RangeFieldType h_;
196 };
197 typedef std::map<IndexType, LocalIntersectionStorage> LocalStorageType;
198
199 LocalStorageType localJumpStorage_;
200 CommunicationStorageType commJumpStorage_;
201
203 public:
204 explicit ParabolicEulerEstimator(const TimeProviderType& timeProvider,
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()),
218 timeIndicator_(0)
219 {
220 }
221
223 template<class DiscreteFunctionType>
224 RangeFieldType estimate(const DiscreteFunctionType& uh)
225 {
226 // clear all local estimators
227 clear();
228
229 // calculate local estimator
230 const GridIteratorType end = dfSpace_.end();
231 for (GridIteratorType it = dfSpace_.begin(); it != end; ++it) {
232 estimateLocal(*it, uh);
233 }
234
235 RangeFieldType error = 0.0;
236
237 // sum up local estimators
238 error = std::accumulate(this->storage_.begin(), this->storage_.end(), error);
239
240 // obtain global sum
241 RangeFieldType commarray[] = { error, timeIndicator_ };
242 grid_.comm().sum(commarray, 2);
243 error = commarray[0];
244 timeIndicator_ = commarray[1];
245
246 if (Dune::Fem::Parameter::verbose()) {
247 // print error estimator if on node 0
248 std::cout << "Estimated " << (Norm == L2Norm ? "L2" : "H1") << "-Error: " << std::sqrt(error) << std::endl;
249 }
250
251 timeIndicator_ = std::sqrt(timeIndicator_);
252
253 return std::sqrt(error);
254 }
255
256 RangeFieldType timeEstimate() const {
257 return timeIndicator_;
258 }
259
260 const DiscreteFunctionSpaceType& space() const
261 {
262 return dfSpace_;
263 }
264
265 protected:
266 void clear()
267 {
268 // resize and clear
269 BaseType::clear();
270 timeIndicator_ = 0;
271
272 // the communication hack for parallel runs. Gnah.
273 localJumpStorage_.clear();
274 commJumpStorage_.clear();
275
276 // debugging and stuff
277 errorMin[bulk] =
278 errorMin[jump] =
279 errorMin[bdry] =
280 errorMin[comm] = std::numeric_limits<RangeFieldType>::max();
281
282 errorMax[bulk] =
283 errorMax[jump] =
284 errorMax[bdry] =
285 errorMax[comm] = 0.0;
286 }
287
289 template<class DiscreteFunctionType>
290 void estimateLocal(const ElementType &entity, const DiscreteFunctionType& uh)
291 {
292 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
293 typedef typename OldSolutionFunctionType::LocalFunctionType ExplicitLocalFunctionType;
294
295 const typename ElementType::Geometry &geometry = entity.geometry();
296
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);
303
304 implicitModel_.bind(entity);
305 explicitModel_.bind(entity);
306
307 ElementQuadratureType quad(entity, 2*(dfSpace_.order() + 1));
308
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);
313
314 RangeType values;
315 uLocal.evaluate(x, values);
316
317 JacobianRangeType jacobian;
318 uLocal.jacobian(x, jacobian);
319
320 HessianRangeType hessian;
321 uLocal.hessian(x, hessian);
322
323 // Now compute the element residual
324 RangeType el_res = 0;
325 if (ImplicitTraits::template Exists<PDEModel::flux>::value) {
326 el_res += implicitModel_.fluxDivergence(quad[qp], values, jacobian, hessian);
327 }
328 if (ImplicitTraits::template Exists<PDEModel::source>::value) {
329 el_res += implicitModel_.source(quad[qp], values, jacobian);
330 }
331
332 // Compute the contribution from the explicit part
333 RangeType oldValues;
334 uOldLocal.evaluate(x, oldValues);
335
336 JacobianRangeType oldJacobian;
337 uOldLocal.jacobian(x, oldJacobian);
338
339 HessianRangeType oldHessian;
340 uOldLocal.hessian(x, oldHessian);
341
342 // add the "explicit" part. In principle overkill here
343 if (ExplicitTraits::template Exists<PDEModel::flux>::value) {
344 el_res += explicitModel_.fluxDivergence(quad[qp], values, jacobian, hessian);
345 }
346 if (ExplicitTraits::template Exists<PDEModel::source>::value) {
347 el_res += explicitModel_.source(quad[qp], values, jacobian);
348 }
349
350 this->storage_[index] += hFactor * weight * (el_res * el_res);
351
352 // Now el_res contains the space error. We also need the error
353 // from the time discretization
354 RangeType deltaU = values;
355 deltaU -= oldValues;
356
357 timeIndicator_ += weight * (deltaU * deltaU);
358 }
359
360 // Calculate face contribution. The explicit part is completely ignored here.
361 const auto end = gridPart_.iend(entity);
362 for (auto it = gridPart_.ibegin(entity); it != end; ++it) {
363 const auto& intersection = *it;
364
365 if (isProcessorBoundary(intersection)) {
366 // interior face accross a process boundary
367 estimateProcessBoundary(intersection, entity, uLocal);
368 } else if (intersection.neighbor()) {
369 // interior face
370 estimateIntersection(intersection, entity, uh, uLocal);
371 } else if (intersection.boundary()) {
372 const auto active = implicitModel_.classifyBoundary(intersection);
373
374 assert(!active.first || active.second.all() || active.second.none());
375
376 if (!active.second.all()) {
377 estimateBoundary(intersection, entity, uLocal, active);
378 }
379 }
380 }
381 }
382
384 template<class DiscreteFunctionType>
385 void estimateIntersection(const IntersectionType &intersection,
386 const ElementType &inside,
387 const DiscreteFunctionType& uh,
388 const typename DiscreteFunctionType::LocalFunctionType &uInside)
389 {
390 typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
391
392 // get outside entity pointer
393 const auto outside = intersection.outside();
394
395 const int insideIndex = indexSet_.index(inside);
396 const int outsideIndex = indexSet_.index(outside);
397
398 const bool isOutsideInterior = (outside.partitionType() == Dune::InteriorEntity);
399 if (!isOutsideInterior || (insideIndex < outsideIndex)) {
400 const LocalFunctionType uOutside = uh.localFunction(outside);
401
402 RangeFieldType error;
403
404 if (intersection.conforming())
405 error = estimateIntersection<true>(intersection, inside, uInside, outside, uOutside);
406 else
407 error = estimateIntersection<false>(intersection, inside, uInside, outside, uOutside);
408
409 if (error > 0.0) {
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;
417 }
418 }
419 }
420 }
421
423 template<bool conforming, class LocalFunctionType>
424 RangeFieldType estimateIntersection(const IntersectionType &intersection,
425 const ElementType &inside,
426 const LocalFunctionType &uInside,
427 const ElementType &outside,
428 const LocalFunctionType &uOutside)
429 {
430 // make sure correct method is called
431 assert(intersection.conforming() == conforming);
432
433 // use IntersectionQuadrature to create appropriate face quadratures
434 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
435 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
436
437 const int quadOrder = 2 * (dfSpace_.order() - 1);
438 // create intersection quadrature
439 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
440
441 // get appropriate quadrature references
442 const Quadrature &quadInside = intersectionQuad.inside();
443 const Quadrature &quadOutside = intersectionQuad.outside();
444
445 const int numQuadraturePoints = quadInside.nop();
446
447 implicitModelNeighbour_.bind(outside); // go to neighbour
448
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();
454
455 // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
456 // evaluate jacobian left and right of the interface and apply
457 // the diffusion tensor
458
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);
464
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);
470
471 // Multiply with normal
472 auto jump = contractInner(fluxInside - fluxOutside, integrationNormal);
473
474 error += quadInside.weight(qp) * (jump * jump) / integrationElement;
475 }
476 return error;
477 }
478
483 {
484 if (commJumpStorage_.size() == 0) {
485 // not a parallel run.
486 return;
487 }
488
489 const bool verbose = Dune::Fem::Parameter::getValue<int>("fem.verboserank", 0) != -1;
490
491 DataHandleType dataHandle(indexSet_, commJumpStorage_);
492
493 gridPart_.communicate(dataHandle,
494 InteriorBorder_InteriorBorder_Interface,
495 ForwardCommunication);
496
497 // At this point commJumpStorage_ should contain the proper
498 // differences of the boundary flux contributions. It remains
499 // to performs the actual numerical quadrature summation.
500
501 auto commEnd = commJumpStorage_.end();
502 auto localEnd = localJumpStorage_.end();
503 auto commIt = commJumpStorage_.begin();
504 auto localIt = localJumpStorage_.begin();
505
506 while (commIt != commEnd) {
507 assert(commIt->first == localIt->first);
508
509 const LocalIntersectionStorage& localData = localIt->second;
510 const IntersectionStorageType& commData = commIt->second;
511
512 const size_t numQuadraturePoints = localData.size();
513 assert(numQuadraturePoints+1 == commData.size());
514
515 // form the square sum
516 RangeFieldType error = 0.0;
517 for (unsigned qp = 0; qp < numQuadraturePoints; ++qp) {
518 error += localData[qp] * (commData[qp] * commData[qp]);
519 }
520
521 // add the appropriate weights
522 // HACK PLEASE FIXME;
523 RangeFieldType h = localData.hEstimate() + commData[numQuadraturePoints][0];
524 RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
525
526 // add contribution to the estimator array
527 error *= hFactor;
528 this->storage_[localData.bulkEntityIndex()] += error;
529
530 errorMin[comm] = std::min(errorMin[comm], error);
531 errorMax[comm] = std::max(errorMax[comm], error);
532
533 ++commIt;
534 ++localIt;
535 }
536
537 assert(localIt == localEnd);
538
539 if (verbose) {
540 size_t nFaces = commJumpStorage_.size();
541 nFaces = grid_.comm().sum(nFaces);
542
543 if (Dune::Fem::Parameter::verbose()) {
544 dwarn << "*** Processor Boundaries: "
545 << (RangeFieldType)nFaces/2.0
546 << " Faces ***" << std::endl;
547 }
548 }
549 }
550
563 template<class LocalFunctionType>
564 void estimateProcessBoundary(const IntersectionType &intersection,
565 const ElementType &inside,
566 const LocalFunctionType &uInside)
567 {
568 if (intersection.conforming()) {
569 estimateProcessBoundary<true>(intersection, inside, uInside);
570 } else {
571 estimateProcessBoundary<false>(intersection, inside, uInside);
572 }
573 }
574
579 template<bool conforming, class LocalFunctionType>
580 void estimateProcessBoundary(const IntersectionType &intersection,
581 const ElementType &inside,
582 const LocalFunctionType &uInside)
583 {
584 // make sure correct method is called
585 assert(intersection.conforming() == conforming);
586
587 // use IntersectionQuadrature to create appropriate face quadratures
588 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
589 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
590
591 const int quadOrder = 2 * (dfSpace_.order() - 1);
592 // create intersection quadrature
593 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
594
595 // get appropriate quadrature references
596 const Quadrature &quadInside = intersectionQuad.inside();
597 const int numQuadraturePoints = quadInside.nop();
598
599 // FIXME: is there any easier way to get hold of the face-index?
600 IndexType faceIndex = indexSet_.index(inside.template subEntity<1>(intersection.indexInInside()));
601 IndexType bulkIndex = indexSet_.index(inside);
602
603 // IntersectionStorageType& commData =
604 // (commJumpStorage_[faceIndex] = IntersectionStorageType(numQuadraturePoints+1));
605 // LocalIntersectionStorage& localData =
606 // (localJumpStorage_[faceIndex] = LocalIntersectionStorage(bulkIndex, numQuadraturePoints));
607 IntersectionStorageType commData = IntersectionStorageType(numQuadraturePoints+1);
608 LocalIntersectionStorage localData = LocalIntersectionStorage(bulkIndex, numQuadraturePoints);
609
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;
614
615 // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
616 // evaluate jacobian left and right of the interface and apply
617 // the diffusion tensor
618
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);
624
625 // Multiply with normal and store in the communication array
626 commData[qp] = contractInner(fluxInside, normal);
627
628 // Remember weight and integration element for this point
629 localData[qp] = quadInside.weight(qp) * integrationElement;
630 }
631 localData.hEstimate() = hEstimate(inside.geometry());
632 // THIS IS A HACK. PLEASE FIXME
633 commData[numQuadraturePoints][0] = localData.hEstimate();
634
635 commJumpStorage_[faceIndex] = commData;
636 localJumpStorage_[faceIndex] = localData;
637 }
638
646 template<class LocalFunctionType>
647 void estimateBoundary(const IntersectionType &intersection,
648 const ElementType &inside,
649 const LocalFunctionType &uLocal,
650 const BoundaryConditionsType& active)
651 {
652 if (!ImplicitTraits::template Exists<PDEModel::flux>::value
653 &&
654 !ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
655 return;
656 }
657
658 assert(intersection.conforming() == true);
659
660 typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, true /* conforming */> IntersectionQuadratureType;
661 typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
662
663 // TODO: make more realistic assumptions on the
664 // quad-order. HOWTO?
665 const auto quadOrder = 2*dfSpace_.order();
666
667 // create intersection quadrature
668 IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
669 // get appropriate quadrature references
670 const Quadrature &bndryQuad = intersectionQuad.inside();
671 const int numQuadraturePoints = bndryQuad.nop();
672
673 RangeFieldType error = 0.0;
674
675 for (int qp = 0; qp < numQuadraturePoints; ++qp) {
676 const RangeFieldType weight = bndryQuad.weight(qp);
677
678 // Get the un-normalized outer normal
679 DomainType normal = intersection.integrationOuterNormal(bndryQuad.localPoint(qp));
680 const auto integrationElement = normal.two_norm();
681 normal /= integrationElement;
682
683 RangeType value;
684 uLocal.evaluate(bndryQuad[qp], value);
685
686 JacobianRangeType jacobian;
687 if (ImplicitTraits::template Exists<PDEModel::flux>::value
688 ||
689 ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
690 uLocal.jacobian(bndryQuad[qp], jacobian);
691 }
692
693 RangeType residual(0);
694 if (ImplicitTraits::template Exists<PDEModel::flux>::value) {
695 residual += contractInner(implicitModel_.flux(bndryQuad[qp], value, jacobian),
696 normal);
697 }
698
699 if (ImplicitTraits::template Exists<PDEModel::robinFlux>::value) {
700 if (active.first) { // TODO: component-wise
701 residual += implicitModel_.robinFlux(bndryQuad[qp], normal, value, jacobian);
702 }
703 }
704
705 error += weight * integrationElement * (residual * residual);
706 }
707
708 if (error > 0.0) {
709 // Get index into estimator vector
710 const int insideIndex = indexSet_.index(inside);
711
712 const RangeFieldType volume = inside.geometry().volume();
713
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;
717 }
718 }
719 };
720
722
724
725 } // ACFem::
726
727} // Dune::
728
729#endif // __PARABOLIC_ESTIMATOR_HH__
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 27, 23:30, 2024)