27#ifndef OPM_OUTPUT_BLACK_OIL_MODULE_HPP
28#define OPM_OUTPUT_BLACK_OIL_MODULE_HPP
30#include <dune/common/fvector.hh>
34#include <opm/common/Exceptions.hpp>
35#include <opm/common/TimingMacros.hpp>
36#include <opm/common/OpmLog/OpmLog.hpp>
37#include <opm/common/utility/Visitor.hpp>
39#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
41#include <opm/material/common/Valgrind.hpp>
42#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
43#include <opm/material/fluidstates/BlackOilFluidState.hpp>
44#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
51#include <opm/output/data/Cells.hpp>
52#include <opm/output/eclipse/EclipseIO.hpp>
53#include <opm/output/eclipse/Inplace.hpp>
75template <
class TypeTag>
76class EcfvDiscretization;
80 template <
typename... T>
90template <
class TypeTag>
102 using FluidState =
typename IntensiveQuantities::FluidState;
104 using Element =
typename GridView::template Codim<0>::Entity;
105 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
108 using Dir = FaceDir::DirEnum;
115 static constexpr int conti0EqIdx = Indices::conti0EqIdx;
116 static constexpr int numPhases = FluidSystem::numPhases;
117 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
118 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
119 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
120 static constexpr int gasCompIdx = FluidSystem::gasCompIdx;
121 static constexpr int oilCompIdx = FluidSystem::oilCompIdx;
122 static constexpr int waterCompIdx = FluidSystem::waterCompIdx;
123 static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
124 static constexpr bool enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>();
125 static constexpr bool enableExtbo = getPropValue<TypeTag, Properties::EnableExtbo>();
126 static constexpr bool enableFoam = getPropValue<TypeTag, Properties::EnableFoam>();
127 static constexpr bool enablePolymer = getPropValue<TypeTag, Properties::EnablePolymer>();
128 static constexpr bool enableSolvent = getPropValue<TypeTag, Properties::EnableSolvent>();
129 enum { enableMICP = Indices::enableMICP };
130 enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
131 enum { enableDisgasInWater = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
132 static constexpr bool enableDissolvedGas =
133 Indices::compositionSwitchIdx != std::numeric_limits<unsigned>::max();
135 template<
class VectorType>
136 static Scalar value_or_zero(
int idx,
const VectorType& v)
141 return v.empty() ? 0.0 : v[idx];
146 const SummaryConfig& smryCfg,
148 :
BaseType(simulator.vanguard().eclState(),
149 simulator.vanguard().schedule(),
151 simulator.vanguard().summaryState(),
153 [this](const int idx)
154 {
return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
155 [&collectOnIORank](
const int idx)
156 {
return collectOnIORank.isCartIdxOnThisRank(idx); },
157 simulator.vanguard().grid().comm(),
158 energyModuleType == EnergyModules::FullyImplicitThermal ||
159 energyModuleType == EnergyModules::SequentialImplicitThermal,
160 energyModuleType == EnergyModules::ConstantTemperature,
161 getPropValue<TypeTag, Properties::EnableMech>(),
162 getPropValue<TypeTag, Properties::EnableSolvent>(),
163 getPropValue<TypeTag, Properties::EnablePolymer>(),
164 getPropValue<TypeTag, Properties::EnableFoam>(),
165 getPropValue<TypeTag, Properties::EnableBrine>(),
166 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
167 getPropValue<TypeTag, Properties::EnableExtbo>(),
168 getPropValue<TypeTag, Properties::EnableBioeffects>(),
169 getPropValue<TypeTag, Properties::EnableGeochemistry>())
170 , simulator_(simulator)
171 , collectOnIORank_(collectOnIORank)
173 for (
auto& region_pair : this->
regions_) {
174 this->createLocalRegion_(region_pair.second);
177 auto isCartIdxOnThisRank = [&collectOnIORank](
const int idx) {
178 return collectOnIORank.isCartIdxOnThisRank(idx);
183 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
184 const std::string msg =
"The output code does not support --owner-cells-first=false.";
185 if (collectOnIORank.isIORank()) {
188 OPM_THROW_NOLOG(std::runtime_error, msg);
191 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
192 auto rset = this->
eclState_.fieldProps().fip_regions();
193 rset.push_back(
"PVTNUM");
199 .emplace(this->simulator_.gridView().comm(),
200 FluidSystem::numPhases, rset,
201 [fp = std::cref(this->eclState_.fieldProps())]
202 (
const std::string& rsetName) ->
decltype(
auto)
203 { return fp.get().get_int(rsetName); });
213 const unsigned reportStepNum,
216 const bool isRestart)
222 const auto& problem = this->simulator_.problem();
229 &problem.materialLawManager()->hysteresisConfig(),
230 problem.eclWriter().getOutputNnc().front().size());
235 const int reportStepNum)
237 this->setupElementExtractors_();
238 this->setupBlockExtractors_(isSubStep, reportStepNum);
244 this->extractors_.clear();
245 this->blockExtractors_.clear();
246 this->extraBlockExtractors_.clear();
260 if (this->extractors_.empty()) {
264 const auto& matLawManager = simulator_.problem().materialLawManager();
267 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
268 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
269 const auto& fs = intQuants.fluidState();
272 elemCtx.globalSpaceIndex(dofIdx, 0),
273 elemCtx.primaryVars(dofIdx, 0).pvtRegionIndex(),
280 if (matLawManager->enableHysteresis()) {
281 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
282 matLawManager->oilWaterHysteresisParams(hysterParams.
somax,
287 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
288 matLawManager->gasOilHysteresisParams(hysterParams.
sgmax,
306 if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
310 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
312 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
313 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
315 const auto be_it = this->blockExtractors_.find(cartesianIdx);
316 const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
317 if (be_it == this->blockExtractors_.end() &&
318 bee_it == this->extraBlockExtractors_.end())
323 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
324 const auto& fs = intQuants.fluidState();
334 if (be_it != this->blockExtractors_.end()) {
337 if (bee_it != this->extraBlockExtractors_.end()) {
344 const std::size_t reportStepNum,
346 boost::posix_time::ptime currentDate,
351 if (comm.rank() != 0) {
356 std::unique_ptr<FIPConfig> fipSched;
357 if (reportStepNum > 0) {
358 const auto& rpt = this->
schedule_[reportStepNum-1].rpt_config.get();
359 fipSched = std::make_unique<FIPConfig>(rpt);
361 const FIPConfig& fipc = reportStepNum == 0 ? this->
eclState_.getEclipseConfig().fip()
366 this->
logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
369 this->
logOutput_.fip(inplace, initial_inplace,
"");
371 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
372 this->
logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
374 if (fipc.output(FIPConfig::OutputField::RESV))
378 if (fipc.output(FIPConfig::OutputField::FIP)) {
379 for (
const auto& reg : this->regions_) {
380 if (reg.first !=
"FIPNUM") {
381 std::ostringstream ss;
382 ss <<
"BAL" << reg.first.substr(3);
383 this->
logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
384 this->
logOutput_.fip(inplace, initial_inplace, reg.first);
386 if (fipc.output(FIPConfig::OutputField::RESV))
398 if (comm.rank() != 0) {
402 if ((reportStepNum == 0) && (!substep) &&
403 (this->
schedule_.initialReportConfiguration().has_value()) &&
404 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
406 std::ostringstream csv_stream;
412 this->
logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
414 for (
const auto& reg : this->regions_) {
415 if (reg.first !=
"FIPNUM") {
416 this->
logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
420 const IOConfig& io = this->
eclState_.getIOConfig();
421 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
423 std::ofstream outputFile(csv_fname);
425 outputFile << csv_stream.str();
459 template <
class ActiveIndex,
class CartesianIndex>
461 ActiveIndex&& activeIndex,
462 CartesianIndex&& cartesianIndex)
465 const auto identifyCell = [&activeIndex, &cartesianIndex](
const Element& elem)
468 const auto cellIndex = activeIndex(elem);
471 static_cast<int>(cellIndex),
472 cartesianIndex(cellIndex),
473 elem.partitionType() == Dune::InteriorEntity
477 const auto timeIdx = 0u;
478 const auto& stencil = elemCtx.stencil(timeIdx);
479 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
481 for (
auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
482 const auto& face = stencil.interiorFace(scvfIdx);
483 const auto left = identifyCell(stencil.element(face.interiorIndex()));
484 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
486 const auto rates = this->
487 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
520 template <
class Flu
idState>
523 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
527 fs.setSaturation(phaseIdx, this->
saturation_[phaseIdx][elemIdx]);
533 std::array<Scalar, numPhases> pc = {0};
534 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
535 MaterialLaw::capillaryPressures(pc, matParams, fs);
537 Valgrind::CheckDefined(pc);
539 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
540 if (!FluidSystem::phaseIsActive(phaseIdx))
543 if (Indices::oilEnabled)
544 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
545 else if (Indices::gasEnabled)
546 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
547 else if (Indices::waterEnabled)
549 fs.setPressure(phaseIdx, pressure);
553 if constexpr (energyModuleType != EnergyModules::NoTemperature) {
555 fs.setTemperature(this->temperature_[elemIdx]);
557 if constexpr (enableDissolvedGas) {
558 if (!this->
rs_.empty())
559 fs.setRs(this->rs_[elemIdx]);
560 if (!this->
rv_.empty())
561 fs.setRv(this->rv_[elemIdx]);
563 if constexpr (enableDisgasInWater) {
564 if (!this->
rsw_.empty())
565 fs.setRsw(this->rsw_[elemIdx]);
567 if constexpr (enableVapwat) {
568 if (!this->
rvw_.empty())
569 fs.setRvw(this->rvw_[elemIdx]);
575 if (!this->
soMax_.empty())
576 simulator.problem().setMaxOilSaturation(elemIdx, this->
soMax_[elemIdx]);
578 if (simulator.problem().materialLawManager()->enableHysteresis()) {
579 auto matLawManager = simulator.problem().materialLawManager();
581 if (FluidSystem::phaseIsActive(oilPhaseIdx)
582 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
587 if (matLawManager->enableNonWettingHysteresis()) {
588 if (!this->
soMax_.empty()) {
589 somax = this->
soMax_[elemIdx];
592 if (matLawManager->enableWettingHysteresis()) {
593 if (!this->
swMax_.empty()) {
594 swmax = this->
swMax_[elemIdx];
597 if (matLawManager->enablePCHysteresis()) {
598 if (!this->
swmin_.empty()) {
599 swmin = this->
swmin_[elemIdx];
602 matLawManager->setOilWaterHysteresisParams(
603 somax, swmax, swmin, elemIdx);
605 if (FluidSystem::phaseIsActive(oilPhaseIdx)
606 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
611 if (matLawManager->enableNonWettingHysteresis()) {
612 if (!this->
sgmax_.empty()) {
613 sgmax = this->
sgmax_[elemIdx];
616 if (matLawManager->enableWettingHysteresis()) {
617 if (!this->
shmax_.empty()) {
618 shmax = this->
shmax_[elemIdx];
621 if (matLawManager->enablePCHysteresis()) {
622 if (!this->
somin_.empty()) {
623 somin = this->
somin_[elemIdx];
626 matLawManager->setGasOilHysteresisParams(
627 sgmax, shmax, somin, elemIdx);
632 if (simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT")) {
633 simulator.problem().materialLawManager()
634 ->applyRestartSwatInit(elemIdx, this->
ppcw_[elemIdx]);
640 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
641 updateFluidInPlace_(elemCtx, dofIdx);
646 const IntensiveQuantities& intQuants,
647 const double totVolume)
649 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
653 template <
typename T>
654 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
656 template <
typename,
class =
void>
657 struct HasGeoMech :
public std::false_type {};
659 template <
typename Problem>
661 Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
662 > :
public std::true_type {};
664 template <
typename,
class =
void>
665 struct HasGeochemistry :
public std::false_type {};
667 template <
typename Problem>
668 struct HasGeochemistry<
669 Problem, std::void_t<decltype(std::declval<Problem>().geochemistryModel())>
670 > :
public std::true_type {};
672 bool isDefunctParallelWell(
const std::string& wname)
const override
674 if (simulator_.gridView().comm().size() == 1)
676 const auto& parallelWells = simulator_.vanguard().parallelWells();
677 std::pair<std::string, bool> value {wname,
true};
678 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
679 return candidate == parallelWells.end() || *candidate != value;
682 bool isOwnedByCurrentRank(
const std::string& wname)
const override
684 return this->simulator_.problem().wellModel().isOwner(wname);
687 bool isOnCurrentRank(
const std::string& wname)
const override
689 return this->simulator_.problem().wellModel().hasLocalCells(wname);
692 void updateFluidInPlace_(
const ElementContext& elemCtx,
const unsigned dofIdx)
694 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
695 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
696 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
698 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
701 void updateFluidInPlace_(
const unsigned globalDofIdx,
702 const IntensiveQuantities& intQuants,
703 const double totVolume)
707 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
710 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
714 void createLocalRegion_(std::vector<int>& region)
720 region.resize(simulator_.gridView().size(0));
721 std::size_t elemIdx = 0;
722 for (
const auto& elem : elements(simulator_.gridView())) {
723 if (elem.partitionType() != Dune::InteriorEntity) {
731 template <
typename Flu
idState>
732 void aggregateAverageDensityContributions_(
const FluidState& fs,
733 const unsigned int globalDofIdx,
736 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
737 pvCellValue.porv = porv;
739 for (
auto phaseIdx = 0*FluidSystem::numPhases;
740 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
742 if (! FluidSystem::phaseIsActive(phaseIdx)) {
746 pvCellValue.value = getValue(fs.density(phaseIdx));
747 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
750 ->addCell(globalDofIdx,
771 data::InterRegFlowMap::FlowRates
772 getComponentSurfaceRates(
const ElementContext& elemCtx,
773 const Scalar faceArea,
774 const std::size_t scvfIdx,
775 const std::size_t timeIdx)
const
777 using Component = data::InterRegFlowMap::Component;
779 auto rates = data::InterRegFlowMap::FlowRates {};
781 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
783 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
785 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
786 const auto& up = elemCtx
787 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
789 const auto pvtReg = up.pvtRegionIndex();
791 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
792 (up.fluidState(), oilPhaseIdx, pvtReg));
794 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
796 rates[Component::Oil] += qO;
798 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
799 const auto Rs = getValue(
800 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
801 (up.fluidState(), pvtReg));
803 rates[Component::Gas] += qO *
Rs;
804 rates[Component::Disgas] += qO *
Rs;
808 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
809 const auto& up = elemCtx
810 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
812 const auto pvtReg = up.pvtRegionIndex();
814 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
815 (up.fluidState(), gasPhaseIdx, pvtReg));
817 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
819 rates[Component::Gas] += qG;
821 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
822 const auto Rv = getValue(
823 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
824 (up.fluidState(), pvtReg));
826 rates[Component::Oil] += qG *
Rv;
827 rates[Component::Vapoil] += qG *
Rv;
831 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
832 const auto& up = elemCtx
833 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
835 const auto pvtReg = up.pvtRegionIndex();
837 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
838 (up.fluidState(), waterPhaseIdx, pvtReg));
840 rates[Component::Water] +=
841 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
847 template <
typename Flu
idState>
848 Scalar hydroCarbonFraction(
const FluidState& fs)
const
850 if (this->
eclState_.runspec().co2Storage()) {
857 auto hydrocarbon = Scalar {0};
858 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
859 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
862 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
863 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
869 void updateTotalVolumesAndPressures_(
const unsigned globalDofIdx,
870 const IntensiveQuantities& intQuants,
871 const double totVolume)
873 const auto& fs = intQuants.fluidState();
875 const double pv = totVolume * intQuants.porosity().value();
876 const auto hydrocarbon = this->hydroCarbonFraction(fs);
880 totVolume * intQuants.referencePorosity());
887 !this->pressureTimesPoreVolume_.empty())
890 assert(this->
fipC_.
get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
892 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
894 getValue(fs.pressure(oilPhaseIdx)) * pv;
899 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
901 getValue(fs.pressure(gasPhaseIdx)) * pv;
906 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
908 getValue(fs.pressure(waterPhaseIdx)) * pv;
913 void updatePhaseInplaceVolumes_(
const unsigned globalDofIdx,
914 const IntensiveQuantities& intQuants,
915 const double totVolume)
917 std::array<Scalar, FluidSystem::numPhases> fip {};
918 std::array<Scalar, FluidSystem::numPhases> fipr{};
920 const auto& fs = intQuants.fluidState();
921 const auto pv = totVolume * intQuants.porosity().value();
923 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
924 if (!FluidSystem::phaseIsActive(phaseIdx)) {
928 const auto b = getValue(fs.invB(phaseIdx));
929 const auto s = getValue(fs.saturation(phaseIdx));
931 fipr[phaseIdx] = s * pv;
932 fip [phaseIdx] = b * fipr[phaseIdx];
937 fs.saltConcentration().value(),
940 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
941 FluidSystem::phaseIsActive(gasPhaseIdx))
943 this->updateOilGasDistribution(globalDofIdx, fs, fip);
946 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
947 FluidSystem::phaseIsActive(gasPhaseIdx))
949 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
952 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
955 this->updateCO2InGas(globalDofIdx, pv, intQuants);
959 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
960 FluidSystem::phaseIsActive(oilPhaseIdx)))
962 this->updateCO2InWater(globalDofIdx, pv, fs);
965 if constexpr(enableBioeffects) {
966 const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
967 getValue(fs.invB(waterPhaseIdx));
969 this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
972 this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
974 if constexpr(enableMICP) {
976 this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
979 this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
982 this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
989 this->updateWaterMass(globalDofIdx, fs, fip);
993 template <
typename Flu
idState,
typename FIPArray>
994 void updateOilGasDistribution(
const unsigned globalDofIdx,
995 const FluidState& fs,
999 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
1000 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
1005 template <
typename Flu
idState,
typename FIPArray>
1006 void updateGasWaterDistribution(
const unsigned globalDofIdx,
1007 const FluidState& fs,
1008 const FIPArray& fip)
1011 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
1012 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
1017 template <
typename IntensiveQuantities>
1018 void updateCO2InGas(
const unsigned globalDofIdx,
1020 const IntensiveQuantities& intQuants)
1022 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
1023 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
1025 const auto& fs = intQuants.fluidState();
1026 Scalar sgcr = scaledDrainageInfo.Sgcr;
1027 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1028 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1029 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
1032 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1033 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
1034 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
1036 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1037 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1039 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams,
true);
1043 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1044 Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
1045 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
1046 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
1048 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1049 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1050 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1051 strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1055 const typename FIPContainer<FluidSystem>::Co2InGasInput v{
1059 getValue(fs.density(gasPhaseIdx)),
1060 FluidSystem::phaseIsActive(waterPhaseIdx)
1061 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1062 : FluidSystem::convertRvToXgO(getValue(fs.
Rv()), fs.pvtRegionIndex()),
1063 FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
1064 trappedGasSaturation,
1065 strandedGasSaturation,
1071 template <
typename Flu
idState>
1072 void updateCO2InWater(
const unsigned globalDofIdx,
1074 const FluidState& fs)
1076 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1077 ? this->co2InWaterFromOil(fs, pv)
1078 : this->co2InWaterFromWater(fs, pv);
1080 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1085 template <
typename Flu
idState>
1086 Scalar co2InWaterFromWater(
const FluidState& fs,
const double pv)
const
1088 const double rhow = getValue(fs.density(waterPhaseIdx));
1089 const double sw = getValue(fs.saturation(waterPhaseIdx));
1090 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1092 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1094 return xwG * pv * rhow * sw / mM;
1097 template <
typename Flu
idState>
1098 Scalar co2InWaterFromOil(
const FluidState& fs,
const double pv)
const
1100 const double rhoo = getValue(fs.density(oilPhaseIdx));
1101 const double so = getValue(fs.saturation(oilPhaseIdx));
1102 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1104 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1106 return xoG * pv * rhoo * so / mM;
1109 template <
typename Flu
idState,
typename FIPArray>
1110 void updateWaterMass(
const unsigned globalDofIdx,
1111 const FluidState& fs,
1115 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
1120 template <
typename IntensiveQuantities>
1121 void updateMicrobialMass(
const unsigned globalDofIdx,
1122 const IntensiveQuantities& intQuants,
1123 const double surfVolWat)
1125 const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
1130 template <
typename IntensiveQuantities>
1131 void updateOxygenMass(
const unsigned globalDofIdx,
1132 const IntensiveQuantities& intQuants,
1133 const double surfVolWat)
1135 const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
1140 template <
typename IntensiveQuantities>
1141 void updateUreaMass(
const unsigned globalDofIdx,
1142 const IntensiveQuantities& intQuants,
1143 const double surfVolWat)
1145 const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
1150 template <
typename IntensiveQuantities>
1151 void updateBiofilmMass(
const unsigned globalDofIdx,
1152 const IntensiveQuantities& intQuants,
1153 const double totVolume)
1155 const Scalar mass = totVolume * intQuants.biofilmMass().value();
1160 template <
typename IntensiveQuantities>
1161 void updateCalciteMass(
const unsigned globalDofIdx,
1162 const IntensiveQuantities& intQuants,
1163 const double totVolume)
1165 const Scalar mass = totVolume * intQuants.calciteMass().value();
1171 void setupElementExtractors_()
1173 using Entry =
typename Extractor::Entry;
1174 using Context =
typename Extractor::Context;
1175 using ScalarEntry =
typename Extractor::ScalarEntry;
1176 using PhaseEntry =
typename Extractor::PhaseEntry;
1178 const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
1179 const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
1181 auto extractors = std::array{
1183 [](
const unsigned phase,
const Context& ectx)
1184 {
return getValue(ectx.fs.saturation(phase)); }
1187 Entry{PhaseEntry{&this->
invB_,
1188 [](
const unsigned phase,
const Context& ectx)
1189 {
return getValue(ectx.fs.invB(phase)); }
1193 [](
const unsigned phase,
const Context& ectx)
1194 {
return getValue(ectx.fs.density(phase)); }
1198 [](
const unsigned phase,
const Context& ectx)
1199 {
return getValue(ectx.intQuants.relativePermeability(phase)); }
1203 [
this](
const unsigned phaseIdx,
const Context& ectx)
1206 if constexpr (enableExtbo) {
1207 if (this->
extboC_.allocated() && phaseIdx == oilPhaseIdx) {
1208 return getValue(ectx.intQuants.oilViscosity());
1210 else if (this->
extboC_.allocated() && phaseIdx == gasPhaseIdx) {
1211 return getValue(ectx.intQuants.gasViscosity());
1214 return getValue(ectx.fs.viscosity(phaseIdx));
1219 [&modelResid = this->simulator_.model().linearizer().residual()]
1220 (
const unsigned phaseIdx,
const Context& ectx)
1222 const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
1223 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
1224 return modelResid[ectx.globalDofIdx][activeCompIdx];
1230 [&problem = this->simulator_.problem()](
const Context& ectx)
1232 return problem.template
1233 rockCompPoroMultiplier<Scalar>(ectx.intQuants,
1239 [&problem = this->simulator_.problem()](
const Context& ectx)
1242 template rockCompTransMultiplier<Scalar>(ectx.intQuants,
1247 [&problem = this->simulator_.problem()](
const Context& ectx)
1249 return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
1250 problem.minOilPressure(ectx.globalDofIdx));
1256 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1260 FluidSystem::bubblePointPressure(ectx.fs,
1261 ectx.intQuants.pvtRegionIndex())
1263 }
catch (
const NumericalProblem&) {
1264 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1265 failedCells.push_back(cartesianIdx);
1273 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1277 FluidSystem::dewPointPressure(ectx.fs,
1278 ectx.intQuants.pvtRegionIndex())
1280 }
catch (
const NumericalProblem&) {
1281 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1282 failedCells.push_back(cartesianIdx);
1289 [&problem = simulator_.problem()](
const Context& ectx)
1290 {
return problem.overburdenPressure(ectx.globalDofIdx); }
1294 [](
const Context& ectx)
1295 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }
1298 Entry{ScalarEntry{&this->
sSol_,
1299 [](
const Context& ectx)
1301 if constexpr (enableSolvent) {
1302 return getValue(ectx.intQuants.solventSaturation());
1310 Entry{ScalarEntry{&this->
rswSol_,
1311 [](
const Context& ectx)
1313 if constexpr (enableSolvent) {
1314 return getValue(ectx.intQuants.rsSolw());
1323 [](
const Context& ectx)
1325 if constexpr (enablePolymer) {
1326 return getValue(ectx.intQuants.polymerConcentration());
1334 Entry{ScalarEntry{&this->
cFoam_,
1335 [](
const Context& ectx)
1337 if constexpr (enableFoam) {
1338 return getValue(ectx.intQuants.foamConcentration());
1346 Entry{ScalarEntry{&this->
cSalt_,
1347 [](
const Context& ectx)
1348 {
return getValue(ectx.fs.saltConcentration()); }
1351 Entry{ScalarEntry{&this->
pSalt_,
1352 [](
const Context& ectx)
1353 {
return getValue(ectx.fs.saltSaturation()); }
1357 [](
const Context& ectx)
1358 {
return getValue(ectx.intQuants.permFactor()); }
1361 Entry{ScalarEntry{&this->
rPorV_,
1362 [&model = this->simulator_.model()](
const Context& ectx)
1364 const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
1365 return totVolume * getValue(ectx.intQuants.porosity());
1369 Entry{ScalarEntry{&this->
rs_,
1370 [](
const Context& ectx)
1371 {
return getValue(ectx.fs.Rs()); }
1374 Entry{ScalarEntry{&this->
rv_,
1375 [](
const Context& ectx)
1376 {
return getValue(ectx.fs.Rv()); }
1379 Entry{ScalarEntry{&this->
rsw_,
1380 [](
const Context& ectx)
1381 {
return getValue(ectx.fs.Rsw()); }
1384 Entry{ScalarEntry{&this->
rvw_,
1385 [](
const Context& ectx)
1386 {
return getValue(ectx.fs.Rvw()); }
1389 Entry{ScalarEntry{&this->
ppcw_,
1390 [&matLawManager = *this->simulator_.problem().materialLawManager()]
1391 (
const Context& ectx)
1393 return matLawManager.
1394 oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
1399 [&problem = this->simulator_.problem()](
const Context& ectx)
1401 return problem.drsdtcon(ectx.globalDofIdx,
1406 Entry{ScalarEntry{&this->
pcgw_,
1407 [](
const Context& ectx)
1409 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1410 getValue(ectx.fs.pressure(waterPhaseIdx));
1414 Entry{ScalarEntry{&this->
pcow_,
1415 [](
const Context& ectx)
1417 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1418 getValue(ectx.fs.pressure(waterPhaseIdx));
1422 Entry{ScalarEntry{&this->
pcog_,
1423 [](
const Context& ectx)
1425 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1426 getValue(ectx.fs.pressure(oilPhaseIdx));
1431 [](
const Context& ectx)
1433 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1435 return getValue(ectx.fs.pressure(oilPhaseIdx));
1437 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1439 return getValue(ectx.fs.pressure(gasPhaseIdx));
1443 return getValue(ectx.fs.pressure(waterPhaseIdx));
1449 [&problem = this->simulator_.problem()](
const Context& ectx)
1451 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1452 return FluidSystem::template
1453 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1461 [&problem = this->simulator_.problem()](
const Context& ectx)
1463 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1464 return FluidSystem::template
1465 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1473 [&problem = this->simulator_.problem()](
const Context& ectx)
1475 const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
1476 return FluidSystem::template
1477 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1485 [](
const Context& ectx)
1487 return FluidSystem::template
1488 saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
1495 [](
const Context& ectx)
1497 return 1.0 / FluidSystem::template
1498 inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1505 [](
const Context& ectx)
1507 return 1.0 / FluidSystem::template
1508 saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1515 [](
const Context& ectx)
1517 return FluidSystem::template
1518 saturationPressure<FluidState, Scalar>(ectx.fs,
1524 Entry{ScalarEntry{&this->
soMax_,
1525 [&problem = this->simulator_.problem()](
const Context& ectx)
1527 return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
1528 problem.maxOilSaturation(ectx.globalDofIdx));
1531 !hysteresisConfig.enableHysteresis()
1533 Entry{ScalarEntry{&this->
swMax_,
1534 [&problem = this->simulator_.problem()](
const Context& ectx)
1536 return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
1537 problem.maxWaterSaturation(ectx.globalDofIdx));
1540 !hysteresisConfig.enableHysteresis()
1542 Entry{ScalarEntry{&this->
soMax_,
1543 [](
const Context& ectx)
1544 {
return ectx.hParams.somax; }
1546 hysteresisConfig.enableHysteresis() &&
1547 hysteresisConfig.enableNonWettingHysteresis() &&
1548 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1549 FluidSystem::phaseIsActive(waterPhaseIdx)
1551 Entry{ScalarEntry{&this->
swMax_,
1552 [](
const Context& ectx)
1553 {
return ectx.hParams.swmax; }
1555 hysteresisConfig.enableHysteresis() &&
1556 hysteresisConfig.enableWettingHysteresis() &&
1557 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1558 FluidSystem::phaseIsActive(waterPhaseIdx)
1560 Entry{ScalarEntry{&this->
swmin_,
1561 [](
const Context& ectx)
1562 {
return ectx.hParams.swmin; }
1564 hysteresisConfig.enableHysteresis() &&
1565 hysteresisConfig.enablePCHysteresis() &&
1566 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1567 FluidSystem::phaseIsActive(waterPhaseIdx)
1569 Entry{ScalarEntry{&this->
sgmax_,
1570 [](
const Context& ectx)
1571 {
return ectx.hParams.sgmax; }
1573 hysteresisConfig.enableHysteresis() &&
1574 hysteresisConfig.enableNonWettingHysteresis() &&
1575 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1576 FluidSystem::phaseIsActive(gasPhaseIdx)
1578 Entry{ScalarEntry{&this->
shmax_,
1579 [](
const Context& ectx)
1580 {
return ectx.hParams.shmax; }
1582 hysteresisConfig.enableHysteresis() &&
1583 hysteresisConfig.enableWettingHysteresis() &&
1584 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1585 FluidSystem::phaseIsActive(gasPhaseIdx)
1587 Entry{ScalarEntry{&this->
somin_,
1588 [](
const Context& ectx)
1589 {
return ectx.hParams.somin; }
1591 hysteresisConfig.enableHysteresis() &&
1592 hysteresisConfig.enablePCHysteresis() &&
1593 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1594 FluidSystem::phaseIsActive(gasPhaseIdx)
1596 Entry{[&model = this->simulator_.model(),
this](
const Context& ectx)
1600 const auto porv = ectx.intQuants.referencePorosity()
1601 * model.dofTotalVolume(ectx.globalDofIdx);
1603 this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
1604 static_cast<double>(porv));
1607 Entry{[&extboC = this->
extboC_](
const Context& ectx)
1610 if constexpr (enableExtbo) {
1611 extboC.assignVolumes(ectx.globalDofIdx,
1612 ectx.intQuants.xVolume().value(),
1613 ectx.intQuants.yVolume().value());
1614 extboC.assignZFraction(ectx.globalDofIdx,
1615 ectx.intQuants.zFraction().value());
1617 const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
1618 getValue(ectx.fs.invB(oilPhaseIdx)) +
1619 getValue(ectx.fs.saturation(gasPhaseIdx)) *
1620 getValue(ectx.fs.invB(gasPhaseIdx)) *
1621 getValue(ectx.fs.Rv());
1622 const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1623 getValue(ectx.fs.invB(gasPhaseIdx)) *
1624 (1.0 - ectx.intQuants.yVolume().value()) +
1625 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1626 getValue(ectx.fs.invB(oilPhaseIdx)) *
1627 getValue(ectx.fs.Rs()) *
1628 (1.0 - ectx.intQuants.xVolume().value());
1629 const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1630 getValue(ectx.fs.invB(gasPhaseIdx)) *
1631 ectx.intQuants.yVolume().value() +
1632 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1633 getValue(ectx.fs.invB(oilPhaseIdx)) *
1634 getValue(ectx.fs.Rs()) *
1635 ectx.intQuants.xVolume().value();
1636 const Scalar rhoO = FluidSystem::referenceDensity(oilPhaseIdx, ectx.pvtRegionIdx);
1637 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1638 const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
1639 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
1640 extboC.assignMassFractions(ectx.globalDofIdx,
1641 stdVolGas * rhoG / stdMassTotal,
1642 stdVolOil * rhoO / stdMassTotal,
1643 stdVolCo2 * rhoCO2 / stdMassTotal);
1647 Entry{[&bioeffectsC = this->
bioeffectsC_](
const Context& ectx)
1650 if constexpr (enableBioeffects) {
1651 bioeffectsC.assign(ectx.globalDofIdx,
1652 ectx.intQuants.microbialConcentration().value(),
1653 ectx.intQuants.biofilmVolumeFraction().value());
1654 if (Indices::enableMICP) {
1655 bioeffectsC.assign(ectx.globalDofIdx,
1656 ectx.intQuants.oxygenConcentration().value(),
1657 ectx.intQuants.ureaConcentration().value(),
1658 ectx.intQuants.calciteVolumeFraction().value());
1663 Entry{[&runspec = this->
eclState_.runspec(),
1664 &CO2H2C = this->
CO2H2C_](
const Context& ectx)
1666 const auto xwg = FluidSystem::convertRswToXwG(getValue(ectx.fs.Rsw()), ectx.pvtRegionIdx);
1667 const auto xgw = FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.pvtRegionIdx);
1668 CO2H2C.assign(ectx.globalDofIdx,
1669 FluidSystem::convertXwGToxwG(xwg, ectx.pvtRegionIdx),
1670 FluidSystem::convertXgWToxgW(xgw, ectx.pvtRegionIdx),
1671 runspec.co2Storage());
1674 Entry{[&rftC = this->
rftC_,
1675 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1677 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1678 rftC.assign(cartesianIdx,
1679 [&fs = ectx.fs]() {
return getValue(fs.pressure(oilPhaseIdx)); },
1680 [&fs = ectx.fs]() {
return getValue(fs.saturation(waterPhaseIdx)); },
1681 [&fs = ectx.fs]() {
return getValue(fs.saturation(gasPhaseIdx)); });
1685 &tM = this->simulator_.problem().tracerModel()](
const Context& ectx)
1687 tC.assignFreeConcentrations(ectx.globalDofIdx,
1688 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1689 {
return tM.freeTracerConcentration(tracerIdx, gIdx); });
1690 tC.assignSolConcentrations(ectx.globalDofIdx,
1691 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1692 {
return tM.solTracerConcentration(tracerIdx, gIdx); });
1695 Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
1697 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1699 const auto gas_idx = Indices::gasEnabled ?
1700 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1701 const auto oil_idx = Indices::oilEnabled ?
1702 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1703 const auto water_idx = Indices::waterEnabled ?
1704 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1705 const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
1706 if (!flowsC.blockFlows().empty()) {
1707 const std::vector<int>& blockIdxs = flowsC.blockFlows();
1708 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1709 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1710 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1711 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1712 for (
const auto& flowsInfo : flowsInfos) {
1713 if (flowsInfo.faceId < 0) {
1716 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1717 if (!compEnabled[ii]) {
1720 if (flowsC.hasBlockFlowValue(cartesianIdx, flowsInfo.faceId, compIdxs[ii])) {
1721 flowsC.assignBlockFlows(flowsC.blockFlowsIds(cartesianIdx, flowsInfo.faceId, compIdxs[ii]),
1724 flowsInfo.flow[conti0EqIdx
1725 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1732 for (
const auto& flowsInfo : flowsInfos) {
1733 flowsC.assignFlows(ectx.globalDofIdx,
1736 value_or_zero(gas_idx, flowsInfo.flow),
1737 value_or_zero(oil_idx, flowsInfo.flow),
1738 value_or_zero(water_idx, flowsInfo.flow));
1741 }, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
1743 Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
1744 &flowsC = this->
flowsC_](
const Context& ectx)
1746 const auto gas_idx = Indices::gasEnabled ?
1747 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1748 const auto oil_idx = Indices::oilEnabled ?
1749 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1750 const auto water_idx = Indices::waterEnabled ?
1751 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1752 const auto& floresInfos = floresInf[ectx.globalDofIdx];
1753 for (
const auto& floresInfo : floresInfos) {
1754 flowsC.assignFlores(ectx.globalDofIdx,
1757 value_or_zero(gas_idx, floresInfo.flow),
1758 value_or_zero(oil_idx, floresInfo.flow),
1759 value_or_zero(water_idx, floresInfo.flow));
1761 }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
1763 Entry{[&velocityInf = this->simulator_.problem().model().linearizer().getVelocityInfo(),
1765 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1767 const auto& velocityInfos = velocityInf[ectx.globalDofIdx];
1768 const std::vector<int>& blockIdxs = flowsC.blockVelocity();
1769 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1770 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1771 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1772 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1773 for (
const auto& velocityInfo : velocityInfos) {
1774 if (velocityInfo.faceId < 0) {
1777 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1778 if (!compEnabled[ii]) {
1781 if (flowsC.hasBlockVelocityValue(cartesianIdx, velocityInfo.faceId, compIdxs[ii])) {
1782 flowsC.assignBlockVelocity(flowsC.blockVelocityIds(cartesianIdx, velocityInfo.faceId, compIdxs[ii]),
1783 velocityInfo.faceId,
1785 velocityInfo.velocity[conti0EqIdx
1786 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1792 !this->simulator_.problem().model().linearizer().getVelocityInfo().empty()
1799 Entry{ScalarEntry{&this->
rv_,
1800 [&problem = this->simulator_.problem()](
const Context& ectx)
1801 {
return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
1803 simulator_.episodeIndex() < 0 &&
1804 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1805 FluidSystem::phaseIsActive(gasPhaseIdx)
1807 Entry{ScalarEntry{&this->
rs_,
1808 [&problem = this->simulator_.problem()](
const Context& ectx)
1809 {
return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
1811 simulator_.episodeIndex() < 0 &&
1812 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1813 FluidSystem::phaseIsActive(gasPhaseIdx)
1815 Entry{ScalarEntry{&this->
rsw_,
1816 [&problem = this->simulator_.problem()](
const Context& ectx)
1817 {
return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
1819 simulator_.episodeIndex() < 0 &&
1820 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1821 FluidSystem::phaseIsActive(gasPhaseIdx)
1823 Entry{ScalarEntry{&this->
rvw_,
1824 [&problem = this->simulator_.problem()](
const Context& ectx)
1825 {
return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
1827 simulator_.episodeIndex() < 0 &&
1828 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1829 FluidSystem::phaseIsActive(gasPhaseIdx)
1833 [&problem = this->simulator_.problem()](
const unsigned phase,
1834 const Context& ectx)
1836 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1837 return FluidSystem::density(fsInitial,
1839 ectx.intQuants.pvtRegionIndex());
1842 simulator_.episodeIndex() < 0 &&
1843 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1844 FluidSystem::phaseIsActive(gasPhaseIdx)
1846 Entry{PhaseEntry{&this->
invB_,
1847 [&problem = this->simulator_.problem()](
const unsigned phase,
1848 const Context& ectx)
1850 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1851 return FluidSystem::inverseFormationVolumeFactor(fsInitial,
1853 ectx.intQuants.pvtRegionIndex());
1856 simulator_.episodeIndex() < 0 &&
1857 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1858 FluidSystem::phaseIsActive(gasPhaseIdx)
1861 [&problem = this->simulator_.problem()](
const unsigned phase,
1862 const Context& ectx)
1864 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1865 return FluidSystem::viscosity(fsInitial,
1867 ectx.intQuants.pvtRegionIndex());
1870 simulator_.episodeIndex() < 0 &&
1871 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1872 FluidSystem::phaseIsActive(gasPhaseIdx)
1880 if constexpr (getPropValue<TypeTag, Properties::EnableGeochemistry>()) {
1882 this->extractors_.emplace_back(
1884 &gM = this->simulator_.problem().geochemistryModel()](
const Context& ectx)
1886 gC.assignSpeciesConcentrations(
1888 [gIdx = ectx.globalDofIdx, &gM](
const unsigned speciesIdx)
1889 {
return gM.speciesConcentration(speciesIdx, gIdx); }
1891 gC.assignMineralConcentrations(
1893 [gIdx = ectx.globalDofIdx, &gM](
const unsigned mineralIdx)
1894 {
return gM.mineralConcentration(mineralIdx, gIdx); }
1896 gC.assignPH(ectx.globalDofIdx, gM.PH(ectx.globalDofIdx));
1904 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
1905 if (this->
mech_.allocated()) {
1906 this->extractors_.emplace_back(
1907 [&mech = this->
mech_,
1908 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1910 mech.assignDelStress(ectx.globalDofIdx,
1911 model.delstress(ectx.globalDofIdx));
1913 mech.assignDisplacement(ectx.globalDofIdx,
1914 model.disp(ectx.globalDofIdx,
true));
1917 mech.assignFracStress(ectx.globalDofIdx,
1918 model.fractureStress(ectx.globalDofIdx));
1920 mech.assignLinStress(ectx.globalDofIdx,
1921 model.linstress(ectx.globalDofIdx));
1923 mech.assignPotentialForces(ectx.globalDofIdx,
1924 model.mechPotentialForce(ectx.globalDofIdx),
1925 model.mechPotentialPressForce(ectx.globalDofIdx),
1926 model.mechPotentialTempForce(ectx.globalDofIdx));
1928 mech.assignStrain(ectx.globalDofIdx,
1929 model.strain(ectx.globalDofIdx,
true));
1932 mech.assignStress(ectx.globalDofIdx,
1933 model.stress(ectx.globalDofIdx,
true));
1942 void setupBlockExtractors_(
const bool isSubStep,
1943 const int reportStepNum)
1946 using Context =
typename BlockExtractor::Context;
1947 using PhaseEntry =
typename BlockExtractor::PhaseEntry;
1948 using ScalarEntry =
typename BlockExtractor::ScalarEntry;
1950 using namespace std::string_view_literals;
1952 const auto pressure_handler =
1953 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1954 [](
const Context& ectx)
1956 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1957 return getValue(ectx.fs.pressure(oilPhaseIdx));
1959 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1960 return getValue(ectx.fs.pressure(gasPhaseIdx));
1963 return getValue(ectx.fs.pressure(waterPhaseIdx));
1969 const auto handlers = std::array{
1971 Entry{PhaseEntry{std::array{
1972 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1973 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1975 [](
const unsigned phaseIdx,
const Context& ectx)
1977 return getValue(ectx.fs.saturation(phaseIdx));
1981 Entry{ScalarEntry{
"BNSAT",
1982 [](
const Context& ectx)
1984 if constexpr (enableSolvent) {
1985 return ectx.intQuants.solventSaturation().value();
1993 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1994 [](
const Context& ectx)
1996 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1997 return getValue(ectx.fs.temperature(oilPhaseIdx));
1999 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2000 return getValue(ectx.fs.temperature(gasPhaseIdx));
2003 return getValue(ectx.fs.temperature(waterPhaseIdx));
2008 Entry{PhaseEntry{std::array{
2009 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
2010 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
2012 [](
const unsigned phaseIdx,
const Context& ectx)
2014 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
2018 Entry{ScalarEntry{
"BKROG",
2019 [&problem = this->simulator_.problem()](
const Context& ectx)
2021 const auto& materialParams =
2022 problem.materialLawParams(ectx.elemCtx,
2025 return getValue(MaterialLaw::template
2026 relpermOilInOilGasSystem<Evaluation>(materialParams,
2031 Entry{ScalarEntry{
"BKROW",
2032 [&problem = this->simulator_.problem()](
const Context& ectx)
2034 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
2037 return getValue(MaterialLaw::template
2038 relpermOilInOilWaterSystem<Evaluation>(materialParams,
2043 Entry{ScalarEntry{
"BWPC",
2044 [](
const Context& ectx)
2046 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2047 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
2048 getValue(ectx.fs.pressure(waterPhaseIdx));
2050 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2051 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2052 getValue(ectx.fs.pressure(waterPhaseIdx));
2060 Entry{ScalarEntry{
"BGPC",
2061 [](
const Context& ectx)
2063 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2064 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2065 getValue(ectx.fs.pressure(oilPhaseIdx));
2067 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
2068 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2069 getValue(ectx.fs.pressure(waterPhaseIdx));
2077 Entry{ScalarEntry{
"BWPR",
2078 [](
const Context& ectx)
2080 return getValue(ectx.fs.pressure(waterPhaseIdx));
2084 Entry{ScalarEntry{
"BGPR",
2085 [](
const Context& ectx)
2087 return getValue(ectx.fs.pressure(gasPhaseIdx));
2091 Entry{PhaseEntry{std::array{
2092 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
2093 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
2095 [](
const unsigned phaseIdx,
const Context& ectx)
2097 return getValue(ectx.fs.viscosity(phaseIdx));
2101 Entry{PhaseEntry{std::array{
2102 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
2103 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
2105 [](
const unsigned phaseIdx,
const Context& ectx)
2107 return getValue(ectx.fs.density(phaseIdx));
2111 Entry{ScalarEntry{
"BFLOGI",
2113 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2115 const unsigned index = !flowsC.blockFlows().empty() ?
2116 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2117 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx) : ectx.globalDofIdx;
2118 return flowsC.getFlow(index, Dir::XPlus, gasCompIdx);
2122 Entry{ScalarEntry{
"BFLOGI-",
2124 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2126 const unsigned index = !flowsC.blockFlows().empty() ?
2127 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2128 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx) : ectx.globalDofIdx;
2129 return flowsC.getFlow(index, Dir::XMinus, gasCompIdx);
2133 Entry{ScalarEntry{
"BFLOGJ",
2135 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2137 const unsigned index = !flowsC.blockFlows().empty() ?
2138 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2139 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx) : ectx.globalDofIdx;
2140 return flowsC.getFlow(index, Dir::YPlus, gasCompIdx);
2144 Entry{ScalarEntry{
"BFLOGJ-",
2146 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2148 const unsigned index = !flowsC.blockFlows().empty() ?
2149 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2150 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx) : ectx.globalDofIdx;
2151 return flowsC.getFlow(index, Dir::YMinus, gasCompIdx);
2155 Entry{ScalarEntry{
"BFLOGK",
2157 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2159 const unsigned index = !flowsC.blockFlows().empty() ?
2160 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2161 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx) : ectx.globalDofIdx;
2162 return flowsC.getFlow(index, Dir::ZPlus, gasCompIdx);
2166 Entry{ScalarEntry{
"BFLOGK-",
2168 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2170 const unsigned index = !flowsC.blockFlows().empty() ?
2171 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2172 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx) : ectx.globalDofIdx;
2173 return flowsC.getFlow(index, Dir::ZMinus, gasCompIdx);
2177 Entry{ScalarEntry{
"BFLOOI",
2179 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2181 const unsigned index = !flowsC.blockFlows().empty() ?
2182 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2183 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx) : ectx.globalDofIdx;
2184 return flowsC.getFlow(index, Dir::XPlus, oilCompIdx);
2188 Entry{ScalarEntry{
"BFLOOI-",
2190 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2192 const unsigned index = !flowsC.blockFlows().empty() ?
2193 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2194 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx) : ectx.globalDofIdx;
2195 return flowsC.getFlow(index, Dir::XMinus, oilCompIdx);
2199 Entry{ScalarEntry{
"BFLOOJ",
2201 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2203 const unsigned index = !flowsC.blockFlows().empty() ?
2204 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2205 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx) : ectx.globalDofIdx;
2206 return flowsC.getFlow(index, Dir::YPlus, oilCompIdx);
2210 Entry{ScalarEntry{
"BFLOOJ-",
2212 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2214 const unsigned index = !flowsC.blockFlows().empty() ?
2215 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2216 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx) : ectx.globalDofIdx;
2217 return flowsC.getFlow(index, Dir::YMinus, oilCompIdx);
2221 Entry{ScalarEntry{
"BFLOOK",
2223 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2225 const unsigned index = !flowsC.blockFlows().empty() ?
2226 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2227 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx) : ectx.globalDofIdx;
2228 return flowsC.getFlow(index, Dir::ZPlus, oilCompIdx);
2232 Entry{ScalarEntry{
"BFLOOK-",
2234 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2236 const unsigned index = !flowsC.blockFlows().empty() ?
2237 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2238 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx) : ectx.globalDofIdx;
2239 return flowsC.getFlow(index, Dir::ZMinus, oilCompIdx);
2243 Entry{ScalarEntry{
"BFLOWI",
2245 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2247 const unsigned index = !flowsC.blockFlows().empty() ?
2248 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2249 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx) : ectx.globalDofIdx;
2250 return flowsC.getFlow(index, Dir::XPlus, waterCompIdx);
2254 Entry{ScalarEntry{
"BFLOWI-",
2256 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2258 const unsigned index = !flowsC.blockFlows().empty() ?
2259 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2260 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx) : ectx.globalDofIdx;
2261 return flowsC.getFlow(index, Dir::XMinus, waterCompIdx);
2265 Entry{ScalarEntry{
"BFLOWJ",
2267 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2269 const unsigned index = !flowsC.blockFlows().empty() ?
2270 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2271 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx) : ectx.globalDofIdx;
2272 return flowsC.getFlow(index, Dir::YPlus, waterCompIdx);
2276 Entry{ScalarEntry{
"BFLOWJ-",
2278 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2280 const unsigned index = !flowsC.blockFlows().empty() ?
2281 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2282 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx) : ectx.globalDofIdx;
2283 return flowsC.getFlow(index, Dir::YMinus, waterCompIdx);
2287 Entry{ScalarEntry{
"BFLOWK",
2289 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2291 const unsigned index = !flowsC.blockFlows().empty() ?
2292 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2293 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx) : ectx.globalDofIdx;
2294 return flowsC.getFlow(index, Dir::ZPlus, waterCompIdx);
2298 Entry{ScalarEntry{
"BFLOWK-",
2300 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2302 const unsigned index = !flowsC.blockFlows().empty() ?
2303 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2304 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx) : ectx.globalDofIdx;
2305 return flowsC.getFlow(index, Dir::ZMinus, waterCompIdx);
2309 Entry{ScalarEntry{
"BVELGI",
2311 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2313 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2314 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx);
2315 return flowsC.getVelocity(index, Dir::XPlus, gasCompIdx);
2319 Entry{ScalarEntry{
"BVELGI-",
2321 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2323 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2324 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx);
2325 return flowsC.getVelocity(index, Dir::XMinus, gasCompIdx);
2329 Entry{ScalarEntry{
"BVELGJ",
2331 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2333 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2334 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx);
2335 return flowsC.getVelocity(index, Dir::YPlus, gasCompIdx);
2339 Entry{ScalarEntry{
"BVELGJ-",
2341 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2343 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2344 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx);
2345 return flowsC.getVelocity(index, Dir::YMinus, gasCompIdx);
2349 Entry{ScalarEntry{
"BVELGK",
2351 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2353 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2354 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx);
2355 return flowsC.getVelocity(index, Dir::ZPlus, gasCompIdx);
2359 Entry{ScalarEntry{
"BVELGK-",
2361 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2363 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2364 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx);
2365 return flowsC.getVelocity(index, Dir::ZMinus, gasCompIdx);
2369 Entry{ScalarEntry{
"BVELOI",
2371 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2373 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2374 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx);
2375 return flowsC.getVelocity(index, Dir::XPlus, oilCompIdx);
2379 Entry{ScalarEntry{
"BVELOI-",
2381 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2383 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2384 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx);
2385 return flowsC.getVelocity(index, Dir::XMinus, oilCompIdx);
2389 Entry{ScalarEntry{
"BVELOJ",
2391 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2393 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2394 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx);
2395 return flowsC.getVelocity(index, Dir::YPlus, oilCompIdx);
2399 Entry{ScalarEntry{
"BVELOJ-",
2401 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2403 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2404 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx);
2405 return flowsC.getVelocity(index, Dir::YMinus, oilCompIdx);
2409 Entry{ScalarEntry{
"BVELOK",
2411 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2413 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2414 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx);
2415 return flowsC.getVelocity(index, Dir::ZPlus, oilCompIdx);
2419 Entry{ScalarEntry{
"BVELOK-",
2421 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2423 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2424 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx);
2425 return flowsC.getVelocity(index, Dir::ZMinus, oilCompIdx);
2429 Entry{ScalarEntry{
"BVELWI",
2431 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2433 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2434 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx);
2435 return flowsC.getVelocity(index, Dir::XPlus, waterCompIdx);
2439 Entry{ScalarEntry{
"BVELWI-",
2441 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2443 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2444 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx);
2445 return flowsC.getVelocity(index, Dir::XMinus, waterCompIdx);
2449 Entry{ScalarEntry{
"BVELWJ",
2451 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2453 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2454 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx);
2455 return flowsC.getVelocity(index, Dir::YPlus, waterCompIdx);
2459 Entry{ScalarEntry{
"BVELWJ-",
2461 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2463 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2464 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx);
2465 return flowsC.getVelocity(index, Dir::YMinus, waterCompIdx);
2469 Entry{ScalarEntry{
"BVELWK",
2471 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2473 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2474 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx);
2475 return flowsC.getVelocity(index, Dir::ZPlus, waterCompIdx);
2479 Entry{ScalarEntry{
"BVELWK-",
2481 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2483 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2484 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx);
2485 return flowsC.getVelocity(index, Dir::ZMinus, waterCompIdx);
2489 Entry{ScalarEntry{
"BRPV",
2490 [&model = this->simulator_.model()](
const Context& ectx)
2492 return getValue(ectx.intQuants.porosity()) *
2493 model.dofTotalVolume(ectx.globalDofIdx);
2497 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
2498 [&model = this->simulator_.model()](
const unsigned phaseIdx,
2499 const Context& ectx)
2501 return getValue(ectx.fs.saturation(phaseIdx)) *
2502 getValue(ectx.intQuants.porosity()) *
2503 model.dofTotalVolume(ectx.globalDofIdx);
2507 Entry{ScalarEntry{
"BRS",
2508 [](
const Context& ectx)
2510 return getValue(ectx.fs.Rs());
2514 Entry{ScalarEntry{
"BRV",
2515 [](
const Context& ectx)
2517 return getValue(ectx.fs.Rv());
2521 Entry{ScalarEntry{
"BOIP",
2522 [&model = this->simulator_.model()](
const Context& ectx)
2524 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
2525 getValue(ectx.fs.saturation(oilPhaseIdx)) +
2526 getValue(ectx.fs.Rv()) *
2527 getValue(ectx.fs.invB(gasPhaseIdx)) *
2528 getValue(ectx.fs.saturation(gasPhaseIdx))) *
2529 model.dofTotalVolume(ectx.globalDofIdx) *
2530 getValue(ectx.intQuants.porosity());
2534 Entry{ScalarEntry{
"BGIP",
2535 [&model = this->simulator_.model()](
const Context& ectx)
2537 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2538 getValue(ectx.fs.saturation(gasPhaseIdx));
2540 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2541 result += getValue(ectx.fs.Rs()) *
2542 getValue(ectx.fs.invB(oilPhaseIdx)) *
2543 getValue(ectx.fs.saturation(oilPhaseIdx));
2546 result += getValue(ectx.fs.Rsw()) *
2547 getValue(ectx.fs.invB(waterPhaseIdx)) *
2548 getValue(ectx.fs.saturation(waterPhaseIdx));
2552 model.dofTotalVolume(ectx.globalDofIdx) *
2553 getValue(ectx.intQuants.porosity());
2557 Entry{ScalarEntry{
"BWIP",
2558 [&model = this->simulator_.model()](
const Context& ectx)
2560 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2561 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2562 model.dofTotalVolume(ectx.globalDofIdx) *
2563 getValue(ectx.intQuants.porosity());
2567 Entry{ScalarEntry{
"BOIPL",
2568 [&model = this->simulator_.model()](
const Context& ectx)
2570 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2571 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2572 model.dofTotalVolume(ectx.globalDofIdx) *
2573 getValue(ectx.intQuants.porosity());
2577 Entry{ScalarEntry{
"BGIPL",
2578 [&model = this->simulator_.model()](
const Context& ectx)
2581 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2582 result = getValue(ectx.fs.Rs()) *
2583 getValue(ectx.fs.invB(oilPhaseIdx)) *
2584 getValue(ectx.fs.saturation(oilPhaseIdx));
2587 result = getValue(ectx.fs.Rsw()) *
2588 getValue(ectx.fs.invB(waterPhaseIdx)) *
2589 getValue(ectx.fs.saturation(waterPhaseIdx));
2592 model.dofTotalVolume(ectx.globalDofIdx) *
2593 getValue(ectx.intQuants.porosity());
2597 Entry{ScalarEntry{
"BGIPG",
2598 [&model = this->simulator_.model()](
const Context& ectx)
2600 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2601 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2602 model.dofTotalVolume(ectx.globalDofIdx) *
2603 getValue(ectx.intQuants.porosity());
2607 Entry{ScalarEntry{
"BOIPG",
2608 [&model = this->simulator_.model()](
const Context& ectx)
2610 return getValue(ectx.fs.Rv()) *
2611 getValue(ectx.fs.invB(gasPhaseIdx)) *
2612 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2613 model.dofTotalVolume(ectx.globalDofIdx) *
2614 getValue(ectx.intQuants.porosity());
2618 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2619 [&simConfig = this->
eclState_.getSimulationConfig(),
2620 &grav = this->simulator_.problem().gravity(),
2622 &problem = this->simulator_.problem(),
2623 ®ions = this->
regions_](
const unsigned phaseIdx,
const Context& ectx)
2626 phase.ix = phaseIdx;
2635 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2638 const auto region = RegionPhasePoreVolAverage::Region {
2639 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2642 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2644 const auto press = getValue(ectx.fs.pressure(phase.ix));
2645 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2646 return press - density*dz*grav[GridView::dimensionworld - 1];
2650 Entry{ScalarEntry{
"BAMIP",
2651 [&model = this->simulator_.model()](
const Context& ectx)
2653 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2654 ectx.intQuants.pvtRegionIndex());
2655 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2656 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2658 model.dofTotalVolume(ectx.globalDofIdx) *
2659 getValue(ectx.intQuants.porosity());
2663 Entry{ScalarEntry{
"BMMIP",
2664 [&model = this->simulator_.model()](
const Context& ectx)
2666 if constexpr (enableBioeffects) {
2667 return getValue(ectx.intQuants.microbialConcentration()) *
2668 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2669 getValue(ectx.intQuants.porosity()) *
2670 model.dofTotalVolume(ectx.globalDofIdx);
2678 Entry{ScalarEntry{
"BMOIP",
2679 [&model = this->simulator_.model()](
const Context& ectx)
2681 if constexpr (enableBioeffects) {
2682 return getValue(ectx.intQuants.oxygenConcentration()) *
2683 getValue(ectx.intQuants.porosity()) *
2684 model.dofTotalVolume(ectx.globalDofIdx);
2692 Entry{ScalarEntry{
"BMUIP",
2693 [&model = this->simulator_.model()](
const Context& ectx)
2695 if constexpr (enableBioeffects) {
2696 return getValue(ectx.intQuants.ureaConcentration()) *
2697 getValue(ectx.intQuants.porosity()) *
2698 model.dofTotalVolume(ectx.globalDofIdx);
2706 Entry{ScalarEntry{
"BMBIP",
2707 [&model = this->simulator_.model()](
const Context& ectx)
2709 if constexpr (enableBioeffects) {
2710 return model.dofTotalVolume(ectx.globalDofIdx) *
2711 getValue(ectx.intQuants.biofilmMass());
2719 Entry{ScalarEntry{
"BMCIP",
2720 [&model = this->simulator_.model()](
const Context& ectx)
2722 if constexpr (enableBioeffects) {
2723 return model.dofTotalVolume(ectx.globalDofIdx) *
2724 getValue(ectx.intQuants.calciteMass());
2732 Entry{ScalarEntry{
"BGMIP",
2733 [&model = this->simulator_.model()](
const Context& ectx)
2735 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2736 getValue(ectx.fs.saturation(gasPhaseIdx));
2738 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2739 result += getValue(ectx.fs.Rs()) *
2740 getValue(ectx.fs.invB(oilPhaseIdx)) *
2741 getValue(ectx.fs.saturation(oilPhaseIdx));
2744 result += getValue(ectx.fs.Rsw()) *
2745 getValue(ectx.fs.invB(waterPhaseIdx)) *
2746 getValue(ectx.fs.saturation(waterPhaseIdx));
2748 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2749 ectx.intQuants.pvtRegionIndex());
2751 model.dofTotalVolume(ectx.globalDofIdx) *
2752 getValue(ectx.intQuants.porosity()) *
2757 Entry{ScalarEntry{
"BGMGP",
2758 [&model = this->simulator_.model()](
const Context& ectx)
2760 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2761 ectx.intQuants.pvtRegionIndex());
2762 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2763 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2764 model.dofTotalVolume(ectx.globalDofIdx) *
2765 getValue(ectx.intQuants.porosity()) *
2770 Entry{ScalarEntry{
"BGMDS",
2771 [&model = this->simulator_.model()](
const Context& ectx)
2774 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2775 result = getValue(ectx.fs.Rs()) *
2776 getValue(ectx.fs.invB(oilPhaseIdx)) *
2777 getValue(ectx.fs.saturation(oilPhaseIdx));
2780 result = getValue(ectx.fs.Rsw()) *
2781 getValue(ectx.fs.invB(waterPhaseIdx)) *
2782 getValue(ectx.fs.saturation(waterPhaseIdx));
2784 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2785 ectx.intQuants.pvtRegionIndex());
2787 model.dofTotalVolume(ectx.globalDofIdx) *
2788 getValue(ectx.intQuants.porosity()) *
2793 Entry{ScalarEntry{
"BGMST",
2794 [&model = this->simulator_.model(),
2795 &problem = this->simulator_.problem()](
const Context& ectx)
2797 const auto& scaledDrainageInfo = problem.materialLawManager()
2798 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2799 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2800 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2801 if (problem.materialLawManager()->enableHysteresis()) {
2802 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2803 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2804 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2806 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2807 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2808 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2809 return (1.0 - xgW) *
2810 model.dofTotalVolume(ectx.globalDofIdx) *
2811 getValue(ectx.intQuants.porosity()) *
2812 getValue(ectx.fs.density(gasPhaseIdx)) *
2813 std::min(strandedGas, sg);
2817 Entry{ScalarEntry{
"BGMUS",
2818 [&model = this->simulator_.model(),
2819 &problem = this->simulator_.problem()](
const Context& ectx)
2821 const auto& scaledDrainageInfo = problem.materialLawManager()
2822 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2823 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2824 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2825 if (problem.materialLawManager()->enableHysteresis()) {
2826 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2827 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2828 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2830 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2831 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2832 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2833 return (1.0 - xgW) *
2834 model.dofTotalVolume(ectx.globalDofIdx) *
2835 getValue(ectx.intQuants.porosity()) *
2836 getValue(ectx.fs.density(gasPhaseIdx)) *
2837 std::max(Scalar{0.0}, sg - strandedGas);
2841 Entry{ScalarEntry{
"BGMTR",
2842 [&model = this->simulator_.model(),
2843 &problem = this->simulator_.problem()](
const Context& ectx)
2845 const auto& scaledDrainageInfo = problem.materialLawManager()
2846 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2847 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2848 if (problem.materialLawManager()->enableHysteresis()) {
2849 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2850 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2852 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2853 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2854 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2855 return (1.0 - xgW) *
2856 model.dofTotalVolume(ectx.globalDofIdx) *
2857 getValue(ectx.intQuants.porosity()) *
2858 getValue(ectx.fs.density(gasPhaseIdx)) *
2859 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2863 Entry{ScalarEntry{
"BGMMO",
2864 [&model = this->simulator_.model(),
2865 &problem = this->simulator_.problem()](
const Context& ectx)
2867 const auto& scaledDrainageInfo = problem.materialLawManager()
2868 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2869 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2870 if (problem.materialLawManager()->enableHysteresis()) {
2871 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2872 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2874 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2875 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2876 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2877 return (1.0 - xgW) *
2878 model.dofTotalVolume(ectx.globalDofIdx) *
2879 getValue(ectx.intQuants.porosity()) *
2880 getValue(ectx.fs.density(gasPhaseIdx)) *
2881 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2885 Entry{ScalarEntry{
"BGKTR",
2886 [&model = this->simulator_.model(),
2887 &problem = this->simulator_.problem()](
const Context& ectx)
2889 const auto& scaledDrainageInfo = problem.materialLawManager()
2890 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2891 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2892 Scalar sgcr = scaledDrainageInfo.Sgcr;
2893 if (problem.materialLawManager()->enableHysteresis()) {
2894 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2895 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2901 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2902 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2903 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2904 return (1.0 - xgW) *
2905 model.dofTotalVolume(ectx.globalDofIdx) *
2906 getValue(ectx.intQuants.porosity()) *
2907 getValue(ectx.fs.density(gasPhaseIdx)) *
2908 getValue(ectx.fs.saturation(gasPhaseIdx));
2913 Entry{ScalarEntry{
"BGKMO",
2914 [&model = this->simulator_.model(),
2915 &problem = this->simulator_.problem()](
const Context& ectx)
2917 const auto& scaledDrainageInfo = problem.materialLawManager()
2918 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2919 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2920 Scalar sgcr = scaledDrainageInfo.Sgcr;
2921 if (problem.materialLawManager()->enableHysteresis()) {
2922 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2923 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2929 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2930 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2931 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2932 return (1.0 - xgW) *
2933 model.dofTotalVolume(ectx.globalDofIdx) *
2934 getValue(ectx.intQuants.porosity()) *
2935 getValue(ectx.fs.density(gasPhaseIdx)) *
2936 getValue(ectx.fs.saturation(gasPhaseIdx));
2941 Entry{ScalarEntry{
"BGCDI",
2942 [&model = this->simulator_.model(),
2943 &problem = this->simulator_.problem()](
const Context& ectx)
2945 const auto& scaledDrainageInfo = problem.materialLawManager()
2946 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2947 Scalar sgcr = scaledDrainageInfo.Sgcr;
2948 if (problem.materialLawManager()->enableHysteresis()) {
2949 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2950 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2952 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2953 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2954 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2955 return (1.0 - xgW) *
2956 model.dofTotalVolume(ectx.globalDofIdx) *
2957 getValue(ectx.intQuants.porosity()) *
2958 getValue(ectx.fs.density(gasPhaseIdx)) *
2959 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2960 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2964 Entry{ScalarEntry{
"BGCDM",
2965 [&model = this->simulator_.model(),
2966 &problem = this->simulator_.problem()](
const Context& ectx)
2968 const auto& scaledDrainageInfo = problem.materialLawManager()
2969 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2970 Scalar sgcr = scaledDrainageInfo.Sgcr;
2971 if (problem.materialLawManager()->enableHysteresis()) {
2972 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2973 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2975 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2976 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2977 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2978 return (1.0 - xgW) *
2979 model.dofTotalVolume(ectx.globalDofIdx) *
2980 getValue(ectx.intQuants.porosity()) *
2981 getValue(ectx.fs.density(gasPhaseIdx)) *
2982 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2983 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2987 Entry{ScalarEntry{
"BGKDI",
2988 [&model = this->simulator_.model(),
2989 &problem = this->simulator_.problem()](
const Context& ectx)
2991 const auto& scaledDrainageInfo = problem.materialLawManager()
2992 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2993 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2994 Scalar sgcr = scaledDrainageInfo.Sgcr;
2995 if (problem.materialLawManager()->enableHysteresis()) {
2996 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2997 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
3003 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
3004 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
3005 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
3006 return (1.0 - xgW) *
3007 model.dofTotalVolume(ectx.globalDofIdx) *
3008 getValue(ectx.intQuants.porosity()) *
3009 getValue(ectx.fs.density(gasPhaseIdx)) *
3010 getValue(ectx.fs.saturation(gasPhaseIdx)) /
3011 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
3016 Entry{ScalarEntry{
"BGKDM",
3017 [&model = this->simulator_.model(),
3018 &problem = this->simulator_.problem()](
const Context& ectx)
3020 const auto& scaledDrainageInfo = problem.materialLawManager()
3021 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
3022 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
3023 Scalar sgcr = scaledDrainageInfo.Sgcr;
3024 if (problem.materialLawManager()->enableHysteresis()) {
3025 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
3026 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
3032 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
3033 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
3034 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
3035 return (1.0 - xgW) *
3036 model.dofTotalVolume(ectx.globalDofIdx) *
3037 getValue(ectx.intQuants.porosity()) *
3038 getValue(ectx.fs.density(gasPhaseIdx)) *
3039 getValue(ectx.fs.saturation(gasPhaseIdx)) /
3040 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
3045 Entry{ScalarEntry{
"BWCD",
3046 [&model = this->simulator_.model()](
const Context& ectx)
3049 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
3050 result = getValue(ectx.fs.Rs()) *
3051 getValue(ectx.fs.invB(oilPhaseIdx)) *
3052 getValue(ectx.fs.saturation(oilPhaseIdx));
3055 result = getValue(ectx.fs.Rsw()) *
3056 getValue(ectx.fs.invB(waterPhaseIdx)) *
3057 getValue(ectx.fs.saturation(waterPhaseIdx));
3059 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
3060 ectx.intQuants.pvtRegionIndex());
3062 model.dofTotalVolume(ectx.globalDofIdx) *
3063 getValue(ectx.intQuants.porosity()) *
3065 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
3069 Entry{ScalarEntry{
"BWIPG",
3070 [&model = this->simulator_.model()](
const Context& ectx)
3072 Scalar result = 0.0;
3073 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
3074 result = getValue(ectx.fs.Rvw()) *
3075 getValue(ectx.fs.invB(gasPhaseIdx)) *
3076 getValue(ectx.fs.saturation(gasPhaseIdx));
3079 model.dofTotalVolume(ectx.globalDofIdx) *
3080 getValue(ectx.intQuants.porosity());
3084 Entry{ScalarEntry{
"BWIPL",
3085 [&model = this->simulator_.model()](
const Context& ectx)
3087 return getValue(ectx.fs.invB(waterPhaseIdx)) *
3088 getValue(ectx.fs.saturation(waterPhaseIdx)) *
3089 model.dofTotalVolume(ectx.globalDofIdx) *
3090 getValue(ectx.intQuants.porosity());
3099 if (reportStepNum > 0 && !isSubStep) {
3101 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
3102 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
3104 [&c = this->collectOnIORank_](
const int idx)
3105 {
return c.isCartIdxOnThisRank(idx); });
3107 const auto extraHandlers = std::array{
3116 const Simulator& simulator_;
3117 const CollectDataOnIORankType& collectOnIORank_;
3118 std::vector<typename Extractor::Entry> extractors_;
Declares the properties required by the black oil model.
Definition: CollectDataOnIORank.hpp:56
The base class for the element-centered finite-volume discretization scheme.
Definition: ecfvdiscretization.hh:160
void assignMicrobialMass(const unsigned globalDofIdx, const Scalar microbialMass)
void assignCalciteMass(const unsigned globalDofIdx, const Scalar calciteMass)
void assignCo2InWater(const unsigned globalDofIdx, const Scalar co2InWater, const Scalar mM)
void assignVolumesSurface(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip)
bool has(const Inplace::Phase phase) const
bool hasMicrobialMass() const
void assignWaterMass(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip, const Scalar rhoW)
void assignCo2InGas(const unsigned globalDofIdx, const Co2InGasInput &v)
bool hasOxygenMass() const
void assignVolumesReservoir(const unsigned globalDofIdx, const Scalar saltConcentration, const std::array< Scalar, numPhases > &fipr)
void assignPoreVolume(const unsigned globalDofIdx, const Scalar value)
void assignOxygenMass(const unsigned globalDofIdx, const Scalar oxygenMass)
void assignOilGasDistribution(const unsigned globalDofIdx, const Scalar gasInPlaceLiquid, const Scalar oilInPlaceGas)
void assignBiofilmMass(const unsigned globalDofIdx, const Scalar biofilmMass)
bool hasWaterMass() const
bool hasCo2InWater() const
void assignUreaMass(const unsigned globalDofIdx, const Scalar ureaMass)
bool hasCalciteMass() const
bool hasBiofilmMass() const
const std::vector< Scalar > & get(const Inplace::Phase phase) const
void assignGasWater(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip, const Scalar gasInPlaceWater, const Scalar waterInPlaceGas)
const std::vector< int > blockVelocity() const
Definition: FlowsContainer.hpp:103
Definition: GenericOutputBlackoilModule.hpp:78
std::map< std::pair< std::string, int >, double > blockData_
Definition: GenericOutputBlackoilModule.hpp:469
std::array< ScalarBuffer, numPhases > relativePermeability_
Definition: GenericOutputBlackoilModule.hpp:456
const Inplace * initialInplace() const
Definition: GenericOutputBlackoilModule.hpp:251
ScalarBuffer fluidPressure_
Definition: GenericOutputBlackoilModule.hpp:409
std::array< ScalarBuffer, numPhases > density_
Definition: GenericOutputBlackoilModule.hpp:454
ScalarBuffer saturatedOilFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:441
ScalarBuffer overburdenPressure_
Definition: GenericOutputBlackoilModule.hpp:415
ScalarBuffer gasDissolutionFactorInWater_
Definition: GenericOutputBlackoilModule.hpp:435
const EclipseState & eclState_
Definition: GenericOutputBlackoilModule.hpp:367
ScalarBuffer swmin_
Definition: GenericOutputBlackoilModule.hpp:431
ScalarBuffer rockCompPorvMultiplier_
Definition: GenericOutputBlackoilModule.hpp:439
RFTContainer< GetPropType< TypeTag, Properties::FluidSystem > > rftC_
Definition: GenericOutputBlackoilModule.hpp:466
bool computeFip_
Definition: GenericOutputBlackoilModule.hpp:391
ScalarBuffer dewPointPressure_
Definition: GenericOutputBlackoilModule.hpp:438
LogOutputHelper< Scalar > logOutput_
Definition: GenericOutputBlackoilModule.hpp:374
GeochemistryContainer< Scalar > geochemC_
Definition: GenericOutputBlackoilModule.hpp:458
std::vector< int > failedCellsPb_
Definition: GenericOutputBlackoilModule.hpp:400
ScalarBuffer permFact_
Definition: GenericOutputBlackoilModule.hpp:424
ScalarBuffer rsw_
Definition: GenericOutputBlackoilModule.hpp:412
ScalarBuffer pcog_
Definition: GenericOutputBlackoilModule.hpp:447
std::optional< RegionPhasePoreVolAverage > regionAvgDensity_
Definition: GenericOutputBlackoilModule.hpp:477
std::array< ScalarBuffer, numPhases > invB_
Definition: GenericOutputBlackoilModule.hpp:453
ScalarBuffer pSalt_
Definition: GenericOutputBlackoilModule.hpp:423
ScalarBuffer cFoam_
Definition: GenericOutputBlackoilModule.hpp:421
ScalarBuffer bubblePointPressure_
Definition: GenericOutputBlackoilModule.hpp:437
ScalarBuffer temperature_
Definition: GenericOutputBlackoilModule.hpp:410
ScalarBuffer ppcw_
Definition: GenericOutputBlackoilModule.hpp:432
FIPContainer< GetPropType< TypeTag, Properties::FluidSystem > > fipC_
Definition: GenericOutputBlackoilModule.hpp:393
ScalarBuffer rockCompTransMultiplier_
Definition: GenericOutputBlackoilModule.hpp:442
MechContainer< Scalar > mech_
Definition: GenericOutputBlackoilModule.hpp:450
ScalarBuffer dynamicPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:407
ScalarBuffer minimumOilPressure_
Definition: GenericOutputBlackoilModule.hpp:440
ScalarBuffer gasFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:403
std::array< ScalarBuffer, numPhases > residual_
Definition: GenericOutputBlackoilModule.hpp:462
void doAllocBuffers(unsigned bufferSize, unsigned reportStepNum, const bool substep, const bool log, const bool isRestart, const EclHysteresisConfig *hysteresisConfig, unsigned numOutputNnc=0, std::map< std::string, int > rstKeywords={})
ScalarBuffer shmax_
Definition: GenericOutputBlackoilModule.hpp:429
BioeffectsContainer< Scalar > bioeffectsC_
Definition: GenericOutputBlackoilModule.hpp:443
const Schedule & schedule_
Definition: GenericOutputBlackoilModule.hpp:368
FlowsContainer< GetPropType< TypeTag, Properties::FluidSystem > > flowsC_
Definition: GenericOutputBlackoilModule.hpp:464
ExtboContainer< Scalar > extboC_
Definition: GenericOutputBlackoilModule.hpp:425
void setupExtraBlockData(const std::size_t reportStepNum, std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer oilSaturationPressure_
Definition: GenericOutputBlackoilModule.hpp:416
InterRegFlowMap interRegionFlows_
Definition: GenericOutputBlackoilModule.hpp:373
ScalarBuffer pcgw_
Definition: GenericOutputBlackoilModule.hpp:445
ScalarBuffer cPolymer_
Definition: GenericOutputBlackoilModule.hpp:420
void setupBlockData(std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer rvw_
Definition: GenericOutputBlackoilModule.hpp:414
std::array< ScalarBuffer, numPhases > saturation_
Definition: GenericOutputBlackoilModule.hpp:452
std::unordered_map< std::string, std::vector< int > > regions_
Definition: GenericOutputBlackoilModule.hpp:394
ScalarBuffer rPorV_
Definition: GenericOutputBlackoilModule.hpp:408
ScalarBuffer oilVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:434
std::vector< int > failedCellsPd_
Definition: GenericOutputBlackoilModule.hpp:401
ScalarBuffer rs_
Definition: GenericOutputBlackoilModule.hpp:411
ScalarBuffer drsdtcon_
Definition: GenericOutputBlackoilModule.hpp:417
ScalarBuffer sSol_
Definition: GenericOutputBlackoilModule.hpp:418
std::map< std::pair< std::string, int >, double > extraBlockData_
Definition: GenericOutputBlackoilModule.hpp:472
ScalarBuffer pressureTimesPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:405
ScalarBuffer gasDissolutionFactor_
Definition: GenericOutputBlackoilModule.hpp:433
std::array< ScalarBuffer, numPhases > viscosity_
Definition: GenericOutputBlackoilModule.hpp:455
bool forceDisableFipOutput_
Definition: GenericOutputBlackoilModule.hpp:389
ScalarBuffer soMax_
Definition: GenericOutputBlackoilModule.hpp:426
ScalarBuffer sgmax_
Definition: GenericOutputBlackoilModule.hpp:428
ScalarBuffer somin_
Definition: GenericOutputBlackoilModule.hpp:430
ScalarBuffer hydrocarbonPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:404
ScalarBuffer waterVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:436
ScalarBuffer cSalt_
Definition: GenericOutputBlackoilModule.hpp:422
TracerContainer< GetPropType< TypeTag, Properties::FluidSystem > > tracerC_
Definition: GenericOutputBlackoilModule.hpp:460
ScalarBuffer rv_
Definition: GenericOutputBlackoilModule.hpp:413
ScalarBuffer pcow_
Definition: GenericOutputBlackoilModule.hpp:446
ScalarBuffer swMax_
Definition: GenericOutputBlackoilModule.hpp:427
CO2H2Container< Scalar > CO2H2C_
Definition: GenericOutputBlackoilModule.hpp:444
ScalarBuffer pressureTimesHydrocarbonVolume_
Definition: GenericOutputBlackoilModule.hpp:406
ScalarBuffer rswSol_
Definition: GenericOutputBlackoilModule.hpp:419
Inter-region flow accumulation maps for all region definition arrays.
Definition: InterRegFlows.hpp:179
void addConnection(const Cell &source, const Cell &destination, const data::InterRegFlowMap::FlowRates &rates)
void clear()
Clear all internal buffers, but preserve allocated capacity.
Output module for the results black oil model writing in ECL binary format.
Definition: OutputBlackoilModule.hpp:92
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition: OutputBlackoilModule.hpp:253
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:497
void setupExtractors(const bool isSubStep, const int reportStepNum)
Setup list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:234
void allocBuffers(const unsigned bufferSize, const unsigned reportStepNum, const bool substep, const bool log, const bool isRestart)
Allocate memory for the scalar fields we would like to write to ECL output files.
Definition: OutputBlackoilModule.hpp:212
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:460
void clearExtractors()
Clear list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:242
void outputFipAndResvLogToCSV(const std::size_t reportStepNum, const bool substep, const Parallel::Communication &comm)
Definition: OutputBlackoilModule.hpp:394
void assignToFluidState(FluidState &fs, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:521
void initHysteresisParams(Simulator &simulator, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:573
void updateFluidInPlace(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:638
OutputBlackOilModule(const Simulator &simulator, const SummaryConfig &smryCfg, const CollectDataOnIORankType &collectOnIORank)
Definition: OutputBlackoilModule.hpp:145
void outputFipAndResvLog(const Inplace &inplace, const std::size_t reportStepNum, double elapsed, boost::posix_time::ptime currentDate, const bool substep, const Parallel::Communication &comm)
Definition: OutputBlackoilModule.hpp:343
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputBlackoilModule.hpp:515
void processElementBlockData(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:299
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputBlackoilModule.hpp:507
void updateFluidInPlace(const unsigned globalDofIdx, const IntensiveQuantities &intQuants, const double totVolume)
Definition: OutputBlackoilModule.hpp:645
Declare the properties used by the infrastructure code of the finite volume discretizations.
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Phase
Phase indices for reservoir coupling, we currently only support black-oil phases (oil,...
Definition: ReservoirCoupling.hpp:165
constexpr void ignoreUnused(T &&...) noexcept
Utility to silence "unused variable" warnings in lambdas.
Definition: OutputBlackoilModule.hpp:81
Definition: blackoilbioeffectsmodules.hh:45
std::string moduleVersionName()
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:233
This file provides the infrastructure to retrieve run-time parameters.
The Opm property system, traits with inheritance.
Minimal characteristics of a cell from a simulation grid.
Definition: InterRegFlows.hpp:50