307 using ConstEvaluation = std::remove_reference_t<typename FluidState::Scalar>;
308 using FsEvaluation = std::remove_const_t<ConstEvaluation>;
309 using FsToolbox = MathToolbox<FsEvaluation>;
311 const bool gasPresent =
312 FluidSystem::phaseIsActive(gasPhaseIdx)
313 ? fluidState.saturation(gasPhaseIdx) > 0.0
315 const bool oilPresent =
316 FluidSystem::phaseIsActive(oilPhaseIdx)
317 ? fluidState.saturation(oilPhaseIdx) > 0.0
319 const bool waterPresent =
320 FluidSystem::phaseIsActive(waterPhaseIdx)
321 ? fluidState.saturation(waterPhaseIdx) > 0.0
323 const auto& saltSaturation =
324 BlackOil::getSaltSaturation_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
325 const bool precipitatedSaltPresent = enableSaltPrecipitation ? saltSaturation > 0.0 :
false;
326 const bool oneActivePhases = FluidSystem::numActivePhases() == 1;
333 if (gasPresent && FluidSystem::enableVaporizedOil() && !oilPresent) {
334 primaryVarsMeaningPressure_ = PressureMeaning::Pg;
336 else if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
337 primaryVarsMeaningPressure_ = PressureMeaning::Po;
339 else if (waterPresent && FluidSystem::enableDissolvedGasInWater() && !gasPresent) {
340 primaryVarsMeaningPressure_ = PressureMeaning::Pw;
342 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
343 primaryVarsMeaningPressure_ = PressureMeaning::Pg;
346 assert(FluidSystem::phaseIsActive(waterPhaseIdx));
347 primaryVarsMeaningPressure_ = PressureMeaning::Pw;
354 if (waterPresent && gasPresent) {
355 primaryVarsMeaningWater_ = WaterMeaning::Sw;
357 else if (gasPresent && FluidSystem::enableVaporizedWater()) {
358 primaryVarsMeaningWater_ = WaterMeaning::Rvw;
360 else if (waterPresent && FluidSystem::enableDissolvedGasInWater()) {
361 primaryVarsMeaningWater_ = WaterMeaning::Rsw;
363 else if (FluidSystem::phaseIsActive(waterPhaseIdx) && !oneActivePhases) {
364 primaryVarsMeaningWater_ = WaterMeaning::Sw;
367 primaryVarsMeaningWater_ = WaterMeaning::Disabled;
375 if (gasPresent && oilPresent) {
376 primaryVarsMeaningGas_ = GasMeaning::Sg;
378 else if (oilPresent && FluidSystem::enableDissolvedGas()) {
379 primaryVarsMeaningGas_ = GasMeaning::Rs;
381 else if (gasPresent && FluidSystem::enableVaporizedOil()) {
382 primaryVarsMeaningGas_ = GasMeaning::Rv;
384 else if (FluidSystem::phaseIsActive(gasPhaseIdx) && FluidSystem::phaseIsActive(oilPhaseIdx)) {
385 primaryVarsMeaningGas_ = GasMeaning::Sg;
388 primaryVarsMeaningGas_ = GasMeaning::Disabled;
392 if constexpr (enableSaltPrecipitation) {
393 if (precipitatedSaltPresent) {
394 primaryVarsMeaningBrine_ = BrineMeaning::Sp;
397 primaryVarsMeaningBrine_ = BrineMeaning::Cs;
401 primaryVarsMeaningBrine_ = BrineMeaning::Disabled;
406 case PressureMeaning::Po:
407 this->setScaledPressure_(FsToolbox::value(fluidState.pressure(oilPhaseIdx)));
409 case PressureMeaning::Pg:
410 this->setScaledPressure_(FsToolbox::value(fluidState.pressure(gasPhaseIdx)));
412 case PressureMeaning::Pw:
413 this->setScaledPressure_(FsToolbox::value(fluidState.pressure(waterPhaseIdx)));
416 throw std::logic_error(
"No valid primary variable selected for pressure");
420 case WaterMeaning::Sw:
422 (*this)[waterSwitchIdx] = FsToolbox::value(fluidState.saturation(waterPhaseIdx));
425 case WaterMeaning::Rvw:
427 const auto& rvw = BlackOil::getRvw_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
428 (*this)[waterSwitchIdx] = rvw;
431 case WaterMeaning::Rsw:
433 const auto& Rsw = BlackOil::getRsw_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
434 (*this)[waterSwitchIdx] = Rsw;
437 case WaterMeaning::Disabled:
440 throw std::logic_error(
"No valid primary variable selected for water");
444 (*this)[compositionSwitchIdx] = FsToolbox::value(fluidState.saturation(gasPhaseIdx));
448 const auto& rs = BlackOil::getRs_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
449 (*this)[compositionSwitchIdx] = rs;
454 const auto& rv = BlackOil::getRv_<FluidSystem, FluidState, Scalar>(fluidState, pvtRegionIdx_);
455 (*this)[compositionSwitchIdx] = rv;
458 case GasMeaning::Disabled:
461 throw std::logic_error(
"No valid primary variable selected for composision");
477 unsigned globalDofIdx,
478 [[maybe_unused]] Scalar swMaximum,
479 Scalar thresholdWaterFilledCell, Scalar eps = 0.0)
498 Scalar saltConcentration = 0.0;
499 const Scalar& T = asImp_().temperature_(problem, globalDofIdx);
501 sw = (*this)[waterSwitchIdx];
504 sg = (*this)[compositionSwitchIdx];
516 if constexpr (enableSaltPrecipitation) {
517 const Scalar saltSolubility = BrineModule::saltSol(
pvtRegionIndex());
518 if (primaryVarsMeaningBrine() == BrineMeaning::Sp) {
519 saltConcentration = saltSolubility;
520 const Scalar saltSat = (*this)[saltConcentrationIdx];
521 if (saltSat < -eps) {
523 (*this)[saltConcentrationIdx] = saltSolubility;
526 else if (primaryVarsMeaningBrine() == BrineMeaning::Cs) {
527 saltConcentration = (*this)[saltConcentrationIdx];
528 if (saltConcentration > saltSolubility + eps) {
530 (*this)[saltConcentrationIdx] = 0.0;
538 if constexpr (enableSolvent) {
539 if (SolventModule::isSolubleInWater()) {
540 const Scalar p = (*this)[pressureSwitchIdx];
541 const Scalar solLimit =
542 SolventModule::solubilityLimit(
pvtRegionIndex(), T , p, saltConcentration);
543 if (primaryVarsMeaningSolvent() == SolventMeaning::Ss) {
544 const Scalar solSat = (*this)[solventSaturationIdx];
547 (*this)[solventSaturationIdx] = solLimit;
550 else if (primaryVarsMeaningSolvent() == SolventMeaning::Rsolw) {
551 const Scalar rsolw = (*this)[solventSaturationIdx];
552 if (rsolw > solLimit + eps) {
554 (*this)[solventSaturationIdx] = 0.0;
561 bool changed =
false;
569 if (sw >= thresholdWaterFilledCell && !FluidSystem::enableDissolvedGasInWater()) {
571 if constexpr (waterEnabled) {
572 (*this)[Indices::waterSwitchIdx] = std::min(swMaximum, sw);
576 if constexpr (compositionSwitchEnabled) {
577 (*this)[Indices::compositionSwitchIdx] = 0.0;
582 if constexpr (compositionSwitchEnabled) {
592 if constexpr (enableBrine) {
593 if (BrineModule::hasPcfactTables() && primaryVarsMeaningBrine() == BrineMeaning::Sp) {
594 unsigned satnumRegionIdx = problem.satnumRegionIndex(globalDofIdx);
595 Scalar Sp = saltConcentration_();
596 Scalar porosityFactor = std::min(1.0 - Sp, 1.0);
597 const auto& pcfactTable = BrineModule::pcfactTable(satnumRegionIdx);
598 pcFactor_ = pcfactTable.eval(porosityFactor,
true);
601 else if constexpr (enableBioeffects) {
602 if (BioeffectsModule::hasPcfactTables() && problem.referencePorosity(globalDofIdx, 0) > 0) {
603 unsigned satnumRegionIdx = problem.satnumRegionIndex(globalDofIdx);
604 Scalar Sb = biofilmVolumeFraction_() /
605 problem.referencePorosity(globalDofIdx, 0);
606 Scalar porosityFactor = std::min(1.0 - Sb, 1.0);
607 const auto& pcfactTable = BioeffectsModule::pcfactTable(satnumRegionIdx);
608 pcFactor_ = pcfactTable.eval(porosityFactor,
true);
613 case WaterMeaning::Sw:
616 if (sw < -eps && sg > eps && FluidSystem::enableVaporizedWater()) {
617 Scalar p = this->pressure_();
619 std::array<Scalar, numPhases> pC{};
620 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
621 const Scalar so = 1.0 - sg - solventSaturation_();
622 computeCapillaryPressures_(pC, so, sg + solventSaturation_(), 0.0, matParams);
623 p += pcFactor_ * (pC[gasPhaseIdx] - pC[oilPhaseIdx]);
625 const Scalar rvwSat =
626 FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_,
631 (*this)[Indices::waterSwitchIdx] = rvwSat;
637 if (sg < -eps && sw > eps && FluidSystem::enableDissolvedGasInWater()) {
638 const Scalar pg = this->pressure_();
640 std::array<Scalar, numPhases> pC = { 0.0 };
641 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
642 const Scalar so = 1.0 - sw - solventSaturation_();
643 computeCapillaryPressures_(pC, so, 0.0, sw, matParams);
644 const Scalar pw = pg + pcFactor_ * (pC[waterPhaseIdx] - pC[gasPhaseIdx]);
645 const Scalar rswSat =
646 FluidSystem::waterPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
651 const Scalar rswMax = problem.maxGasDissolutionFactor(0, globalDofIdx);
652 (*this)[Indices::waterSwitchIdx] = std::min(rswSat, rswMax);
654 this->setScaledPressure_(pw);
660 case WaterMeaning::Rvw:
662 const Scalar& rvw = (*this)[waterSwitchIdx];
663 Scalar p = this->pressure_();
665 std::array<Scalar, numPhases> pC{};
666 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
667 const Scalar so = 1.0 - sg - solventSaturation_();
668 computeCapillaryPressures_(pC, so, sg + solventSaturation_(), 0.0, matParams);
669 p += pcFactor_ * (pC[gasPhaseIdx] - pC[oilPhaseIdx]);
671 const Scalar rvwSat =
672 FluidSystem::gasPvt().saturatedWaterVaporizationFactor(pvtRegionIdx_,
677 if (rvw > rvwSat * (1.0 + eps)) {
679 (*this)[Indices::waterSwitchIdx] = 0.0;
684 case WaterMeaning::Rsw:
689 const Scalar& pw = this->pressure_();
691 const Scalar rswSat =
692 FluidSystem::waterPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
697 const Scalar rsw = (*this)[Indices::waterSwitchIdx];
698 const Scalar rswMax = problem.maxGasDissolutionFactor(0, globalDofIdx);
699 if (rsw > std::min(rswSat, rswMax)) {
702 (*this)[Indices::waterSwitchIdx] = 1.0;
704 std::array<Scalar, numPhases> pC{};
705 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
706 computeCapillaryPressures_(pC, 0.0, 0.0, 1.0, matParams);
707 const Scalar pg = pw + pcFactor_ * (pC[gasPhaseIdx] - pC[waterPhaseIdx]);
708 this->setScaledPressure_(pg);
713 case WaterMeaning::Disabled:
716 throw std::logic_error(
"No valid primary variable selected for water");
729 const Scalar s = 1.0 - sw - solventSaturation_();
730 if (sg < -eps && s > 0.0 && FluidSystem::enableDissolvedGas()) {
731 const Scalar po = this->pressure_();
733 const Scalar soMax = std::max(s, problem.maxOilSaturation(globalDofIdx));
734 const Scalar rsMax = problem.maxGasDissolutionFactor(0, globalDofIdx);
738 : FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
743 (*this)[Indices::compositionSwitchIdx] = std::min(rsMax, rsSat);
746 const Scalar so = 1.0 - sw - solventSaturation_() - sg;
747 if (so < -eps && sg > 0.0 && FluidSystem::enableVaporizedOil()) {
752 const Scalar po = this->pressure_();
753 std::array<Scalar, numPhases> pC{};
754 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
755 computeCapillaryPressures_(pC, 0.0, sg + solventSaturation_(), sw, matParams);
756 const Scalar pg = po + pcFactor_ * (pC[gasPhaseIdx] - pC[oilPhaseIdx]);
761 this->setScaledPressure_(pg);
762 const Scalar soMax = problem.maxOilSaturation(globalDofIdx);
763 const Scalar rvMax = problem.maxOilVaporizationFactor(0, globalDofIdx);
767 : FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_,
773 (*this)[Indices::compositionSwitchIdx] = std::min(rvMax, rvSat);
783 const Scalar po = this->pressure_();
784 const Scalar so = 1.0 - sw - solventSaturation_();
785 const Scalar soMax = std::max(so, problem.maxOilSaturation(globalDofIdx));
786 const Scalar rsMax = problem.maxGasDissolutionFactor(0, globalDofIdx);
790 : FluidSystem::oilPvt().saturatedGasDissolutionFactor(pvtRegionIdx_,
796 const Scalar rs = (*this)[Indices::compositionSwitchIdx];
797 if (rs > std::min(rsMax, rsSat * (Scalar{1.0} + eps))) {
800 (*this)[Indices::compositionSwitchIdx] = 0.0;
811 const Scalar pg = this->pressure_();
812 const Scalar soMax = problem.maxOilSaturation(globalDofIdx);
813 const Scalar rvMax = problem.maxOilVaporizationFactor(0, globalDofIdx);
817 : FluidSystem::gasPvt().saturatedOilVaporizationFactor(pvtRegionIdx_,
823 const Scalar rv = (*this)[Indices::compositionSwitchIdx];
824 if (rv > std::min(rvMax, rvSat * (Scalar{1.0} + eps))) {
828 const Scalar sg2 = 1.0 - sw - solventSaturation_();
829 std::array<Scalar, numPhases> pC{};
830 const MaterialLawParams& matParams = problem.materialLawParams(globalDofIdx);
831 computeCapillaryPressures_(pC,
833 sg2 + solventSaturation_(),
836 const Scalar po = pg + pcFactor_ * (pC[oilPhaseIdx] - pC[gasPhaseIdx]);
840 this->setScaledPressure_(po);
841 (*this)[Indices::compositionSwitchIdx] = sg2;
846 case GasMeaning::Disabled:
849 throw std::logic_error(
"No valid primary variable selected for water");