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