DUNE-ACFEM (2.5.1)

ellipticestimator.hh
1 #ifndef __ELLIPTIC_ESTIMATOR_HH__
2 #define __ELLIPTIC_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 
34  template<class DiscreteFunctionSpace, class Model, enum FunctionSpaceNorm Norm = H1Norm>
36  : public DefaultEstimator<EllipticEstimator<DiscreteFunctionSpace, Model, Norm> >
37  {
39  typedef DefaultEstimator<ThisType> BaseType;
40  public:
41  // Interface types
42  typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
43  typedef typename DiscreteFunctionSpaceType::RangeFieldType RangeFieldType; // aka double
44  typedef typename DiscreteFunctionSpaceType::GridPartType GridPartType;
45  typedef typename GridPartType::GridType GridType;
46  typedef typename GridType::template Codim<0>::Entity ElementType;
47  protected:
48  typedef std::vector<RangeFieldType> ErrorIndicatorType;
49  public:
50  typedef typename ErrorIndicatorType::const_iterator IteratorType;
51 
52  protected:
53  // Everything else why might need
56  typedef typename ModelType::OperatorPartsType OperatorPartsType;
57 
58  typedef typename DiscreteFunctionSpaceType::DomainFieldType DomainFieldType;
59  typedef typename DiscreteFunctionSpaceType::DomainType DomainType;
60  typedef typename DiscreteFunctionSpaceType::RangeType RangeType;
61  typedef typename DiscreteFunctionSpaceType::JacobianRangeType JacobianRangeType;
62 
63  // Various data functions ...
64  typedef typename ModelType::BulkForcesFunctionType BulkForcesFunctionType;
65  typedef typename BulkForcesFunctionType::LocalFunctionType BulkForcesLocalFunctionType;
66  typedef typename ModelType::DirichletBoundaryFunctionType DirichletFunctionType;
67  typedef typename DirichletFunctionType::LocalFunctionType DirichletLocalFunctionType;
68  typedef typename ModelType::NeumannBoundaryFunctionType NeumannFunctionType;
69  typedef typename NeumannFunctionType::LocalFunctionType NeumannLocalFunctionType;
70 
71  // Boundary classification
72  typedef typename ModelType::DirichletIndicatorType DirichletIndicatorType;
73  typedef typename ModelType::NeumannIndicatorType NeumannIndicatorType;
74 
75  //typedef typename GridPartType::GridType GridType;
76  typedef typename DiscreteFunctionSpaceType::IteratorType GridIteratorType;
77  typedef typename GridPartType::IndexSetType IndexSetType;
78  typedef typename IndexSetType::IndexType IndexType;
79  typedef typename GridPartType::IntersectionIteratorType IntersectionIteratorType;
80 
81  typedef typename IntersectionIteratorType::Intersection IntersectionType;
82 
83  typedef typename ElementType::Geometry GeometryType;
84  static const int dimension = GridType::dimension;
85 
86  typedef Dune::Fem::CachingQuadrature<GridPartType, 0> ElementQuadratureType;
87  typedef Dune::Fem::CachingQuadrature<GridPartType, 1> FaceQuadratureType;
88 
89  //typedef Dune::Fem::ElementQuadrature<GridPartType, 0> ElementQuadratureType;
90  //typedef Dune::Fem::ElementQuadrature<GridPartType, 1> FaceQuadratureType;
91 
92  typedef Dune::FieldMatrix<DomainFieldType,dimension,dimension> JacobianInverseType;
93 
94  protected:
95  const ModelType& model_; //< The underlying model.
96  OperatorPartsType operatorParts_;
97  OperatorPartsType operatorPartsNeighbour_;
98 
99  const DiscreteFunctionSpaceType &dfSpace_;
100  GridPartType &gridPart_;
101  const IndexSetType &indexSet_;
102  GridType &grid_;
103 
104  private:
105  BulkForcesFunctionType bulkForcesFunction_;
106  NeumannFunctionType neumannFunction_;
107  NeumannIndicatorType neumannBndry_;
108  DirichletIndicatorType dirichletBndry_;
109  ErrorIndicatorType localIndicators_;
110  mutable std::vector<JacobianRangeType> outsideFaceFluxCache;
111 
120  enum { bulk, jump, bdry, comm, numContributions };
121  RangeFieldType errorMin[numContributions];
122  RangeFieldType errorMax[numContributions];
123 
134  typedef RangeType DataItemType;
135  typedef std::vector<DataItemType> IntersectionStorageType;
136  typedef std::map<IndexType, IntersectionStorageType> CommunicationStorageType;
137  typedef typename Fem::DFCommunicationOperation::Add OperationType;
139 
147  class LocalIntersectionStorage
148  {
149  typedef std::vector<RangeFieldType> WeightStorageType;
150  public:
151  LocalIntersectionStorage()
152  {}
153  LocalIntersectionStorage(IndexType bulkEntityIndex, size_t nop)
154  : bulkEntityIndex_(bulkEntityIndex), weights_(nop), h_(0)
155  {}
156  IndexType bulkEntityIndex() const { return bulkEntityIndex_; }
157  IndexType& bulkEntityIndex() { return bulkEntityIndex_; }
158  const RangeFieldType& operator[](size_t idx) const { return weights_[idx]; }
159  RangeFieldType& operator[](size_t idx) { return weights_[idx]; }
160  size_t size() const { return weights_.size(); }
161  RangeFieldType& hEstimate() { return h_; }
162  const RangeFieldType& hEstimate() const { return h_; }
163  private:
164  IndexType bulkEntityIndex_;
165  WeightStorageType weights_;
166  RangeFieldType h_;
167  };
168  typedef std::map<IndexType, LocalIntersectionStorage> LocalStorageType;
169 
170  LocalStorageType localJumpStorage_;
171  CommunicationStorageType commJumpStorage_;
172 
175  public:
176  explicit EllipticEstimator(const ModelType& model, const DiscreteFunctionSpaceType& dfSpace)
177  : model_(model),
178  operatorParts_(model.operatorParts()),
179  operatorPartsNeighbour_(model.operatorParts()),
180  dfSpace_(dfSpace),
181  gridPart_(dfSpace_.gridPart()),
182  indexSet_(gridPart_.indexSet()),
183  grid_(gridPart_.grid()),
184  bulkForcesFunction_(model.bulkForcesFunction(gridPart_)),
185  neumannFunction_(model.neumannBoundaryFunction(gridPart_)),
186  neumannBndry_(model.neumannIndicator()),
187  dirichletBndry_(model.dirichletIndicator())
188  {
189  localIndicators_.resize(indexSet_.size(0));
190  }
191 
193  template<class DiscreteFunctionType>
194  RangeFieldType estimate(const DiscreteFunctionType& uh)
195  {
197 
198  // clear all local estimators
199  clear();
200 
201  RangeFieldType hMax = 0.0;
202 
203  // calculate local estimator
204  const GridIteratorType end = dfSpace_.end();
205  for (GridIteratorType it = dfSpace_.begin(); it != end; ++it) {
206  estimateLocal(*it, uh);
207  hMax = std::max(hMax, hEstimate(it->geometry()));
208  }
209 
210  // do the comm-stuff at inter-process boundaries
212 
213  RangeFieldType error = 0.0;
214 
215  // sum up local estimators
216  const IteratorType endEstimator = localIndicators_.end();
217  for (IteratorType it = localIndicators_.begin(); it != endEstimator; ++it) {
218  error += *it;
219  }
220 
221  // obtain global sum
222  error = grid_.comm().sum(error);
223 
224  grid_.comm().max(errorMax, numContributions);
225  grid_.comm().min(errorMin, numContributions);
226 
227  if (Dune::Fem::Parameter::verbose()) {
228  // print error estimator if on node 0
229  std::cout << "Estimated " << (Norm == L2Norm ? "L2" : "H1") << "-Error: "
230  << std::sqrt(error) << " (squared: " << error << ")" << std::endl;
231  const char *errorNames[numContributions] = { "bulk", "jump", "bdry", "comm" };
232  for (int i = 0; i < numContributions; ++i) {
233  if (errorMax[i] == 0.0) {
234  continue; // no contribution, just skip
235  }
236  std::cout << " " << errorNames[i] << "^2 min: " << errorMin[i] << std::endl;
237  std::cout << " " << errorNames[i] << "^2 max: " << errorMax[i] << std::endl;
238  }
239  std::cout << "hMax: " << hMax << std::endl;
240  }
241  return std::sqrt(error);
242  }
243 
244  const RangeFieldType& operator[](const size_t& idx) const
245  {
246  return localIndicators_[idx];
247  }
248 
249  const RangeFieldType& operator[](const ElementType& entity) const
250  {
251  return (*this)[indexSet_.index(entity)];
252  }
253 
254  size_t size() const
255  {
256  return indexSet_.size(0);
257  }
258 
259  IteratorType begin() const {
260  return localIndicators_.begin();
261  }
262 
263  IteratorType end() const {
264  return localIndicators_.end();
265  }
266 
267  GridType& grid() const
268  {
269  return grid_;
270  }
271 
272  const DiscreteFunctionSpaceType& space() const
273  {
274  return dfSpace_;
275  }
276 
277  protected:
278  void clear()
279  {
280  // resize and clear
281  localIndicators_.resize(indexSet_.size(0));
282  const typename ErrorIndicatorType::iterator end = localIndicators_.end();
283  for (typename ErrorIndicatorType::iterator it = localIndicators_.begin();
284  it != end; ++it) {
285  *it = 0.0;
286  }
287 
288  // the communication hack for parallel runs. Gnah.
289  localJumpStorage_.clear();
290  commJumpStorage_.clear();
291 
292  // debugging and stuff
293  errorMin[bulk] =
294  errorMin[jump] =
295  errorMin[bdry] =
296  errorMin[comm] = std::numeric_limits<RangeFieldType>::max();
297 
298  errorMax[bulk] =
299  errorMax[jump] =
300  errorMax[bdry] =
301  errorMax[comm] = 0.0;
302  }
303 
305  template<class DiscreteFunctionType>
306  void estimateLocal(const ElementType &entity, const DiscreteFunctionType& uh)
307  {
308  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
309 
310  const typename ElementType::Geometry &geometry = entity.geometry();
311  const RangeFieldType h2 = h2Estimate(geometry);
312  const RangeFieldType hFactor = Norm == L2Norm ? h2*h2 : h2;
313  const int index = indexSet_.index(entity);
314  const LocalFunctionType uLocal = uh.localFunction(entity);
315  const BulkForcesLocalFunctionType fLocal = bulkForcesFunction_.localFunction(entity);
316 
317  ElementQuadratureType quad(entity, 2*(dfSpace_.order() + 1));
318 
319  operatorParts_.setEntity(entity);
320 
321  RangeFieldType localEstimate = 0.0;
322  const int numQuadraturePoints = quad.nop();
323  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
324 
325  const typename ElementQuadratureType :: CoordinateType &x = quad.point(qp); //
326  const RangeFieldType weight = quad.weight(qp) * geometry.integrationElement(x);
327 
328  typename LocalFunctionType::RangeType values;
329  uLocal.evaluate(x, values);
330 
331  typename LocalFunctionType::JacobianRangeType jacobian;
332  uLocal.jacobian(x, jacobian);
333 
334  typename LocalFunctionType::HessianRangeType hessian;
335  uLocal.hessian(x, hessian);
336 
337  // Now compute the element residual
338  RangeType el_res(0.);
339  if (Constituents::hasFlux) {
340  RangeType tmp;
341  operatorParts_.fluxDivergence(entity, quad[qp], values, jacobian, hessian, tmp);
342  el_res += tmp;
343  }
344  if (Constituents::hasSources) {
345  RangeType tmp;
346  operatorParts_.source(entity, quad[qp], values, jacobian, tmp);
347  el_res += tmp;
348  }
349  if (Constituents::hasBulkForces) {
350  RangeType tmp;
351  fLocal.evaluate(x, tmp);
352  el_res -= tmp;
353  }
354 
355  localEstimate += hFactor * weight * (el_res * el_res);
356  }
357  localIndicators_[index] += localEstimate;
358 
359  errorMin[bulk] = std::min(errorMin[bulk], localEstimate);
360  errorMax[bulk] = std::max(errorMax[bulk], localEstimate);
361 
362  // calculate face contribution
363  IntersectionIteratorType end = gridPart_.iend(entity);
364  for (IntersectionIteratorType it = gridPart_.ibegin(entity); it != end; ++it) {
365 
366  const IntersectionType &intersection = *it;
367 
368  if (isProcessorBoundary(intersection)) {
369  // interior face accross a process boundary
370  estimateProcessorBoundary(intersection, entity, uLocal);
371  } else if (intersection.neighbor()) {
372  // interior face
373  estimateIntersection(intersection, entity, uh, uLocal);
374  } else if (intersection.boundary() && !dirichletBndry_.applies(intersection)) {
375  // boundary face
376  bool isRobin = operatorParts_.setIntersection(intersection);
377 
378  estimateBoundary(intersection, entity, uLocal,
379  neumannBndry_.applies(intersection),
380  isRobin);
381  }
382  }
383  }
384 
386  template<class DiscreteFunctionType>
387  void estimateIntersection (const IntersectionType &intersection,
388  const ElementType &inside,
389  const DiscreteFunctionType& uh,
390  const typename DiscreteFunctionType::LocalFunctionType &uInside)
391  {
392  typedef typename DiscreteFunctionType::LocalFunctionType LocalFunctionType;
393 
394  // get outside entity pointer
395  const auto outside = intersection.outside();
396 
397  const int insideIndex = indexSet_.index(inside);
398  const int outsideIndex = indexSet_.index(outside);
399 
400  const bool isOutsideInterior = (outside.partitionType() == Dune::InteriorEntity);
401  if (!isOutsideInterior || (insideIndex < outsideIndex)) {
402  const LocalFunctionType uOutside = uh.localFunction(outside);
403 
404  RangeFieldType error;
405 
406  if (intersection.conforming())
407  error = estimateIntersection<true>(intersection, inside, uInside, outside, uOutside);
408  else
409  error = estimateIntersection<false>(intersection, inside, uInside, outside, uOutside);
410 
411  if (error > 0.0) {
412  const RangeFieldType h = 0.5 * (hEstimate(inside.geometry()) + hEstimate(outside.geometry()));
413  const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
414  error *= hFactor;
415  localIndicators_[insideIndex] += error;
416  if (isOutsideInterior) {
417  localIndicators_[outsideIndex] += error;
418  }
419  }
420 
421  errorMin[jump] = std::min(errorMin[jump], error);
422  errorMax[jump] = std::max(errorMax[jump], error);
423  }
424  }
425 
434  template<bool conforming, class LocalFunctionType>
435  RangeFieldType estimateIntersection(const IntersectionType &intersection,
436  const ElementType &inside,
437  const LocalFunctionType &uInside,
438  const ElementType &outside,
439  const LocalFunctionType &uOutside) const
440  {
441  // make sure correct method is called
442  assert(intersection.conforming() == conforming);
443 
444  // use IntersectionQuadrature to create appropriate face quadratures
445  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
446  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
447 
448  const int quadOrder = 2 * (dfSpace_.order() - 1);
449  // create intersection quadrature
450  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
451 
452  // get appropriate quadrature references
453  const Quadrature &quadInside = intersectionQuad.inside();
454  const Quadrature &quadOutside = intersectionQuad.outside();
455 
456  const int numQuadraturePoints = quadInside.nop();
457 
458  operatorPartsNeighbour_.setEntity(outside); // go to neighbour
459  RangeFieldType error = 0.0;
460  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
461  DomainType integrationNormal
462  = intersection.integrationOuterNormal(quadInside.localPoint(qp));
463  const RangeFieldType integrationElement = integrationNormal.two_norm();
464 
465  // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
466  // evaluate jacobian left and right of the interface and apply
467  // the diffusion tensor
468 
469  RangeType valueInside, valueOutside;
470  JacobianRangeType jacobianInside, jacobianOutside;
471  JacobianRangeType fluxInside, fluxOutside;
472  uInside.evaluate(quadInside[qp], valueInside);
473  uInside.jacobian(quadInside[qp], jacobianInside);
474  operatorParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
475  fluxInside);
476  uOutside.evaluate(quadOutside[qp], valueOutside);
477  uOutside.jacobian(quadOutside[qp], jacobianOutside);
478  operatorPartsNeighbour_.flux(outside, quadOutside[qp], valueOutside, jacobianOutside,
479  fluxOutside);
480 
481  // Compute difference
482  JacobianRangeType& fluxJump(fluxInside);
483  fluxJump -= fluxOutside;
484 
485  // Multiply with normal
486  RangeType jump;
487  fluxJump.mv(integrationNormal, jump);
488 
489  error += quadInside.weight(qp) * (jump * jump) / integrationElement;
490  }
491  return error;
492  }
493 
498  {
499  if (commJumpStorage_.size() == 0) {
500  // not a parallel run.
501  return;
502  }
503 
504  const bool verbose = Dune::Fem::Parameter::getValue<int>("fem.verboserank", -1) != -1;
505 
506  DataHandleType dataHandle(indexSet_, commJumpStorage_);
507 
508  gridPart_.communicate(dataHandle,
509  InteriorBorder_InteriorBorder_Interface,
510  ForwardCommunication);
511 
512  // At this point commJumpStorage_ should contain the proper
513  // differences of the boundary flux contributions. It remains
514  // to performs the actual numerical quadrature summation.
515 
516  auto commEnd = commJumpStorage_.end();
517  auto commIt = commJumpStorage_.begin();
518  auto localIt = localJumpStorage_.begin();
519 
520  while (commIt != commEnd) {
521  assert(commIt->first == localIt->first);
522 
523  const LocalIntersectionStorage& localData = localIt->second;
524  const IntersectionStorageType& commData = commIt->second;
525 
526  const size_t numQuadraturePoints = localData.size();
527  assert(numQuadraturePoints+1 == commData.size());
528 
529  // form the square sum
530  RangeFieldType error = 0.0;
531  for (unsigned qp = 0; qp < numQuadraturePoints; ++qp) {
532  error += localData[qp] * (commData[qp] * commData[qp]);
533  }
534 
535  // add the appropriate weights
536  // Storing the h-estimate in the last component of commData is a hack, PLEASE FIX ME ;)
537  // Note that after communication commData[#QP][0] already
538  // contains the sum of the h-estimate from both side.
539  RangeFieldType h = 0.5 * commData[numQuadraturePoints][0];
540  RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
541 
542  // add contribution to the estimator array
543  error *= hFactor;
544  localIndicators_[localData.bulkEntityIndex()] += error;
545 
546  errorMin[comm] = std::min(errorMin[comm], error);
547  errorMax[comm] = std::max(errorMax[comm], error);
548 
549  ++commIt;
550  ++localIt;
551  }
552 
553  assert(localIt == localJumpStorage_.end());
554 
555  if (verbose) {
556  size_t nFaces = commJumpStorage_.size();
557  nFaces = grid_.comm().sum(nFaces);
558 
559  if (Dune::Fem::Parameter::verbose()) {
560  dwarn << "*** Processor Boundaries: "
561  << (RangeFieldType)nFaces/2.0
562  << " Faces ***" << std::endl;
563  }
564  }
565  }
566 
579  template<class LocalFunctionType>
580  void estimateProcessorBoundary(const IntersectionType &intersection,
581  const ElementType &inside,
582  const LocalFunctionType &uInside)
583  {
584  if (intersection.conforming()) {
585  estimateProcessorBoundary<true>(intersection, inside, uInside);
586  } else {
587  estimateProcessorBoundary<false>(intersection, inside, uInside);
588  }
589  }
590 
595  template<bool conforming, class LocalFunctionType>
596  void estimateProcessorBoundary(const IntersectionType &intersection,
597  const ElementType &inside,
598  const LocalFunctionType &uInside)
599  {
600  // make sure correct method is called
601  assert(intersection.conforming() == conforming);
602 
603  // use IntersectionQuadrature to create appropriate face quadratures
604  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, conforming> IntersectionQuadratureType;
605  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
606 
607  const int quadOrder = 2 * (dfSpace_.order() - 1);
608  // create intersection quadrature
609  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
610 
611  // get appropriate quadrature references
612  const Quadrature &quadInside = intersectionQuad.inside();
613  const int numQuadraturePoints = quadInside.nop();
614 
615  // FIXME: is there any easier way to get hold of the face-index?
616  IndexType faceIndex = indexSet_.index(inside.template subEntity<1>(intersection.indexInInside()));
617  IndexType bulkIndex = indexSet_.index(inside);
618 
619  // IntersectionStorageType& commData =
620  // (commJumpStorage_[faceIndex] = IntersectionStorageType(numQuadraturePoints+1));
621  // LocalIntersectionStorage& localData =
622  // (localJumpStorage_[faceIndex] = LocalIntersectionStorage(bulkIndex, numQuadraturePoints));
623  IntersectionStorageType commData = IntersectionStorageType(numQuadraturePoints+1);
624  LocalIntersectionStorage localData = LocalIntersectionStorage(bulkIndex, numQuadraturePoints);
625 
626  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
627  DomainType integrationNormal
628  = intersection.integrationOuterNormal(quadInside.localPoint(qp));
629  const RangeFieldType integrationElement = integrationNormal.two_norm();
630  integrationNormal /= integrationElement;
631 
632  // evaluate | (d u_l * n_l) + (d u_r * n_r) | = | (d u_l - d u_r) * n_l |
633  // evaluate jacobian left and right of the interface and apply
634  // the diffusion tensor
635 
636  RangeType valueInside;
637  JacobianRangeType jacobianInside;
638  JacobianRangeType fluxInside;
639  uInside.evaluate(quadInside[qp], valueInside);
640  uInside.jacobian(quadInside[qp], jacobianInside);
641  operatorParts_.flux(inside, quadInside[qp], valueInside, jacobianInside,
642  fluxInside);
643 
644  // Multiply with normal and store in the communication array
645  fluxInside.mv(integrationNormal, commData[qp]);
646 
647  // Remember weight and integration element for this point
648  localData[qp] = quadInside.weight(qp) * integrationElement;
649  }
650  localData.hEstimate() = hEstimate(inside.geometry());
651  // THIS IS A HACK. PLEASE FIXME
652  commData[numQuadraturePoints][0] = localData.hEstimate();
653 
654  commJumpStorage_[faceIndex] = commData;
655  localJumpStorage_[faceIndex] = localData;
656  }
657 
665  template<class LocalFunctionType>
666  void estimateBoundary(const IntersectionType &intersection,
667  const ElementType &inside,
668  const LocalFunctionType &uLocal,
669  bool isNeumann, bool isRobin)
670  {
671  assert(intersection.conforming() == true);
672 
673  if (!isNeumann && !isRobin) {
674  return;
675  }
676 
677  // Maybe optimize away if not Neumann.
678  const NeumannLocalFunctionType neumannLocal = neumannFunction_.localFunction(inside, intersection);
679 
680  typedef Dune::Fem::IntersectionQuadrature<FaceQuadratureType, true /* conforming */> IntersectionQuadratureType;
681  typedef typename IntersectionQuadratureType::FaceQuadratureType Quadrature ;
682 
683  // TODO: make more realistic assumptions on the
684  // quad-order. HOWTO?
685  int quadOrder = isRobin ? 2*dfSpace_.order() : 2*(dfSpace_.order() - 1);
686 
687  // create intersection quadrature
688  IntersectionQuadratureType intersectionQuad(gridPart_, intersection, quadOrder);
689  // get appropriate quadrature references
690  const Quadrature &bndryQuad = intersectionQuad.inside();
691  const int numQuadraturePoints = bndryQuad.nop();
692 
693  RangeFieldType error = 0.0;
694 
695  for (int qp = 0; qp < numQuadraturePoints; ++qp) {
696  const RangeFieldType weight = bndryQuad.weight(qp);
697 
698  // Get the un-normalized outer normal
699  DomainType integrationNormal
700  = intersection.integrationOuterNormal(bndryQuad.localPoint(qp));
701 
702  const RangeFieldType integrationElement = integrationNormal.two_norm();
703  integrationNormal /= integrationElement;
704 
705  RangeType value;
706  uLocal.evaluate(bndryQuad[qp], value);
707  JacobianRangeType jacobian;
708  uLocal.jacobian(bndryQuad[qp], jacobian);
709 
710  JacobianRangeType flux;
711  operatorParts_.flux(inside, bndryQuad[qp], value, jacobian, flux);
712 
713  RangeType residual;
714  flux.mv(integrationNormal, residual);
715 
716  if (isRobin) {
717  RangeType alphau;
718  operatorParts_.robinFlux(intersection, bndryQuad[qp], integrationNormal, value, alphau);
719  residual += alphau;
720  }
721 
722  if (isNeumann) {
723  RangeType gN;
724  neumannLocal.evaluate(bndryQuad[qp], gN);
725  residual -= gN;
726  }
727 
728  error += weight * integrationElement * (residual * residual);
729  }
730 
731  if (error > 0.0) {
732  // Get index into estimator vector
733  const int insideIndex = indexSet_.index(inside);
734 
735  const RangeFieldType volume = inside.geometry().volume();
736 
737  const RangeFieldType h = (dimension == 1 ? volume : std::pow(volume, 1.0 / (RangeFieldType)dimension));
738  const RangeFieldType hFactor = Norm == L2Norm ? h * h * h : h;
739  error *= hFactor;
740  localIndicators_[insideIndex] += error;
741  }
742 
743  errorMin[bdry] = std::min(errorMin[bdry], error);
744  errorMax[bdry] = std::max(errorMax[bdry], error);
745  }
746  };
747 
748  template<class DiscreteFunctionSpace, class Model, enum FunctionSpaceNorm Norm>
749  struct EstimatorTraits<EllipticEstimator<DiscreteFunctionSpace, Model, Norm> >
750  {
751  typedef DiscreteFunctionSpace DiscreteFunctionSpaceType;
752  typedef typename
753  std::vector<typename DiscreteFunctionSpaceType::RangeFieldType>::const_iterator
754  IteratorType;
755  };
756 
758 
760 
761  } // ACFem:.
762 
763 } // Dune::
764 
765 #endif // __ELLIPTIC_ESTIMATOR_HH__
An standard residual estimator for elliptic problems.
Definition: ellipticestimator.hh:37
void estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const DiscreteFunctionType &uh, const typename DiscreteFunctionType::LocalFunctionType &uInside)
caclulate error on element boundary intersections
Definition: ellipticestimator.hh:387
RangeFieldType estimate(const DiscreteFunctionType &uh)
calculate estimator
Definition: ellipticestimator.hh:194
void estimateProcessorBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Compute the jump contribution to the estimator on process-boundaries.
Definition: ellipticestimator.hh:580
void estimateBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uLocal, bool isNeumann, bool isRobin)
calculate error over a boundary segment; yields zero for Dirichlet boundary values,...
Definition: ellipticestimator.hh:666
RangeFieldType estimateIntersection(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside, const ElementType &outside, const LocalFunctionType &uOutside) const
caclulate error on element intersections
Definition: ellipticestimator.hh:435
void communicateJumpContributions()
Helper function in order to add the jump contributions on inter-process boundaries.
Definition: ellipticestimator.hh:497
void estimateLocal(const ElementType &entity, const DiscreteFunctionType &uh)
caclulate error on element
Definition: ellipticestimator.hh:306
void estimateProcessorBoundary(const IntersectionType &intersection, const ElementType &inside, const LocalFunctionType &uInside)
Helper function for estimateProcessorBoundary() in order to distinguish between conforming and non-co...
Definition: ellipticestimator.hh:596
General intersection - intersection communication which communicates for each intersection a potentia...
Definition: intersectiondatahandle.hh:48
Interface class for second order elliptic models.
Definition: modelinterface.hh:192
NeumannBoundaryFunctionType neumannBoundaryFunction(const GridPartType &gridPart) const
Generate an instance of a class defining Neumann boundary values as a Fem grid-function.
Definition: modelinterface.hh:302
OperatorPartsType operatorParts() const
Return the integral kernels for the bilinear form.
Definition: modelinterface.hh:253
DirichletIndicatorType dirichletIndicator() const
Generate an object to identify parts of the boundary subject to Dirichlet boundary conditions.
Definition: modelinterface.hh:310
BulkForcesFunctionType bulkForcesFunction(const GridPartType &gridPart) const
Generate an instance of a class defining the bulk-forces the model is subject to.
Definition: modelinterface.hh:263
TraitsType::DirichletBoundaryFunctionType DirichletBoundaryFunctionType
A BoundarySupportedFunction which must be sub-ordinate to the DirichletIndicatorType.
Definition: modelinterface.hh:241
TraitsType::DirichletIndicatorType DirichletIndicatorType
A BoundarySupportedFunction which must be sub-ordinate to the DirichletIndicatorType.
Definition: modelinterface.hh:243
TraitsType::BulkForcesFunctionType BulkForcesFunctionType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:226
TraitsType::NeumannBoundaryFunctionType NeumannBoundaryFunctionType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:227
TraitsType::NeumannIndicatorType NeumannIndicatorType
A function modelling "force" terms in the bulk-phase.
Definition: modelinterface.hh:228
NeumannIndicatorType neumannIndicator() const
Generate an object to identify parts of the boundary subject to Neumann boundary conditions.
Definition: modelinterface.hh:318
bool isProcessorBoundary(const Intersection &intersection)
Retrun true if at the border to another computing note.
Definition: boundaryindicator.hh:134
Geometry::ctype h2Estimate(const Geometry &geometry)
Compute a rough estimate of the square of the diameter of the element's Geometry.
Definition: geometry.hh:18
Geometry::ctype hEstimate(const Geometry &geometry)
Compute a rough estimate of the diameter of the element's Geometry.
Definition: geometry.hh:39
LocalFunctionWrapper< LocalMaxAdapter< GridFunction1, GridFunction2 >, typename GridFunction1::GridPartType > max(const Fem::Function< typename GridFunction1::FunctionSpaceType, GridFunction1 > &f1, const Fem::Function< typename GridFunction2::FunctionSpaceType, GridFunction2 > &f2, const std::string &name="")
Pointwise maximum of two given functions.
Definition: maxfunction.hh:121
A helper class which identifies which components are provided by the given model.
Definition: modelinterface.hh:447
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 16, 22:29, 2024)