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 
25 namespace 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.80.0 (May 4, 22:30, 2024)