82 using FluidState =
typename IntensiveQuantities::FluidState;
84 enum { conti0EqIdx = Indices::conti0EqIdx };
89 enum { dimWorld = GridView::dimensionworld };
90 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
91 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
92 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
94 enum { gasCompIdx = FluidSystem::gasCompIdx };
95 enum { oilCompIdx = FluidSystem::oilCompIdx };
96 enum { waterCompIdx = FluidSystem::waterCompIdx };
97 enum { compositionSwitchIdx = Indices::compositionSwitchIdx };
99 static constexpr bool waterEnabled = Indices::waterEnabled;
100 static constexpr bool gasEnabled = Indices::gasEnabled;
101 static constexpr bool oilEnabled = Indices::oilEnabled;
102 static constexpr bool compositionSwitchEnabled = compositionSwitchIdx >= 0;
104 static constexpr bool blackoilConserveSurfaceVolume
110 static constexpr bool enableFullyImplicitThermal
112 == EnergyModules::FullyImplicitThermal);
117 static constexpr bool enableConvectiveMixing
120 static constexpr bool enableSaltPrecipitation
122 static constexpr bool enableMICP = Indices::enableMICP;
138 using Toolbox = MathToolbox<Evaluation>;
146 FaceDir::DirEnum faceDir;
149 ConditionalStorage<enableFullyImplicitThermal, double> inAlpha;
150 ConditionalStorage<enableFullyImplicitThermal, double> outAlpha;
151 ConditionalStorage<enableDiffusion, double> diffusivity;
152 ConditionalStorage<enableDispersion, double> dispersivity;
158 template <
class LhsEval>
160 const ElementContext& elemCtx,
162 unsigned timeIdx)
const
164 const IntensiveQuantities& intQuants = elemCtx.intensiveQuantities(dofIdx, timeIdx);
168 template <
class LhsEval,
class StorageType,
class IntensiveQuantitiesType = IntensiveQuantities>
170 const IntensiveQuantitiesType& intQuants)
174 const auto& fs = intQuants.fluidState();
177 const FluidSystem& fsys = intQuants.getFluidSystem();
179 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
180 if (!fsys.phaseIsActive(phaseIdx)) {
183 unsigned activeCompIdx
184 = fsys.canonicalToActiveCompIdx(fsys.solventComponentIndex(phaseIdx));
185 LhsEval surfaceVolume = Toolbox::template decay<LhsEval>(fs.saturation(phaseIdx))
186 * Toolbox::template decay<LhsEval>(fs.invB(phaseIdx))
187 * Toolbox::template decay<LhsEval>(intQuants.porosity());
189 storage[conti0EqIdx + activeCompIdx] += surfaceVolume;
192 if (phaseIdx == oilPhaseIdx && fsys.enableDissolvedGas()) {
193 unsigned activeGasCompIdx = fsys.canonicalToActiveCompIdx(gasCompIdx);
194 storage[conti0EqIdx + activeGasCompIdx]
195 += Toolbox::template decay<LhsEval>(intQuants.fluidState().Rs())
200 if (phaseIdx == waterPhaseIdx && fsys.enableDissolvedGasInWater()) {
201 unsigned activeGasCompIdx = fsys.canonicalToActiveCompIdx(gasCompIdx);
202 storage[conti0EqIdx + activeGasCompIdx]
203 += Toolbox::template decay<LhsEval>(intQuants.fluidState().Rsw())
208 if (phaseIdx == gasPhaseIdx && fsys.enableVaporizedOil()) {
209 unsigned activeOilCompIdx = fsys.canonicalToActiveCompIdx(oilCompIdx);
210 storage[conti0EqIdx + activeOilCompIdx]
211 += Toolbox::template decay<LhsEval>(intQuants.fluidState().Rv())
216 if (phaseIdx == gasPhaseIdx && fsys.enableVaporizedWater()) {
217 unsigned activeWaterCompIdx = fsys.canonicalToActiveCompIdx(waterCompIdx);
218 storage[conti0EqIdx + activeWaterCompIdx]
219 += Toolbox::template decay<LhsEval>(intQuants.fluidState().Rvw())
227 SolventModule::addStorage(storage, intQuants);
230 ExtboModule::addStorage(storage, intQuants);
233 PolymerModule::addStorage(storage, intQuants);
236 EnergyModule::addStorage(storage, intQuants);
239 FoamModule::addStorage(storage, intQuants);
242 BrineModule::addStorage(storage, intQuants);
245 BioeffectsModule::addStorage(storage, intQuants);
253 template <
class ModuleParamsT,
255 class IntensiveQuantitiesT,
256 class ResidualNBInfoT>
259 const unsigned globalIndexIn,
260 const unsigned globalIndexEx,
261 const IntensiveQuantitiesT& intQuantsIn,
262 const IntensiveQuantitiesT& intQuantsEx,
263 const ResidualNBInfoT& nbInfo,
264 const ModuleParamsT& moduleParams)
266 OPM_TIMEBLOCK_LOCAL(
computeFlux, Subsystem::Assembly);
270 calculateFluxes_(flux,
284 computeFlux(RateVector& flux,
const ElementContext& elemCtx,
unsigned scvfIdx,
unsigned timeIdx)
286 OPM_TIMEBLOCK_LOCAL(
computeFlux, Subsystem::Assembly);
287 assert(timeIdx == 0);
290 RateVector darcy = 0.0;
292 const auto& problem = elemCtx.problem();
293 const auto& stencil = elemCtx.stencil(timeIdx);
294 const auto& scvf = stencil.interiorFace(scvfIdx);
296 unsigned interiorDofIdx = scvf.interiorIndex();
297 unsigned exteriorDofIdx = scvf.exteriorIndex();
298 assert(interiorDofIdx != exteriorDofIdx);
302 Scalar Vin = elemCtx.dofVolume(interiorDofIdx, 0);
303 Scalar Vex = elemCtx.dofVolume(exteriorDofIdx, 0);
304 const auto& globalIndexIn = stencil.globalSpaceIndex(interiorDofIdx);
305 const auto& globalIndexEx = stencil.globalSpaceIndex(exteriorDofIdx);
306 Scalar trans = problem.transmissibility(elemCtx, interiorDofIdx, exteriorDofIdx);
307 Scalar faceArea = scvf.area();
308 const auto faceDir = faceDirFromDirId(scvf.dirId());
309 Scalar thpres = problem.thresholdPressure(globalIndexIn, globalIndexEx);
314 const Scalar g = problem.gravity()[dimWorld - 1];
315 const auto& intQuantsIn = elemCtx.intensiveQuantities(interiorDofIdx, timeIdx);
316 const auto& intQuantsEx = elemCtx.intensiveQuantities(exteriorDofIdx, timeIdx);
323 const Scalar zIn = problem.dofCenterDepth(elemCtx, interiorDofIdx, timeIdx);
324 const Scalar zEx = problem.dofCenterDepth(elemCtx, exteriorDofIdx, timeIdx);
327 const Scalar distZ = zIn - zEx;
329 const Scalar inAlpha = problem.thermalHalfTransmissibility(globalIndexIn, globalIndexEx);
330 const Scalar outAlpha = problem.thermalHalfTransmissibility(globalIndexEx, globalIndexIn);
331 const Scalar diffusivity = problem.diffusivity(globalIndexEx, globalIndexIn);
332 const Scalar dispersivity = problem.dispersivity(globalIndexEx, globalIndexIn);
334 const ResidualNBInfo res_nbinfo {trans,
346 calculateFluxes_(flux,
353 problem.moduleParams());
356 template <
class RateVectorT,
357 class IntensiveQuantitiesT,
358 class ResidualNBInfoT,
360 OPM_HOST_DEVICE
static void calculateFluxes_(RateVectorT& flux,
362 const IntensiveQuantitiesT& intQuantsIn,
363 const IntensiveQuantitiesT& intQuantsEx,
364 const unsigned& globalIndexIn,
365 const unsigned& globalIndexEx,
366 const ResidualNBInfoT& nbInfo,
367 const ModuleParamsT& moduleParams)
369 OPM_TIMEBLOCK_LOCAL(calculateFluxes, Subsystem::Assembly);
370 const Scalar Vin = nbInfo.Vin;
371 const Scalar Vex = nbInfo.Vex;
372 const Scalar distZg = nbInfo.dZg;
373 const Scalar thpres = nbInfo.thpres;
374 const Scalar trans = nbInfo.trans;
375 const Scalar faceArea = nbInfo.faceArea;
376 FaceDir::DirEnum facedir = nbInfo.faceDir;
378 const FluidSystem& fsys = intQuantsIn.getFluidSystem();
380 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
381 if (!fsys.phaseIsActive(phaseIdx)) {
389 short interiorDofIdx = 0;
390 short exteriorDofIdx = 1;
391 Evaluation pressureDifference;
392 ExtensiveQuantities::calculatePhasePressureDiff_(upIdx,
408 const IntensiveQuantities& up = (upIdx == interiorDofIdx) ? intQuantsIn : intQuantsEx;
409 unsigned globalUpIndex = (upIdx == interiorDofIdx) ? globalIndexIn : globalIndexEx;
412 Evaluation transMult = (intQuantsIn.rockCompTransMultiplier()
413 + Toolbox::value(intQuantsEx.rockCompTransMultiplier()))
415 if constexpr (enableBioeffects || enableSaltPrecipitation) {
417 *= (intQuantsIn.permFactor() + Toolbox::value(intQuantsEx.permFactor())) / 2;
420 Evaluation darcyFlux;
421 if (globalUpIndex == globalIndexIn) {
422 darcyFlux = pressureDifference * up.mobility(phaseIdx, facedir) * transMult
423 * (-trans / faceArea);
425 darcyFlux = pressureDifference
426 * (Toolbox::value(up.mobility(phaseIdx, facedir)) * transMult
427 * (-trans / faceArea));
430 unsigned activeCompIdx
431 = fsys.canonicalToActiveCompIdx(fsys.solventComponentIndex(phaseIdx));
433 darcy[conti0EqIdx + activeCompIdx] = darcyFlux.value() * faceArea;
435 unsigned pvtRegionIdx = up.pvtRegionIndex();
437 if (globalUpIndex == globalIndexIn) {
438 const auto& invB = getInvB_<FluidSystem, FluidState, Evaluation>(
439 up.fluidState(), phaseIdx, pvtRegionIdx, fsys);
440 const auto& surfaceVolumeFlux = invB * darcyFlux;
442 evalPhaseFluxes_<Evaluation>(
443 flux, phaseIdx, pvtRegionIdx, surfaceVolumeFlux, up.fluidState());
444 if constexpr (enableFullyImplicitThermal) {
445 EnergyModule::template addPhaseEnthalpyFluxes_<Evaluation>(
446 flux, phaseIdx, darcyFlux, up.fluidState());
448 if constexpr (enableBioeffects) {
449 BioeffectsModule::template addBioeffectsFluxes_<Evaluation>(
450 flux, phaseIdx, darcyFlux, up);
452 if constexpr (enableBrine) {
453 BrineModule::template addBrineFluxes_<Evaluation, FluidState>(
454 flux, phaseIdx, darcyFlux, up.fluidState());
457 const auto& invB = getInvB_<FluidSystem, FluidState, Scalar>(
458 up.fluidState(), phaseIdx, pvtRegionIdx, fsys);
459 const auto& surfaceVolumeFlux = invB * darcyFlux;
460 evalPhaseFluxes_<Scalar>(
461 flux, phaseIdx, pvtRegionIdx, surfaceVolumeFlux, up.fluidState());
462 if constexpr (enableFullyImplicitThermal) {
463 EnergyModule::template addPhaseEnthalpyFluxes_<Scalar>(
464 flux, phaseIdx, darcyFlux, up.fluidState());
466 if constexpr (enableBioeffects) {
467 BioeffectsModule::template addBioeffectsFluxes_<Scalar>(
468 flux, phaseIdx, darcyFlux, up);
470 if constexpr (enableBrine) {
471 BrineModule::template addBrineFluxes_<Scalar, FluidState>(
472 flux, phaseIdx, darcyFlux, up.fluidState());
480 "Relevant computeFlux() method must be implemented for this module before enabling.");
486 "Relevant computeFlux() method must be implemented for this module before enabling.");
492 "Relevant computeFlux() method must be implemented for this module before enabling.");
496 if constexpr (enableConvectiveMixing) {
497 ConvectiveMixingModule::addConvectiveMixingFlux(
506 moduleParams.convectiveMixingModuleParam);
510 if constexpr (enableFullyImplicitThermal) {
511 const Scalar inAlpha = nbInfo.inAlpha;
512 const Scalar outAlpha = nbInfo.outAlpha;
515 short interiorDofIdx = 0;
516 short exteriorDofIdx = 1;
518 EnergyModule::ExtensiveQuantities::updateEnergy(heatFlux,
524 intQuantsIn.fluidState(),
525 intQuantsEx.fluidState(),
529 EnergyModule::addHeatFlux(flux, heatFlux);
537 "Relevant computeFlux() method must be implemented for this module before enabling.");
542 if constexpr (enableDiffusion) {
543 typename DiffusionModule::ExtensiveQuantities::EvaluationArray
544 effectiveDiffusionCoefficient;
545 DiffusionModule::ExtensiveQuantities::update(
546 effectiveDiffusionCoefficient, intQuantsIn, intQuantsEx);
547 const Scalar diffusivity = nbInfo.diffusivity;
548 const Scalar tmpdiffusivity = diffusivity / faceArea;
549 DiffusionModule::addDiffusiveFlux(
550 flux, intQuantsIn, intQuantsEx, tmpdiffusivity, effectiveDiffusionCoefficient);
555 if constexpr (enableDispersion) {
556 typename DispersionModule::ExtensiveQuantities::ScalarArray normVelocityAvg;
557 DispersionModule::ExtensiveQuantities::update(
558 normVelocityAvg, intQuantsIn, intQuantsEx);
559 const Scalar dispersivity = nbInfo.dispersivity;
560 const Scalar tmpdispersivity = dispersivity / faceArea;
561 DispersionModule::addDispersiveFlux(
562 flux, intQuantsIn, intQuantsEx, tmpdispersivity, normVelocityAvg);
566 if constexpr (enableMICP) {
567 BioeffectsModule::applyScaling(flux);
571 template <
class BoundaryConditionData,
class RateVectorLocal,
class LocalProblem>
572 OPM_HOST_DEVICE
static void computeBoundaryFlux(RateVectorLocal& bdyFlux,
573 const LocalProblem& problem,
574 const BoundaryConditionData& bdyInfo,
575 const IntensiveQuantities& insideIntQuants,
576 unsigned globalSpaceIdx)
578#if OPM_IS_INSIDE_HOST_FUNCTION
579 switch (bdyInfo.type) {
584 computeBoundaryFluxRate(bdyFlux, bdyInfo);
587 case BCType::DIRICHLET:
588 computeBoundaryFluxFree(problem, bdyFlux, bdyInfo, insideIntQuants, globalSpaceIdx);
590 case BCType::THERMAL:
591 computeBoundaryThermal(problem, bdyFlux, bdyInfo, insideIntQuants, globalSpaceIdx);
594 throw std::logic_error(
"Unknown boundary condition type "
595 + std::to_string(
static_cast<int>(bdyInfo.type))
596 +
" in computeBoundaryFlux().");
599 switch (bdyInfo.type) {
603 case BCType::THERMAL:
604 computeBoundaryThermal(problem, bdyFlux, bdyInfo, insideIntQuants, globalSpaceIdx);
607 OPM_THROW(std::logic_error,
608 "Boundary condition type " + std::to_string(
static_cast<int>(bdyInfo.type))
609 +
" is not supported for GPU fluid systems in computeBoundaryFlux().");
614 template <
class BoundaryConditionData>
615 static void computeBoundaryFluxRate(RateVector& bdyFlux,
const BoundaryConditionData& bdyInfo)
617 bdyFlux.setMassRate(bdyInfo.massRate, bdyInfo.pvtRegionIdx);
620 template <
class BoundaryConditionData>
621 static void computeBoundaryFluxFree(
const Problem& problem,
623 const BoundaryConditionData& bdyInfo,
624 const IntensiveQuantities& insideIntQuants,
625 unsigned globalSpaceIdx)
627 OPM_TIMEBLOCK_LOCAL(computeBoundaryFluxFree, Subsystem::Assembly);
628 std::array<short, numPhases> upIdx;
629 std::array<short, numPhases> dnIdx;
630 std::array<Evaluation, numPhases> volumeFlux;
631 std::array<Evaluation, numPhases> pressureDifference;
633 ExtensiveQuantities::calculateBoundaryGradients_(problem,
636 bdyInfo.boundaryFaceIndex,
639 bdyInfo.exFluidState,
649 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
650 if (!FluidSystem::phaseIsActive(phaseIdx)) {
653 const auto& pBoundary = bdyInfo.exFluidState.pressure(phaseIdx);
654 const Evaluation& pInside = insideIntQuants.fluidState().pressure(phaseIdx);
655 const unsigned pvtRegionIdx = insideIntQuants.pvtRegionIndex();
658 const auto& darcyFlux = volumeFlux[phaseIdx];
660 if (pBoundary < pInside) {
662 const auto& invB = getInvB_<FluidSystem, FluidState, Evaluation>(
663 insideIntQuants.fluidState(), phaseIdx, pvtRegionIdx);
664 Evaluation surfaceVolumeFlux = invB * darcyFlux;
665 evalPhaseFluxes_<Evaluation>(tmp,
667 insideIntQuants.pvtRegionIndex(),
669 insideIntQuants.fluidState());
670 if constexpr (enableFullyImplicitThermal) {
671 EnergyModule::template addPhaseEnthalpyFluxes_<Evaluation>(
672 tmp, phaseIdx, darcyFlux, insideIntQuants.fluidState());
674 }
else if (pBoundary > pInside) {
676 using ScalarFluidState =
decltype(bdyInfo.exFluidState);
677 const auto& invB = getInvB_<FluidSystem, ScalarFluidState, Scalar>(
678 bdyInfo.exFluidState, phaseIdx, pvtRegionIdx);
679 Evaluation surfaceVolumeFlux = invB * darcyFlux;
680 evalPhaseFluxes_<Scalar>(tmp,
682 insideIntQuants.pvtRegionIndex(),
684 bdyInfo.exFluidState);
685 if constexpr (enableFullyImplicitThermal) {
686 EnergyModule::template addPhaseEnthalpyFluxes_<Scalar>(
687 tmp, phaseIdx, darcyFlux, bdyInfo.exFluidState);
691 for (
unsigned i = 0; i < tmp.size(); ++i) {
692 bdyFlux[i] += tmp[i];
697 if constexpr (enableFullyImplicitThermal) {
700 Scalar alpha = problem.eclTransmissibilities().thermalHalfTransBoundary(
701 globalSpaceIdx, bdyInfo.boundaryFaceIndex);
704 EnergyModule::ExtensiveQuantities::updateEnergyBoundary(heatFlux,
709 bdyInfo.exFluidState);
710 EnergyModule::addHeatFlux(bdyFlux, heatFlux);
715 "Relevant treatment of boundary conditions must be implemented before enabling.");
718 "Relevant treatment of boundary conditions must be implemented before enabling.");
720 const FluidSystem& fsys = insideIntQuants.getFluidSystem();
726 for (
unsigned i = 0; i < numEq; ++i) {
727 Valgrind::CheckDefined(bdyFlux[i]);
729 Valgrind::CheckDefined(bdyFlux);
733 template <
class ProblemLocal,
class BoundaryConditionData,
class RateVectorLocal>
734 OPM_HOST_DEVICE
static void computeBoundaryThermal(
const ProblemLocal& problem,
735 RateVectorLocal& bdyFlux,
736 const BoundaryConditionData& bdyInfo,
737 const IntensiveQuantities& insideIntQuants,
738 [[maybe_unused]]
unsigned globalSpaceIdx)
740 OPM_TIMEBLOCK_LOCAL(computeBoundaryThermal, Subsystem::Assembly);
745 if constexpr (enableFullyImplicitThermal) {
750 if constexpr (runAssemblyOnGpu) {
753 alpha = problem.getAlpha(globalSpaceIdx, bdyInfo.boundaryFaceIndex);
755 alpha = problem.eclTransmissibilities().thermalHalfTransBoundary(
756 globalSpaceIdx, bdyInfo.boundaryFaceIndex);
761 EnergyModule::ExtensiveQuantities::updateEnergyBoundary(heatFlux,
766 bdyInfo.exFluidState);
767 EnergyModule::addHeatFlux(bdyFlux, heatFlux);
771 for (
unsigned i = 0; i < numEq; ++i) {
772 Valgrind::CheckDefined(bdyFlux[i]);
774 Valgrind::CheckDefined(bdyFlux);
778 static void computeSource(RateVector& source,
779 const Problem& problem,
780 const IntensiveQuantities& insideIntQuants,
781 unsigned globalSpaceIdex,
784 OPM_TIMEBLOCK_LOCAL(computeSource, Subsystem::Assembly);
786 problem.source(source, globalSpaceIdex, timeIdx);
789 BioeffectsModule::addSource(source, problem, insideIntQuants, globalSpaceIdex);
792 if constexpr (enableFullyImplicitThermal) {
793 source[Indices::contiEnergyEqIdx]
798 static void computeSourceDense(RateVector& source,
799 const Problem& problem,
800 const IntensiveQuantities& insideIntQuants,
801 unsigned globalSpaceIdex,
805 problem.addToSourceDense(source, globalSpaceIdex, timeIdx);
808 BioeffectsModule::addSource(source, problem, insideIntQuants, globalSpaceIdex);
811 if constexpr (enableFullyImplicitThermal) {
812 source[Indices::contiEnergyEqIdx]
821 const ElementContext& elemCtx,
823 unsigned timeIdx)
const
825 OPM_TIMEBLOCK_LOCAL(computeSource, Subsystem::Assembly);
827 elemCtx.problem().source(source, elemCtx, dofIdx, timeIdx);
830 BioeffectsModule::addSource(source, elemCtx, dofIdx, timeIdx);
833 if constexpr (enableFullyImplicitThermal) {
834 source[Indices::contiEnergyEqIdx]
839 template <
class UpEval,
class Flu
idState>
840 static void evalPhaseFluxes_(RateVector& flux,
842 unsigned pvtRegionIdx,
843 const ExtensiveQuantities& extQuants,
844 const FluidState& upFs)
846 const auto& invB = getInvB_<FluidSystem, FluidState, UpEval>(upFs, phaseIdx, pvtRegionIdx);
847 const auto& surfaceVolumeFlux = invB * extQuants.volumeFlux(phaseIdx);
848 evalPhaseFluxes_<UpEval>(flux, phaseIdx, pvtRegionIdx, surfaceVolumeFlux, upFs);
855 template <
class UpEval,
class Eval,
class Flu
idState,
class RateVectorT = RateVector>
858 unsigned pvtRegionIdx,
859 const Eval& surfaceVolumeFlux,
860 const FluidState& upFs)
862 const FluidSystem& fsys = upFs.fluidSystem();
864 unsigned activeCompIdx
865 = fsys.canonicalToActiveCompIdx(fsys.solventComponentIndex(phaseIdx));
867 if constexpr (blackoilConserveSurfaceVolume) {
868 flux[conti0EqIdx + activeCompIdx] += surfaceVolumeFlux;
870 flux[conti0EqIdx + activeCompIdx]
871 += surfaceVolumeFlux * fsys.referenceDensity(phaseIdx, pvtRegionIdx);
874 if (phaseIdx == oilPhaseIdx) {
876 if (fsys.enableDissolvedGas()) {
878 = BlackOil::getRs_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
880 const unsigned activeGasCompIdx = fsys.canonicalToActiveCompIdx(gasCompIdx);
881 if constexpr (blackoilConserveSurfaceVolume) {
882 flux[conti0EqIdx + activeGasCompIdx] += Rs * surfaceVolumeFlux;
884 flux[conti0EqIdx + activeGasCompIdx] += Rs * surfaceVolumeFlux
885 * fsys.referenceDensity(gasPhaseIdx, pvtRegionIdx);
888 }
else if (phaseIdx == waterPhaseIdx) {
890 if (fsys.enableDissolvedGasInWater()) {
892 = BlackOil::getRsw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
894 const unsigned activeGasCompIdx = fsys.canonicalToActiveCompIdx(gasCompIdx);
895 if constexpr (blackoilConserveSurfaceVolume) {
896 flux[conti0EqIdx + activeGasCompIdx] += Rsw * surfaceVolumeFlux;
898 flux[conti0EqIdx + activeGasCompIdx] += Rsw * surfaceVolumeFlux
899 * fsys.referenceDensity(gasPhaseIdx, pvtRegionIdx);
902 }
else if (phaseIdx == gasPhaseIdx) {
904 if (fsys.enableVaporizedOil()) {
906 = BlackOil::getRv_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
908 const unsigned activeOilCompIdx = fsys.canonicalToActiveCompIdx(oilCompIdx);
909 if constexpr (blackoilConserveSurfaceVolume) {
910 flux[conti0EqIdx + activeOilCompIdx] += Rv * surfaceVolumeFlux;
912 flux[conti0EqIdx + activeOilCompIdx] += Rv * surfaceVolumeFlux
913 * fsys.referenceDensity(oilPhaseIdx, pvtRegionIdx);
917 if (fsys.enableVaporizedWater()) {
919 = BlackOil::getRvw_<FluidSystem, FluidState, UpEval>(upFs, pvtRegionIdx);
921 const unsigned activeWaterCompIdx = fsys.canonicalToActiveCompIdx(waterCompIdx);
922 if constexpr (blackoilConserveSurfaceVolume) {
923 flux[conti0EqIdx + activeWaterCompIdx] += Rvw * surfaceVolumeFlux;
925 flux[conti0EqIdx + activeWaterCompIdx] += Rvw * surfaceVolumeFlux
926 * fsys.referenceDensity(waterPhaseIdx, pvtRegionIdx);
940 template <
class Scalar>
942 unsigned pvtRegionIdx)
961 template <
class ScalarVector,
class FsysType>
963 unsigned pvtRegionIdx,
964 const FsysType& fsys)
966 if constexpr (!blackoilConserveSurfaceVolume) {
971 if constexpr (waterEnabled) {
972 const unsigned activeWaterCompIdx = fsys.canonicalToActiveCompIdx(waterCompIdx);
973 container[conti0EqIdx + activeWaterCompIdx]
974 *= fsys.referenceDensity(waterPhaseIdx, pvtRegionIdx);
977 if constexpr (gasEnabled) {
978 const unsigned activeGasCompIdx = fsys.canonicalToActiveCompIdx(gasCompIdx);
979 container[conti0EqIdx + activeGasCompIdx]
980 *= fsys.referenceDensity(gasPhaseIdx, pvtRegionIdx);
983 if constexpr (oilEnabled) {
984 const unsigned activeOilCompIdx = fsys.canonicalToActiveCompIdx(oilCompIdx);
985 container[conti0EqIdx + activeOilCompIdx]
986 *= fsys.referenceDensity(oilPhaseIdx, pvtRegionIdx);
992 static FaceDir::DirEnum faceDirFromDirId(
const int dirId)
994 return dirId < 0 ? FaceDir::DirEnum::Unknown : FaceDir::FromIntersectionIndex(dirId);