23#ifndef DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
24#define DUMUX_FVMPFAL2DPRESSURE2P_ADAPTIVE_HH
75template<
class TypeTag>
83 dim = GridView::dimension, dimWorld = GridView::dimensionworld
101 using PrimaryVariables =
typename SolutionTypes::PrimaryVariables;
102 using ScalarSolutionType =
typename SolutionTypes::ScalarSolution;
108 pw = Indices::pressureW,
109 pn = Indices::pressureNw,
110 sw = Indices::saturationW,
111 sn = Indices::saturationNw
115 wPhaseIdx = Indices::wPhaseIdx,
116 nPhaseIdx = Indices::nPhaseIdx,
117 pressureIdx = Indices::pressureIdx,
118 saturationIdx = Indices::saturationIdx,
119 pressEqIdx = Indices::pressureEqIdx,
120 satEqIdx = Indices::satEqIdx,
121 numPhases = getPropValue<TypeTag, Properties::NumPhases>()
128 dirichletDirichlet = 1,
129 dirichletNeumann = 2,
134 using Element =
typename GridView::Traits::template Codim<0>::Entity;
135 using IntersectionIterator =
typename GridView::IntersectionIterator;
136 using Intersection =
typename GridView::Intersection;
137 using Grid =
typename GridView::Grid;
139 using LocalPosition = Dune::FieldVector<Scalar, dim>;
140 using GlobalPosition =
typename Element::Geometry::GlobalCoordinate;
141 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
143 using DimVector = Dune::FieldVector<Scalar, dim>;
158 using GlobalInteractionVolumeVector = std::vector<InteractionVolume>;
159 using InnerBoundaryVolumeFaces = std::vector<Dune::FieldVector<bool, 2*dim> >;
162 Intersection getNextIntersection_(
const Element&,
const IntersectionIterator&);
166 void initializeMatrix();
168 void storeInteractionVolumeInfo();
170 void printInteractionVolumes();
193 storeInteractionVolumeInfo();
206 const auto element = *problem_.gridView().template begin<0>();
207 FluidState fluidState;
208 fluidState.setPressure(wPhaseIdx, problem_.referencePressure(element));
209 fluidState.setPressure(nPhaseIdx, problem_.referencePressure(element));
210 fluidState.setTemperature(problem_.temperature(element));
211 fluidState.setSaturation(wPhaseIdx, 1.);
212 fluidState.setSaturation(nPhaseIdx, 0.);
236 for (
const auto& element : elements(problem_.gridView()))
249 int eIdxGlobal = problem_.variables().index(element);
250 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
252 switch (pressureType_)
256 Scalar potW = this->
pressure()[eIdxGlobal];
258 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
259 Scalar potPc = cellData.capillaryPressure()
260 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
262 cellData.setPotential(wPhaseIdx, potW);
263 cellData.setPotential(nPhaseIdx, potW + potPc);
265 Scalar pressW = potW - gravityDiff * density_[wPhaseIdx];
267 cellData.setPressure(wPhaseIdx, pressW);
268 cellData.setPressure(nPhaseIdx, pressW + cellData.capillaryPressure());
274 Scalar potNw = this->
pressure()[eIdxGlobal];
276 Scalar gravityDiff = (problem_.bBoxMax() - element.geometry().center()) * gravity_;
277 Scalar potPc = cellData.capillaryPressure()
278 + gravityDiff * (density_[nPhaseIdx] - density_[wPhaseIdx]);
280 cellData.setPotential(nPhaseIdx, potNw);
281 cellData.setPotential(wPhaseIdx, potNw - potPc);
283 Scalar pressNw = potNw - gravityDiff * density_[nPhaseIdx];
285 cellData.setPressure(wPhaseIdx, pressNw - cellData.capillaryPressure());
286 cellData.setPressure(nPhaseIdx, pressNw);
292 cellData.fluxData().resetVelocity();
302 int gridSize = problem_.gridView().size(0);
306 timeStep_ = problem_.timeManager().timeStepSize();
308 for (
int i = 0; i < gridSize; i++)
312 switch (saturationType_)
315 sat = problem_.variables().cellData(i).saturation(wPhaseIdx);
318 sat = problem_.variables().cellData(i).saturation(nPhaseIdx);
323 maxError_ = max(maxError_, (sat - 1.0) / timeStep_);
327 maxError_ = max(maxError_, (-sat) / timeStep_);
331 if (problem_.gridAdapt().wasAdapted())
334 this->
A_.setSize(gridSize, gridSize);
335 this->
f_.resize(gridSize);
338 for (
int i = 0; i < gridSize; i++)
340 CellData& cellData = problem_.variables().cellData(i);
342 switch (pressureType_)
345 this->
pressure()[i] = cellData.pressure(wPhaseIdx);
348 this->
pressure()[i] = cellData.pressure(nPhaseIdx);
375 template<
class MultiWriter>
378 int size = problem_.gridView().size(0);
379 ScalarSolutionType *potential = writer.allocateManagedBuffer(size);
383 if (pressureType_ == pw)
385 writer.attachCellData(*potential,
"wetting potential");
388 if (pressureType_ == pn)
390 writer.attachCellData(*potential,
"nonwetting potential");
393 if (vtkOutputLevel_ > 0)
395 ScalarSolutionType *
pressure = writer.allocateManagedBuffer(size);
396 ScalarSolutionType *pressureSecond = writer.allocateManagedBuffer(size);
397 ScalarSolutionType *potentialSecond = writer.allocateManagedBuffer(size);
398 ScalarSolutionType *pc = writer.allocateManagedBuffer(size);
400 for (
const auto& element : elements(problem_.gridView()))
402 int idx = problem_.variables().index(element);
403 CellData& cellData = problem_.variables().cellData(idx);
405 (*pc)[idx] = cellData.capillaryPressure();
407 if (pressureType_ == pw)
409 (*pressure)[idx] = cellData.pressure(wPhaseIdx);
410 (*potentialSecond)[idx] = cellData.potential(nPhaseIdx);
411 (*pressureSecond)[idx] = cellData.pressure(nPhaseIdx);
414 if (pressureType_ == pn)
416 (*pressure)[idx] = cellData.pressure(nPhaseIdx);
417 (*potentialSecond)[idx] = cellData.potential(wPhaseIdx);
418 (*pressureSecond)[idx] = cellData.pressure(wPhaseIdx);
422 if (pressureType_ == pw)
424 writer.attachCellData(*
pressure,
"wetting pressure");
425 writer.attachCellData(*pressureSecond,
"nonwetting pressure");
426 writer.attachCellData(*potentialSecond,
"nonwetting potential");
429 if (pressureType_ == pn)
431 writer.attachCellData(*
pressure,
"nonwetting pressure");
432 writer.attachCellData(*pressureSecond,
"wetting pressure");
433 writer.attachCellData(*potentialSecond,
"wetting potential");
436 writer.attachCellData(*pc,
"capillary pressure");
447 ParentType(problem), problem_(problem), transmissibilityCalculator_(problem),
448 gravity_(problem.gravity()),
449 maxError_(0.), timeStep_(1.)
451 if (pressureType_ != pw && pressureType_ != pn)
453 DUNE_THROW(Dune::NotImplemented,
"Pressure type not supported!");
455 if (saturationType_ != sw && saturationType_ != sn)
457 DUNE_THROW(Dune::NotImplemented,
"Saturation type not supported!");
463 #ifndef DUMUX_2P2CPROPERTIES_HH
464 if (getPropValue<TypeTag, Properties::EnableCompressibility>())
466 DUNE_THROW(Dune::NotImplemented,
"Compressibility not supported!");
471 DUNE_THROW(Dune::NotImplemented,
"Dimension not supported!");
474 ErrorTermFactor_ = getParam<Scalar>(
"Impet.ErrorTermFactor");
475 ErrorTermLowerBound_ = getParam<Scalar>(
"Impet.ErrorTermLowerBound");
476 ErrorTermUpperBound_ = getParam<Scalar>(
"Impet.ErrorTermUpperBound");
478 density_[wPhaseIdx] = 0.;
479 density_[nPhaseIdx] = 0.;
480 viscosity_[wPhaseIdx] = 0.;
481 viscosity_[nPhaseIdx] = 0.;
483 vtkOutputLevel_ = getParam<int>(
"Vtk.OutputLevel");
495 const Dune::FieldVector<Scalar, dimWorld>& gravity_;
499 Scalar ErrorTermFactor_;
500 Scalar ErrorTermLowerBound_;
501 Scalar ErrorTermUpperBound_;
503 Scalar density_[numPhases];
504 Scalar viscosity_[numPhases];
508 static constexpr Scalar threshold_ = 1e-15;
510 static const int pressureType_ = getPropValue<TypeTag, Properties::PressureFormulation>();
512 static const int saturationType_ = getPropValue<TypeTag, Properties::SaturationFormulation>();
514 static const int velocityType_ = getPropValue<TypeTag, Properties::VelocityFormulation>();
517 Scalar evaluateErrorTerm_(CellData& cellData)
522 switch (saturationType_)
525 sat = cellData.saturation(wPhaseIdx);
528 sat = cellData.saturation(nPhaseIdx);
532 Scalar error = (sat > 1.0) ? sat - 1.0 : 0.0;
540 Scalar errorAbs = abs(error);
542 if ((errorAbs * timeStep_ > 1e-6) && (errorAbs > ErrorTermLowerBound_ * maxError_)
543 && (!problem_.timeManager().willBeFinished()))
545 return ErrorTermFactor_ * error;
553template<
class TypeTag>
554typename FvMpfaL2dPressure2pAdaptive<TypeTag>::Intersection
555 FvMpfaL2dPressure2pAdaptive<TypeTag>::getNextIntersection_(
const Element& element,
556 const IntersectionIterator& isIt)
558 auto isItBegin = problem_.gridView().ibegin(element);
559 const auto isEndIt = problem_.gridView().iend(element);
561 auto tempIsIt = isIt;
562 auto nextIsIt = ++tempIsIt;
565 switch (getPropValue<TypeTag, Properties::GridImplementation>())
568 case GridTypeIndices::aluGrid:
569 case GridTypeIndices::ugGrid:
571 if (nextIsIt == isEndIt)
572 nextIsIt = isItBegin;
578 DUNE_THROW(Dune::NotImplemented,
579 "GridType can not be used with adaptive MPFAL!");
588template<
class TypeTag>
589void FvMpfaL2dPressure2pAdaptive<TypeTag>::initializeMatrix()
592 for (
const auto& element : elements(problem_.gridView()))
595 int eIdxGlobalI = problem_.variables().index(element);
601 const auto isEndIt = problem_.gridView().iend(element);
602 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
604 const auto& intersection = *isIt;
606 if (intersection.neighbor())
610 auto nextIntersection = getNextIntersection_(element, isIt);
612 if (nextIntersection.neighbor())
614 bool isCorner =
true;
616 for (
const auto& innerIntersection
617 : intersections(problem_.gridView(), intersection.outside()))
619 for (
const auto& innerNextIntersection
620 : intersections(problem_.gridView(), nextIntersection.outside()))
622 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
624 if (innerIntersection.outside() == nextIntersection.outside()
625 || innerNextIntersection.outside() == intersection.outside())
647 rowSize = min(rowSize, 13);
650 this->A_.setrowsize(eIdxGlobalI, rowSize);
655 this->A_.endrowsizes();
657 for (
const auto& element : elements(problem_.gridView()))
660 int eIdxGlobalI = problem_.variables().index(element);
663 this->A_.addindex(eIdxGlobalI, eIdxGlobalI);
666 const auto isEndIt = problem_.gridView().iend(element);
667 for (
auto isIt = problem_.gridView().ibegin(element); isIt != isEndIt; ++isIt)
669 const auto& intersection = *isIt;
671 if (intersection.neighbor())
674 auto outside = intersection.outside();
675 int eIdxGlobalJ = problem_.variables().index(outside);
679 this->A_.addindex(eIdxGlobalI, eIdxGlobalJ);
681 if (element.level() < outside.level())
686 auto nextIntersection = getNextIntersection_(element, isIt);
688 if (nextIntersection.neighbor())
691 if (element.level() < nextIntersection.outside().level())
696 for (
const auto& innerIntersection
697 : intersections(problem_.gridView(), intersection.outside()))
699 for (
const auto& innerNextIntersection
700 : intersections(problem_.gridView(), nextIntersection.outside()))
702 if (innerIntersection.neighbor() && innerNextIntersection.neighbor())
704 auto innerOutside = innerIntersection.outside();
705 auto nextOutside = nextIntersection.outside();
707 if (innerOutside == innerNextIntersection.outside() && innerOutside != element
708 && innerOutside != nextOutside)
710 int eIdxGlobalCorner = problem_.variables().index(innerOutside);
712 this->A_.addindex(eIdxGlobalI, eIdxGlobalCorner);
714 if (element.level() > outside.level())
716 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
718 this->A_.addindex(eIdxGlobalJ, eIdxGlobalJCorner);
720 if (element.level() > nextOutside.level())
722 int eIdxGlobalJCorner = problem_.variables().index(nextOutside);
724 this->A_.addindex(eIdxGlobalJCorner, eIdxGlobalJ);
726 if (element.level() > innerOutside.level())
728 this->A_.addindex(eIdxGlobalCorner, eIdxGlobalI);
740 this->A_.endindices();
767template<
class TypeTag>
768void FvMpfaL2dPressure2pAdaptive<TypeTag>::storeInteractionVolumeInfo()
770 BoundaryTypes bcType;
773 for (
const auto& element : elements(problem_.gridView()))
776 int eIdxGlobal1 = problem_.variables().index(element);
778 const auto refElement = referenceElement(element);
780 const auto isEndIt12 = problem_.gridView().iend(element);
781 for (
auto isIt12 = problem_.gridView().ibegin(element); isIt12 != isEndIt12; ++isIt12)
783 const auto& intersection12 = *isIt12;
785 int indexInInside12 = intersection12.indexInInside();
787 if (intersection12.neighbor())
790 auto element2 = intersection12.outside();
791 int eIdxGlobal2 = problem_.variables().index(element2);
793 if (element.level() < element2.level())
798 auto intersection14 = getNextIntersection_(element, isIt12);
800 int indexInInside14 = intersection14.indexInInside();
803 GlobalPosition corner1234(0);
804 int globalVertIdx1234 = 0;
805 bool finished =
false;
807 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
809 int localVertIdx12corner = refElement.subEntity(indexInInside12, dim - 1, i, dim);
811 int globalVertIdx12corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx12corner));
813 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
815 int localVertIdx14corner = refElement.subEntity(indexInInside14, dim - 1, j, dim);
817 int globalVertIdx14corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx14corner));
819 if (globalVertIdx12corner == globalVertIdx14corner)
821 corner1234 = element.geometry().corner(localVertIdx12corner);
823 globalVertIdx1234 = globalVertIdx12corner;
836 if (interactionVolumes_[globalVertIdx1234].isStored() || !finished)
842 interactionVolumes_[globalVertIdx1234].setStored();
845 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
848 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
849 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
850 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
853 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
856 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
859 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
862 GlobalPosition globalPosFace41 = intersection14.geometry().center();
865 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
868 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
870 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
871 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
873 unitOuterNormal14 *= -1;
874 unitOuterNormal12 *= -1;
875 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
876 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
877 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
878 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
881 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element2, 1);
882 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection12.indexInOutside(), 1, 1);
883 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 1, 1);
884 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 1, 1);
885 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 1, 1);
888 if (intersection14.neighbor())
892 auto element4 = intersection14.outside();
895 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
896 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
898 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
899 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
900 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
903 GlobalPosition globalPosFace23(0);
904 GlobalPosition globalPosFace34(0);
906 if (element4.level() < element.level())
908 bool isHangingNode =
false;
910 for (
const auto& intersection2
911 : intersections(problem_.gridView(), element2))
913 bool breakLoop =
false;
914 for (
const auto& intersection4
915 : intersections(problem_.gridView(), element4))
917 if (intersection2.neighbor() && intersection4.neighbor())
919 auto element32 = intersection2.outside();
920 auto element34 = intersection4.outside();
923 if (element32 == element4)
925 if (element.level() != element2.level())
928 isHangingNode =
false;
932 isHangingNode =
true;
934 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
936 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInOutside(),
939 globalPosFace23 = intersection2.geometry().center();
940 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
941 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 3, 1);
943 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
944 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
945 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 3, 1);
948 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
950 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
951 unitOuterNormal23 *= -1;
952 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 3, 1);
954 else if (element34 == element2)
956 if (element.level() != element2.level())
959 isHangingNode =
false;
963 isHangingNode =
true;
965 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
967 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInOutside(),
971 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
972 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
983 bool regularNode =
false;
985 for (
const auto& intersection2
986 : intersections(problem_.gridView(), element2))
988 for (
const auto& intersection4
989 : intersections(problem_.gridView(), element4))
991 if (intersection4.neighbor())
993 auto element41 = intersection4.outside();
995 if (element41 == element && element41.level() > element.level())
998 globalPosFace41 = intersection4.geometry().center();
999 faceVol41 = intersection4.geometry().volume() / 2.0;
1001 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1002 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0,
1004 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1005 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3,
1010 if (intersection2.neighbor() && intersection4.neighbor())
1012 auto element32 = intersection2.outside();
1013 auto element34 = intersection4.outside();
1016 if (element32 == element34 && element32 != element)
1019 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32,
1022 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1023 intersection2.indexInInside(), 1, 0);
1024 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1025 intersection2.indexInOutside(), 2, 1);
1026 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1027 intersection4.indexInInside(), 3, 1);
1028 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1029 intersection4.indexInOutside(), 2, 0);
1031 globalPosFace23 = intersection2.geometry().center();
1032 globalPosFace34 = intersection4.geometry().center();
1034 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1035 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1038 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1039 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1041 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1042 unitOuterNormal23 *= -1;
1043 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1044 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1045 unitOuterNormal43 *= -1;
1046 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1048 if (element32.level() > element2.level())
1050 for (
const auto& intersection3
1051 : intersections(problem_.gridView(), element32))
1053 if (intersection3.neighbor())
1055 auto element23 = intersection3.outside();
1057 if (element23 == element2)
1059 globalPosFace23 = intersection3.geometry().center();
1060 faceVol23 = intersection3.geometry().volume() / 2.0;
1066 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1067 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1068 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1,
1070 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2,
1073 if (element34.level() > element4.level())
1075 for (
const auto& intersection3
1076 : intersections(problem_.gridView(), element34))
1078 if (intersection3.neighbor())
1080 auto element43 = intersection3.outside();
1082 if (element43 == element4)
1084 globalPosFace34 = intersection3.geometry().center();
1085 faceVol34 = intersection3.geometry().volume() / 2.0;
1092 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1093 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1094 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2,
1096 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3,
1111 interactionVolumes_[globalVertIdx1234].reset();
1118 bool regularNode =
false;
1119 for (
const auto& intersection2
1120 : intersections(problem_.gridView(), element2))
1122 for (
const auto& intersection4
1123 : intersections(problem_.gridView(), element4))
1125 if (intersection4.neighbor())
1127 auto element41 = intersection4.outside();
1129 if (element41 == element && element41.level() > element.level())
1132 globalPosFace41 = intersection4.geometry().center();
1133 faceVol41 = intersection4.geometry().volume() / 2.0;
1135 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1136 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1137 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1138 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1142 if (intersection2.neighbor() && intersection4.neighbor())
1144 auto element32 = intersection2.outside();
1145 auto element34 = intersection4.outside();
1148 if (element32 == element34 && element32 != element)
1151 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element32, 2);
1153 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(),
1155 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1156 intersection2.indexInOutside(), 2, 1);
1157 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(),
1159 interactionVolumes_[globalVertIdx1234].setIndexOnElement(
1160 intersection4.indexInOutside(), 2, 0);
1162 globalPosFace23 = intersection2.geometry().center();
1163 globalPosFace34 = intersection4.geometry().center();
1165 Scalar faceVol23 = intersection2.geometry().volume() / 2.0;
1166 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1169 DimVector unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1171 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1173 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1174 unitOuterNormal23 *= -1;
1175 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 2, 1);
1176 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1177 unitOuterNormal43 *= -1;
1178 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 2, 0);
1179 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1180 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 2, 1);
1181 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 2, 0);
1182 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1183 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1184 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 2, 1);
1185 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 2, 0);
1186 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1200 interactionVolumes_[globalVertIdx1234].reset();
1210 problem_.boundaryTypes(bcType, intersection14);
1211 PrimaryVariables boundValues(0.0);
1213 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1214 if (bcType.isNeumann(pressEqIdx))
1216 problem_.neumann(boundValues, intersection14);
1217 boundValues *= faceVol41;
1218 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1220 if (bcType.hasDirichlet())
1222 problem_.dirichlet(boundValues, intersection14);
1223 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1230 GlobalPosition globalPosFace23(0);
1233 Scalar faceVol23 = 0;
1236 DimVector unitOuterNormal23(0);
1240 for (
const auto& intersection2
1241 : intersections(problem_.gridView(), element2))
1243 if (intersection2.boundary())
1245 for (
int i = 0; i < intersection2.geometry().corners(); ++i)
1247 int localVertIdx2corner = refElement.subEntity(intersection2.indexInInside(), dim - 1, i,
1250 int globalVertIdx2corner = problem_.variables().index(element2.template subEntity<dim>(localVertIdx2corner));
1252 if (globalVertIdx2corner == globalVertIdx1234)
1254 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection2.indexInInside(), 1,
1257 globalPosFace23 = intersection2.geometry().center();
1259 faceVol23 = intersection2.geometry().volume() / 2.0;
1261 unitOuterNormal23 = intersection2.centerUnitOuterNormal();
1263 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal23, 1, 0);
1264 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol23, 1, 0);
1265 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace23, 1, 0);
1267 problem_.boundaryTypes(bcType, intersection2);
1270 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 1);
1271 if (bcType.isNeumann(pressEqIdx))
1273 problem_.neumann(boundValues, intersection2);
1274 boundValues *= faceVol23;
1275 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 1);
1277 if (bcType.hasDirichlet())
1279 problem_.dirichlet(boundValues, intersection2);
1280 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 1);
1283 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1286 if (element.level() == element2.level())
1288 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1289 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1291 else if (element.level() < element2.level())
1293 innerBoundaryVolumeFaces_[eIdxGlobal2][intersection12.indexInOutside()] =
true;
1295 else if (element.level() > element2.level())
1297 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection12.indexInInside()] =
true;
1314 Dune::NotImplemented,
1315 "fvmpfao2pfaboundpressure2p.hh, l. 997: boundary shape not available as interaction volume shape");
1323 auto intersection14 = getNextIntersection_(element, isIt12);
1325 int indexInInside14 = intersection14.indexInInside();
1328 GlobalPosition corner1234(0);
1329 int globalVertIdx1234 = 0;
1332 for (
int i = 0; i < intersection12.geometry().corners(); ++i)
1334 bool finished =
false;
1336 int localVertIdx12corner = refElement.subEntity(indexInInside12, dim - 1, i, dim);
1338 int globalVertIdx12corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx12corner));
1340 for (
int j = 0; j < intersection14.geometry().corners(); ++j)
1342 int localVertIdx14corner = refElement.subEntity(indexInInside14, dim - 1, j, dim);
1344 int globalVertIdx14corner = problem_.variables().index(element.template subEntity<dim>(localVertIdx14corner));
1346 if (globalVertIdx12corner == globalVertIdx14corner)
1348 corner1234 = element.geometry().corner(localVertIdx12corner);
1350 globalVertIdx1234 = globalVertIdx12corner;
1363 if (interactionVolumes_[globalVertIdx1234].isStored())
1369 interactionVolumes_[globalVertIdx1234].setStored();
1372 interactionVolumes_[globalVertIdx1234].setCenterPosition(corner1234);
1375 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element, 0);
1376 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside12, 0, 0);
1377 interactionVolumes_[globalVertIdx1234].setIndexOnElement(indexInInside14, 0, 1);
1380 const GlobalPosition& globalPosFace12 = intersection12.geometry().center();
1383 Scalar faceVol12 = intersection12.geometry().volume() / 2.0;
1386 DimVector unitOuterNormal12 = intersection12.centerUnitOuterNormal();
1389 const GlobalPosition& globalPosFace41 = intersection14.geometry().center();
1392 Scalar faceVol41 = intersection14.geometry().volume() / 2.0;
1395 DimVector unitOuterNormal14 = intersection14.centerUnitOuterNormal();
1397 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal12, 0, 0);
1398 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 0, 1);
1400 unitOuterNormal14 *= -1;
1401 unitOuterNormal12 *= -1;
1402 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol12, 0, 0);
1403 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 0, 1);
1404 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace12, 0, 0);
1405 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 0, 1);
1407 problem_.boundaryTypes(bcType, intersection12);
1408 PrimaryVariables boundValues(0.0);
1410 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 0);
1411 if (bcType.isNeumann(pressEqIdx))
1413 problem_.neumann(boundValues, intersection12);
1414 boundValues *= faceVol12;
1415 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 0);
1417 if (bcType.hasDirichlet())
1419 problem_.dirichlet(boundValues, intersection12);
1420 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 0);
1424 if (intersection14.boundary())
1426 problem_.boundaryTypes(bcType, intersection14);
1429 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 3);
1430 if (bcType.isNeumann(pressEqIdx))
1432 problem_.neumann(boundValues, intersection14);
1433 boundValues *= faceVol41;
1434 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 3);
1436 if (bcType.hasDirichlet())
1438 problem_.dirichlet(boundValues, intersection14);
1439 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 3);
1442 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1443 interactionVolumes_[globalVertIdx1234].setOutsideFace(2);
1447 else if (intersection14.neighbor())
1451 auto element4 = intersection14.outside();
1452 int eIdxGlobal4 = problem_.variables().index(element4);
1454 if ((element.level() == element4.level() && eIdxGlobal1 > eIdxGlobal4)
1455 || element.level() < element4.level())
1457 interactionVolumes_[globalVertIdx1234].reset();
1461 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection14.indexInOutside(), 3, 0);
1464 interactionVolumes_[globalVertIdx1234].setSubVolumeElement(element4, 3);
1466 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal14, 3, 0);
1467 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol41, 3, 0);
1468 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace41, 3, 0);
1470 bool finished =
false;
1473 for (
const auto& intersection4
1474 : intersections(problem_.gridView(), element4))
1476 if (intersection4.boundary())
1478 for (
int i = 0; i < intersection4.geometry().corners(); ++i)
1480 int localVertIdx4corner = refElement.subEntity(intersection4.indexInInside(), dim - 1, i,
1483 int globalVertIdx4corner = problem_.variables().index(element4.template subEntity<dim>(localVertIdx4corner));
1485 if (globalVertIdx4corner == globalVertIdx1234)
1487 interactionVolumes_[globalVertIdx1234].setIndexOnElement(intersection4.indexInInside(), 3,
1490 const GlobalPosition& globalPosFace34 = intersection4.geometry().center();
1491 Scalar faceVol34 = intersection4.geometry().volume() / 2.0;
1493 DimVector unitOuterNormal43 = intersection4.centerUnitOuterNormal();
1495 interactionVolumes_[globalVertIdx1234].setNormal(unitOuterNormal43, 3, 1);
1496 interactionVolumes_[globalVertIdx1234].setFaceArea(faceVol34, 3, 1);
1497 interactionVolumes_[globalVertIdx1234].setFacePosition(globalPosFace34, 3, 1);
1499 problem_.boundaryTypes(bcType, intersection4);
1502 interactionVolumes_[globalVertIdx1234].setBoundary(bcType, 2);
1503 if (bcType.isNeumann(pressEqIdx))
1505 problem_.neumann(boundValues, intersection4);
1506 boundValues *= faceVol34;
1507 interactionVolumes_[globalVertIdx1234].setNeumannCondition(boundValues, 2);
1509 if (bcType.hasDirichlet())
1511 problem_.dirichlet(boundValues, intersection4);
1512 interactionVolumes_[globalVertIdx1234].setDirichletCondition(boundValues, 2);
1515 interactionVolumes_[globalVertIdx1234].setOutsideFace(1);
1517 if (element.level() == element4.level())
1519 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1520 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1522 if (element.level() < element4.level())
1524 innerBoundaryVolumeFaces_[eIdxGlobal4][intersection14.indexInOutside()] =
true;
1526 if (element.level() > element4.level())
1528 innerBoundaryVolumeFaces_[eIdxGlobal1][intersection14.indexInInside()] =
true;
1546 Dune::NotImplemented,
1547 "fvmpfao2pfaboundpressure2p_adaptive.hh: boundary shape not available as interaction volume shape");
1552 DUNE_THROW(Dune::NotImplemented,
1553 "fvmpfao2pfaboundpressure2p_adaptive.hh: interface type not supported!");
1564template<
class TypeTag>
1565void FvMpfaL2dPressure2pAdaptive<TypeTag>::printInteractionVolumes()
1567 for (
const auto& vertex : vertices(problem_.gridView()))
1569 int vIdxGlobal = problem_.variables().index(vertex);
1571 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1573 if (interactionVolume.getElementNumber() > 2)
1575 interactionVolume.printInteractionVolumeInfo();
1576 std::cout <<
"global vertex index: " << vIdxGlobal <<
"\n";
1577 if (interactionVolume.getElementNumber() == 3)
1579 auto element1 = interactionVolume.getSubVolumeElement(0);
1580 auto element2 = interactionVolume.getSubVolumeElement(1);
1581 auto element4 = interactionVolume.getSubVolumeElement(3);
1583 int eIdxGlobal1 = problem_.variables().index(element1);
1584 int eIdxGlobal2 = problem_.variables().index(element2);
1585 int eIdxGlobal4 = problem_.variables().index(element4);
1587 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1588 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1589 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1591 if (interactionVolume.getElementNumber() == 4)
1593 auto element1 = interactionVolume.getSubVolumeElement(0);
1594 auto element2 = interactionVolume.getSubVolumeElement(1);
1595 auto element3 = interactionVolume.getSubVolumeElement(2);
1596 auto element4 = interactionVolume.getSubVolumeElement(3);
1598 int eIdxGlobal1 = problem_.variables().index(element1);
1599 int eIdxGlobal2 = problem_.variables().index(element2);
1600 int eIdxGlobal3 = problem_.variables().index(element3);
1601 int eIdxGlobal4 = problem_.variables().index(element4);
1603 std::cout <<
"global element index 1: " << eIdxGlobal1 <<
"\n";
1604 std::cout <<
"global element index 2: " << eIdxGlobal2 <<
"\n";
1605 std::cout <<
"global element index 3: " << eIdxGlobal3 <<
"\n";
1606 std::cout <<
"global element index 4: " << eIdxGlobal4 <<
"\n";
1614template<
class TypeTag>
1615void FvMpfaL2dPressure2pAdaptive<TypeTag>::assemble()
1622 for (
const auto& vertex : vertices(problem_.gridView()))
1624 int vIdxGlobal = problem_.variables().index(vertex);
1626 InteractionVolume& interactionVolume = interactionVolumes_[vIdxGlobal];
1628 if (interactionVolume.isInnerVolume())
1630 if (interactionVolume.getElementNumber() == 4)
1632 auto element1 = interactionVolume.getSubVolumeElement(0);
1633 auto element2 = interactionVolume.getSubVolumeElement(1);
1634 auto element3 = interactionVolume.getSubVolumeElement(2);
1635 auto element4 = interactionVolume.getSubVolumeElement(3);
1638 const GlobalPosition& globalPos1 = element1.geometry().center();
1639 const GlobalPosition& globalPos2 = element2.geometry().center();
1640 const GlobalPosition& globalPos3 = element3.geometry().center();
1641 const GlobalPosition& globalPos4 = element4.geometry().center();
1644 Scalar volume1 = element1.geometry().volume();
1645 Scalar volume2 = element2.geometry().volume();
1646 Scalar volume3 = element3.geometry().volume();
1647 Scalar volume4 = element4.geometry().volume();
1650 int eIdxGlobal1 = problem_.variables().index(element1);
1651 int eIdxGlobal2 = problem_.variables().index(element2);
1652 int eIdxGlobal3 = problem_.variables().index(element3);
1653 int eIdxGlobal4 = problem_.variables().index(element4);
1656 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
1657 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
1658 CellData& cellData3 = problem_.variables().cellData(eIdxGlobal3);
1659 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
1662 PrimaryVariables source(0.0);
1663 problem_.source(source, element1);
1664 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1665 problem_.source(source, element2);
1666 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1667 problem_.source(source, element3);
1668 this->f_[eIdxGlobal3] += volume3 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1669 problem_.source(source, element4);
1670 this->f_[eIdxGlobal4] += volume4 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
1672 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
1673 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
1674 this->f_[eIdxGlobal3] += evaluateErrorTerm_(cellData3) * volume3 / (4.0);
1675 this->f_[eIdxGlobal4] += evaluateErrorTerm_(cellData4) * volume4 / (4.0);
1678 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
1679 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
1682 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
1685 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
1686 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
1689 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
1692 Dune::FieldVector<Scalar, numPhases> lambda3(cellData3.mobility(wPhaseIdx));
1693 lambda3[nPhaseIdx] = cellData3.mobility(nPhaseIdx);
1696 Scalar lambdaTotal3 = lambda3[wPhaseIdx] + lambda3[nPhaseIdx];
1699 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
1700 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
1703 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
1705 std::vector < DimVector > lambda(2 * dim);
1707 lambda[0][0] = lambdaTotal1;
1708 lambda[0][1] = lambdaTotal1;
1709 lambda[1][0] = lambdaTotal2;
1710 lambda[1][1] = lambdaTotal2;
1711 lambda[2][0] = lambdaTotal3;
1712 lambda[2][1] = lambdaTotal3;
1713 lambda[3][0] = lambdaTotal4;
1714 lambda[3][1] = lambdaTotal4;
1718 Dune::FieldVector<Scalar, 2 * dim> pc(0);
1719 pc[0] = cellData1.capillaryPressure();
1720 pc[1] = cellData2.capillaryPressure();
1721 pc[2] = cellData3.capillaryPressure();
1722 pc[3] = cellData4.capillaryPressure();
1724 Dune::FieldVector<Scalar, 2 * dim> gravityDiff(0);
1726 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1727 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1728 gravityDiff[2] = (problem_.bBoxMax() - globalPos3) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1729 gravityDiff[3] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
1733 Dune::FieldVector<Scalar, 2 * dim> pcFlux(0);
1735 Scalar pcPotential12 = 0;
1736 Scalar pcPotential14 = 0;
1737 Scalar pcPotential32 = 0;
1738 Scalar pcPotential34 = 0;
1741 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
1742 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
1744 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 2, 3);
1746 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1748 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1752 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
1753 this->A_[eIdxGlobal1][eIdxGlobal3] += T[1][1];
1754 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
1756 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
1757 this->A_[eIdxGlobal2][eIdxGlobal3] -= T[1][1];
1758 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
1767 pcPotential12 = Tu[1];
1769 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1771 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
1775 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
1776 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
1777 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
1779 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
1780 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
1781 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
1790 pcPotential12 = Tu[1];
1793 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 1, 2, 3, 0);
1795 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1797 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1801 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][0];
1802 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][1];
1803 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][2];
1805 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][0];
1806 this->A_[eIdxGlobal3][eIdxGlobal4] -= T[1][1];
1807 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][2];
1816 pcPotential32 = -Tu[1];
1818 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1820 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
1824 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
1825 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
1826 this->A_[eIdxGlobal2][eIdxGlobal3] += T[1][2];
1828 this->A_[eIdxGlobal3][eIdxGlobal2] -= T[1][0];
1829 this->A_[eIdxGlobal3][eIdxGlobal1] -= T[1][1];
1830 this->A_[eIdxGlobal3][eIdxGlobal3] -= T[1][2];
1839 pcPotential32 = -Tu[1];
1842 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 2, 3, 0, 1);
1844 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1846 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1850 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][0];
1851 this->A_[eIdxGlobal3][eIdxGlobal1] += T[1][1];
1852 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][2];
1854 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][0];
1855 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
1856 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][2];
1865 pcPotential34 = Tu[1];
1867 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1869 if (innerBoundaryVolumeFaces_[eIdxGlobal3][interactionVolume.getIndexOnElement(2, 0)])
1873 this->A_[eIdxGlobal3][eIdxGlobal3] += T[1][0];
1874 this->A_[eIdxGlobal3][eIdxGlobal2] += T[1][1];
1875 this->A_[eIdxGlobal3][eIdxGlobal4] += T[1][2];
1877 this->A_[eIdxGlobal4][eIdxGlobal3] -= T[1][0];
1878 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][1];
1879 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
1888 pcPotential34 = Tu[1];
1891 transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 3, 0, 1, 2);
1893 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
1895 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1899 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
1900 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
1901 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
1903 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
1904 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
1905 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
1914 pcPotential14 = -Tu[1];
1916 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
1918 if (innerBoundaryVolumeFaces_[eIdxGlobal4][interactionVolume.getIndexOnElement(3, 0)])
1922 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][0];
1923 this->A_[eIdxGlobal4][eIdxGlobal3] += T[1][1];
1924 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][2];
1926 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][0];
1927 this->A_[eIdxGlobal1][eIdxGlobal3] -= T[1][1];
1928 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][2];
1937 pcPotential14 = -Tu[1];
1940 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0 && pc[3] == 0)
1946 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
1947 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
1948 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
1951 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
1952 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
1953 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
1956 Dune::FieldVector<Scalar, numPhases> lambda32Upw(0.0);
1957 lambda32Upw[wPhaseIdx] = (pcPotential32 >= 0) ? lambda3[wPhaseIdx] : lambda2[wPhaseIdx];
1958 lambda32Upw[nPhaseIdx] = (pcPotential32 >= 0) ? lambda3[nPhaseIdx] : lambda2[nPhaseIdx];
1961 Dune::FieldVector<Scalar, numPhases> lambda34Upw(0.0);
1962 lambda34Upw[wPhaseIdx] = (pcPotential34 >= 0) ? lambda3[wPhaseIdx] : lambda4[wPhaseIdx];
1963 lambda34Upw[nPhaseIdx] = (pcPotential34 >= 0) ? lambda3[nPhaseIdx] : lambda4[nPhaseIdx];
1965 for (
int i = 0; i < numPhases; i++)
1967 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
1968 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
1969 Scalar lambdaT32 = lambda32Upw[wPhaseIdx] + lambda32Upw[nPhaseIdx];
1970 Scalar lambdaT34 = lambda34Upw[wPhaseIdx] + lambda34Upw[nPhaseIdx];
1971 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
1972 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
1973 Scalar fracFlow32 = (lambdaT32 > threshold_) ? lambda32Upw[i] / (lambdaT32) : 0.0;
1974 Scalar fracFlow34 = (lambdaT34 > threshold_) ? lambda34Upw[i] / (lambdaT34) : 0.0;
1976 Dune::FieldVector<Scalar, 2 * dim> pcFluxReal(pcFlux);
1978 pcFluxReal[0] *= fracFlow12;
1979 pcFluxReal[1] *= fracFlow32;
1980 pcFluxReal[2] *= fracFlow34;
1981 pcFluxReal[3] *= fracFlow14;
1983 switch (pressureType_)
1990 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[3]);
1991 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
1992 this->f_[eIdxGlobal3] -= (pcFluxReal[2] - pcFluxReal[1]);
1993 this->f_[eIdxGlobal4] -= (pcFluxReal[3] - pcFluxReal[2]);
2003 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[3]);
2004 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2005 this->f_[eIdxGlobal3] += (pcFluxReal[2] - pcFluxReal[1]);
2006 this->f_[eIdxGlobal4] += (pcFluxReal[3] - pcFluxReal[2]);
2013 else if (interactionVolume.getElementNumber() == 3)
2015 auto element1 = interactionVolume.getSubVolumeElement(0);
2016 auto element2 = interactionVolume.getSubVolumeElement(1);
2017 auto element4 = interactionVolume.getSubVolumeElement(3);
2020 const GlobalPosition& globalPos1 = element1.geometry().center();
2021 const GlobalPosition& globalPos2 = element2.geometry().center();
2022 const GlobalPosition& globalPos4 = element4.geometry().center();
2025 Scalar volume1 = element1.geometry().volume();
2026 Scalar volume2 = element2.geometry().volume();
2029 int eIdxGlobal1 = problem_.variables().index(element1);
2030 int eIdxGlobal2 = problem_.variables().index(element2);
2031 int eIdxGlobal4 = problem_.variables().index(element4);
2034 CellData& cellData1 = problem_.variables().cellData(eIdxGlobal1);
2035 CellData& cellData2 = problem_.variables().cellData(eIdxGlobal2);
2036 CellData& cellData4 = problem_.variables().cellData(eIdxGlobal4);
2040 PrimaryVariables source(0.0);
2041 problem_.source(source, element1);
2042 this->f_[eIdxGlobal1] += volume1 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2043 problem_.source(source, element2);
2044 this->f_[eIdxGlobal2] += volume2 / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2046 this->f_[eIdxGlobal1] += evaluateErrorTerm_(cellData1) * volume1 / (4.0);
2047 this->f_[eIdxGlobal2] += evaluateErrorTerm_(cellData2) * volume2 / (4.0);
2050 Dune::FieldVector<Scalar, numPhases> lambda1(cellData1.mobility(wPhaseIdx));
2051 lambda1[nPhaseIdx] = cellData1.mobility(nPhaseIdx);
2054 Scalar lambdaTotal1 = lambda1[wPhaseIdx] + lambda1[nPhaseIdx];
2057 Dune::FieldVector<Scalar, numPhases> lambda2(cellData2.mobility(wPhaseIdx));
2058 lambda2[nPhaseIdx] = cellData2.mobility(nPhaseIdx);
2061 Scalar lambdaTotal2 = lambda2[wPhaseIdx] + lambda2[nPhaseIdx];
2064 Dune::FieldVector<Scalar, numPhases> lambda4(cellData4.mobility(wPhaseIdx));
2065 lambda4[nPhaseIdx] = cellData4.mobility(nPhaseIdx);
2068 Scalar lambdaTotal4 = lambda4[wPhaseIdx] + lambda4[nPhaseIdx];
2070 std::vector < DimVector > lambda(4);
2072 lambda[0][0] = lambdaTotal1;
2073 lambda[0][1] = lambdaTotal1;
2074 lambda[1][0] = lambdaTotal2;
2075 lambda[1][1] = lambdaTotal2;
2076 lambda[3][0] = lambdaTotal4;
2077 lambda[3][1] = lambdaTotal4;
2081 Dune::FieldVector<Scalar, 3> pc(0);
2082 pc[0] = cellData1.capillaryPressure();
2083 pc[1] = cellData2.capillaryPressure();
2084 pc[2] = cellData4.capillaryPressure();
2086 Dune::FieldVector<Scalar, 3> gravityDiff(0);
2088 gravityDiff[0] = (problem_.bBoxMax() - globalPos1) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2089 gravityDiff[1] = (problem_.bBoxMax() - globalPos2) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2090 gravityDiff[2] = (problem_.bBoxMax() - globalPos4) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2094 Dune::FieldVector<Scalar, 3> pcFlux(0);
2096 Scalar pcPotential12 = 0;
2097 Scalar pcPotential14 = 0;
2098 Scalar pcPotential24 = 0;
2101 Dune::FieldVector<Scalar, 2 * dim - dim + 1> u(0);
2102 Dune::FieldMatrix<Scalar, dim, 2 * dim - dim + 1> T(0);
2104 int transmissibilityType = transmissibilityCalculator_.calculateTransmissibility(T, interactionVolume, lambda, 0, 1, 3, 3);
2106 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2108 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2112 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][0];
2113 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2114 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][2];
2116 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][0];
2117 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2118 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][2];
2127 pcPotential12 = Tu[1];
2129 else if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2131 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 0)])
2135 this->A_[eIdxGlobal1][eIdxGlobal1] += T[1][0];
2136 this->A_[eIdxGlobal1][eIdxGlobal4] += T[1][1];
2137 this->A_[eIdxGlobal1][eIdxGlobal2] += T[1][2];
2139 this->A_[eIdxGlobal2][eIdxGlobal1] -= T[1][0];
2140 this->A_[eIdxGlobal2][eIdxGlobal4] -= T[1][1];
2141 this->A_[eIdxGlobal2][eIdxGlobal2] -= T[1][2];
2150 pcPotential12 = Tu[1];
2154 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2157 transmissibilityType = transmissibilityCalculator_.calculateLeftHNTransmissibility(T, interactionVolume, lambda, 1, 3, 0);
2159 if (transmissibilityType == TransmissibilityCalculator::leftTriangle)
2161 if (innerBoundaryVolumeFaces_[eIdxGlobal2][interactionVolume.getIndexOnElement(1, 0)])
2165 this->A_[eIdxGlobal2][eIdxGlobal2] += T[1][0];
2166 this->A_[eIdxGlobal2][eIdxGlobal1] += T[1][1];
2167 this->A_[eIdxGlobal2][eIdxGlobal4] += T[1][2];
2169 this->A_[eIdxGlobal4][eIdxGlobal2] -= T[1][0];
2170 this->A_[eIdxGlobal4][eIdxGlobal1] -= T[1][1];
2171 this->A_[eIdxGlobal4][eIdxGlobal4] -= T[1][2];
2180 pcPotential24 = Tu[1];
2184 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2187 transmissibilityType = transmissibilityCalculator_.calculateRightHNTransmissibility(T, interactionVolume, lambda, 3, 0, 1);
2189 if (transmissibilityType == TransmissibilityCalculator::rightTriangle)
2191 if (innerBoundaryVolumeFaces_[eIdxGlobal1][interactionVolume.getIndexOnElement(0, 1)])
2196 this->A_[eIdxGlobal4][eIdxGlobal1] += T[1][0];
2197 this->A_[eIdxGlobal4][eIdxGlobal2] += T[1][1];
2198 this->A_[eIdxGlobal4][eIdxGlobal4] += T[1][2];
2200 this->A_[eIdxGlobal1][eIdxGlobal1] -= T[1][0];
2201 this->A_[eIdxGlobal1][eIdxGlobal2] -= T[1][1];
2202 this->A_[eIdxGlobal1][eIdxGlobal4] -= T[1][2];
2211 pcPotential14 = -Tu[1];
2215 DUNE_THROW(Dune::RangeError,
"Could not calculate Tranmissibility!");
2218 if (pc[0] == 0 && pc[1] == 0 && pc[2] == 0)
2224 Dune::FieldVector<Scalar, numPhases> lambda12Upw(0.0);
2225 lambda12Upw[wPhaseIdx] = (pcPotential12 >= 0) ? lambda1[wPhaseIdx] : lambda2[wPhaseIdx];
2226 lambda12Upw[nPhaseIdx] = (pcPotential12 >= 0) ? lambda1[nPhaseIdx] : lambda2[nPhaseIdx];
2229 Dune::FieldVector<Scalar, numPhases> lambda14Upw(0.0);
2230 lambda14Upw[wPhaseIdx] = (pcPotential14 >= 0) ? lambda1[wPhaseIdx] : lambda4[wPhaseIdx];
2231 lambda14Upw[nPhaseIdx] = (pcPotential14 >= 0) ? lambda1[nPhaseIdx] : lambda4[nPhaseIdx];
2234 Dune::FieldVector<Scalar, numPhases> lambda24Upw(0.0);
2235 lambda24Upw[wPhaseIdx] = (pcPotential24 >= 0) ? lambda2[wPhaseIdx] : lambda4[wPhaseIdx];
2236 lambda24Upw[nPhaseIdx] = (pcPotential24 >= 0) ? lambda2[nPhaseIdx] : lambda4[nPhaseIdx];
2238 for (
int i = 0; i < numPhases; i++)
2240 Scalar lambdaT12 = lambda12Upw[wPhaseIdx] + lambda12Upw[nPhaseIdx];
2241 Scalar lambdaT14 = lambda14Upw[wPhaseIdx] + lambda14Upw[nPhaseIdx];
2242 Scalar lambdaT24 = lambda24Upw[wPhaseIdx] + lambda24Upw[nPhaseIdx];
2243 Scalar fracFlow12 = (lambdaT12 > threshold_) ? lambda12Upw[i] / (lambdaT12) : 0.0;
2244 Scalar fracFlow14 = (lambdaT14 > threshold_) ? lambda14Upw[i] / (lambdaT14) : 0.0;
2245 Scalar fracFlow24 = (lambdaT24 > threshold_) ? lambda24Upw[i] / (lambdaT24) : 0.0;
2247 Dune::FieldVector<Scalar, 3> pcFluxReal(pcFlux);
2249 pcFluxReal[0] *= fracFlow12;
2250 pcFluxReal[1] *= fracFlow24;
2251 pcFluxReal[2] *= fracFlow14;
2253 switch (pressureType_)
2260 this->f_[eIdxGlobal1] -= (pcFluxReal[0] - pcFluxReal[2]);
2261 this->f_[eIdxGlobal2] -= (pcFluxReal[1] - pcFluxReal[0]);
2262 this->f_[eIdxGlobal4] -= (pcFluxReal[2] - pcFluxReal[1]);
2272 this->f_[eIdxGlobal1] += (pcFluxReal[0] - pcFluxReal[2]);
2273 this->f_[eIdxGlobal2] += (pcFluxReal[1] - pcFluxReal[0]);
2274 this->f_[eIdxGlobal4] += (pcFluxReal[2] - pcFluxReal[1]);
2283 DUNE_THROW(Dune::NotImplemented,
"Unknown interactionvolume type!");
2290 for (
int elemIdx = 0; elemIdx < 2 * dim; elemIdx++)
2292 bool isOutside =
false;
2293 for (
int fIdx = 0; fIdx < dim; fIdx++)
2295 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2296 if (interactionVolume.isOutsideFace(intVolFaceIdx))
2307 auto element = interactionVolume.getSubVolumeElement(elemIdx);
2310 const GlobalPosition& globalPos = element.geometry().center();
2313 Scalar volume = element.geometry().volume();
2316 int eIdxGlobal = problem_.variables().index(element);
2319 CellData& cellData = problem_.variables().cellData(eIdxGlobal);
2322 DimMatrix
permeability(problem_.spatialParams().intrinsicPermeability(element));
2325 PrimaryVariables source(0);
2326 problem_.source(source, element);
2327 this->f_[eIdxGlobal] += volume / (4.0) * (source[wPhaseIdx] / density_[wPhaseIdx] + source[nPhaseIdx] / density_[nPhaseIdx]);
2329 this->f_[eIdxGlobal] += evaluateErrorTerm_(cellData) * volume / (4.0);
2332 Dune::FieldVector<Scalar, numPhases> lambda(cellData.mobility(wPhaseIdx));
2333 lambda[nPhaseIdx] = cellData.mobility(nPhaseIdx);
2335 Scalar pc = cellData.capillaryPressure();
2337 Scalar gravityDiff = (problem_.bBoxMax() - globalPos) * gravity_ * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2341 for (
int fIdx = 0; fIdx < dim; fIdx++)
2343 int intVolFaceIdx = interactionVolume.getFaceIndexFromSubVolume(elemIdx, fIdx);
2345 if (interactionVolume.isBoundaryFace(intVolFaceIdx))
2348 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(pressEqIdx))
2350 int boundaryFaceIdx = interactionVolume.getIndexOnElement(elemIdx, fIdx);
2352 const auto refElement = referenceElement(element);
2354 const LocalPosition& localPos = refElement.position(boundaryFaceIdx, 1);
2356 const GlobalPosition& globalPosFace = element.geometry().global(localPos);
2358 DimVector distVec(globalPosFace - globalPos);
2359 Scalar dist = distVec.two_norm();
2360 DimVector unitDistVec(distVec);
2361 unitDistVec /= dist;
2363 Scalar faceArea = interactionVolume.getFaceArea(elemIdx, fIdx);
2366 Scalar satWBound = cellData.saturation(wPhaseIdx);
2368 if (interactionVolume.getBoundaryType(intVolFaceIdx).isDirichlet(satEqIdx))
2370 Scalar satBound = interactionVolume.getDirichletValues(intVolFaceIdx)[saturationIdx];
2371 switch (saturationType_)
2375 satWBound = satBound;
2380 satWBound = 1 - satBound;
2390 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element);
2392 Scalar pcBound = fluidMatrixInteraction.pc(satWBound);
2394 Scalar gravityDiffBound = (problem_.bBoxMax() - globalPosFace) * gravity_
2395 * (density_[nPhaseIdx] - density_[wPhaseIdx]);
2397 pcBound += gravityDiffBound;
2399 Dune::FieldVector<Scalar, numPhases> lambdaBound(fluidMatrixInteraction.krw(satWBound));
2400 lambdaBound[nPhaseIdx] = fluidMatrixInteraction.krn(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 const Scalar satW = cellData.saturation(wPhaseIdx);
2566 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem_.spatialParams(), element);
2568 const Scalar pc = fluidMatrixInteraction.pc(satW);
2570 cellData.setCapillaryPressure(pc);
2573 const Scalar mobilityW = fluidMatrixInteraction.krw(satW) / viscosity_[wPhaseIdx];
2574 const Scalar mobilityNw = fluidMatrixInteraction.krn(satW) / viscosity_[nPhaseIdx];
2577 cellData.setMobility(wPhaseIdx, mobilityW);
2578 cellData.setMobility(nPhaseIdx, mobilityNw);
2581 cellData.setFracFlowFunc(wPhaseIdx, mobilityW / (mobilityW + mobilityNw));
2582 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 (equivalent to old macro GET_PROP(...))
Definition: propertysystem.hh:140
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:149
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:77
void storePressureSolution(const Element &element)
Stores the pressure solution of a cell.
Definition: 2dpressureadaptive.hh:247
void addOutputVtkFields(MultiWriter &writer)
Adds pressure output to the output file.
Definition: 2dpressureadaptive.hh:376
void updateInteractionVolumeInfo()
Updates interaction volumes.
Definition: 2dpressureadaptive.hh:185
InnerBoundaryVolumeFaces innerBoundaryVolumeFaces_
Vector marking faces which intersect the boundary.
Definition: 2dpressureadaptive.hh:492
void storePressureSolution()
Globally stores the pressure solution.
Definition: 2dpressureadaptive.hh:233
FvMpfaL2dPressure2pAdaptive(Problem &problem)
Constructs a FvMpfaL2dPressure2pAdaptive object.
Definition: 2dpressureadaptive.hh:446
void initialize()
Initializes the pressure model.
Definition: 2dpressureadaptive.hh:202
FvMpfaL2dTransmissibilityCalculator< TypeTag > TransmissibilityCalculator
Definition: 2dpressureadaptive.hh:155
void updateMaterialLaws()
constitutive functions are initialized and stored in the variables object
Definition: 2dpressureadaptive.hh:2552
void update()
Pressure update.
Definition: 2dpressureadaptive.hh:300
GlobalInteractionVolumeVector interactionVolumes_
Global Vector of interaction volumes.
Definition: 2dpressureadaptive.hh:491
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.