23#ifndef DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
24#define DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
73template<
class TypeTag>
81 dim = GridView::dimension, dimWorld = GridView::dimensionworld
99 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
100 using ScalarSolutionType =
typename SolutionTypes::ScalarSolution;
106 pw = Indices::pressureW,
107 pn = Indices::pressureNw,
108 sw = Indices::saturationW,
109 sn = Indices::saturationNw
113 wPhaseIdx = Indices::wPhaseIdx,
114 nPhaseIdx = Indices::nPhaseIdx,
115 pressureIdx = Indices::pressureIdx,
116 saturationIdx = Indices::saturationIdx,
117 pressEqIdx = Indices::pressureEqIdx,
118 satEqIdx = Indices::satEqIdx,
119 numPhases = getPropValue<TypeTag, Properties::NumPhases>()
126 dirichletDirichlet = 1,
127 dirichletNeumann = 2,
132 using Element =
typename GridView::Traits::template Codim<0>::Entity;
133 using IntersectionIterator =
typename GridView::IntersectionIterator;
134 using Intersection =
typename GridView::Intersection;
135 using Grid =
typename GridView::Grid;
137 using LocalPosition = Dune::FieldVector<Scalar, dim>;
138 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
139 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
141 using DimVector = Dune::FieldVector<Scalar, dim>;
156 using GlobalInteractionVolumeVector = std::vector<InteractionVolume>;
157 using InnerBoundaryVolumeFaces = std::vector<Dune::FieldVector<bool, 2*dim> >;
160 Intersection getNextIntersection_(
const Element&,
const IntersectionIterator&);
164 void initializeMatrix();
166 void storeInteractionVolumeInfo();
168 void printInteractionVolumes();
191 storeInteractionVolumeInfo();
204 const auto element = *problem_.gridView().template begin<0>();
205 FluidState fluidState;
206 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
207 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
208 fluidState.setTemperature(problem_.temperature(element));
209 fluidState.setSaturation(wPhaseIdx, 1.);
210 fluidState.setSaturation(nPhaseIdx, 0.);
234 for (
const auto& element : elements(problem_.gridView()))
247 int eIdxGlobal = problem_.variables().index(element);
248 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
250 switch (pressureType_)
254 Scalar potW = this->
pressure()[eIdxGlobal];
256 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
257 Scalar potPc = cellData.capillaryPressure()
258 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
260 cellData.setPotential(wPhaseIdx, potW);
261 cellData.setPotential(nPhaseIdx, potW + potPc);
263 Scalar pressW = potW - gravityDiff * density_[wPhaseIdx];
265 cellData.setPressure(wPhaseIdx, pressW);
266 cellData.setPressure(nPhaseIdx, pressW + cellData.capillaryPressure());
272 Scalar potNw = this->
pressure()[eIdxGlobal];
274 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
275 Scalar potPc = cellData.capillaryPressure()
276 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
278 cellData.setPotential(nPhaseIdx, potNw);
279 cellData.setPotential(wPhaseIdx, potNw - potPc);
281 Scalar pressNw = potNw - gravityDiff * density_[nPhaseIdx];
283 cellData.setPressure(wPhaseIdx, pressNw - cellData.capillaryPressure());
284 cellData.setPressure(nPhaseIdx, pressNw);
290 cellData.fluxData().resetVelocity();
300 int gridSize = problem_.gridView().size(0);
304 timeStep_ = problem_.timeManager().timeStepSize();
306 for (
int i = 0; i < gridSize; i++)
310 switch (saturationType_)
313 sat = problem_.variables().cellData(i).saturation(wPhaseIdx);
316 sat = problem_.variables().cellData(i).saturation(nPhaseIdx);
321 maxError_ = max(maxError_, (sat - 1.0) / timeStep_);
325 maxError_ = max(maxError_, (-sat) / timeStep_);
329 if (problem_.gridAdapt().wasAdapted())
332 this->
A_.setSize(gridSize, gridSize);
333 this->
f_.resize(gridSize);
336 for (
int i = 0; i < gridSize; i++)
338 CellData& cellData = problem_.variables().cellData(i);
340 switch (pressureType_)
343 this->
pressure()[i] = cellData.pressure(wPhaseIdx);
346 this->
pressure()[i] = cellData.pressure(nPhaseIdx);
373 template<
class MultiWriter>
376 int size = problem_.gridView().size(0);
377 ScalarSolutionType *potential = writer.allocateManagedBuffer(size);
381 if (pressureType_ == pw)
383 writer.attachCellData(*potential,
"wetting potential");
386 if (pressureType_ == pn)
388 writer.attachCellData(*potential,
"nonwetting potential");
391 if (vtkOutputLevel_ > 0)
393 ScalarSolutionType *
pressure = writer.allocateManagedBuffer(size);
394 ScalarSolutionType *pressureSecond = writer.allocateManagedBuffer(size);
395 ScalarSolutionType *potentialSecond = writer.allocateManagedBuffer(size);
396 ScalarSolutionType *pc = writer.allocateManagedBuffer(size);
398 for (
const auto& element : elements(problem_.gridView()))
400 int idx = problem_.variables().index(element);
401 CellData& cellData = problem_.variables().cellData(idx);
403 (*pc)[idx] = cellData.capillaryPressure();
405 if (pressureType_ == pw)
407 (*pressure)[idx] = cellData.pressure(wPhaseIdx);
408 (*potentialSecond)[idx] = cellData.potential(nPhaseIdx);
409 (*pressureSecond)[idx] = cellData.pressure(nPhaseIdx);
412 if (pressureType_ == pn)
414 (*pressure)[idx] = cellData.pressure(nPhaseIdx);
415 (*potentialSecond)[idx] = cellData.potential(wPhaseIdx);
416 (*pressureSecond)[idx] = cellData.pressure(wPhaseIdx);
420 if (pressureType_ == pw)
422 writer.attachCellData(*
pressure,
"wetting pressure");
423 writer.attachCellData(*pressureSecond,
"nonwetting pressure");
424 writer.attachCellData(*potentialSecond,
"nonwetting potential");
427 if (pressureType_ == pn)
429 writer.attachCellData(*
pressure,
"nonwetting pressure");
430 writer.attachCellData(*pressureSecond,
"wetting pressure");
431 writer.attachCellData(*potentialSecond,
"wetting potential");
434 writer.attachCellData(*pc,
"capillary pressure");
445 ParentType(problem), problem_(problem), transmissibilityCalculator_(problem),
446 gravity_(problem.gravity()),
447 maxError_(0.), timeStep_(1.)
449 if (pressureType_ != pw && pressureType_ != pn)
451 DUNE_THROW(Dune::NotImplemented,
"Pressure type not supported!");
453 if (saturationType_ != sw && saturationType_ != sn)
455 DUNE_THROW(Dune::NotImplemented,
"Saturation type not supported!");
461 #ifndef DUMUX_2P2CPROPERTIES_HH
462 if (getPropValue<TypeTag, Properties::EnableCompressibility>())
464 DUNE_THROW(Dune::NotImplemented,
"Compressibility not supported!");
469 DUNE_THROW(Dune::NotImplemented,
"Dimension not supported!");
472 ErrorTermFactor_ = getParam<Scalar>(
"Impet.ErrorTermFactor");
473 ErrorTermLowerBound_ = getParam<Scalar>(
"Impet.ErrorTermLowerBound");
474 ErrorTermUpperBound_ = getParam<Scalar>(
"Impet.ErrorTermUpperBound");
476 density_[wPhaseIdx] = 0.;
477 density_[nPhaseIdx] = 0.;
478 viscosity_[wPhaseIdx] = 0.;
479 viscosity_[nPhaseIdx] = 0.;
481 vtkOutputLevel_ = getParam<int>(
"Vtk.OutputLevel");
493 const Dune::FieldVector<Scalar, dimWorld>& gravity_;
497 Scalar ErrorTermFactor_;
498 Scalar ErrorTermLowerBound_;
499 Scalar ErrorTermUpperBound_;
501 Scalar density_[numPhases];
502 Scalar viscosity_[numPhases];
506 static constexpr Scalar threshold_ = 1e-15;
508 static const int pressureType_ = getPropValue<TypeTag, Properties::PressureFormulation>();
510 static const int saturationType_ = getPropValue<TypeTag, Properties::SaturationFormulation>();
512 static const int velocityType_ = getPropValue<TypeTag, Properties::VelocityFormulation>();
515 Scalar evaluateErrorTerm_(CellData& cellData)
520 switch (saturationType_)
523 sat = cellData.saturation(wPhaseIdx);
526 sat = cellData.saturation(nPhaseIdx);
530 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
538 Scalar errorAbs = abs(error);
540 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
541 && (!problem_.timeManager().willBeFinished()))
543 return ErrorTermFactor_ * error;
551template<
class TypeTag>
552typename FvMpfaL2dPressure2pAdaptive<TypeTag>::Intersection
553 FvMpfaL2dPressure2pAdaptive<TypeTag>::getNextIntersection_(
const Element& element,
554 const IntersectionIterator& isIt)
556 auto isItBegin = problem_.gridView().ibegin(element);
557 const auto isEndIt = problem_.gridView().iend(element);
559 auto tempIsIt = isIt;
560 auto nextIsIt = ++tempIsIt;
563 switch (getPropValue<TypeTag, Properties::GridImplementation>())
566 case GridTypeIndices::aluGrid:
567 case GridTypeIndices::ugGrid:
569 if (nextIsIt == isEndIt)
570 nextIsIt = isItBegin;
576 DUNE_THROW(Dune::NotImplemented,
577 "GridType can not be used with adaptive MPFAL!");
586template<
class TypeTag>
587void FvMpfaL2dPressure2pAdaptive<TypeTag>::initializeMatrix()
590 for (
const auto& element : elements(problem_.gridView()))
593 int eIdxGlobalI = problem_.variables().index(element);
599 const auto isEndIt = problem_.gridView().iend(element);
600 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
602 const auto& intersection = *isIt;
604 if (intersection.neighbor())
608 auto nextIntersection = getNextIntersection_(element, isIt);
610 if (nextIntersection.neighbor())
612 bool isCorner =
true;
614 for (
const auto& innerIntersection
615 : intersections(problem_.gridView(), intersection.outside()))
617 for (
const auto& innerNextIntersection
618 : intersections(problem_.gridView(), nextIntersection.outside()))
620 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
622 if (innerIntersection.outside() == nextIntersection.outside()
623 || innerNextIntersection.outside() == intersection.outside())
645 rowSize = min(rowSize, 13);
648 this->A_.setrowsize(eIdxGlobalI, rowSize);
653 this->A_.endrowsizes();
655 for (
const auto& element : elements(problem_.gridView()))
658 int eIdxGlobalI = problem_.variables().index(element);
661 this->A_.addindex(eIdxGlobalI, eIdxGlobalI);
664 const auto isEndIt = problem_.gridView().iend(element);
665 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
667 const auto& intersection = *isIt;
669 if (intersection.neighbor())
672 auto outside = intersection.outside();
673 int eIdxGlobalJ = problem_.variables().index(outside);
677 this->A_.addindex(eIdxGlobalI, eIdxGlobalJ);
679 if (
element.level() < outside.level())
684 auto nextIntersection = getNextIntersection_(element, isIt);
686 if (nextIntersection.neighbor())
689 if (
element.level() < nextIntersection.outside().level())
694 for (
const auto& innerIntersection
695 : intersections(problem_.gridView(), intersection.outside()))
697 for (
const auto& innerNextIntersection
698 : intersections(problem_.gridView(), nextIntersection.outside()))
700 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
702 auto innerOutside = innerIntersection.outside();
703 auto nextOutside = nextIntersection.outside();
705 if (innerOutside == innerNextIntersection.outside() && innerOutside != element
706 && innerOutside != nextOutside)
708 int eIdxGlobalCorner = problem_.variables().index(innerOutside);
710 this->A_.addindex(eIdxGlobalI, eIdxGlobalCorner);
712 if (
element.level() > outside.level())
714 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
716 this->A_.addindex(eIdxGlobalJ, eIdxGlobalJCorner);
718 if (
element.level() > nextOutside.level())
720 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
722 this->A_.addindex(eIdxGlobalJCorner, eIdxGlobalJ);
724 if (
element.level() > innerOutside.level())
726 this->A_.addindex(eIdxGlobalCorner, eIdxGlobalI);
738 this->A_.endindices();
765template<
class TypeTag>
766void FvMpfaL2dPressure2pAdaptive<TypeTag>::storeInteractionVolumeInfo()
768 BoundaryTypes bcType;
771 for (
const auto& element : elements(problem_.gridView()))
774 int eIdxGlobal1 = problem_.variables().index(element);
776 const auto refElement = referenceElement(element);
778 const auto isEndIt12 = problem_.gridView().iend(element);
779 for (
auto isIt12 = problem_.gridView().ibegin(element); isIt12 != isEndIt12; ++isIt12)
781 const auto& intersection12 = *isIt12;
783 int indexInInside12 = intersection12.indexInInside();
785 if (intersection12.neighbor())
788 auto element2 = intersection12.outside();
789 int eIdxGlobal2 = problem_.variables().index(element2);
791 if (
element.level() < element2.level())
796 auto intersection14 = getNextIntersection_(element, isIt12);
798 int indexInInside14 = intersection14.indexInInside();
801 GlobalPosition corner1234(0);
802 int globalVertIdx1234 = 0;
803 bool finished =
false;
805 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
807 int localVertIdx12corner = refElement.subEntity(indexInInside12, dim - 1, i, dim);
809 int globalVertIdx12corner = problem_.variables().index(
element.template subEntity<dim>(localVertIdx12corner));
811 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
813 int localVertIdx14corner = refElement.subEntity(indexInInside14, dim - 1, j, dim);
815 int globalVertIdx14corner = problem_.variables().index(
element.template subEntity<dim>(localVertIdx14corner));
817 if (globalVertIdx12corner == globalVertIdx14corner)
819 corner1234 =
element.geometry().corner(localVertIdx12corner);
821 globalVertIdx1234 = globalVertIdx12corner;
834 if (interactionVolumes_[globalVertIdx1234].isStored() || !finished)
840 interactionVolumes_[globalVertIdx1234].setStored();
843 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
846 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
847 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
848 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
851 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
854 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
857 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
860 GlobalPosition globalPosFace41 = intersection14.geometry().center();
863 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
866 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
868 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
869 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
871 unitOuterNormal14 *= -1;
872 unitOuterNormal12 *= -1;
873 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
874 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
875 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
876 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
879 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element2, 1);
880 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection12.indexInOutside(), 1, 1);
881 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 1, 1);
882 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 1, 1);
883 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 1, 1);
886 if (intersection14.neighbor())
890 auto element4 = intersection14.outside();
893 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
894 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
896 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
897 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
898 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
901 GlobalPosition globalPosFace23(0);
902 GlobalPosition globalPosFace34(0);
904 if (element4.level() <
element.level())
906 bool isHangingNode =
false;
908 for (
const auto& intersection2
909 : intersections(problem_.gridView(), element2))
911 bool breakLoop =
false;
912 for (
const auto& intersection4
913 : intersections(problem_.gridView(), element4))
915 if (intersection2.neighbor() && intersection4.neighbor())
917 auto element32 = intersection2.outside();
918 auto element34 = intersection4.outside();
921 if (element32 == element4)
923 if (
element.level() != element2.level())
926 isHangingNode =
false;
930 isHangingNode =
true;
932 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
934 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInOutside(),
937 globalPosFace23 = intersection2.geometry().center();
938 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
939 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 3, 1);
941 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
942 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
943 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 3, 1);
946 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
948 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
949 unitOuterNormal23 *= -1;
950 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 3, 1);
952 else if (element34 == element2)
954 if (
element.level() != element2.level())
957 isHangingNode =
false;
961 isHangingNode =
true;
963 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
965 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInOutside(),
969 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
970 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
981 bool regularNode =
false;
983 for (
const auto& intersection2
984 : intersections(problem_.gridView(), element2))
986 for (
const auto& intersection4
987 : intersections(problem_.gridView(), element4))
989 if (intersection4.neighbor())
991 auto element41 = intersection4.outside();
993 if (element41 == element && element41.level() >
element.level())
996 globalPosFace41 = intersection4.geometry().center();
997 faceVol41 = intersection4.geometry().volume() / 2.0;
999 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1000 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0,
1002 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1003 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3,
1008 if (intersection2.neighbor() && intersection4.neighbor())
1010 auto element32 = intersection2.outside();
1011 auto element34 = intersection4.outside();
1014 if (element32 == element34 && element32 != element)
1017 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32,
1020 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1021 intersection2.indexInInside(), 1, 0);
1022 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1023 intersection2.indexInOutside(), 2, 1);
1024 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1025 intersection4.indexInInside(), 3, 1);
1026 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1027 intersection4.indexInOutside(), 2, 0);
1029 globalPosFace23 = intersection2.geometry().center();
1030 globalPosFace34 = intersection4.geometry().center();
1032 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1033 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1036 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1037 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1039 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1040 unitOuterNormal23 *= -1;
1041 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1042 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1043 unitOuterNormal43 *= -1;
1044 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1046 if (element32.level() > element2.level())
1048 for (
const auto& intersection3
1049 : intersections(problem_.gridView(), element32))
1051 if (intersection3.neighbor())
1053 auto element23 = intersection3.outside();
1055 if (element23 == element2)
1057 globalPosFace23 = intersection3.geometry().center();
1058 faceVol23 = intersection3.geometry().volume() / 2.0;
1064 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1065 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1066 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1,
1068 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2,
1071 if (element34.level() > element4.level())
1073 for (
const auto& intersection3
1074 : intersections(problem_.gridView(), element34))
1076 if (intersection3.neighbor())
1078 auto element43 = intersection3.outside();
1080 if (element43 == element4)
1082 globalPosFace34 = intersection3.geometry().center();
1083 faceVol34 = intersection3.geometry().volume() / 2.0;
1090 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1091 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1092 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2,
1094 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3,
1109 interactionVolumes_[globalVertIdx1234].reset();
1116 bool regularNode =
false;
1117 for (
const auto& intersection2
1118 : intersections(problem_.gridView(), element2))
1120 for (
const auto& intersection4
1121 : intersections(problem_.gridView(), element4))
1123 if (intersection4.neighbor())
1125 auto element41 = intersection4.outside();
1127 if (element41 == element && element41.level() >
element.level())
1130 globalPosFace41 = intersection4.geometry().center();
1131 faceVol41 = intersection4.geometry().volume() / 2.0;
1133 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1134 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1135 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1136 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1140 if (intersection2.neighbor() && intersection4.neighbor())
1142 auto element32 = intersection2.outside();
1143 auto element34 = intersection4.outside();
1146 if (element32 == element34 && element32 != element)
1149 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32, 2);
1151 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
1153 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1154 intersection2.indexInOutside(), 2, 1);
1155 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
1157 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1158 intersection4.indexInOutside(), 2, 0);
1160 globalPosFace23 = intersection2.geometry().center();
1161 globalPosFace34 = intersection4.geometry().center();
1163 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1164 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1167 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1169 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1171 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1172 unitOuterNormal23 *= -1;
1173 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1174 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1175 unitOuterNormal43 *= -1;
1176 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1177 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1178 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1179 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1180 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1181 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1182 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2, 1);
1183 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2, 0);
1184 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1198 interactionVolumes_[globalVertIdx1234].reset();
1208 problem_.boundaryTypes(bcType, intersection14);
1209 PrimaryVariables boundValues(0.0);
1211 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1212 if (bcType.isNeumann(pressEqIdx))
1214 problem_.neumann(boundValues, intersection14);
1215 boundValues *= faceVol41;
1216 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1218 if (bcType.hasDirichlet())
1220 problem_.dirichlet(boundValues, intersection14);
1221 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1228 GlobalPosition globalPosFace23(0);
1231 Scalar faceVol23 = 0;
1234 DimVector unitOuterNormal23(0);
1238 for (
const auto& intersection2
1239 : intersections(problem_.gridView(), element2))
1241 if (intersection2.boundary())
1243 for (
int i = 0; i < intersection2.geometry().corners(); ++i)
1245 int localVertIdx2corner = refElement.subEntity(intersection2.indexInInside(), dim - 1, i,
1248 int globalVertIdx2corner = problem_.variables().index(element2.template subEntity<dim>(localVertIdx2corner));
1250 if (globalVertIdx2corner == globalVertIdx1234)
1252 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(), 1,
1255 globalPosFace23 = intersection2.geometry().center();
1257 faceVol23 = intersection2.geometry().volume() / 2.0;
1259 unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1261 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1262 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1263 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1265 problem_.boundaryTypes(bcType, intersection2);
1268 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 1);
1269 if (bcType.isNeumann(pressEqIdx))
1271 problem_.neumann(boundValues, intersection2);
1272 boundValues *= faceVol23;
1273 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 1);
1275 if (bcType.hasDirichlet())
1277 problem_.dirichlet(boundValues, intersection2);
1278 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 1);
1281 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1284 if (
element.level() == element2.level())
1286 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1287 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1289 else if (
element.level() < element2.level())
1291 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1293 else if (
element.level() > element2.level())
1295 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1312 Dune::NotImplemented,
1313 "fvmpfao2pfaboundpressure2p.hh, l. 997: boundary shape not available as interaction volume shape");
1321 auto intersection14 = getNextIntersection_(element, isIt12);
1323 int indexInInside14 = intersection14.indexInInside();
1326 GlobalPosition corner1234(0);
1327 int globalVertIdx1234 = 0;
1330 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
1332 bool finished =
false;
1334 int localVertIdx12corner = refElement.subEntity(indexInInside12, dim - 1, i, dim);
1336 int globalVertIdx12corner = problem_.variables().index(
element.template subEntity<dim>(localVertIdx12corner));
1338 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
1340 int localVertIdx14corner = refElement.subEntity(indexInInside14, dim - 1, j, dim);
1342 int globalVertIdx14corner = problem_.variables().index(
element.template subEntity<dim>(localVertIdx14corner));
1344 if (globalVertIdx12corner == globalVertIdx14corner)
1346 corner1234 =
element.geometry().corner(localVertIdx12corner);
1348 globalVertIdx1234 = globalVertIdx12corner;
1361 if (interactionVolumes_[globalVertIdx1234].isStored())
1367 interactionVolumes_[globalVertIdx1234].setStored();
1370 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
1373 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
1374 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
1375 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
1378 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
1381 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
1384 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
1387 const GlobalPosition& globalPosFace41 = intersection14.geometry().center();
1390 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
1393 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
1395 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
1396 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
1398 unitOuterNormal14 *= -1;
1399 unitOuterNormal12 *= -1;
1400 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
1401 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1402 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
1403 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1405 problem_.boundaryTypes(bcType, intersection12);
1406 PrimaryVariables boundValues(0.0);
1408 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 0);
1409 if (bcType.isNeumann(pressEqIdx))
1411 problem_.neumann(boundValues, intersection12);
1412 boundValues *= faceVol12;
1413 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 0);
1415 if (bcType.hasDirichlet())
1417 problem_.dirichlet(boundValues, intersection12);
1418 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 0);
1422 if (intersection14.boundary())
1424 problem_.boundaryTypes(bcType, intersection14);
1427 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1428 if (bcType.isNeumann(pressEqIdx))
1430 problem_.neumann(boundValues, intersection14);
1431 boundValues *= faceVol41;
1432 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1434 if (bcType.hasDirichlet())
1436 problem_.dirichlet(boundValues, intersection14);
1437 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1440 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1441 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1445 else if (intersection14.neighbor())
1449 auto element4 = intersection14.outside();
1450 int eIdxGlobal4 = problem_.variables().index(element4);
1452 if ((
element.level() == element4.level() && eIdxGlobal1 > eIdxGlobal4)
1453 ||
element.level() < element4.level())
1455 interactionVolumes_[globalVertIdx1234].reset();
1459 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
1462 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
1464 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
1465 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1466 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1468 bool finished =
false;
1471 for (
const auto& intersection4
1472 : intersections(problem_.gridView(), element4))
1474 if (intersection4.boundary())
1476 for (
int i = 0; i < intersection4.geometry().corners(); ++i)
1478 int localVertIdx4corner = refElement.subEntity(intersection4.indexInInside(), dim - 1, i,
1481 int globalVertIdx4corner = problem_.variables().index(element4.template subEntity<dim>(localVertIdx4corner));
1483 if (globalVertIdx4corner == globalVertIdx1234)
1485 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(), 3,
1488 const GlobalPosition& globalPosFace34 = intersection4.geometry().center();
1489 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1491 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1493 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1494 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1495 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1497 problem_.boundaryTypes(bcType, intersection4);
1500 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 2);
1501 if (bcType.isNeumann(pressEqIdx))
1503 problem_.neumann(boundValues, intersection4);
1504 boundValues *= faceVol34;
1505 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 2);
1507 if (bcType.hasDirichlet())
1509 problem_.dirichlet(boundValues, intersection4);
1510 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 2);
1513 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1515 if (
element.level() == element4.level())
1517 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1518 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1520 if (
element.level() < element4.level())
1522 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1524 if (
element.level() > element4.level())
1526 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1544 Dune::NotImplemented,
1545 "fvmpfao2pfaboundpressure2p_adaptive.hh: boundary shape not available as interaction volume shape");
1550 DUNE_THROW(Dune::NotImplemented,
1551 "fvmpfao2pfaboundpressure2p_adaptive.hh: interface type not supported!");
1562template<
class TypeTag>
1563void FvMpfaL2dPressure2pAdaptive<TypeTag>::printInteractionVolumes()
1565 for (
const auto& vertex : vertices(problem_.gridView()))
1567 int vIdxGlobal = problem_.variables().index(vertex);
1569 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1571 if (interactionVolume.getElementNumber() > 2)
1573 interactionVolume.printInteractionVolumeInfo();
1574 std::cout <<
"global vertex index: " << vIdxGlobal <<
"\n";
1575 if (interactionVolume.getElementNumber() == 3)
1577 auto element1 = interactionVolume.getSubVolumeElement(0);
1578 auto element2 = interactionVolume.getSubVolumeElement(1);
1579 auto element4 = interactionVolume.getSubVolumeElement(3);
1581 int eIdxGlobal1 = problem_.variables().index(element1);
1582 int eIdxGlobal2 = problem_.variables().index(element2);
1583 int eIdxGlobal4 = problem_.variables().index(element4);
1585 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1586 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1587 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1589 if (interactionVolume.getElementNumber() == 4)
1591 auto element1 = interactionVolume.getSubVolumeElement(0);
1592 auto element2 = interactionVolume.getSubVolumeElement(1);
1593 auto element3 = interactionVolume.getSubVolumeElement(2);
1594 auto element4 = interactionVolume.getSubVolumeElement(3);
1596 int eIdxGlobal1 = problem_.variables().index(element1);
1597 int eIdxGlobal2 = problem_.variables().index(element2);
1598 int eIdxGlobal3 = problem_.variables().index(element3);
1599 int eIdxGlobal4 = problem_.variables().index(element4);
1601 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1602 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1603 std::cout <<
"global element index 3: " << eIdxGlobal3 <<
"\n";
1604 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1612template<
class TypeTag>
1613void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
1620 for (
const auto& vertex : vertices(problem_.gridView()))
1622 int vIdxGlobal = problem_.variables().index(vertex);
1624 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1626 if (interactionVolume.isInnerVolume())
1628 if (interactionVolume.getElementNumber() == 4)
1630 auto element1 = interactionVolume.getSubVolumeElement(0);
1631 auto element2 = interactionVolume.getSubVolumeElement(1);
1632 auto element3 = interactionVolume.getSubVolumeElement(2);
1633 auto element4 = interactionVolume.getSubVolumeElement(3);
1636 const GlobalPosition& globalPos1 = element1.geometry().center();
1637 const GlobalPosition& globalPos2 = element2.geometry().center();
1638 const GlobalPosition& globalPos3 = element3.geometry().center();
1639 const GlobalPosition& globalPos4 = element4.geometry().center();
1642 Scalar volume1 = element1.geometry().volume();
1643 Scalar volume2 = element2.geometry().volume();
1644 Scalar volume3 = element3.geometry().volume();
1645 Scalar volume4 = element4.geometry().volume();
1648 int eIdxGlobal1 = problem_.variables().index(element1);
1649 int eIdxGlobal2 = problem_.variables().index(element2);
1650 int eIdxGlobal3 = problem_.variables().index(element3);
1651 int eIdxGlobal4 = problem_.variables().index(element4);
1654 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
1655 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
1656 CellData& cellData3 = problem_.variables().cellData(eIdxGlobal3);
1657 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
1660 PrimaryVariables source(0.0);
1661 problem_.source(source, element1);
1662 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1663 problem_.source(source, element2);
1664 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1665 problem_.source(source, element3);
1666 this->f_[eIdxGlobal3] += volume3 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1667 problem_.source(source, element4);
1668 this->f_[eIdxGlobal4] += volume4 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1670 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
1671 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
1672 this->f_[eIdxGlobal3] += evaluateErrorTerm_(cellData3) * volume3 / (4.0);
1673 this->f_[eIdxGlobal4] += evaluateErrorTerm_(cellData4) * volume4 / (4.0);
1676 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
1677 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
1680 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
1683 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
1684 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
1687 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
1690 Dune::FieldVector<Scalar, numPhases> lambda3(cellData3.mobility(wPhaseIdx));
1691 lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
1694 Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
1697 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
1698 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
1701 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
1703 std::vector < DimVector > lambda(2 * dim);
1705 lambda[0][0] = lambdaTotal1;
1706 lambda[0][1] = lambdaTotal1;
1707 lambda[1][0] = lambdaTotal2;
1708 lambda[1][1] = lambdaTotal2;
1709 lambda[2][0] = lambdaTotal3;
1710 lambda[2][1] = lambdaTotal3;
1711 lambda[3][0] = lambdaTotal4;
1712 lambda[3][1] = lambdaTotal4;
1716 Dune::FieldVector<Scalar, 2 * dim> pc(0);
1717 pc[0] = cellData1.capillaryPressure();
1718 pc[1] = cellData2.capillaryPressure();
1719 pc[2] = cellData3.capillaryPressure();
1720 pc[3] = cellData4.capillaryPressure();
1722 Dune::FieldVector<Scalar, 2 * dim> gravityDiff(0);
1724 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1725 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1726 gravityDiff[2] = (problem_.bBoxMax() - globalPos3) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1727 gravityDiff[3] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1731 Dune::FieldVector<Scalar, 2 * dim> pcFlux(0);
1733 Scalar pcPotential12 = 0;
1734 Scalar pcPotential14 = 0;
1735 Scalar pcPotential32 = 0;
1736 Scalar pcPotential34 = 0;
1739 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
1740 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
1742 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
1744 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1746 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1750 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
1751 this->A_[eIdxGlobal1][eIdxGlobal3] += T[1][1];
1752 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
1754 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
1755 this->A_[eIdxGlobal2][eIdxGlobal3] -= T[1][1];
1756 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
1765 pcPotential12 = Tu[1];
1767 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1769 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1773 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
1774 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
1775 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
1777 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
1778 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
1779 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
1788 pcPotential12 = Tu[1];
1791 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
1793 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1795 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1799 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][0];
1800 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][1];
1801 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][2];
1803 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][0];
1804 this->A_[eIdxGlobal3][eIdxGlobal4] -= T[1][1];
1805 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][2];
1814 pcPotential32 = -Tu[1];
1816 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1818 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1822 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
1823 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
1824 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][2];
1826 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][0];
1827 this->A_[eIdxGlobal3][eIdxGlobal1] -= T[1][1];
1828 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][2];
1837 pcPotential32 = -Tu[1];
1840 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
1842 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1844 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1848 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][0];
1849 this->A_[eIdxGlobal3][eIdxGlobal1] += T[1][1];
1850 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][2];
1852 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][0];
1853 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
1854 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][2];
1863 pcPotential34 = Tu[1];
1865 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1867 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1871 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][0];
1872 this->A_[eIdxGlobal3][eIdxGlobal2] += T[1][1];
1873 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][2];
1875 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][0];
1876 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][1];
1877 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
1886 pcPotential34 = Tu[1];
1889 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
1891 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1893 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1897 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
1898 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
1899 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
1901 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
1902 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
1903 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
1912 pcPotential14 = -Tu[1];
1914 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1916 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1920 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][0];
1921 this->A_[eIdxGlobal4][eIdxGlobal3] += T[1][1];
1922 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][2];
1924 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][0];
1925 this->A_[eIdxGlobal1][eIdxGlobal3] -= T[1][1];
1926 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][2];
1935 pcPotential14 = -Tu[1];
1938 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0 && pc[3] == 0)
1944 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
1945 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
1946 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
1949 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
1950 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
1951 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
1954 Dune::FieldVector<Scalar, numPhases> lambda32Upw(0.0);
1955 lambda32Upw[wPhaseIdx] = (pcPotential32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
1956 lambda32Upw[nPhaseIdx] = (pcPotential32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
1959 Dune::FieldVector<Scalar, numPhases> lambda34Upw(0.0);
1960 lambda34Upw[wPhaseIdx] = (pcPotential34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
1961 lambda34Upw[nPhaseIdx] = (pcPotential34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
1963 for (
int i = 0; i < numPhases; i++)
1965 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
1966 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
1967 Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
1968 Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
1969 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
1970 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
1971 Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
1972 Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
1974 Dune::FieldVector<Scalar, 2 * dim> pcFluxReal(pcFlux);
1976 pcFluxReal[0] *= fracFlow12;
1977 pcFluxReal[1] *= fracFlow32;
1978 pcFluxReal[2] *= fracFlow34;
1979 pcFluxReal[3] *= fracFlow14;
1981 switch (pressureType_)
1988 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[3]);
1989 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
1990 this->f_[eIdxGlobal3] -= (pcFluxReal[2] - pcFluxReal[1]);
1991 this->f_[eIdxGlobal4] -= (pcFluxReal[3] - pcFluxReal[2]);
2001 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[3]);
2002 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2003 this->f_[eIdxGlobal3] += (pcFluxReal[2] - pcFluxReal[1]);
2004 this->f_[eIdxGlobal4] += (pcFluxReal[3] - pcFluxReal[2]);
2011 else if (interactionVolume.getElementNumber() == 3)
2013 auto element1 = interactionVolume.getSubVolumeElement(0);
2014 auto element2 = interactionVolume.getSubVolumeElement(1);
2015 auto element4 = interactionVolume.getSubVolumeElement(3);
2018 const GlobalPosition& globalPos1 = element1.geometry().center();
2019 const GlobalPosition& globalPos2 = element2.geometry().center();
2020 const GlobalPosition& globalPos4 = element4.geometry().center();
2023 Scalar volume1 = element1.geometry().volume();
2024 Scalar volume2 = element2.geometry().volume();
2027 int eIdxGlobal1 = problem_.variables().index(element1);
2028 int eIdxGlobal2 = problem_.variables().index(element2);
2029 int eIdxGlobal4 = problem_.variables().index(element4);
2032 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
2033 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
2034 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
2038 PrimaryVariables source(0.0);
2039 problem_.source(source, element1);
2040 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2041 problem_.source(source, element2);
2042 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2044 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
2045 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
2048 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
2049 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
2052 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
2055 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
2056 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
2059 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
2062 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
2063 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
2066 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
2068 std::vector < DimVector > lambda(4);
2070 lambda[0][0] = lambdaTotal1;
2071 lambda[0][1] = lambdaTotal1;
2072 lambda[1][0] = lambdaTotal2;
2073 lambda[1][1] = lambdaTotal2;
2074 lambda[3][0] = lambdaTotal4;
2075 lambda[3][1] = lambdaTotal4;
2079 Dune::FieldVector<Scalar, 3> pc(0);
2080 pc[0] = cellData1.capillaryPressure();
2081 pc[1] = cellData2.capillaryPressure();
2082 pc[2] = cellData4.capillaryPressure();
2084 Dune::FieldVector<Scalar, 3> gravityDiff(0);
2086 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2087 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2088 gravityDiff[2] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2092 Dune::FieldVector<Scalar, 3> pcFlux(0);
2094 Scalar pcPotential12 = 0;
2095 Scalar pcPotential14 = 0;
2096 Scalar pcPotential24 = 0;
2099 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
2100 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
2102 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
2104 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2106 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2110 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
2111 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2112 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
2114 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
2115 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2116 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
2125 pcPotential12 = Tu[1];
2127 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2129 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2133 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
2134 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2135 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
2137 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
2138 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2139 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
2148 pcPotential12 = Tu[1];
2152 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2155 transmissibilityType = transmissibilityCalculator_.calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
2157 if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2159 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
2163 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
2164 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
2165 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][2];
2167 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][0];
2168 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
2169 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
2178 pcPotential24 = Tu[1];
2182 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2185 transmissibilityType = transmissibilityCalculator_.calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
2187 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2189 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 1)])
2194 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
2195 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
2196 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
2198 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
2199 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
2200 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
2209 pcPotential14 = -Tu[1];
2213 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2216 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0)
2222 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
2223 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
2224 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
2227 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
2228 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
2229 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
2232 Dune::FieldVector<Scalar, numPhases> lambda24Upw(0.0);
2233 lambda24Upw[wPhaseIdx] = (pcPotential24 >= 0) ? lambda2[wPhaseIdx] : lambda4[wPhaseIdx];
2234 lambda24Upw[nPhaseIdx] = (pcPotential24 >= 0) ? lambda2[nPhaseIdx] : lambda4[nPhaseIdx];
2236 for (
int i = 0; i < numPhases; i++)
2238 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
2239 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
2240 Scalar lambdaT24 = lambda24Upw[wPhaseIdx] + lambda24Upw[nPhaseIdx];
2241 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
2242 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
2243 Scalar fracFlow24 = (lambdaT24 > threshold_) ? lambda24Upw[i] / (lambdaT24) : 0.0;
2245 Dune::FieldVector<Scalar, 3> pcFluxReal(pcFlux);
2247 pcFluxReal[0] *= fracFlow12;
2248 pcFluxReal[1] *= fracFlow24;
2249 pcFluxReal[2] *= fracFlow14;
2251 switch (pressureType_)
2258 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[2]);
2259 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
2260 this->f_[eIdxGlobal4] -= (pcFluxReal[2] - pcFluxReal[1]);
2270 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[2]);
2271 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2272 this->f_[eIdxGlobal4] += (pcFluxReal[2] - pcFluxReal[1]);
2281 DUNE_THROW(Dune::NotImplemented,
"Unknown interactionvolume type!");
2288 for (
int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
2290 bool isOutside =
false;
2291 for (
int fIdx = 0; fIdx < dim; fIdx++)
2293 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2294 if (interactionVolume.isOutsideFace(intVolFaceIdx))
2305 auto element = interactionVolume.getSubVolumeElement(elemIdx);
2308 const GlobalPosition& globalPos =
element.geometry().center();
2314 int eIdxGlobal = problem_.variables().index(element);
2317 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
2320 DimMatrix
permeability(problem_.spatialParams().intrinsicPermeability(element));
2323 PrimaryVariables source(0);
2324 problem_.source(source, element);
2325 this->f_[eIdxGlobal] +=
volume / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2327 this->f_[eIdxGlobal] += evaluateErrorTerm_(cellData) *
volume / (4.0);
2330 Dune::FieldVector<Scalar, numPhases> lambda(cellData.mobility(wPhaseIdx));
2331 lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
2333 Scalar pc = cellData.capillaryPressure();
2335 Scalar gravityDiff = (problem_.bBoxMax() - globalPos) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2339 for (
int fIdx = 0; fIdx < dim; fIdx++)
2341 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2343 if (interactionVolume.isBoundaryFace(intVolFaceIdx))
2346 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressEqIdx))
2348 int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, fIdx);
2350 const auto refElement = referenceElement(element);
2352 const LocalPosition& localPos = refElement.position(boundaryFaceIdx, 1);
2354 const GlobalPosition& globalPosFace =
element.geometry().global(localPos);
2356 DimVector distVec(globalPosFace - globalPos);
2357 Scalar dist = distVec.two_norm();
2358 DimVector unitDistVec(distVec);
2359 unitDistVec /= dist;
2361 Scalar faceArea = interactionVolume.getFaceArea(elemIdx, fIdx);
2364 Scalar satWBound = cellData.saturation(wPhaseIdx);
2366 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
2368 Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
2369 switch (saturationType_)
2373 satWBound = satBound;
2378 satWBound = 1 - satBound;
2385 const auto fluidMatrixInteraction = problem_.spatialParams().fluidMatrixInteractionAtPos(
element.geometry().center());
2386 Scalar pcBound = fluidMatrixInteraction.pc(satWBound);
2388 Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_
2389 * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2391 pcBound += gravityDiffBound;
2393 Dune::FieldVector<Scalar, numPhases> lambdaBound(fluidMatrixInteraction.krw(satWBound));
2394 lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(satWBound);
2395 lambdaBound[wPhaseIdx] /= viscosity_[wPhaseIdx];
2396 lambdaBound[nPhaseIdx] /= viscosity_[nPhaseIdx];
2398 Scalar potentialBound = interactionVolume.getDirichletValues(intVolFaceIdx)[pressureIdx];
2399 Scalar gdeltaZ = (problem_.bBoxMax()-globalPosFace) * gravity_;
2402 Scalar potentialDiffW = 0;
2403 Scalar potentialDiffNw = 0;
2404 switch (pressureType_)
2408 potentialBound += density_[wPhaseIdx]*gdeltaZ;
2409 potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBound) / dist;
2410 potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBound - pcBound) / dist;
2415 potentialBound += density_[nPhaseIdx]*gdeltaZ;
2416 potentialDiffW = (cellData.potential(wPhaseIdx) - potentialBound + pcBound) / dist;
2417 potentialDiffNw = (cellData.potential(nPhaseIdx) - potentialBound) / dist;
2422 Scalar lambdaTotal = (potentialDiffW >= 0.) ? lambda[wPhaseIdx] : lambdaBound[wPhaseIdx];
2423 lambdaTotal += (potentialDiffNw >= 0.) ? lambda[nPhaseIdx] : lambdaBound[nPhaseIdx];
2425 DimVector permTimesNormal(0);
2429 Scalar entry = lambdaTotal * (unitDistVec * permTimesNormal) / dist * faceArea;
2434 switch (pressureType_)
2439 DimVector pcGradient = unitDistVec;
2440 pcGradient *= (pc - pcBound) / dist;
2443 pcFlux = 0.5 * (lambda[nPhaseIdx] + lambdaBound[nPhaseIdx])
2444 * (permTimesNormal * pcGradient) * faceArea;
2451 DimVector pcGradient = unitDistVec;
2452 pcGradient *= (pc - pcBound) / dist;
2455 pcFlux = 0.5 * (lambda[wPhaseIdx] + lambdaBound[wPhaseIdx])
2456 * (permTimesNormal * pcGradient) * faceArea;
2464 this->A_[eIdxGlobal][eIdxGlobal] += entry;
2465 this->f_[eIdxGlobal] += entry * potentialBound;
2467 if (pc == 0 && pcBound == 0)
2472 for (
int i = 0; i < numPhases; i++)
2474 switch (pressureType_)
2481 this->f_[eIdxGlobal] -= pcFlux;
2490 this->f_[eIdxGlobal] += pcFlux;
2498 else if (interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx))
2500 Scalar J = interactionVolume.getNeumannValues(intVolFaceIdx)[wPhaseIdx] / density_[wPhaseIdx];
2501 J += interactionVolume.getNeumannValues(intVolFaceIdx)[nPhaseIdx] / density_[nPhaseIdx];
2503 this->f_[eIdxGlobal] -= J;
2507 std::cout <<
"interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx)"
2508 << interactionVolume.getBoundaryType(intVolFaceIdx).isNeumann(pressEqIdx) <<
"\n";
2509 DUNE_THROW(Dune::NotImplemented,
2510 "No valid boundary condition type defined for pressure equation!");
2520 if (problem_.gridView().comm().size() > 1)
2523 for (
const auto& element : elements(problem_.gridView()))
2525 if (
element.partitionType() == Dune::InteriorEntity)
2529 int eIdxGlobalI = problem_.variables().index(element);
2531 this->A_[eIdxGlobalI] = 0.0;
2532 this->A_[eIdxGlobalI][eIdxGlobalI] = 1.0;
2533 this->f_[eIdxGlobalI] = this->
pressure()[eIdxGlobalI];
2545template<
class TypeTag>
2549 for (
const auto& element : elements(problem_.gridView()))
2551 int eIdxGlobal = problem_.variables().index(element);
2553 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
2555 const Scalar satW = cellData.saturation(wPhaseIdx);
2557 const auto fluidMatrixInteraction = problem_.spatialParams().fluidMatrixInteractionAtPos(element.geometry().center());
2558 const Scalar pc = fluidMatrixInteraction.pc(satW);
2560 cellData.setCapillaryPressure(pc);
2563 const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx];
2564 const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx];
2567 cellData.setMobility(wPhaseIdx, mobilityW);
2568 cellData.setMobility(nPhaseIdx, mobilityNw);
2571 cellData.setFracFlowFunc(wPhaseIdx, mobilityW / (mobilityW + mobilityNw));
2572 cellData.setFracFlowFunc(nPhaseIdx, mobilityNw / (mobilityW + mobilityNw));
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...
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type GetProp
get the type of a property
Definition: propertysystem.hh:141
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property
Definition: propertysystem.hh:150
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
Scalar volume(Shape shape, Scalar inscribedRadius)
Returns the volume of a given geometry based on the inscribed radius.
Definition: poreproperties.hh:73
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:245
void addOutputVtkFields(MultiWriter &writer)
Adds pressure output to the output file.
Definition: 2dpressureadaptive.hh:374
void updateInteractionVolumeInfo()
Updates interaction volumes.
Definition: 2dpressureadaptive.hh:183
InnerBoundaryVolumeFaces innerBoundaryVolumeFaces_
Vector marking faces which intersect the boundary.
Definition: 2dpressureadaptive.hh:490
void storePressureSolution()
Globally stores the pressure solution.
Definition: 2dpressureadaptive.hh:231
FvMpfaL2dPressure2pAdaptive(Problem &problem)
Constructs a FvMpfaL2dPressure2pAdaptive object.
Definition: 2dpressureadaptive.hh:444
void initialize()
Initializes the pressure model.
Definition: 2dpressureadaptive.hh:200
FvMpfaL2dTransmissibilityCalculator< TypeTag > TransmissibilityCalculator
Definition: 2dpressureadaptive.hh:153
void updateMaterialLaws()
constitutive functions are initialized and stored in the variables object
Definition: 2dpressureadaptive.hh:2546
void update()
Pressure update.
Definition: 2dpressureadaptive.hh:298
GlobalInteractionVolumeVector interactionVolumes_
Global Vector of interaction volumes.
Definition: 2dpressureadaptive.hh:489
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:49
void initialize()
Initialize pressure model.
Definition: sequential/cellcentered/pressure.hh:213
PressureSolution & pressure()
Returns the vector containing the pressure solution.
Definition: sequential/cellcentered/pressure.hh:120
Matrix A_
Global stiffnes matrix (sparse matrix which is build by the initializeMatrix() function)
Definition: sequential/cellcentered/pressure.hh:324
void solve()
Solves the global system of equations to get the spatial distribution of the pressure.
Definition: sequential/cellcentered/pressure.hh:527
RHSVector f_
Right hand side vector.
Definition: sequential/cellcentered/pressure.hh:325
Specifies the properties for immiscible 2p diffusion/pressure models.
Properties for a MPFA method.
Finite Volume Diffusion Model.