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
18namespace 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] =
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.111.3 (Aug 13, 22:30, 2024)