23#ifndef DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
24#define DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
73template<
class TypeTag>
81 dim = GridView::dimension, dimWorld = GridView::dimensionworld
87 using ReferenceElements = Dune::ReferenceElements<Scalar, dim>;
89 using SpatialParams =
typename GET_PROP_TYPE(TypeTag, SpatialParams);
90 using MaterialLaw =
typename SpatialParams::MaterialLaw;
92 using Indices =
typename GET_PROP_TYPE(TypeTag, ModelTraits)::Indices;
94 using FluidSystem =
typename GET_PROP_TYPE(TypeTag, FluidSystem);
95 using FluidState =
typename GET_PROP_TYPE(TypeTag, FluidState);
97 using BoundaryTypes =
typename GET_PROP_TYPE(TypeTag, BoundaryTypes);
100 using SolutionTypes =
typename GET_PROP(TypeTag, SolutionTypes);
102 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
103 using ScalarSolutionType =
typename SolutionTypes::ScalarSolution;
105 using GridTypeIndices =
typename GET_PROP_TYPE(TypeTag, GridTypeIndices);
109 pw = Indices::pressureW,
110 pn = Indices::pressureNw,
111 sw = Indices::saturationW,
112 sn = Indices::saturationNw
116 wPhaseIdx = Indices::wPhaseIdx,
117 nPhaseIdx = Indices::nPhaseIdx,
118 pressureIdx = Indices::pressureIdx,
119 saturationIdx = Indices::saturationIdx,
120 pressEqIdx = Indices::pressureEqIdx,
121 satEqIdx = Indices::satEqIdx,
129 dirichletDirichlet = 1,
130 dirichletNeumann = 2,
135 using Element =
typename GridView::Traits::template Codim<0>::Entity;
136 using IntersectionIterator =
typename GridView::IntersectionIterator;
137 using Intersection =
typename GridView::Intersection;
138 using Grid =
typename GridView::Grid;
140 using LocalPosition = Dune::FieldVector<Scalar, dim>;
141 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
142 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
144 using DimVector = Dune::FieldVector<Scalar, dim>;
159 using GlobalInteractionVolumeVector = std::vector<InteractionVolume>;
160 using InnerBoundaryVolumeFaces = std::vector<Dune::FieldVector<bool, 2*dim> >;
163 Intersection getNextIntersection_(
const Element&,
const IntersectionIterator&);
167 void initializeMatrix();
169 void storeInteractionVolumeInfo();
171 void printInteractionVolumes();
194 storeInteractionVolumeInfo();
207 const auto element = *problem_.gridView().template begin<0>();
208 FluidState fluidState;
209 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
210 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
211 fluidState.setTemperature(problem_.temperature(element));
212 fluidState.setSaturation(wPhaseIdx, 1.);
213 fluidState.setSaturation(nPhaseIdx, 0.);
237 for (
const auto& element : elements(problem_.gridView()))
250 int eIdxGlobal = problem_.variables().index(element);
251 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
253 switch (pressureType_)
257 Scalar potW = this->
pressure()[eIdxGlobal];
259 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
260 Scalar potPc = cellData.capillaryPressure()
261 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
263 cellData.setPotential(wPhaseIdx, potW);
264 cellData.setPotential(nPhaseIdx, potW + potPc);
266 Scalar pressW = potW - gravityDiff * density_[wPhaseIdx];
268 cellData.setPressure(wPhaseIdx, pressW);
269 cellData.setPressure(nPhaseIdx, pressW + cellData.capillaryPressure());
275 Scalar potNw = this->
pressure()[eIdxGlobal];
277 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
278 Scalar potPc = cellData.capillaryPressure()
279 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
281 cellData.setPotential(nPhaseIdx, potNw);
282 cellData.setPotential(wPhaseIdx, potNw - potPc);
284 Scalar pressNw = potNw - gravityDiff * density_[nPhaseIdx];
286 cellData.setPressure(wPhaseIdx, pressNw - cellData.capillaryPressure());
287 cellData.setPressure(nPhaseIdx, pressNw);
293 cellData.fluxData().resetVelocity();
303 int gridSize = problem_.gridView().size(0);
307 timeStep_ = problem_.timeManager().timeStepSize();
309 for (
int i = 0; i < gridSize; i++)
313 switch (saturationType_)
316 sat = problem_.variables().cellData(i).saturation(wPhaseIdx);
319 sat = problem_.variables().cellData(i).saturation(nPhaseIdx);
324 maxError_ = max(maxError_, (sat - 1.0) / timeStep_);
328 maxError_ = max(maxError_, (-sat) / timeStep_);
332 if (problem_.gridAdapt().wasAdapted())
335 this->
A_.setSize(gridSize, gridSize);
336 this->
f_.resize(gridSize);
339 for (
int i = 0; i < gridSize; i++)
341 CellData& cellData = problem_.variables().cellData(i);
343 switch (pressureType_)
346 this->
pressure()[i] = cellData.pressure(wPhaseIdx);
349 this->
pressure()[i] = cellData.pressure(nPhaseIdx);
376 template<
class MultiWriter>
379 int size = problem_.gridView().size(0);
380 ScalarSolutionType *potential = writer.allocateManagedBuffer(size);
384 if (pressureType_ == pw)
386 writer.attachCellData(*potential,
"wetting potential");
389 if (pressureType_ == pn)
391 writer.attachCellData(*potential,
"nonwetting potential");
394 if (vtkOutputLevel_ > 0)
396 ScalarSolutionType *
pressure = writer.allocateManagedBuffer(size);
397 ScalarSolutionType *pressureSecond = writer.allocateManagedBuffer(size);
398 ScalarSolutionType *potentialSecond = writer.allocateManagedBuffer(size);
399 ScalarSolutionType *pc = writer.allocateManagedBuffer(size);
401 for (
const auto& element : elements(problem_.gridView()))
403 int idx = problem_.variables().index(element);
404 CellData& cellData = problem_.variables().cellData(idx);
406 (*pc)[idx] = cellData.capillaryPressure();
408 if (pressureType_ == pw)
410 (*pressure)[idx] = cellData.pressure(wPhaseIdx);
411 (*potentialSecond)[idx] = cellData.potential(nPhaseIdx);
412 (*pressureSecond)[idx] = cellData.pressure(nPhaseIdx);
415 if (pressureType_ == pn)
417 (*pressure)[idx] = cellData.pressure(nPhaseIdx);
418 (*potentialSecond)[idx] = cellData.potential(wPhaseIdx);
419 (*pressureSecond)[idx] = cellData.pressure(wPhaseIdx);
423 if (pressureType_ == pw)
425 writer.attachCellData(*
pressure,
"wetting pressure");
426 writer.attachCellData(*pressureSecond,
"nonwetting pressure");
427 writer.attachCellData(*potentialSecond,
"nonwetting potential");
430 if (pressureType_ == pn)
432 writer.attachCellData(*
pressure,
"nonwetting pressure");
433 writer.attachCellData(*pressureSecond,
"wetting pressure");
434 writer.attachCellData(*potentialSecond,
"wetting potential");
437 writer.attachCellData(*pc,
"capillary pressure");
448 ParentType(problem), problem_(problem), transmissibilityCalculator_(problem),
449 gravity_(problem.gravity()),
450 maxError_(0.), timeStep_(1.)
452 if (pressureType_ != pw && pressureType_ != pn)
454 DUNE_THROW(Dune::NotImplemented,
"Pressure type not supported!");
456 if (saturationType_ != sw && saturationType_ != sn)
458 DUNE_THROW(Dune::NotImplemented,
"Saturation type not supported!");
464 #ifndef DUMUX_2P2CPROPERTIES_HH
467 DUNE_THROW(Dune::NotImplemented,
"Compressibility not supported!");
472 DUNE_THROW(Dune::NotImplemented,
"Dimension not supported!");
475 ErrorTermFactor_ = getParam<Scalar>(
"Impet.ErrorTermFactor");
476 ErrorTermLowerBound_ = getParam<Scalar>(
"Impet.ErrorTermLowerBound");
477 ErrorTermUpperBound_ = getParam<Scalar>(
"Impet.ErrorTermUpperBound");
479 density_[wPhaseIdx] = 0.;
480 density_[nPhaseIdx] = 0.;
481 viscosity_[wPhaseIdx] = 0.;
482 viscosity_[nPhaseIdx] = 0.;
484 vtkOutputLevel_ = getParam<int>(
"Vtk.OutputLevel");
496 const Dune::FieldVector<Scalar, dimWorld>& gravity_;
500 Scalar ErrorTermFactor_;
501 Scalar ErrorTermLowerBound_;
502 Scalar ErrorTermUpperBound_;
504 Scalar density_[numPhases];
505 Scalar viscosity_[numPhases];
509 static constexpr Scalar threshold_ = 1e-15;
511 static const int pressureType_ =
GET_PROP_VALUE(TypeTag, PressureFormulation);
518 Scalar evaluateErrorTerm_(CellData& cellData)
523 switch (saturationType_)
526 sat = cellData.saturation(wPhaseIdx);
529 sat = cellData.saturation(nPhaseIdx);
533 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
541 Scalar errorAbs = abs(error);
543 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
544 && (!problem_.timeManager().willBeFinished()))
546 return ErrorTermFactor_ * error;
554template<
class TypeTag>
555typename FvMpfaL2dPressure2pAdaptive<TypeTag>::Intersection
556 FvMpfaL2dPressure2pAdaptive<TypeTag>::getNextIntersection_(
const Element& element,
557 const IntersectionIterator& isIt)
559 auto isItBegin = problem_.gridView().ibegin(element);
560 const auto isEndIt = problem_.gridView().iend(element);
562 auto tempIsIt = isIt;
563 auto nextIsIt = ++tempIsIt;
569 case GridTypeIndices::aluGrid:
570 case GridTypeIndices::ugGrid:
572 if (nextIsIt == isEndIt)
573 nextIsIt = isItBegin;
579 DUNE_THROW(Dune::NotImplemented,
580 "GridType can not be used with adaptive MPFAL!");
589template<
class TypeTag>
590void FvMpfaL2dPressure2pAdaptive<TypeTag>::initializeMatrix()
593 for (
const auto& element : elements(problem_.gridView()))
596 int eIdxGlobalI = problem_.variables().index(element);
602 const auto isEndIt = problem_.gridView().iend(element);
603 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
605 const auto& intersection = *isIt;
607 if (intersection.neighbor())
611 auto nextIntersection = getNextIntersection_(element, isIt);
613 if (nextIntersection.neighbor())
615 bool isCorner =
true;
617 for (
const auto& innerIntersection
618 :
intersections(problem_.gridView(), intersection.outside()))
620 for (
const auto& innerNextIntersection
621 :
intersections(problem_.gridView(), nextIntersection.outside()))
623 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
625 if (innerIntersection.outside() == nextIntersection.outside()
626 || innerNextIntersection.outside() == intersection.outside())
648 rowSize = min(rowSize, 13);
651 this->A_.setrowsize(eIdxGlobalI, rowSize);
656 this->A_.endrowsizes();
658 for (
const auto& element : elements(problem_.gridView()))
661 int eIdxGlobalI = problem_.variables().index(element);
664 this->A_.addindex(eIdxGlobalI, eIdxGlobalI);
667 const auto isEndIt = problem_.gridView().iend(element);
668 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
670 const auto& intersection = *isIt;
672 if (intersection.neighbor())
675 auto outside = intersection.outside();
676 int eIdxGlobalJ = problem_.variables().index(outside);
680 this->A_.addindex(eIdxGlobalI, eIdxGlobalJ);
682 if (element.level() < outside.level())
687 auto nextIntersection = getNextIntersection_(element, isIt);
689 if (nextIntersection.neighbor())
692 if (element.level() < nextIntersection.outside().level())
697 for (
const auto& innerIntersection
698 :
intersections(problem_.gridView(), intersection.outside()))
700 for (
const auto& innerNextIntersection
701 :
intersections(problem_.gridView(), nextIntersection.outside()))
703 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
705 auto innerOutside = innerIntersection.outside();
706 auto nextOutside = nextIntersection.outside();
708 if (innerOutside == innerNextIntersection.outside() && innerOutside != element
709 && innerOutside != nextOutside)
711 int eIdxGlobalCorner = problem_.variables().index(innerOutside);
713 this->A_.addindex(eIdxGlobalI, eIdxGlobalCorner);
715 if (element.level() > outside.level())
717 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
719 this->A_.addindex(eIdxGlobalJ, eIdxGlobalJCorner);
721 if (element.level() > nextOutside.level())
723 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
725 this->A_.addindex(eIdxGlobalJCorner, eIdxGlobalJ);
727 if (element.level() > innerOutside.level())
729 this->A_.addindex(eIdxGlobalCorner, eIdxGlobalI);
741 this->A_.endindices();
768template<
class TypeTag>
769void FvMpfaL2dPressure2pAdaptive<TypeTag>::storeInteractionVolumeInfo()
771 BoundaryTypes bcType;
774 for (
const auto& element : elements(problem_.gridView()))
777 int eIdxGlobal1 = problem_.variables().index(element);
779 const auto referenceElement = ReferenceElements::general(element.type());
781 const auto isEndIt12 = problem_.gridView().iend(element);
782 for (
auto isIt12 = problem_.gridView().ibegin(element); isIt12 != isEndIt12; ++isIt12)
784 const auto& intersection12 = *isIt12;
786 int indexInInside12 = intersection12.indexInInside();
788 if (intersection12.neighbor())
791 auto element2 = intersection12.outside();
792 int eIdxGlobal2 = problem_.variables().index(element2);
794 if (element.level() < element2.level())
799 auto intersection14 = getNextIntersection_(element, isIt12);
801 int indexInInside14 = intersection14.indexInInside();
804 GlobalPosition corner1234(0);
805 int globalVertIdx1234 = 0;
806 bool finished =
false;
808 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
810 int localVertIdx12corner = referenceElement.subEntity(indexInInside12, dim - 1, i, dim);
812 int globalVertIdx12corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx12corner));
814 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
816 int localVertIdx14corner = referenceElement.subEntity(indexInInside14, dim - 1, j, dim);
818 int globalVertIdx14corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx14corner));
820 if (globalVertIdx12corner == globalVertIdx14corner)
822 corner1234 = element.geometry().corner(localVertIdx12corner);
824 globalVertIdx1234 = globalVertIdx12corner;
837 if (interactionVolumes_[globalVertIdx1234].isStored() || !finished)
843 interactionVolumes_[globalVertIdx1234].setStored();
846 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
849 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
850 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
851 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
854 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
857 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
860 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
863 GlobalPosition globalPosFace41 = intersection14.geometry().center();
866 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
869 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
871 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
872 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
874 unitOuterNormal14 *= -1;
875 unitOuterNormal12 *= -1;
876 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
877 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
878 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
879 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
882 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element2, 1);
883 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection12.indexInOutside(), 1, 1);
884 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 1, 1);
885 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 1, 1);
886 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 1, 1);
889 if (intersection14.neighbor())
893 auto element4 = intersection14.outside();
896 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
897 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
899 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
900 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
901 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
904 GlobalPosition globalPosFace23(0);
905 GlobalPosition globalPosFace34(0);
907 if (element4.level() < element.level())
909 bool isHangingNode =
false;
911 for (
const auto& intersection2
914 bool breakLoop =
false;
915 for (
const auto& intersection4
918 if (intersection2.neighbor() && intersection4.neighbor())
920 auto element32 = intersection2.outside();
921 auto element34 = intersection4.outside();
924 if (element32 == element4)
926 if (element.level() != element2.level())
929 isHangingNode =
false;
933 isHangingNode =
true;
935 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
937 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInOutside(),
940 globalPosFace23 = intersection2.geometry().center();
941 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
942 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 3, 1);
944 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
945 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
946 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 3, 1);
949 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
951 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
952 unitOuterNormal23 *= -1;
953 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 3, 1);
955 else if (element34 == element2)
957 if (element.level() != element2.level())
960 isHangingNode =
false;
964 isHangingNode =
true;
966 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
968 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInOutside(),
972 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
973 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
984 bool regularNode =
false;
986 for (
const auto& intersection2
989 for (
const auto& intersection4
992 if (intersection4.neighbor())
994 auto element41 = intersection4.outside();
996 if (element41 == element && element41.level() > element.level())
999 globalPosFace41 = intersection4.geometry().center();
1000 faceVol41 = intersection4.geometry().volume() / 2.0;
1002 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1003 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0,
1005 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1006 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3,
1011 if (intersection2.neighbor() && intersection4.neighbor())
1013 auto element32 = intersection2.outside();
1014 auto element34 = intersection4.outside();
1017 if (element32 == element34 && element32 != element)
1020 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32,
1023 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1024 intersection2.indexInInside(), 1, 0);
1025 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1026 intersection2.indexInOutside(), 2, 1);
1027 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1028 intersection4.indexInInside(), 3, 1);
1029 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1030 intersection4.indexInOutside(), 2, 0);
1032 globalPosFace23 = intersection2.geometry().center();
1033 globalPosFace34 = intersection4.geometry().center();
1035 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1036 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1039 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1040 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1042 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1043 unitOuterNormal23 *= -1;
1044 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1045 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1046 unitOuterNormal43 *= -1;
1047 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1049 if (element32.level() > element2.level())
1051 for (
const auto& intersection3
1054 if (intersection3.neighbor())
1056 auto element23 = intersection3.outside();
1058 if (element23 == element2)
1060 globalPosFace23 = intersection3.geometry().center();
1061 faceVol23 = intersection3.geometry().volume() / 2.0;
1067 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1068 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1069 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1,
1071 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2,
1074 if (element34.level() > element4.level())
1076 for (
const auto& intersection3
1079 if (intersection3.neighbor())
1081 auto element43 = intersection3.outside();
1083 if (element43 == element4)
1085 globalPosFace34 = intersection3.geometry().center();
1086 faceVol34 = intersection3.geometry().volume() / 2.0;
1093 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1094 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1095 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2,
1097 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3,
1112 interactionVolumes_[globalVertIdx1234].reset();
1119 bool regularNode =
false;
1120 for (
const auto& intersection2
1123 for (
const auto& intersection4
1126 if (intersection4.neighbor())
1128 auto element41 = intersection4.outside();
1130 if (element41 == element && element41.level() > element.level())
1133 globalPosFace41 = intersection4.geometry().center();
1134 faceVol41 = intersection4.geometry().volume() / 2.0;
1136 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1137 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1138 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1139 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1143 if (intersection2.neighbor() && intersection4.neighbor())
1145 auto element32 = intersection2.outside();
1146 auto element34 = intersection4.outside();
1149 if (element32 == element34 && element32 != element)
1152 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32, 2);
1154 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
1156 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1157 intersection2.indexInOutside(), 2, 1);
1158 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
1160 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1161 intersection4.indexInOutside(), 2, 0);
1163 globalPosFace23 = intersection2.geometry().center();
1164 globalPosFace34 = intersection4.geometry().center();
1166 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1167 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1170 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1172 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1174 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1175 unitOuterNormal23 *= -1;
1176 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1177 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1178 unitOuterNormal43 *= -1;
1179 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1180 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1181 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1182 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1183 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1184 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1185 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2, 1);
1186 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2, 0);
1187 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1201 interactionVolumes_[globalVertIdx1234].reset();
1211 problem_.boundaryTypes(bcType, intersection14);
1212 PrimaryVariables boundValues(0.0);
1214 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1215 if (bcType.isNeumann(pressEqIdx))
1217 problem_.neumann(boundValues, intersection14);
1218 boundValues *= faceVol41;
1219 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1221 if (bcType.hasDirichlet())
1223 problem_.dirichlet(boundValues, intersection14);
1224 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1231 GlobalPosition globalPosFace23(0);
1234 Scalar faceVol23 = 0;
1237 DimVector unitOuterNormal23(0);
1241 for (
const auto& intersection2
1244 if (intersection2.boundary())
1246 for (
int i = 0; i < intersection2.geometry().corners(); ++i)
1248 int localVertIdx2corner = referenceElement.subEntity(intersection2.indexInInside(), dim - 1, i,
1251 int globalVertIdx2corner = problem_.variables().index(element2.template subEntity<dim>(localVertIdx2corner));
1253 if (globalVertIdx2corner == globalVertIdx1234)
1255 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(), 1,
1258 globalPosFace23 = intersection2.geometry().center();
1260 faceVol23 = intersection2.geometry().volume() / 2.0;
1262 unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1264 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1265 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1266 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1268 problem_.boundaryTypes(bcType, intersection2);
1271 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 1);
1272 if (bcType.isNeumann(pressEqIdx))
1274 problem_.neumann(boundValues, intersection2);
1275 boundValues *= faceVol23;
1276 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 1);
1278 if (bcType.hasDirichlet())
1280 problem_.dirichlet(boundValues, intersection2);
1281 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 1);
1284 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1287 if (element.level() == element2.level())
1289 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1290 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1292 else if (element.level() < element2.level())
1294 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1296 else if (element.level() > element2.level())
1298 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1315 Dune::NotImplemented,
1316 "fvmpfao2pfaboundpressure2p.hh, l. 997: boundary shape not available as interaction volume shape");
1324 auto intersection14 = getNextIntersection_(element, isIt12);
1326 int indexInInside14 = intersection14.indexInInside();
1329 GlobalPosition corner1234(0);
1330 int globalVertIdx1234 = 0;
1333 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
1335 bool finished =
false;
1337 int localVertIdx12corner = referenceElement.subEntity(indexInInside12, dim - 1, i, dim);
1339 int globalVertIdx12corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx12corner));
1341 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
1343 int localVertIdx14corner = referenceElement.subEntity(indexInInside14, dim - 1, j, dim);
1345 int globalVertIdx14corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx14corner));
1347 if (globalVertIdx12corner == globalVertIdx14corner)
1349 corner1234 = element.geometry().corner(localVertIdx12corner);
1351 globalVertIdx1234 = globalVertIdx12corner;
1364 if (interactionVolumes_[globalVertIdx1234].isStored())
1370 interactionVolumes_[globalVertIdx1234].setStored();
1373 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
1376 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
1377 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
1378 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
1381 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
1384 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
1387 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
1390 const GlobalPosition& globalPosFace41 = intersection14.geometry().center();
1393 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
1396 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
1398 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
1399 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
1401 unitOuterNormal14 *= -1;
1402 unitOuterNormal12 *= -1;
1403 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
1404 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1405 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
1406 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1408 problem_.boundaryTypes(bcType, intersection12);
1409 PrimaryVariables boundValues(0.0);
1411 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 0);
1412 if (bcType.isNeumann(pressEqIdx))
1414 problem_.neumann(boundValues, intersection12);
1415 boundValues *= faceVol12;
1416 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 0);
1418 if (bcType.hasDirichlet())
1420 problem_.dirichlet(boundValues, intersection12);
1421 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 0);
1425 if (intersection14.boundary())
1427 problem_.boundaryTypes(bcType, intersection14);
1430 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1431 if (bcType.isNeumann(pressEqIdx))
1433 problem_.neumann(boundValues, intersection14);
1434 boundValues *= faceVol41;
1435 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1437 if (bcType.hasDirichlet())
1439 problem_.dirichlet(boundValues, intersection14);
1440 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1443 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1444 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1448 else if (intersection14.neighbor())
1452 auto element4 = intersection14.outside();
1453 int eIdxGlobal4 = problem_.variables().index(element4);
1455 if ((element.level() == element4.level() && eIdxGlobal1 > eIdxGlobal4)
1456 || element.level() < element4.level())
1458 interactionVolumes_[globalVertIdx1234].reset();
1462 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
1465 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
1467 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
1468 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1469 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1471 bool finished =
false;
1474 for (
const auto& intersection4
1477 if (intersection4.boundary())
1479 for (
int i = 0; i < intersection4.geometry().corners(); ++i)
1481 int localVertIdx4corner = referenceElement.subEntity(intersection4.indexInInside(), dim - 1, i,
1484 int globalVertIdx4corner = problem_.variables().index(element4.template subEntity<dim>(localVertIdx4corner));
1486 if (globalVertIdx4corner == globalVertIdx1234)
1488 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(), 3,
1491 const GlobalPosition& globalPosFace34 = intersection4.geometry().center();
1492 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1494 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1496 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1497 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1498 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1500 problem_.boundaryTypes(bcType, intersection4);
1503 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 2);
1504 if (bcType.isNeumann(pressEqIdx))
1506 problem_.neumann(boundValues, intersection4);
1507 boundValues *= faceVol34;
1508 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 2);
1510 if (bcType.hasDirichlet())
1512 problem_.dirichlet(boundValues, intersection4);
1513 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 2);
1516 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1518 if (element.level() == element4.level())
1520 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1521 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1523 if (element.level() < element4.level())
1525 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1527 if (element.level() > element4.level())
1529 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1547 Dune::NotImplemented,
1548 "fvmpfao2pfaboundpressure2p_adaptive.hh: boundary shape not available as interaction volume shape");
1553 DUNE_THROW(Dune::NotImplemented,
1554 "fvmpfao2pfaboundpressure2p_adaptive.hh: interface type not supported!");
1565template<
class TypeTag>
1566void FvMpfaL2dPressure2pAdaptive<TypeTag>::printInteractionVolumes()
1568 for (
const auto& vertex : vertices(problem_.gridView()))
1570 int vIdxGlobal = problem_.variables().index(vertex);
1572 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1574 if (interactionVolume.getElementNumber() > 2)
1576 interactionVolume.printInteractionVolumeInfo();
1577 std::cout <<
"global vertex index: " << vIdxGlobal <<
"\n";
1578 if (interactionVolume.getElementNumber() == 3)
1580 auto element1 = interactionVolume.getSubVolumeElement(0);
1581 auto element2 = interactionVolume.getSubVolumeElement(1);
1582 auto element4 = interactionVolume.getSubVolumeElement(3);
1584 int eIdxGlobal1 = problem_.variables().index(element1);
1585 int eIdxGlobal2 = problem_.variables().index(element2);
1586 int eIdxGlobal4 = problem_.variables().index(element4);
1588 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1589 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1590 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1592 if (interactionVolume.getElementNumber() == 4)
1594 auto element1 = interactionVolume.getSubVolumeElement(0);
1595 auto element2 = interactionVolume.getSubVolumeElement(1);
1596 auto element3 = interactionVolume.getSubVolumeElement(2);
1597 auto element4 = interactionVolume.getSubVolumeElement(3);
1599 int eIdxGlobal1 = problem_.variables().index(element1);
1600 int eIdxGlobal2 = problem_.variables().index(element2);
1601 int eIdxGlobal3 = problem_.variables().index(element3);
1602 int eIdxGlobal4 = problem_.variables().index(element4);
1604 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1605 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1606 std::cout <<
"global element index 3: " << eIdxGlobal3 <<
"\n";
1607 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1615template<
class TypeTag>
1616void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
1623 for (
const auto& vertex : vertices(problem_.gridView()))
1625 int vIdxGlobal = problem_.variables().index(vertex);
1627 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1629 if (interactionVolume.isInnerVolume())
1631 if (interactionVolume.getElementNumber() == 4)
1633 auto element1 = interactionVolume.getSubVolumeElement(0);
1634 auto element2 = interactionVolume.getSubVolumeElement(1);
1635 auto element3 = interactionVolume.getSubVolumeElement(2);
1636 auto element4 = interactionVolume.getSubVolumeElement(3);
1639 const GlobalPosition& globalPos1 = element1.geometry().center();
1640 const GlobalPosition& globalPos2 = element2.geometry().center();
1641 const GlobalPosition& globalPos3 = element3.geometry().center();
1642 const GlobalPosition& globalPos4 = element4.geometry().center();
1645 Scalar volume1 = element1.geometry().volume();
1646 Scalar volume2 = element2.geometry().volume();
1647 Scalar volume3 = element3.geometry().volume();
1648 Scalar volume4 = element4.geometry().volume();
1651 int eIdxGlobal1 = problem_.variables().index(element1);
1652 int eIdxGlobal2 = problem_.variables().index(element2);
1653 int eIdxGlobal3 = problem_.variables().index(element3);
1654 int eIdxGlobal4 = problem_.variables().index(element4);
1657 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
1658 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
1659 CellData& cellData3 = problem_.variables().cellData(eIdxGlobal3);
1660 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
1663 PrimaryVariables source(0.0);
1664 problem_.source(source, element1);
1665 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1666 problem_.source(source, element2);
1667 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1668 problem_.source(source, element3);
1669 this->f_[eIdxGlobal3] += volume3 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1670 problem_.source(source, element4);
1671 this->f_[eIdxGlobal4] += volume4 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1673 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
1674 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
1675 this->f_[eIdxGlobal3] += evaluateErrorTerm_(cellData3) * volume3 / (4.0);
1676 this->f_[eIdxGlobal4] += evaluateErrorTerm_(cellData4) * volume4 / (4.0);
1679 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
1680 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
1683 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
1686 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
1687 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
1690 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
1693 Dune::FieldVector<Scalar, numPhases> lambda3(cellData3.mobility(wPhaseIdx));
1694 lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
1697 Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
1700 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
1701 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
1704 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
1706 std::vector < DimVector > lambda(2 * dim);
1708 lambda[0][0] = lambdaTotal1;
1709 lambda[0][1] = lambdaTotal1;
1710 lambda[1][0] = lambdaTotal2;
1711 lambda[1][1] = lambdaTotal2;
1712 lambda[2][0] = lambdaTotal3;
1713 lambda[2][1] = lambdaTotal3;
1714 lambda[3][0] = lambdaTotal4;
1715 lambda[3][1] = lambdaTotal4;
1719 Dune::FieldVector<Scalar, 2 * dim> pc(0);
1720 pc[0] = cellData1.capillaryPressure();
1721 pc[1] = cellData2.capillaryPressure();
1722 pc[2] = cellData3.capillaryPressure();
1723 pc[3] = cellData4.capillaryPressure();
1725 Dune::FieldVector<Scalar, 2 * dim> gravityDiff(0);
1727 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1728 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1729 gravityDiff[2] = (problem_.bBoxMax() - globalPos3) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1730 gravityDiff[3] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1734 Dune::FieldVector<Scalar, 2 * dim> pcFlux(0);
1736 Scalar pcPotential12 = 0;
1737 Scalar pcPotential14 = 0;
1738 Scalar pcPotential32 = 0;
1739 Scalar pcPotential34 = 0;
1742 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
1743 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
1745 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
1747 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1749 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1753 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
1754 this->A_[eIdxGlobal1][eIdxGlobal3] += T[1][1];
1755 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
1757 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
1758 this->A_[eIdxGlobal2][eIdxGlobal3] -= T[1][1];
1759 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
1768 pcPotential12 = Tu[1];
1770 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1772 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1776 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
1777 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
1778 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
1780 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
1781 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
1782 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
1791 pcPotential12 = Tu[1];
1794 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
1796 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1798 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1802 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][0];
1803 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][1];
1804 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][2];
1806 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][0];
1807 this->A_[eIdxGlobal3][eIdxGlobal4] -= T[1][1];
1808 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][2];
1817 pcPotential32 = -Tu[1];
1819 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1821 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1825 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
1826 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
1827 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][2];
1829 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][0];
1830 this->A_[eIdxGlobal3][eIdxGlobal1] -= T[1][1];
1831 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][2];
1840 pcPotential32 = -Tu[1];
1843 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
1845 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1847 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1851 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][0];
1852 this->A_[eIdxGlobal3][eIdxGlobal1] += T[1][1];
1853 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][2];
1855 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][0];
1856 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
1857 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][2];
1866 pcPotential34 = Tu[1];
1868 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1870 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1874 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][0];
1875 this->A_[eIdxGlobal3][eIdxGlobal2] += T[1][1];
1876 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][2];
1878 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][0];
1879 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][1];
1880 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
1889 pcPotential34 = Tu[1];
1892 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
1894 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1896 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1900 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
1901 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
1902 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
1904 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
1905 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
1906 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
1915 pcPotential14 = -Tu[1];
1917 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1919 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1923 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][0];
1924 this->A_[eIdxGlobal4][eIdxGlobal3] += T[1][1];
1925 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][2];
1927 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][0];
1928 this->A_[eIdxGlobal1][eIdxGlobal3] -= T[1][1];
1929 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][2];
1938 pcPotential14 = -Tu[1];
1941 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0 && pc[3] == 0)
1947 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
1948 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
1949 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
1952 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
1953 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
1954 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
1957 Dune::FieldVector<Scalar, numPhases> lambda32Upw(0.0);
1958 lambda32Upw[wPhaseIdx] = (pcPotential32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
1959 lambda32Upw[nPhaseIdx] = (pcPotential32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
1962 Dune::FieldVector<Scalar, numPhases> lambda34Upw(0.0);
1963 lambda34Upw[wPhaseIdx] = (pcPotential34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
1964 lambda34Upw[nPhaseIdx] = (pcPotential34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
1966 for (
int i = 0; i < numPhases; i++)
1968 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
1969 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
1970 Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
1971 Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
1972 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
1973 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
1974 Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
1975 Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
1977 Dune::FieldVector<Scalar, 2 * dim> pcFluxReal(pcFlux);
1979 pcFluxReal[0] *= fracFlow12;
1980 pcFluxReal[1] *= fracFlow32;
1981 pcFluxReal[2] *= fracFlow34;
1982 pcFluxReal[3] *= fracFlow14;
1984 switch (pressureType_)
1991 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[3]);
1992 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
1993 this->f_[eIdxGlobal3] -= (pcFluxReal[2] - pcFluxReal[1]);
1994 this->f_[eIdxGlobal4] -= (pcFluxReal[3] - pcFluxReal[2]);
2004 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[3]);
2005 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2006 this->f_[eIdxGlobal3] += (pcFluxReal[2] - pcFluxReal[1]);
2007 this->f_[eIdxGlobal4] += (pcFluxReal[3] - pcFluxReal[2]);
2014 else if (interactionVolume.getElementNumber() == 3)
2016 auto element1 = interactionVolume.getSubVolumeElement(0);
2017 auto element2 = interactionVolume.getSubVolumeElement(1);
2018 auto element4 = interactionVolume.getSubVolumeElement(3);
2021 const GlobalPosition& globalPos1 = element1.geometry().center();
2022 const GlobalPosition& globalPos2 = element2.geometry().center();
2023 const GlobalPosition& globalPos4 = element4.geometry().center();
2026 Scalar volume1 = element1.geometry().volume();
2027 Scalar volume2 = element2.geometry().volume();
2030 int eIdxGlobal1 = problem_.variables().index(element1);
2031 int eIdxGlobal2 = problem_.variables().index(element2);
2032 int eIdxGlobal4 = problem_.variables().index(element4);
2035 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
2036 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
2037 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
2041 PrimaryVariables source(0.0);
2042 problem_.source(source, element1);
2043 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2044 problem_.source(source, element2);
2045 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2047 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
2048 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
2051 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
2052 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
2055 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
2058 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
2059 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
2062 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
2065 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
2066 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
2069 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
2071 std::vector < DimVector > lambda(4);
2073 lambda[0][0] = lambdaTotal1;
2074 lambda[0][1] = lambdaTotal1;
2075 lambda[1][0] = lambdaTotal2;
2076 lambda[1][1] = lambdaTotal2;
2077 lambda[3][0] = lambdaTotal4;
2078 lambda[3][1] = lambdaTotal4;
2082 Dune::FieldVector<Scalar, 3> pc(0);
2083 pc[0] = cellData1.capillaryPressure();
2084 pc[1] = cellData2.capillaryPressure();
2085 pc[2] = cellData4.capillaryPressure();
2087 Dune::FieldVector<Scalar, 3> gravityDiff(0);
2089 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2090 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2091 gravityDiff[2] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2095 Dune::FieldVector<Scalar, 3> pcFlux(0);
2097 Scalar pcPotential12 = 0;
2098 Scalar pcPotential14 = 0;
2099 Scalar pcPotential24 = 0;
2102 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
2103 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
2105 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
2107 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2109 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2113 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
2114 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2115 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
2117 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
2118 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2119 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
2128 pcPotential12 = Tu[1];
2130 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2132 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2136 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
2137 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2138 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
2140 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
2141 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2142 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
2151 pcPotential12 = Tu[1];
2155 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2158 transmissibilityType = transmissibilityCalculator_.calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
2160 if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2162 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
2166 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
2167 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
2168 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][2];
2170 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][0];
2171 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
2172 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
2181 pcPotential24 = Tu[1];
2185 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2188 transmissibilityType = transmissibilityCalculator_.calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
2190 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2192 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 1)])
2197 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
2198 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
2199 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
2201 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
2202 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
2203 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
2212 pcPotential14 = -Tu[1];
2216 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2219 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0)
2225 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
2226 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
2227 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
2230 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
2231 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
2232 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
2235 Dune::FieldVector<Scalar, numPhases> lambda24Upw(0.0);
2236 lambda24Upw[wPhaseIdx] = (pcPotential24 >= 0) ? lambda2[wPhaseIdx] : lambda4[wPhaseIdx];
2237 lambda24Upw[nPhaseIdx] = (pcPotential24 >= 0) ? lambda2[nPhaseIdx] : lambda4[nPhaseIdx];
2239 for (
int i = 0; i < numPhases; i++)
2241 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
2242 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
2243 Scalar lambdaT24 = lambda24Upw[wPhaseIdx] + lambda24Upw[nPhaseIdx];
2244 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
2245 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
2246 Scalar fracFlow24 = (lambdaT24 > threshold_) ? lambda24Upw[i] / (lambdaT24) : 0.0;
2248 Dune::FieldVector<Scalar, 3> pcFluxReal(pcFlux);
2250 pcFluxReal[0] *= fracFlow12;
2251 pcFluxReal[1] *= fracFlow24;
2252 pcFluxReal[2] *= fracFlow14;
2254 switch (pressureType_)
2261 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[2]);
2262 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
2263 this->f_[eIdxGlobal4] -= (pcFluxReal[2] - pcFluxReal[1]);
2273 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[2]);
2274 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2275 this->f_[eIdxGlobal4] += (pcFluxReal[2] - pcFluxReal[1]);
2284 DUNE_THROW(Dune::NotImplemented,
"Unknown interactionvolume type!");
2291 for (
int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
2293 bool isOutside =
false;
2294 for (
int fIdx = 0; fIdx < dim; fIdx++)
2296 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2297 if (interactionVolume.isOutsideFace(intVolFaceIdx))
2308 auto element = interactionVolume.getSubVolumeElement(elemIdx);
2311 const GlobalPosition& globalPos = element.geometry().center();
2314 Scalar volume = element.geometry().volume();
2317 int eIdxGlobal = problem_.variables().index(element);
2320 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
2323 DimMatrix
permeability(problem_.spatialParams().intrinsicPermeability(element));
2326 PrimaryVariables source(0);
2327 problem_.source(source, element);
2328 this->f_[eIdxGlobal] += volume / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2330 this->f_[eIdxGlobal] += evaluateErrorTerm_(cellData) * volume / (4.0);
2333 Dune::FieldVector<Scalar, numPhases> lambda(cellData.mobility(wPhaseIdx));
2334 lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
2336 Scalar pc = cellData.capillaryPressure();
2338 Scalar gravityDiff = (problem_.bBoxMax() - globalPos) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2342 for (
int fIdx = 0; fIdx < dim; fIdx++)
2344 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2346 if (interactionVolume.isBoundaryFace(intVolFaceIdx))
2349 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressEqIdx))
2351 int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, fIdx);
2353 const auto referenceElement = ReferenceElements::general(element.type());
2355 const LocalPosition& localPos = referenceElement.position(boundaryFaceIdx, 1);
2357 const GlobalPosition& globalPosFace = element.geometry().global(localPos);
2359 DimVector distVec(globalPosFace - globalPos);
2360 Scalar dist = distVec.two_norm();
2361 DimVector unitDistVec(distVec);
2362 unitDistVec /= dist;
2364 Scalar faceArea = interactionVolume.getFaceArea(elemIdx, fIdx);
2367 Scalar satWBound = cellData.saturation(wPhaseIdx);
2369 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
2371 Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
2372 switch (saturationType_)
2376 satWBound = satBound;
2381 satWBound = 1 - satBound;
2388 Scalar pcBound = MaterialLaw::pc(
2389 problem_.spatialParams().materialLawParams(element), satWBound);
2391 Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_
2392 * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2394 pcBound += gravityDiffBound;
2396 Dune::FieldVector<Scalar, numPhases> lambdaBound(
2397 MaterialLaw::krw(problem_.spatialParams().materialLawParams(element),
2399 lambdaBound[nPhaseIdx] = MaterialLaw::krn(
2400 problem_.spatialParams().materialLawParams(element), satWBound);
2401 lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx];
2402 lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx];
2404 Scalar potentialBound = interactionVolume.getDirichletValues(intVolFaceIdx)[pressureIdx];
2405 Scalar gdeltaZ = (problem_.bBoxMax()-globalPosFace) * gravity_;
2408 Scalar potentialDiffW = 0;
2409 Scalar potentialDiffNw = 0;
2410 switch (pressureType_)
2414 potentialBound += density_[wPhaseIdx]*gdeltaZ;
2415 potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBound) / dist;
2416 potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBound - pcBound) / dist;
2421 potentialBound += density_[nPhaseIdx]*gdeltaZ;
2422 potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBound + pcBound) / dist;
2423 potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBound) / dist;
2428 Scalar lambdaTotal = (potentialDiffW >= 0.) ? lambda[wPhaseIdx] : lambdaBound[wPhaseIdx];
2429 lambdaTotal += (potentialDiffNw >= 0.) ? lambda[nPhaseIdx] : lambdaBound[nPhaseIdx];
2431 DimVector permTimesNormal(0);
2435 Scalar entry = lambdaTotal * (unitDistVec * permTimesNormal) / dist * faceArea;
2440 switch (pressureType_)
2445 DimVector pcGradient = unitDistVec;
2446 pcGradient *= (pc - pcBound) / dist;
2449 pcFlux = 0.5 * (lambda[nPhaseIdx] + lambdaBound[nPhaseIdx])
2450 * (permTimesNormal * pcGradient) * faceArea;
2457 DimVector pcGradient = unitDistVec;
2458 pcGradient *= (pc - pcBound) / dist;
2461 pcFlux = 0.5 * (lambda[wPhaseIdx] + lambdaBound[wPhaseIdx])
2462 * (permTimesNormal * pcGradient) * faceArea;
2470 this->A_[eIdxGlobal][eIdxGlobal] += entry;
2471 this->f_[eIdxGlobal] += entry * potentialBound;
2473 if (pc == 0 && pcBound == 0)
2478 for (
int i = 0; i < numPhases; i++)
2480 switch (pressureType_)
2487 this->f_[eIdxGlobal] -= pcFlux;
2496 this->f_[eIdxGlobal] += pcFlux;
2504 else if (interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx))
2506 Scalar J = interactionVolume.getNeumannValues(intVolFaceIdx)[wPhaseIdx] / density_[wPhaseIdx];
2507 J += interactionVolume.getNeumannValues(intVolFaceIdx)[nPhaseIdx] / density_[nPhaseIdx];
2509 this->f_[eIdxGlobal] -= J;
2513 std::cout <<
"interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx)"
2514 << interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx) <<
"\n";
2515 DUNE_THROW(Dune::NotImplemented,
2516 "No valid boundary condition type defined for pressure equation!");
2526 if (problem_.gridView().comm().size() > 1)
2529 for (
const auto& element : elements(problem_.gridView()))
2531 if (element.partitionType() == Dune::InteriorEntity)
2535 int eIdxGlobalI = problem_.variables().index(element);
2537 this->A_[eIdxGlobalI] = 0.0;
2538 this->A_[eIdxGlobalI][eIdxGlobalI] = 1.0;
2539 this->f_[eIdxGlobalI] = this->
pressure()[eIdxGlobalI];
2551template<
class TypeTag>
2555 for (
const auto& element : elements(problem_.gridView()))
2557 int eIdxGlobal = problem_.variables().index(element);
2559 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
2561 Scalar satW = cellData.saturation(wPhaseIdx);
2563 Scalar pc = MaterialLaw::pc(problem_.spatialParams().materialLawParams(element), satW);
2565 cellData.setCapillaryPressure(pc);
2568 Scalar mobilityW = MaterialLaw::krw(problem_.spatialParams().materialLawParams(element), satW)
2569 / viscosity_[wPhaseIdx];
2570 Scalar mobilityNw = MaterialLaw::krn(problem_.spatialParams().materialLawParams(element), satW)
2571 / viscosity_[nPhaseIdx];
2574 cellData.setMobility(wPhaseIdx, mobilityW);
2575 cellData.setMobility(nPhaseIdx, mobilityNw);
2578 cellData.setFracFlowFunc(wPhaseIdx, mobilityW / (mobilityW + mobilityNw));
2579 cellData.setFracFlowFunc(nPhaseIdx, mobilityNw / (mobilityW + mobilityNw));
#define GET_PROP_VALUE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:282
#define GET_PROP(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:281
#define GET_PROP_TYPE(TypeTag, PropTagName)
Definition: propertysystemmacros.hh:283
Provides methods for transmissibility calculation 2-d.
Class including the information of an interaction volume of a MPFA L-method that does not change with...
Dune::IteratorRange< typename MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper >::Intersections::const_iterator > intersections(const MultiDomainGlue< DomainGridView, TargetGridView, DomainMapper, TargetMapper > &glue)
Range generator to iterate with range-based for loops over all intersections as follows: for (const a...
Definition: glue.hh:62
make the local view function available whenever we use the grid geometry
Definition: adapt.hh:29
Property tag CellData
Defines data object to be stored.
Definition: porousmediumflow/sequential/properties.hh:72
Property tag GridImplementation
Gives kind of grid implementation in form of a GridType.
Definition: porousmediumflow/sequential/cellcentered/mpfa/properties.hh:95
Property tag EnableCompressibility
Returns whether compressibility is allowed.
Definition: porousmediumflow/2p/sequential/properties.hh:55
Property tag SaturationFormulation
The formulation of the saturation model.
Definition: porousmediumflow/2p/sequential/properties.hh:53
Property tag NumPhases
Number of phases in the system.
Definition: porousmediumflow/sequential/properties.hh:69
Property tag VelocityFormulation
The type of velocity reconstructed for the transport model.
Definition: porousmediumflow/2p/sequential/properties.hh:54
std::string viscosity(int phaseIdx) noexcept
I/O name of viscosity for multiphase systems.
Definition: name.hh:74
std::string permeability() noexcept
I/O name of permeability.
Definition: name.hh:143
std::string pressure(int phaseIdx) noexcept
I/O name of pressure for multiphase systems.
Definition: name.hh:34
std::string density(int phaseIdx) noexcept
I/O name of density for multiphase systems.
Definition: name.hh:65
Grid adaptive finite volume MPFA L-method discretization of a two-phase flow pressure equation of the...
Definition: 2dpressureadaptive.hh:75
void storePressureSolution(const Element &element)
Stores the pressure solution of a cell.
Definition: 2dpressureadaptive.hh:248
void addOutputVtkFields(MultiWriter &writer)
Adds pressure output to the output file.
Definition: 2dpressureadaptive.hh:377
void updateInteractionVolumeInfo()
Updates interaction volumes.
Definition: 2dpressureadaptive.hh:186
InnerBoundaryVolumeFaces innerBoundaryVolumeFaces_
Vector marking faces which intersect the boundary.
Definition: 2dpressureadaptive.hh:493
void storePressureSolution()
Globally stores the pressure solution.
Definition: 2dpressureadaptive.hh:234
FvMpfaL2dPressure2pAdaptive(Problem &problem)
Constructs a FvMpfaL2dPressure2pAdaptive object.
Definition: 2dpressureadaptive.hh:447
void initialize()
Initializes the pressure model.
Definition: 2dpressureadaptive.hh:203
FvMpfaL2dTransmissibilityCalculator< TypeTag > TransmissibilityCalculator
Definition: 2dpressureadaptive.hh:156
void updateMaterialLaws()
constitutive functions are initialized and stored in the variables object
Definition: 2dpressureadaptive.hh:2552
void update()
Pressure update.
Definition: 2dpressureadaptive.hh:301
GlobalInteractionVolumeVector interactionVolumes_
Global Vector of interaction volumes.
Definition: 2dpressureadaptive.hh:492
Provides methods for transmissibility calculation in 2-d.
Definition: 2dtransmissibilitycalculator.hh:44
Class including the information of an interaction volume of a MPFA L-method that does not change with...
Definition: linteractionvolume.hh:41
The finite volume base class for the solution of a pressure equation.
Definition: sequential/cellcentered/pressure.hh:48
void initialize()
Initialize pressure model.
Definition: sequential/cellcentered/pressure.hh:212
PressureSolution & pressure()
Returns the vector containing the pressure solution.
Definition: sequential/cellcentered/pressure.hh:119
Matrix A_
Global stiffnes matrix (sparse matrix which is build by the initializeMatrix() function)
Definition: sequential/cellcentered/pressure.hh:323
void solve()
Solves the global system of equations to get the spatial distribution of the pressure.
Definition: sequential/cellcentered/pressure.hh:526
RHSVector f_
Right hand side vector.
Definition: sequential/cellcentered/pressure.hh:324
Specifies the properties for immiscible 2p diffusion/pressure models.
Properties for a MPFA method.
Finite Volume Diffusion Model.