DUNE-ACFEM (2.5.1)

parabolicestimator.hh
1 #ifndef __PARABOLIC_ESTIMATOR_HH__
2 #define __PARABOLIC_ESTIMATOR_HH__
3 
4 //- Dune-fem includes
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>
11 
12 // Local includes
13 #include "../estimators/estimatorinterface.hh"
14 #include "../models/modelinterface.hh"
15 #include "../common/geometry.hh"
16 #include "../common/intersectiondatahandle.hh"
17 
18 namespace Dune {
19 
20  namespace ACFem {
21 
56  template<class OldSolutionFunction, class TimeProvider, class ImplicitModel, class ExplicitModel>
58  : public DefaultEstimator<ParabolicEulerEstimator<OldSolutionFunction, TimeProvider,
59  ImplicitModel, ExplicitModel> >
60  {
61  enum FunctionSpaceNorm
62  {
63  L2Norm,
64  H1Norm,
65  Norm = L2Norm
66  };
67  typedef ParabolicEulerEstimator ThisType;
68  typedef DefaultEstimator<ThisType> BaseType;
69  public:
70  // Interface types
71  typedef typename OldSolutionFunction::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
72  typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType;
73  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
74  typedef typename GridPartType::GridType GridType;
75  typedef typename GridType::template Codim<0>::Entity ElementType;
76  protected:
77  typedef std::vector<RangeFieldType> ErrorIndicatorType;
78  public:
79  typedef typename ErrorIndicatorType::const_iterator IteratorType;
80 
81  protected:
82  // Everything else why might need
83  typedef TimeProvider TimeProviderType;
86  typedef typename ImplicitModelType::OperatorPartsType ImplicitOperatorPartsType;
87  typedef typename ExplicitModelType::OperatorPartsType ExplicitOperatorPartsType;
90 
91  typedef OldSolutionFunction OldSolutionFunctionType;
92 
93  typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
94  typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
95  typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
96  typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
97  typedef typename DiscreteFunctionSpaceType::HessianRangeType HessianRangeType;
98 
99  // Various data functions ...
100  typedef typename ImplicitModelType::BulkForcesFunctionType BulkForcesFunctionType;
101  typedef typename BulkForcesFunctionType::LocalFunctionType BulkForcesLocalFunctionType;
102  typedef typename ImplicitModelType::DirichletBoundaryFunctionType DirichletFunctionType;
103  typedef typename DirichletFunctionType::LocalFunctionType DirichletLocalFunctionType;
104  typedef typename ImplicitModelType::NeumannBoundaryFunctionType NeumannFunctionType;
105  typedef typename NeumannFunctionType::LocalFunctionType NeumannLocalFunctionType;
106 
107  // Boundary classification
108  typedef typename ImplicitModelType::DirichletIndicatorType DirichletIndicatorType;
109  typedef typename ImplicitModelType::NeumannIndicatorType NeumannIndicatorType;
110 
111  // Just to have a draft what might be needed to take contributions
112  // from the explicit model into account
113  typedef typename ExplicitModelType::BulkForcesFunctionType ExplicitBulkForcesFunctionType;
114  typedef typename ExplicitBulkForcesFunctionType::LocalFunctionType ExplicitBulkForcesLocalFunctionType;
115  // and so on, but even the above is not really needed here
116 
117  //typedef typename GridPartType::GridType GridType;
118  typedef typename DiscreteFunctionSpaceType::IteratorType GridIteratorType;
119  typedef typename GridPartType::IndexSetType IndexSetType;
120  typedef typename IndexSetType::IndexType IndexType;
121  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
122 
123  typedef typename IntersectionIteratorType::Intersection IntersectionType;
124 
125  //typedef typename GridType::template Codim<0>::Entity ElementType; see above
126  typedef typename ElementType::Geometry GeometryType;
127  static const int dimension = GridType::dimension;
128 
129  typedef Dune::Fem::CachingQuadrature<GridPartType, 0> ElementQuadratureType;
130  typedef Dune::Fem::CachingQuadrature<GridPartType, 1> FaceQuadratureType;
131 
132  //typedef Dune::Fem::ElementQuadrature<GridPartType, 0> ElementQuadratureType;
133  //typedef Dune::Fem::ElementQuadrature<GridPartType, 1> FaceQuadratureType;
134 
135  typedef Dune::FieldMatrix<DomainFieldType,dimension,dimension> JacobianInverseType;
136 
137  protected:
138  const TimeProviderType& timeProvider_;
139  const ImplicitModelType& implicitModel_;
140  const ImplicitOperatorPartsType implicitParts_;
141  const ImplicitOperatorPartsType implicitPartsNeighbour_;
142  const ExplicitModelType& explicitModel_;
143  const ExplicitOperatorPartsType explicitParts_;
144  const OldSolutionFunctionType& oldSolution_;
145 
146  const DiscreteFunctionSpaceType &dfSpace_;
147  GridPartType &gridPart_;
148  const IndexSetType &indexSet_;
149  GridType &grid_;
150 
151  private:
152  BulkForcesFunctionType bulkForcesFunction_;
153  ExplicitBulkForcesFunctionType explicitBulkForcesFunction_;
154  NeumannFunctionType neumannFunction_;
155  NeumannIndicatorType neumannBndry_;
156  ErrorIndicatorType localIndicators_;
157  RangeFieldType timeIndicator_;
158 
159  mutable std::vector<JacobianRangeType> outsideFaceFluxCache;
160 
169  enum { bulk, jump, bdry, comm, numContributions };
170  RangeFieldType errorMin[numContributions];
171  RangeFieldType errorMax[numContributions];
172 
183  typedef RangeType DataItemType;
184  typedef std::vector<DataItemType> IntersectionStorageType;
185  typedef std::map<IndexType, IntersectionStorageType> CommunicationStorageType;
186  typedef typename Fem::DFCommunicationOperation::Add OperationType;
188 
196  class LocalIntersectionStorage
197  {
198  typedef std::vector<RangeFieldType> WeightStorageType;
199  public:
200  LocalIntersectionStorage()
201  {}
202  LocalIntersectionStorage(IndexType bulkEntityIndex, size_t nop)
203  : bulkEntityIndex_(bulkEntityIndex), weights_(nop), h_(0)
204  {}
205  IndexType bulkEntityIndex() const { return bulkEntityIndex_; }
206  IndexType& bulkEntityIndex() { return bulkEntityIndex_; }
207  const RangeFieldType& operator[](size_t idx) const { return weights_[idx]; }
208  RangeFieldType& operator[](size_t idx) { return weights_[idx]; }
209  size_t size() const { return weights_.size(); }
210  RangeFieldType& hEstimate() { return h_; }
211  const RangeFieldType& hEstimate() const { return h_; }
212  private:
213  IndexType bulkEntityIndex_;
214  WeightStorageType weights_;
215  RangeFieldType h_;
216  };
217  typedef std::map<IndexType, LocalIntersectionStorage> LocalStorageType;
218 
219  LocalStorageType localJumpStorage_;
220  CommunicationStorageType commJumpStorage_;
221 
223  public:
224  explicit ParabolicEulerEstimator(const TimeProviderType& timeProvider,
225  const ImplicitModelType& implicitModel,
226  const ExplicitModelType& explicitModel,
227  const OldSolutionFunctionType& oldSolution)
228  : timeProvider_(timeProvider),
229  implicitModel_(implicitModel),
230  implicitParts_(implicitModel_.operatorParts()),
231  implicitPartsNeighbour_(implicitModel_.operatorParts()),
232  explicitModel_(explicitModel),
233  explicitParts_(explicitModel_.operatorParts()),
234  oldSolution_(oldSolution),
235  dfSpace_(oldSolution_.space()),
236  gridPart_(dfSpace_.gridPart()),
237  indexSet_(gridPart_.indexSet()),
238  grid_(gridPart_.grid()),
239  bulkForcesFunction_(implicitModel_.bulkForcesFunction(gridPart_)),
240  explicitBulkForcesFunction_(explicitModel_.bulkForcesFunction(gridPart_)),
241  neumannFunction_(implicitModel_.neumannBoundaryFunction(gridPart_)),
242  neumannBndry_(implicitModel_.neumannIndicator()),
243  timeIndicator_(0)
244  {
245  localIndicators_.resize(indexSet_.size(0));
246  }
247 
249  template<class DiscreteFunctionType>
250  RangeFieldType estimate(const DiscreteFunctionType& uh)
251  {
254 
255  // clear all local estimators
256  clear();
257 
258  // calculate local estimator
259  const GridIteratorType end = dfSpace_.end();
260  for (GridIteratorType it = dfSpace_.begin(); it != end; ++it) {
261  estimateLocal(*it, uh);
262  }
263 
264  RangeFieldType error = 0.0;
265 
266  // sum up local estimators
267  const IteratorType endEstimator = localIndicators_.end();
268  for (IteratorType it = localIndicators_.begin(); it != endEstimator; ++it) {
269  error += *it;
270  }
271 
272  // obtain global sum
273  RangeFieldType commarray[] = { error, timeIndicator_ };
274  grid_.comm().sum(commarray, 2);
275  error = commarray[0];
276  timeIndicator_ = commarray[1];
277 
278  if (Dune::Fem::Parameter::verbose()) {
279  // print error estimator if on node 0
280  std::cout << "Estimated " << (Norm == L2Norm ? "L2" : "H1") << "-Error: " << std::sqrt(error) << std::endl;
281  }
282 
283  timeIndicator_ = std::sqrt(timeIndicator_);
284 
285  return std::sqrt(error);
286  }
287 
288  const RangeFieldType& operator[](const size_t& idx) const
289  {
290  return localIndicators_[idx];
291  }
292 
293  const RangeFieldType& operator[](const ElementType& entity) const
294  {
295  return (*this)[indexSet_.index(entity)];
296  }
297 
298  size_t size() const
299  {
300  return indexSet_.size(0);
301  }
302 
303  IteratorType begin() const {
304  return localIndicators_.begin();
305  }
306 
307  IteratorType end() const {
308  return localIndicators_.end();
309  }
310 
311  RangeFieldType timeEstimate() const {
312  return timeIndicator_;
313  }
314 
315  GridType& grid() const
316  {
317  return grid_;
318  }
319 
320  const DiscreteFunctionSpaceType& space() const
321  {
322  return dfSpace_;
323  }
324 
325  protected:
326  void clear()
327  {
328  // resize and clear
329  localIndicators_.resize(indexSet_.size(0));
330  const typename ErrorIndicatorType::iterator end = localIndicators_.end();
331  for (typename ErrorIndicatorType::iterator it = localIndicators_.begin();
332  it != end; ++it) {
333  *it = 0.0;
334  }
335  timeIndicator_ = 0;
336 
337  // the communication hack for parallel runs. Gnah.
338  localJumpStorage_.clear();
339  commJumpStorage_.clear();
340 
341  // debugging and stuff
342  errorMin[bulk] =
343  errorMin[jump] =
344  errorMin[bdry] =
345  errorMin[comm] = std::numeric_limits<RangeFieldType>::max();
346 
347  errorMax[bulk] =
348  errorMax[jump] =
349  errorMax[bdry] =
350  errorMax[comm] = 0.0;
351  }
352 
354  template<class DiscreteFunctionType>
355  void estimateLocal(const ElementType &entity, const DiscreteFunctionType& uh)
356  {
357  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
358  typedef typename OldSolutionFunctionType::LocalFunctionType ExplicitLocalFunctionType;
359 
360  const typename ElementType::Geometry &geometry = entity.geometry();
361 
362  const RangeFieldType volume = geometry.volume();
363  const RangeFieldType h2 = (dimension == 2 ? volume : std::pow(volume, 2.0 / (RangeFieldType)dimension));
364  const RangeFieldType hFactor = Norm == L2Norm ? h2 * h2 : h2;
365  const int index = indexSet_.index(entity);
366  const LocalFunctionType uLocal = uh.localFunction(entity);
367  const ExplicitLocalFunctionType uOldLocal = oldSolution_.localFunction(entity);
368  const BulkForcesLocalFunctionType fLocal = bulkForcesFunction_.localFunction(entity);
369  const ExplicitBulkForcesLocalFunctionType fOldLocal = explicitBulkForcesFunction_.localFunction(entity);
370 
371  implicitParts_.setEntity(entity);
372  explicitParts_.setEntity(entity);
373 
374  ElementQuadratureType quad(entity, 2*(dfSpace_.order() + 1));
375 
376  const int numQuadraturePoints = quad.nop();
377  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
378  const typename ElementQuadratureType::CoordinateType &x = quad.point(qp); //
379  const RangeFieldType weight = quad.weight(qp) * geometry.integrationElement(x);
380 
381  RangeType values;
382  uLocal.evaluate(x, values);
383 
384  JacobianRangeType jacobian;
385  uLocal.jacobian(x, jacobian);
386 
387  HessianRangeType hessian;
388  uLocal.hessian(x, hessian);
389 
390  // Now compute the element residual
391  RangeType el_res = 0;
392  if (ImplicitConstituents::hasFlux) {
393  RangeType tmp;
394  implicitParts_.fluxDivergence(entity, quad[qp], values, jacobian, hessian, tmp);
395  el_res += tmp;
396  }
397  if (ImplicitConstituents::hasSources) {
398  RangeType tmp;
399  implicitParts_.source(entity, quad[qp], values, jacobian, tmp);
400  el_res += tmp;
401  }
402  if (ImplicitConstituents::hasBulkForces) {
403  RangeType tmp;
404  fLocal.evaluate(x, tmp);
405  el_res -= tmp;
406  }
407 
408  // Compute the contribution from the explicit part
409  RangeType oldValues;
410  uOldLocal.evaluate(x, oldValues);
411 
412  JacobianRangeType oldJacobian;
413  uOldLocal.jacobian(x, oldJacobian);
414 
415  HessianRangeType oldHessian;
416  uOldLocal.hessian(x, oldHessian);
417 
418  // add the "explicit" part. In principle overkill here
419  if (ExplicitConstituents::hasFlux) {
420  RangeType tmp;
421  explicitParts_.fluxDivergence(entity, quad[qp], values, jacobian, hessian, tmp);
422  el_res += tmp;
423  }
424  if (ExplicitConstituents::hasSources) {
425  RangeType tmp;
426  explicitParts_.source(entity, quad[qp], values, jacobian, tmp);
427  el_res += tmp;
428  }
429  if (ExplicitConstituents::hasBulkForces) {
430  // should not happen here, in principle ...
431  RangeType tmp;
432  fOldLocal.evaluate(x, tmp);
433  el_res -= tmp;
434  }
435 
436  localIndicators_[index] += hFactor * weight * (el_res * el_res);
437 
438  // Now el_res contains the space error. We also need the error
439  // from the time discretization
440  RangeType deltaU = values;
441  deltaU -= oldValues;
442 
443  timeIndicator_ += weight * (deltaU * deltaU);
444  }
445 
446  // Calculate face contribution. The explicit part is completely ignored here.
447  IntersectionIteratorType end = gridPart_.iend(entity);
448  for (IntersectionIteratorType it = gridPart_.ibegin(entity); it != end; ++it) {
449  const IntersectionType &intersection = *it;
450 
451  bool isRobin = implicitParts_.setIntersection(intersection);
452 
453  if (isProcessorBoundary(intersection)) {
454  // interior face accross a process boundary
455  estimateProcessBoundary(intersection, entity, uLocal);
456  } else if (intersection.neighbor()) {
457  // interior face
458  estimateIntersection(intersection, entity, uh, uLocal);
459  } else if (intersection.boundary()) {
460  // boundary face
461  estimateBoundary(intersection, entity, uLocal,
462  neumannBndry_.applies(intersection),
463  isRobin);
464  }
465  }
466  }
467 
469  template<class DiscreteFunctionType>
470  void estimateIntersection(const IntersectionType &intersection,
471  const ElementType &inside,
472  const DiscreteFunctionType& uh,
473  const typename DiscreteFunctionType::LocalFunctionType &uInside)
474  {
475  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
476 
477  // get outside entity pointer
478  const auto outside = intersection.outside();
479 
480  const int insideIndex = indexSet_.index(inside);
481  const int outsideIndex = indexSet_.index(outside);
482 
483  const bool isOutsideInterior = (outside.partitionType() == Dune::InteriorEntity);
484  if (!isOutsideInterior || (insideIndex < outsideIndex)) {
485  const LocalFunctionType uOutside = uh.localFunction(outside);
486 
487  RangeFieldType error;
488 
489  if (intersection.conforming())
490  error = estimateIntersection<true>(intersection, inside, uInside, outside, uOutside);
491  else
492  error = estimateIntersection<false>(intersection, inside, uInside, outside, uOutside);
493 
494  if (error > 0.0) {
495  const RangeFieldType volume
496  = 0.5 * (inside.geometry().volume() + outside.geometry().volume());
497  const RangeFieldType h = (dimension == 1 ? volume : std::pow(volume, 1.0 / (RangeFieldType)dimension));
498  const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
499  localIndicators_[insideIndex] += hFactor * error;
500  if (isOutsideInterior) {
501  localIndicators_[outsideIndex] += hFactor * error;
502  }
503  }
504  }
505  }
506 
508  template<bool conforming, class LocalFunctionType>
509  RangeFieldType estimateIntersection(const IntersectionType &intersection,
510  const ElementType &inside,
511  const LocalFunctionType &uInside,
512  const ElementType &outside,
513  const LocalFunctionType &uOutside) const
514  {
515  // make sure correct method is called
516  assert(intersection.conforming() == conforming);
517 
518  // use IntersectionQuadrature to create appropriate face quadratures
519  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
520  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
521 
522  const int quadOrder = 2 * (dfSpace_.order() - 1);
523  // create intersection quadrature
524  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
525 
526  // get appropriate quadrature references
527  const Quadrature &quadInside = intersectionQuad.inside();
528  const Quadrature &quadOutside = intersectionQuad.outside();
529 
530  const int numQuadraturePoints = quadInside.nop();
531 
532  implicitPartsNeighbour_.setEntity(outside); // go to neighbour
533 
534  RangeFieldType error = 0.0;
535  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
536  DomainType integrationNormal
537  = intersection.integrationOuterNormal(quadInside.localPoint(qp));
538  const RangeFieldType integrationElement = integrationNormal.two_norm();
539 
540  // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
541  // evaluate jacobian left and right of the interface and apply
542  // the diffusion tensor
543 
544  RangeType valueInside;
545  JacobianRangeType jacobianInside;
546  JacobianRangeType fluxInside;
547  uInside.evaluate(quadInside[qp], valueInside);
548  uInside.jacobian(quadInside[qp], jacobianInside);
549  implicitParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
550  fluxInside);
551 
552  RangeType valueOutside;
553  JacobianRangeType jacobianOutside;
554  JacobianRangeType fluxOutside;
555  uOutside.evaluate(quadOutside[qp], valueOutside);
556  uOutside.jacobian(quadOutside[qp], jacobianOutside);
557  implicitPartsNeighbour_.flux(outside, quadOutside[qp], valueOutside, jacobianOutside,
558  fluxOutside);
559 
560  // Compute difference
561  JacobianRangeType& fluxJump(fluxInside);
562  fluxJump -= fluxOutside;
563 
564  // Multiply with normal
565  RangeType jump;
566  fluxJump.mv(integrationNormal, jump);
567 
568  error += quadInside.weight(qp) * (jump * jump) / integrationElement;
569  }
570  return error;
571  }
572 
577  {
578  if (commJumpStorage_.size() == 0) {
579  // not a parallel run.
580  return;
581  }
582 
583  const bool verbose = Dune::Fem::Parameter::getValue<int>("fem.verboserank", -1) != -1;
584 
585  DataHandleType dataHandle(indexSet_, commJumpStorage_);
586 
587  gridPart_.communicate(dataHandle,
588  InteriorBorder_InteriorBorder_Interface,
589  ForwardCommunication);
590 
591  // At this point commJumpStorage_ should contain the proper
592  // differences of the boundary flux contributions. It remains
593  // to performs the actual numerical quadrature summation.
594 
595  auto commEnd = commJumpStorage_.end();
596  auto localEnd = localJumpStorage_.end();
597  auto commIt = commJumpStorage_.begin();
598  auto localIt = localJumpStorage_.begin();
599 
600  while (commIt != commEnd) {
601  assert(commIt->first == localIt->first);
602 
603  const LocalIntersectionStorage& localData = localIt->second;
604  const IntersectionStorageType& commData = commIt->second;
605 
606  const size_t numQuadraturePoints = localData.size();
607  assert(numQuadraturePoints+1 == commData.size());
608 
609  // form the square sum
610  RangeFieldType error = 0.0;
611  for (unsigned qp = 0; qp < numQuadraturePoints; ++qp) {
612  error += localData[qp] * (commData[qp] * commData[qp]);
613  }
614 
615  // add the appropriate weights
616  // HACK PLEASE FIXME;
617  RangeFieldType h = localData.hEstimate() + commData[numQuadraturePoints][0];
618  RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
619 
620  // add contribution to the estimator array
621  error *= hFactor;
622  localIndicators_[localData.bulkEntityIndex()] += error;
623 
624  errorMin[comm] = std::min(errorMin[comm], error);
625  errorMax[comm] = std::max(errorMax[comm], error);
626 
627  ++commIt;
628  ++localIt;
629  }
630 
631  assert(localIt == localEnd);
632 
633  if (verbose) {
634  size_t nFaces = commJumpStorage_.size();
635  nFaces = grid_.comm().sum(nFaces);
636 
637  if (Dune::Fem::Parameter::verbose()) {
638  dwarn << "*** Processor Boundaries: "
639  << (RangeFieldType)nFaces/2.0
640  << " Faces ***" << std::endl;
641  }
642  }
643  }
644 
657  template<class LocalFunctionType>
658  void estimateProcessBoundary(const IntersectionType &intersection,
659  const ElementType &inside,
660  const LocalFunctionType &uInside)
661  {
662  if (intersection.conforming()) {
663  estimateProcessBoundary<true>(intersection, inside, uInside);
664  } else {
665  estimateProcessBoundary<false>(intersection, inside, uInside);
666  }
667  }
668 
673  template<bool conforming, class LocalFunctionType>
674  void estimateProcessBoundary(const IntersectionType &intersection,
675  const ElementType &inside,
676  const LocalFunctionType &uInside)
677  {
678  // make sure correct method is called
679  assert(intersection.conforming() == conforming);
680 
681  // use IntersectionQuadrature to create appropriate face quadratures
682  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
683  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
684 
685  const int quadOrder = 2 * (dfSpace_.order() - 1);
686  // create intersection quadrature
687  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
688 
689  // get appropriate quadrature references
690  const Quadrature &quadInside = intersectionQuad.inside();
691  const int numQuadraturePoints = quadInside.nop();
692 
693  // FIXME: is there any easier way to get hold of the face-index?
694  IndexType faceIndex = indexSet_.index(inside.template subEntity<1>(intersection.indexInInside()));
695  IndexType bulkIndex = indexSet_.index(inside);
696 
697  // IntersectionStorageType& commData =
698  // (commJumpStorage_[faceIndex] = IntersectionStorageType(numQuadraturePoints+1));
699  // LocalIntersectionStorage& localData =
700  // (localJumpStorage_[faceIndex] = LocalIntersectionStorage(bulkIndex, numQuadraturePoints));
701  IntersectionStorageType commData = IntersectionStorageType(numQuadraturePoints+1);
702  LocalIntersectionStorage localData = LocalIntersectionStorage(bulkIndex, numQuadraturePoints);
703 
704  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
705  DomainType integrationNormal
706  = intersection.integrationOuterNormal(quadInside.localPoint(qp));
707  const RangeFieldType integrationElement = integrationNormal.two_norm();
708  integrationNormal /= integrationElement;
709 
710  // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
711  // evaluate jacobian left and right of the interface and apply
712  // the diffusion tensor
713 
714  RangeType valueInside;
715  JacobianRangeType jacobianInside;
716  JacobianRangeType fluxInside;
717  uInside.evaluate(quadInside[qp], valueInside);
718  uInside.jacobian(quadInside[qp], jacobianInside);
719  implicitParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
720  fluxInside);
721 
722  // Multiply with normal and store in the communication array
723  fluxInside.mv(integrationNormal, commData[qp]);
724 
725  // Remember weight and integration element for this point
726  localData[qp] = quadInside.weight(qp) * integrationElement;
727  }
728  localData.hEstimate() = hEstimate(inside.geometry());
729  // THIS IS A HACK. PLEASE FIXME
730  commData[numQuadraturePoints][0] = localData.hEstimate();
731 
732  commJumpStorage_[faceIndex] = commData;
733  localJumpStorage_[faceIndex] = localData;
734  }
735 
743  template<class LocalFunctionType>
744  void estimateBoundary(const IntersectionType &intersection,
745  const ElementType &inside,
746  const LocalFunctionType &uLocal,
747  bool isNeumann, bool isRobin)
748  {
749  assert(intersection.conforming() == true);
750 
751  if (!isNeumann && !isRobin) {
752  return;
753  }
754 
755  // Maybe optimize away if not Neumann.
756  const NeumannLocalFunctionType neumannLocal = neumannFunction_.localFunction(inside, intersection);
757 
758  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, true /* conforming */> IntersectionQuadratureType;
759  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
760 
761  // TODO: make more realistic assumptions on the
762  // quad-order. HOWTO?
763  int quadOrder = isRobin ? 2*dfSpace_.order() : 2*(dfSpace_.order() - 1);
764 
765  // create intersection quadrature
766  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
767  // get appropriate quadrature references
768  const Quadrature &bndryQuad = intersectionQuad.inside();
769  const int numQuadraturePoints = bndryQuad.nop();
770 
771  RangeFieldType error = 0.0;
772 
773  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
774  const RangeFieldType weight = bndryQuad.weight(qp);
775 
776  // Get the un-normalized outer normal
777  DomainType integrationNormal
778  = intersection.integrationOuterNormal(bndryQuad.localPoint(qp));
779 
780  const RangeFieldType integrationElement = integrationNormal.two_norm();
781  integrationNormal /= integrationElement;
782 
783  RangeType value;
784  uLocal.evaluate(bndryQuad[qp], value);
785  JacobianRangeType jacobian;
786  uLocal.jacobian(bndryQuad[qp], jacobian);
787 
788  JacobianRangeType flux;
789  implicitParts_.flux(inside, bndryQuad[qp], value, jacobian, flux);
790 
791  RangeType residual;
792  flux.mv(integrationNormal, residual);
793 
794  if (isRobin) {
795  RangeType alphau;
796  implicitParts_.robinFlux(intersection, bndryQuad[qp], integrationNormal, value, alphau);
797  residual += alphau;
798  }
799 
800  if (isNeumann) {
801  RangeType gN;
802  neumannLocal.evaluate(bndryQuad[qp], gN);
803  residual -= gN;
804  }
805 
806  error += weight * integrationElement * (residual * residual);
807  }
808 
809  if (error > 0.0) {
810  // Get index into estimator vector
811  const int insideIndex = indexSet_.index(inside);
812 
813  const RangeFieldType volume = inside.geometry().volume();
814 
815  const RangeFieldType h = (dimension == 1 ? volume : std::pow(volume, 1.0 / (RangeFieldType)dimension));
816  const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
817  localIndicators_[insideIndex] += hFactor * error;
818  }
819  }
820  };
821 
822  template<class OldSolutionFunction, class TimeProvider, class ImplicitModel, class ExplicitModel>
823  struct EstimatorTraits<ParabolicEulerEstimator<OldSolutionFunction, TimeProvider, ImplicitModel, ExplicitModel> >
824  {
825  typedef typename OldSolutionFunction::DiscreteFunctionSpaceType DiscreteFunctionSpaceType;
826  typedef typename
827  std::vector<typename DiscreteFunctionSpaceType::RangeFieldType>::const_iterator
828  IteratorType;
829  };
830 
832 
834 
835  } // ACFem::
836 
837 } // Dune::
838 
839 #endif // __PARABOLIC_ESTIMATOR_HH__
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
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
Residual estimator for the heat equation.
Definition: parabolicestimator.hh:60
void estimateBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uLocal, bool isNeumann, bool isRobin)
caclulate error over a boundary segment; yields zero for Dirichlet boundary values,...
Definition: parabolicestimator.hh:744
void communicateJumpContributions()
Helper function in order to add the jump contributions on inter-process boundaries.
Definition: parabolicestimator.hh:576
void estimateLocal(const ElementType &entity, const DiscreteFunctionType &uh)
caclulate error on element
Definition: parabolicestimator.hh:355
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:470
void estimateProcessBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Compute the jump contribution to the estimator on process-boundaries.
Definition: parabolicestimator.hh:658
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:674
RangeFieldType estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside, const ElementType &outside, const LocalFunctionType &uOutside) const
caclulate error on element intersections
Definition: parabolicestimator.hh:509
RangeFieldType estimate(const DiscreteFunctionType &uh)
calculate estimator
Definition: parabolicestimator.hh:250
bool isProcessorBoundary(const Intersection &intersection)
Retrun true if at the border to another computing note.
Definition: boundaryindicator.hh:134
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)