24#ifndef DUMUX_FVPRESSURE2P2C_HH
25#define DUMUX_FVPRESSURE2P2C_HH
28#include <dune/istl/bvector.hh>
29#include <dune/istl/operators.hh>
30#include <dune/istl/solvers.hh>
31#include <dune/istl/preconditioners.hh>
32#include <dune/common/float_cmp.hh>
94 dim = GridView::dimension, dimWorld = GridView::dimensionworld
98 pw = Indices::pressureW,
99 pn = Indices::pressureN,
100 pGlobal = Indices::pressureGlobal
104 wPhaseIdx = Indices::wPhaseIdx, nPhaseIdx = Indices::nPhaseIdx,
105 wCompIdx = Indices::wPhaseIdx, nCompIdx = Indices::nPhaseIdx,
106 contiWEqIdx = Indices::contiWEqIdx, contiNEqIdx = Indices::contiNEqIdx
123 using Element =
typename GridView::Traits::template Codim<0>::Entity;
124 using Intersection =
typename GridView::Intersection;
127 using GlobalPosition = Dune::FieldVector<Scalar, dimWorld>;
128 using DimMatrix = Dune::FieldMatrix<Scalar, dim, dim>;
129 using PhaseVector = Dune::FieldVector<Scalar, getPropValue<TypeTag, Properties::NumPhases>()>;
150 void getSource(
EntryType& sourceEntry,
const Element& elementI,
const CellData& cellDataI,
const bool first);
152 void getStorage(
EntryType& storageEntry,
const Element& elementI,
const CellData& cellDataI,
const bool first);
154 void getFlux(
EntryType& entries,
const Intersection& intersection,
const CellData& cellDataI,
const bool first);
177 Dune::dinfo <<
" Warning: Regulating Boundary Permeability requires correct subface indices on reference elements!"
191 static constexpr int pressureType = getPropValue<TypeTag, Properties::PressureFormulation>();
194 Implementation &asImp_()
195 {
return *
static_cast<Implementation *
>(
this);}
198 const Implementation &asImp_()
const
199 {
return *
static_cast<const Implementation *
>(
this);}
213template<
class TypeTag>
215 const Element& elementI,
216 const CellData& cellDataI,
221 Scalar volume = elementI.geometry().volume();
224 PrimaryVariables source(NAN);
225 problem().source(source, elementI);
229 source[contiWEqIdx] /= cellDataI.density(wPhaseIdx);
230 source[contiNEqIdx] /= cellDataI.density(nPhaseIdx);
235 const GlobalPosition& globalPos = elementI.geometry().center();
237 if (!cellDataI.hasVolumeDerivatives())
238 asImp_().volumeDerivatives(globalPos, elementI);
240 source[contiWEqIdx] *= cellDataI.dv(wCompIdx);
241 source[contiNEqIdx] *= cellDataI.dv(nCompIdx);
243 sourceEntry[rhs] = volume * (source[contiWEqIdx] + source[contiNEqIdx]);
263template<
class TypeTag>
265 const Element& elementI,
266 const CellData& cellDataI,
271 int eIdxGlobalI = problem().variables().index(elementI);
272 Scalar volume = elementI.geometry().volume();
275 Scalar timestep_ = problem().timeManager().timeStepSize();
278 if (!first && Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(timestep_, 0.0, 1.0e-30))
280 Scalar compress_term = cellDataI.dv_dp() / timestep_;
282 storageEntry[matrix] -= compress_term*volume;
285 storageEntry[rhs] -= cellDataI.pressure(pressureType) * compress_term * volume;
289 if (isnan(compress_term) || isinf(compress_term))
290 DUNE_THROW(Dune::MathError,
"Compressibility term leads to NAN matrix entry at index " << eIdxGlobalI);
292 if(!getPropValue<TypeTag, Properties::EnableCompressibility>())
293 DUNE_THROW(Dune::NotImplemented,
"Compressibility is switched off???");
298 if( problem().timeManager().episodeWillBeFinished()
299 || problem().timeManager().willBeFinished())
301 problem().variables().cellData(eIdxGlobalI).errorCorrection() = 0.;
307 problem().variables().cellData(eIdxGlobalI).volumeError() /= timestep_;
308 Scalar erri = fabs(cellDataI.volumeError());
309 Scalar x_lo = ErrorTermLowerBound_;
310 Scalar x_mi = ErrorTermUpperBound_;
311 Scalar fac = ErrorTermFactor_;
313 Scalar hifac = 1.-x_mi;
315 if ((erri*timestep_ > 5e-5) && (erri > x_lo * this->maxError_))
317 if (erri <= x_mi * this->maxError_)
319 problem().variables().cellData(eIdxGlobalI).errorCorrection() =
320 fac* (1-x_mi*(lofac-1)/(x_lo-x_mi) + (lofac-1)/(x_lo-x_mi)*erri/this->maxError_)
321 * cellDataI.volumeError() * volume;
324 problem().variables().cellData(eIdxGlobalI).errorCorrection() =
325 fac * (1 + x_mi - hifac*x_mi/(1-x_mi) + (hifac/(1-x_mi)-1)*erri/this->maxError_)
326 * cellDataI.volumeError() * volume;
329 problem().variables().cellData(eIdxGlobalI).errorCorrection() = 0.;
355template<
class TypeTag>
357 const Intersection& intersection,
358 const CellData& cellDataI,
362 auto elementI = intersection.inside();
363 int eIdxGlobalI = problem().variables().index(elementI);
366 const GlobalPosition& globalPos = elementI.geometry().center();
369 Scalar volume = elementI.geometry().volume();
370 Scalar perimeter = cellDataI.perimeter();
374 const GlobalPosition& gravity_ = problem().gravity();
377 DimMatrix permeabilityI(problem().spatialParams().intrinsicPermeability(elementI));
380 Scalar fractionalWI=0, fractionalNWI=0;
383 fractionalWI = cellDataI.mobility(wPhaseIdx)
384 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
385 fractionalNWI = cellDataI.mobility(nPhaseIdx)
386 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
390 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
393 Scalar faceArea = intersection.geometry().volume();
396 auto neighbor = intersection.outside();
397 int eIdxGlobalJ = problem().variables().index(neighbor);
398 CellData& cellDataJ = problem().variables().cellData(eIdxGlobalJ);
401 const GlobalPosition& globalPosNeighbor = neighbor.geometry().center();
404 GlobalPosition distVec = globalPosNeighbor - globalPos;
407 Scalar dist = distVec.two_norm();
409 GlobalPosition unitDistVec(distVec);
412 DimMatrix permeabilityJ
413 = problem().spatialParams().intrinsicPermeability(neighbor);
416 DimMatrix meanPermeability(0);
423 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + cellDataJ.density(wPhaseIdx));
424 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + cellDataJ.density(nPhaseIdx));
427 Scalar potentialW = 0;
428 Scalar potentialNW = 0;
433 Scalar fractionalWJ = cellDataJ.mobility(wPhaseIdx)
434 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
435 Scalar fractionalNWJ = cellDataJ.mobility(nPhaseIdx)
436 / (cellDataJ.mobility(wPhaseIdx)+ cellDataJ.mobility(nPhaseIdx));
439 Scalar lambda = (cellDataI.mobility(wPhaseIdx) + cellDataJ.mobility(wPhaseIdx)) * 0.5
440 + (cellDataI.mobility(nPhaseIdx) + cellDataJ.mobility(nPhaseIdx)) * 0.5;
442 entries[0] = fabs(lambda*faceArea*fabs(
permeability*unitOuterNormal)/(dist));
444 Scalar factor = (fractionalWI + fractionalWJ) * (rhoMeanW) * 0.5
445 + (fractionalNWI + fractionalNWJ) * (rhoMeanNW) * 0.5;
446 entries[1] = factor * lambda * faceArea * fabs(unitOuterNormal*
permeability)
447 * (gravity_ * unitDistVec);
452 if (!cellDataJ.hasVolumeDerivatives())
453 asImp_().volumeDerivatives(globalPosNeighbor, neighbor);
455 Scalar dv_dC1 = (cellDataJ.dv(wPhaseIdx)
456 + cellDataI.dv(wPhaseIdx)) / 2;
457 Scalar dv_dC2 = (cellDataJ.dv(nPhaseIdx)
458 + cellDataI.dv(nPhaseIdx)) / 2;
460 Scalar graddv_dC1 = (cellDataJ.dv(wPhaseIdx)
461 - cellDataI.dv(wPhaseIdx)) / dist;
462 Scalar graddv_dC2 = (cellDataJ.dv(nPhaseIdx)
463 - cellDataI.dv(nPhaseIdx)) / dist;
474 Scalar densityW = rhoMeanW;
475 Scalar densityNW = rhoMeanNW;
477 potentialW = (cellDataI.pressure(wPhaseIdx) - cellDataJ.pressure(wPhaseIdx))/dist;
478 potentialNW = (cellDataI.pressure(nPhaseIdx) - cellDataJ.pressure(nPhaseIdx))/dist;
480 potentialW += densityW * (unitDistVec * gravity_);
481 potentialNW += densityNW * (unitDistVec * gravity_);
484 Scalar lambdaW(0.), lambdaN(0.);
485 Scalar dV_w(0.), dV_n(0.);
486 Scalar gV_w(0.), gV_n(0.);
490 const CellData* upwindWCellData(0);
491 const CellData* upwindNCellData(0);
493 upwindWCellData = &cellDataI;
494 else if (potentialW < 0.)
495 upwindWCellData = &cellDataJ;
498 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiWEqIdx))
499 upwindWCellData = &cellDataI;
500 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiWEqIdx))
501 upwindWCellData = &cellDataJ;
506 if (potentialNW > 0.)
507 upwindNCellData = &cellDataI;
508 else if (potentialNW < 0.)
509 upwindNCellData = &cellDataJ;
512 if(cellDataI.isUpwindCell(intersection.indexInInside(), contiNEqIdx))
513 upwindNCellData = &cellDataI;
514 else if(cellDataJ.isUpwindCell(intersection.indexInOutside(), contiNEqIdx))
515 upwindNCellData = &cellDataJ;
521 if(!upwindWCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined() && elementI.father() == neighbor.father()))
523 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
525 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiWEqIdx,
false);
526 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiWEqIdx,
false);
529 Scalar averagedMassFraction[2];
530 averagedMassFraction[wCompIdx]
531 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, wCompIdx), cellDataJ.massFraction(wPhaseIdx, wCompIdx));
532 averagedMassFraction[nCompIdx]
533 =
harmonicMean(cellDataI.massFraction(wPhaseIdx, nCompIdx), cellDataJ.massFraction(wPhaseIdx, nCompIdx));
534 Scalar averageDensity =
harmonicMean(cellDataI.density(wPhaseIdx), cellDataJ.density(wPhaseIdx));
537 dV_w = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
538 dV_w *= averageDensity;
539 gV_w = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
540 gV_w *= averageDensity;
541 lambdaW =
harmonicMean(cellDataI.mobility(wPhaseIdx), cellDataJ.mobility(wPhaseIdx));
545 dV_w = (dv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
546 + dv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
547 lambdaW = upwindWCellData->mobility(wPhaseIdx);
548 gV_w = (graddv_dC1 * upwindWCellData->massFraction(wPhaseIdx, wCompIdx)
549 + graddv_dC2 * upwindWCellData->massFraction(wPhaseIdx, nCompIdx));
550 dV_w *= upwindWCellData->density(wPhaseIdx);
551 gV_w *= upwindWCellData->density(wPhaseIdx);
554 if(!upwindNCellData or (cellDataI.wasRefined() && cellDataJ.wasRefined()))
556 if (cellDataI.wasRefined() && cellDataJ.wasRefined())
558 problem().variables().cellData(eIdxGlobalI).setUpwindCell(intersection.indexInInside(), contiNEqIdx,
false);
559 cellDataJ.setUpwindCell(intersection.indexInOutside(), contiNEqIdx,
false);
561 Scalar averagedMassFraction[2];
562 averagedMassFraction[wCompIdx]
563 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, wCompIdx), cellDataJ.massFraction(nPhaseIdx, wCompIdx));
564 averagedMassFraction[nCompIdx]
565 =
harmonicMean(cellDataI.massFraction(nPhaseIdx, nCompIdx), cellDataJ.massFraction(nPhaseIdx, nCompIdx));
566 Scalar averageDensity =
harmonicMean(cellDataI.density(nPhaseIdx), cellDataJ.density(nPhaseIdx));
569 dV_n = dv_dC1 * averagedMassFraction[wCompIdx] + dv_dC2 * averagedMassFraction[nCompIdx];
570 dV_n *= averageDensity;
571 gV_n = graddv_dC1 * averagedMassFraction[wCompIdx] + graddv_dC2 * averagedMassFraction[nCompIdx];
572 gV_n *= averageDensity;
573 lambdaN =
harmonicMean(cellDataI.mobility(nPhaseIdx), cellDataJ.mobility(nPhaseIdx));
577 dV_n = (dv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
578 + dv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
579 lambdaN = upwindNCellData->mobility(nPhaseIdx);
580 gV_n = (graddv_dC1 * upwindNCellData->massFraction(nPhaseIdx, wCompIdx)
581 + graddv_dC2 * upwindNCellData->massFraction(nPhaseIdx, nCompIdx));
582 dV_n *= upwindNCellData->density(nPhaseIdx);
583 gV_n *= upwindNCellData->density(nPhaseIdx);
587 entries[matrix] = faceArea * (lambdaW * dV_w + lambdaN * dV_n)
589 if(enableVolumeIntegral)
590 entries[matrix] -= volume * faceArea / perimeter * (lambdaW * gV_w + lambdaN * gV_n)
594 entries[rhs] = faceArea * (densityW * lambdaW * dV_w + densityNW * lambdaN * dV_n);
596 if(enableVolumeIntegral)
597 entries[rhs] -= volume * faceArea / perimeter * (densityW * lambdaW * gV_w + densityNW * lambdaN * gV_n)
599 entries[rhs] *= (gravity_ * unitDistVec);
602 Scalar pCGradient = (cellDataI.capillaryPressure() - cellDataJ.capillaryPressure()) / dist;
605 switch (pressureType)
610 entries[rhs] += lambdaN * dV_n * fabs(
permeability * unitOuterNormal) * pCGradient * faceArea;
611 if(enableVolumeIntegral)
612 entries[rhs]-= lambdaN * gV_n * (
permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
618 entries[rhs] -= lambdaW * dV_w * fabs(
permeability * unitOuterNormal) * pCGradient * faceArea;
619 if(enableVolumeIntegral)
620 entries[rhs]+= lambdaW * gV_w * (
permeability * unitDistVec) * pCGradient * volume * faceArea / perimeter;
646template<
class TypeTag>
648 const Intersection& intersection,
const CellData& cellDataI,
const bool first)
652 auto elementI = intersection.inside();
653 const GlobalPosition& globalPos = elementI.geometry().center();
656 const GlobalPosition& unitOuterNormal = intersection.centerUnitOuterNormal();
658 Scalar faceArea = intersection.geometry().volume();
661 Scalar dv_dC1 = cellDataI.dv(wCompIdx);
662 Scalar dv_dC2 = cellDataI.dv(nCompIdx);
665 const GlobalPosition& globalPosFace = intersection.geometry().center();
668 GlobalPosition distVec(globalPosFace - globalPos);
669 Scalar dist = distVec.two_norm();
670 GlobalPosition unitDistVec(distVec);
674 BoundaryTypes bcType;
675 problem().boundaryTypes(bcType, intersection);
678 PhaseVector pressBC(0.);
684 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), elementI);
687 if (bcType.isDirichlet(Indices::pressureEqIdx))
690 DimMatrix permeabilityI(problem().spatialParams().intrinsicPermeability(elementI));
692 if(regulateBoundaryPermeability)
694 int axis = intersection.indexInInside() / 2;
695 if(permeabilityI[axis][axis] < minimalBoundaryPermeability)
696 permeabilityI[axis][axis] = minimalBoundaryPermeability;
698 const GlobalPosition& gravity_ = problem().gravity();
705 FluidState BCfluidState;
708 PrimaryVariables primaryVariablesOnBoundary(NAN);
709 problem().dirichlet(primaryVariablesOnBoundary, intersection);
714 Scalar fractionalWI=0, fractionalNWI=0;
715 fractionalWI = cellDataI.mobility(wPhaseIdx)
716 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
717 fractionalNWI = cellDataI.mobility(nPhaseIdx)
718 / (cellDataI.mobility(wPhaseIdx)+ cellDataI.mobility(nPhaseIdx));
720 Scalar lambda = cellDataI.mobility(wPhaseIdx)+cellDataI.mobility(nPhaseIdx);
721 entries[matrix] += lambda * faceArea * fabs(
permeability * unitOuterNormal) / (dist);
722 Scalar pressBoundary = primaryVariablesOnBoundary[Indices::pressureEqIdx];
723 entries[rhs] += lambda * faceArea * pressBoundary * fabs(
permeability * unitOuterNormal) / (dist);
724 Scalar rightentry = (fractionalWI * cellDataI.density(wPhaseIdx)
725 + fractionalNWI * cellDataI.density(nPhaseIdx))
726 * lambda * faceArea * fabs(unitOuterNormal *
permeability)
727 * ( unitDistVec * gravity_);
728 entries[rhs] -= rightentry;
733 problem().transportModel().evalBoundary(globalPosFace,
737 pcBound = pressBC[nPhaseIdx] - pressBC[wPhaseIdx];
740 Scalar lambdaWBound = 0.;
741 Scalar lambdaNWBound = 0.;
743 Scalar densityWBound =
745 Scalar densityNWBound =
747 Scalar viscosityWBound =
749 Scalar viscosityNWBound =
753 if(getPropValue<TypeTag, Properties::BoundaryMobility>() == Indices::satDependent)
755 lambdaWBound = BCfluidState.saturation(wPhaseIdx)
757 lambdaNWBound = BCfluidState.saturation(nPhaseIdx)
760 else if(getPropValue<TypeTag, Properties::BoundaryMobility>() == Indices::permDependent)
763 = fluidMatrixInteraction.krw(BCfluidState.saturation(wPhaseIdx)) / viscosityWBound;
765 = fluidMatrixInteraction.krn(BCfluidState.saturation(wPhaseIdx)) / viscosityNWBound;
768 Scalar rhoMeanW = 0.5 * (cellDataI.density(wPhaseIdx) + densityWBound);
769 Scalar rhoMeanNW = 0.5 * (cellDataI.density(nPhaseIdx) + densityNWBound);
771 Scalar potentialW = 0;
772 Scalar potentialNW = 0;
784 Scalar densityW=rhoMeanW;
785 Scalar densityNW=rhoMeanNW;
788 potentialW = (cellDataI.pressure(wPhaseIdx) - pressBC[wPhaseIdx])/dist;
789 potentialNW = (cellDataI.pressure(nPhaseIdx) - pressBC[nPhaseIdx])/dist;
791 potentialW += densityW * (unitDistVec * gravity_);
792 potentialNW += densityNW * (unitDistVec * gravity_);
796 Scalar lambdaW, lambdaNW;
797 Scalar densityW(0.), densityNW(0.);
801 if (potentialW >= 0.)
803 densityW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? rhoMeanW : cellDataI.density(wPhaseIdx);
804 dV_w = (dv_dC1 * cellDataI.massFraction(wPhaseIdx, wCompIdx)
805 + dv_dC2 * cellDataI.massFraction(wPhaseIdx, nCompIdx));
807 lambdaW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(wPhaseIdx) + lambdaWBound)
808 : cellDataI.mobility(wPhaseIdx);
812 densityW = densityWBound;
813 dV_w = (dv_dC1 * BCfluidState.massFraction(wPhaseIdx, wCompIdx)
814 + dv_dC2 * BCfluidState.massFraction(wPhaseIdx, nCompIdx));
816 lambdaW = lambdaWBound;
818 if (potentialNW >= 0.)
820 densityNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? rhoMeanNW : cellDataI.density(nPhaseIdx);
821 dV_n = (dv_dC1 * cellDataI.massFraction(nPhaseIdx, wCompIdx)
822 + dv_dC2 * cellDataI.massFraction(nPhaseIdx, nCompIdx));
824 lambdaNW = (Dune::FloatCmp::eq<Scalar, Dune::FloatCmp::absolute>(potentialNW, 0.0, 1.0e-30)) ? 0.5 * (cellDataI.mobility(nPhaseIdx) + lambdaNWBound)
825 : cellDataI.mobility(nPhaseIdx);
829 densityNW = densityNWBound;
830 dV_n = (dv_dC1 * BCfluidState.massFraction(nPhaseIdx, wCompIdx)
831 + dv_dC2 * BCfluidState.massFraction(nPhaseIdx, nCompIdx));
833 lambdaNW = lambdaNWBound;
837 Scalar entry = (lambdaW * dV_w + lambdaNW * dV_n)
838 * (fabs(unitOuterNormal *
permeability) / dist) * faceArea;
841 Scalar rightEntry = (lambdaW * densityW * dV_w + lambdaNW * densityNW * dV_n)
842 * fabs(unitOuterNormal *
permeability) * (gravity_ * unitDistVec) * faceArea ;
846 Scalar pCGradient = (cellDataI.capillaryPressure() - pcBound) / dist;
847 switch (pressureType)
852 rightEntry += lambdaNW * dV_n * pCGradient * fabs(unitOuterNormal *
permeability) * faceArea;
858 rightEntry -= lambdaW * dV_w * pCGradient * fabs(unitOuterNormal *
permeability) * faceArea;
865 entries[matrix] += entry;
866 entries[rhs] += entry * primaryVariablesOnBoundary[Indices::pressureEqIdx];
867 entries[rhs] -= rightEntry;
874 else if(bcType.isNeumann(Indices::pressureEqIdx))
876 PrimaryVariables J(NAN);
877 problem().neumann(J, intersection);
880 J[contiWEqIdx] /= cellDataI.density(wPhaseIdx);
881 J[contiNEqIdx] /= cellDataI.density(nPhaseIdx);
885 J[contiWEqIdx] *= dv_dC1;
886 J[contiNEqIdx] *= dv_dC2;
889 entries[rhs] -= (J[contiWEqIdx] + J[contiNEqIdx]) * faceArea;
892 DUNE_THROW(Dune::NotImplemented,
"Boundary Condition neither Dirichlet nor Neumann!");
907template<
class TypeTag>
911 GlobalPosition globalPos = element.geometry().center();
914 int eIdxGlobal = problem().variables().index(element);
915 CellData& cellData = problem().variables().cellData(eIdxGlobal);
918 FluidState& fluidState = cellData.manipulateFluidState();
920 Scalar temperature_ = problem().temperatureAtPos(globalPos);
927 Scalar Z0 = cellData.massConcentration(wCompIdx)
928 / (cellData.massConcentration(wCompIdx)
929 + cellData.massConcentration(nCompIdx));
932 if(Z0 < 0. || Z0 > 1.)
934 Dune::dgrave <<
"Feed mass fraction unphysical: Z0 = " << Z0
935 <<
" at global Idx " << eIdxGlobal
936 <<
" , because totalConcentration(wCompIdx) = "
937 << cellData.totalConcentration(wCompIdx)
938 <<
" and totalConcentration(nCompIdx) = "
939 << cellData.totalConcentration(nCompIdx)<< std::endl;
943 cellData.setTotalConcentration(wCompIdx, 0.);
944 problem().transportModel().totalConcentration(wCompIdx, eIdxGlobal) = 0.;
945 Dune::dgrave <<
"Regularize totalConcentration(wCompIdx) = "
946 << cellData.totalConcentration(wCompIdx)<< std::endl;
951 cellData.setTotalConcentration(nCompIdx, 0.);
952 problem().transportModel().totalConcentration(nCompIdx,eIdxGlobal) = 0.;
953 Dune::dgrave <<
"Regularize totalConcentration(eIdxGlobal, nCompIdx) = "
954 << cellData.totalConcentration(nCompIdx)<< std::endl;
964 const auto fluidMatrixInteraction = Deprecated::makePcKrSw(Scalar{}, problem().spatialParams(), element);
967 if(getPropValue<TypeTag, Properties::EnableCapillarity>())
969 unsigned int maxiter = 6;
970 Scalar pc = cellData.capillaryPressure();
972 for (
unsigned int iter = 0; iter < maxiter; iter++)
974 switch (pressureType)
978 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal);
979 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal) + pc;
984 pressure[wPhaseIdx] = asImp_().pressure(eIdxGlobal) - pc;
985 pressure[nPhaseIdx] = asImp_().pressure(eIdxGlobal);
995 pc = fluidMatrixInteraction.pc(fluidState.saturation(wPhaseIdx));
997 if (fabs(oldPc-pc)<10 && iter != 0)
1000 if (iter++ == maxiter)
1001 Dune::dinfo << iter <<
"times iteration of pc was applied at Idx " << eIdxGlobal
1002 <<
", pc delta still " << fabs(oldPc-pc) << std::endl;
1007 pressure[wPhaseIdx] =
pressure[nPhaseIdx] = asImp_().pressure()[eIdxGlobal];
1012 cellData.setMobility(wPhaseIdx, fluidMatrixInteraction.krw(fluidState.saturation(wPhaseIdx))
1013 / cellData.viscosity(wPhaseIdx));
1014 cellData.setMobility(nPhaseIdx, fluidMatrixInteraction.krn(fluidState.saturation(wPhaseIdx))
1015 / cellData.viscosity(nPhaseIdx));
1018 Scalar sumConc = (cellData.totalConcentration(wCompIdx)
1019 + cellData.totalConcentration(nCompIdx));
1020 Scalar massw = sumConc * fluidState.phaseMassFraction(wPhaseIdx);
1021 Scalar massn = sumConc * fluidState.phaseMassFraction(nPhaseIdx);
1023 if (Dune::FloatCmp::eq<Scalar>((cellData.density(wPhaseIdx)*cellData.density(nPhaseIdx)), 0))
1024 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate: try to divide by 0 density");
1025 Scalar vol = massw / cellData.density(wPhaseIdx) + massn / cellData.density(nPhaseIdx);
1026 if (Dune::FloatCmp::ne<Scalar, Dune::FloatCmp::absolute>(problem().timeManager().timeStepSize(), 0.0, 1.0e-30))
1028 cellData.volumeError()=(vol - problem().spatialParams().porosity(element));
1031 if (isnan(cellData.volumeError()))
1033 DUNE_THROW(Dune::MathError,
"Sequential2p2c::postProcessUpdate:\n"
1034 <<
"volErr[" << eIdxGlobal <<
"] isnan: vol = " << vol
1035 <<
", massw = " << massw <<
", rho_l = " << cellData.density(wPhaseIdx)
1036 <<
", massn = " << massn <<
", rho_g = " << cellData.density(nPhaseIdx)
1037 <<
", poro = " << problem().spatialParams().
porosity(element)
1038 <<
", dt = " << problem().timeManager().timeStepSize());
1042 cellData.volumeError()=0.;
Define some often used mathematical functions.
Simplifies writing multi-file VTK datasets.
Determines the pressures and saturations of all fluid phases given the total mass of all components.
Base class for compositional pressure equations.
constexpr Scalar harmonicMean(Scalar x, Scalar y, Scalar wx=1.0, Scalar wy=1.0) noexcept
Calculate the (weighted) harmonic mean of two scalar values.
Definition: math.hh:68
void harmonicMeanMatrix(Dune::FieldMatrix< Scalar, m, n > &K, const Dune::FieldMatrix< Scalar, m, n > &Ki, const Dune::FieldMatrix< Scalar, m, n > &Kj)
Calculate the harmonic mean of a fixed-size matrix.
Definition: math.hh:108
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
std::string porosity() noexcept
I/O name of porosity.
Definition: name.hh:139
Flash calculation routines for compositional sequential models.
Definition: compositionalflash.hh:51
static void concentrationFlash2p2c(FluidState &fluidState, const Scalar &Z0, const PhaseVector &phasePressure, const Scalar &porosity, const Scalar &temperature)
Definition: compositionalflash.hh:71
The finite volume model for the solution of the compositional pressure equation.
Definition: fvpressure.hh:75
bool enableVolumeIntegral
Enables the volume integral of the pressure equation.
Definition: fvpressure.hh:184
Scalar ErrorTermLowerBound_
Handling of error term: lower bound for error dampening.
Definition: fvpressure.hh:188
void getSource(EntryType &sourceEntry, const Element &elementI, const CellData &cellDataI, const bool first)
Assembles the source term.
Definition: fvpressure.hh:214
Scalar ErrorTermFactor_
Handling of error term: relaxation factor.
Definition: fvpressure.hh:187
void getFlux(EntryType &entries, const Intersection &intersection, const CellData &cellDataI, const bool first)
Get flux at an interface between two cells.
Definition: fvpressure.hh:356
void getFluxOnBoundary(EntryType &entries, const Intersection &intersection, const CellData &cellDataI, const bool first)
Get flux on Boundary.
Definition: fvpressure.hh:647
const Problem & problem() const
Definition: fvpressure.hh:143
Problem & problem_
Definition: fvpressure.hh:183
static constexpr int pressureType
gives kind of pressure used ( , , )
Definition: fvpressure.hh:191
bool regulateBoundaryPermeability
Enables regulation of permeability in the direction of a Dirichlet Boundary Condition.
Definition: fvpressure.hh:185
Problem & problem()
Definition: fvpressure.hh:139
Scalar minimalBoundaryPermeability
Minimal limit for the boundary permeability.
Definition: fvpressure.hh:186
Dune::FieldVector< Scalar, 2 > EntryType
Definition: fvpressure.hh:137
void getStorage(EntryType &storageEntry, const Element &elementI, const CellData &cellDataI, const bool first)
Assembles the storage term.
Definition: fvpressure.hh:264
Scalar ErrorTermUpperBound_
Definition: fvpressure.hh:189
FVPressure2P2C(Problem &problem)
Constructs a FVPressure2P2C object.
Definition: fvpressure.hh:165
void updateMaterialLawsInElement(const Element &elementI, bool postTimeStep)
Updates secondary variables of one cell.
Definition: fvpressure.hh:908
The finite volume model for the solution of the compositional pressure equation.
Definition: fvpressurecompositional.hh:69
Defines the properties required for the sequential 2p2c models.