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>
52#include <opm/output/data/Cells.hpp>
53#include <opm/output/eclipse/EclipseIO.hpp>
54#include <opm/output/eclipse/Inplace.hpp>
75template <
class TypeTag>
76class EcfvDiscretization;
84template <
class TypeTag>
96 using FluidState =
typename IntensiveQuantities::FluidState;
98 using Element =
typename GridView::template Codim<0>::Entity;
99 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
102 using Dir = FaceDir::DirEnum;
109 static constexpr int conti0EqIdx = Indices::conti0EqIdx;
110 static constexpr int numPhases = FluidSystem::numPhases;
111 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
112 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
113 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
114 static constexpr int gasCompIdx = FluidSystem::gasCompIdx;
115 static constexpr int oilCompIdx = FluidSystem::oilCompIdx;
116 static constexpr int waterCompIdx = FluidSystem::waterCompIdx;
117 static constexpr EnergyModules energyModuleType = getPropValue<TypeTag, Properties::EnergyModuleType>();
118 enum { enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>() };
119 enum { enableMICP = Indices::enableMICP };
120 enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
121 enum { enableDisgasInWater = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
122 enum { enableDissolvedGas = Indices::compositionSwitchIdx >= 0 };
124 template<
class VectorType>
125 static Scalar value_or_zero(
int idx,
const VectorType& v)
130 return v.empty() ? 0.0 : v[idx];
135 const SummaryConfig& smryCfg,
137 :
BaseType(simulator.vanguard().eclState(),
138 simulator.vanguard().schedule(),
140 simulator.vanguard().summaryState(),
142 [this](const int idx)
143 {
return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
144 [&collectOnIORank](
const int idx)
145 {
return collectOnIORank.isCartIdxOnThisRank(idx); },
146 simulator.vanguard().grid().comm(),
147 energyModuleType == EnergyModules::FullyImplicitThermal ||
148 energyModuleType == EnergyModules::SequentialImplicitThermal,
149 energyModuleType == EnergyModules::ConstantTemperature,
150 getPropValue<TypeTag, Properties::EnableMech>(),
151 getPropValue<TypeTag, Properties::EnableSolvent>(),
152 getPropValue<TypeTag, Properties::EnablePolymer>(),
153 getPropValue<TypeTag, Properties::EnableFoam>(),
154 getPropValue<TypeTag, Properties::EnableBrine>(),
155 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
156 getPropValue<TypeTag, Properties::EnableExtbo>(),
157 getPropValue<TypeTag, Properties::EnableBioeffects>(),
158 getPropValue<TypeTag, Properties::EnableGeochemistry>())
159 , simulator_(simulator)
160 , collectOnIORank_(collectOnIORank)
162 for (
auto& region_pair : this->
regions_) {
163 this->createLocalRegion_(region_pair.second);
166 auto isCartIdxOnThisRank = [&collectOnIORank](
const int idx) {
167 return collectOnIORank.isCartIdxOnThisRank(idx);
172 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
173 const std::string msg =
"The output code does not support --owner-cells-first=false.";
174 if (collectOnIORank.isIORank()) {
177 OPM_THROW_NOLOG(std::runtime_error, msg);
180 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
181 auto rset = this->
eclState_.fieldProps().fip_regions();
182 rset.push_back(
"PVTNUM");
188 .emplace(this->simulator_.gridView().comm(),
189 FluidSystem::numPhases, rset,
190 [fp = std::cref(this->eclState_.fieldProps())]
191 (
const std::string& rsetName) ->
decltype(
auto)
192 { return fp.get().get_int(rsetName); });
202 const unsigned reportStepNum,
205 const bool isRestart)
211 const auto& problem = this->simulator_.problem();
218 &problem.materialLawManager()->hysteresisConfig(),
219 problem.eclWriter().getOutputNnc().front().size());
224 const int reportStepNum)
226 this->setupElementExtractors_();
227 this->setupBlockExtractors_(isSubStep, reportStepNum);
233 this->extractors_.clear();
234 this->blockExtractors_.clear();
235 this->extraBlockExtractors_.clear();
249 if (this->extractors_.empty()) {
253 const auto& matLawManager = simulator_.problem().materialLawManager();
256 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
257 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
258 const auto& fs = intQuants.fluidState();
261 elemCtx.globalSpaceIndex(dofIdx, 0),
262 elemCtx.primaryVars(dofIdx, 0).pvtRegionIndex(),
269 if (matLawManager->enableHysteresis()) {
270 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
271 matLawManager->oilWaterHysteresisParams(hysterParams.
somax,
276 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
277 matLawManager->gasOilHysteresisParams(hysterParams.
sgmax,
295 if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
299 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
301 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
302 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
304 const auto be_it = this->blockExtractors_.find(cartesianIdx);
305 const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
306 if (be_it == this->blockExtractors_.end() &&
307 bee_it == this->extraBlockExtractors_.end())
312 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
313 const auto& fs = intQuants.fluidState();
323 if (be_it != this->blockExtractors_.end()) {
326 if (bee_it != this->extraBlockExtractors_.end()) {
333 const std::size_t reportStepNum,
335 boost::posix_time::ptime currentDate,
340 if (comm.rank() != 0) {
345 std::unique_ptr<FIPConfig> fipSched;
346 if (reportStepNum > 0) {
347 const auto& rpt = this->
schedule_[reportStepNum-1].rpt_config.get();
348 fipSched = std::make_unique<FIPConfig>(rpt);
350 const FIPConfig& fipc = reportStepNum == 0 ? this->
eclState_.getEclipseConfig().fip()
355 this->
logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
358 this->
logOutput_.fip(inplace, initial_inplace,
"");
360 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
361 this->
logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
363 if (fipc.output(FIPConfig::OutputField::RESV))
367 if (fipc.output(FIPConfig::OutputField::FIP)) {
368 for (
const auto& reg : this->regions_) {
369 if (reg.first !=
"FIPNUM") {
370 std::ostringstream ss;
371 ss <<
"BAL" << reg.first.substr(3);
372 this->
logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
373 this->
logOutput_.fip(inplace, initial_inplace, reg.first);
375 if (fipc.output(FIPConfig::OutputField::RESV))
387 if (comm.rank() != 0) {
391 if ((reportStepNum == 0) && (!substep) &&
392 (this->
schedule_.initialReportConfiguration().has_value()) &&
393 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
395 std::ostringstream csv_stream;
401 this->
logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
403 for (
const auto& reg : this->regions_) {
404 if (reg.first !=
"FIPNUM") {
405 this->
logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
409 const IOConfig& io = this->
eclState_.getIOConfig();
410 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
412 std::ofstream outputFile(csv_fname);
414 outputFile << csv_stream.str();
448 template <
class ActiveIndex,
class CartesianIndex>
450 ActiveIndex&& activeIndex,
451 CartesianIndex&& cartesianIndex)
454 const auto identifyCell = [&activeIndex, &cartesianIndex](
const Element& elem)
457 const auto cellIndex = activeIndex(elem);
460 static_cast<int>(cellIndex),
461 cartesianIndex(cellIndex),
462 elem.partitionType() == Dune::InteriorEntity
466 const auto timeIdx = 0u;
467 const auto& stencil = elemCtx.stencil(timeIdx);
468 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
470 for (
auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
471 const auto& face = stencil.interiorFace(scvfIdx);
472 const auto left = identifyCell(stencil.element(face.interiorIndex()));
473 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
475 const auto rates = this->
476 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
509 template <
class Flu
idState>
512 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
516 fs.setSaturation(phaseIdx, this->
saturation_[phaseIdx][elemIdx]);
522 std::array<Scalar, numPhases> pc = {0};
523 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
524 MaterialLaw::capillaryPressures(pc, matParams, fs);
526 Valgrind::CheckDefined(pc);
528 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
529 if (!FluidSystem::phaseIsActive(phaseIdx))
532 if (Indices::oilEnabled)
533 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
534 else if (Indices::gasEnabled)
535 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
536 else if (Indices::waterEnabled)
538 fs.setPressure(phaseIdx, pressure);
542 if constexpr (energyModuleType != EnergyModules::NoTemperature) {
544 fs.setTemperature(this->temperature_[elemIdx]);
546 if constexpr (enableDissolvedGas) {
547 if (!this->
rs_.empty())
548 fs.setRs(this->rs_[elemIdx]);
549 if (!this->
rv_.empty())
550 fs.setRv(this->rv_[elemIdx]);
552 if constexpr (enableDisgasInWater) {
553 if (!this->
rsw_.empty())
554 fs.setRsw(this->rsw_[elemIdx]);
556 if constexpr (enableVapwat) {
557 if (!this->
rvw_.empty())
558 fs.setRvw(this->rvw_[elemIdx]);
564 if (!this->
soMax_.empty())
565 simulator.problem().setMaxOilSaturation(elemIdx, this->
soMax_[elemIdx]);
567 if (simulator.problem().materialLawManager()->enableHysteresis()) {
568 auto matLawManager = simulator.problem().materialLawManager();
570 if (FluidSystem::phaseIsActive(oilPhaseIdx)
571 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
576 if (matLawManager->enableNonWettingHysteresis()) {
577 if (!this->
soMax_.empty()) {
578 somax = this->
soMax_[elemIdx];
581 if (matLawManager->enableWettingHysteresis()) {
582 if (!this->
swMax_.empty()) {
583 swmax = this->
swMax_[elemIdx];
586 if (matLawManager->enablePCHysteresis()) {
587 if (!this->
swmin_.empty()) {
588 swmin = this->
swmin_[elemIdx];
591 matLawManager->setOilWaterHysteresisParams(
592 somax, swmax, swmin, elemIdx);
594 if (FluidSystem::phaseIsActive(oilPhaseIdx)
595 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
600 if (matLawManager->enableNonWettingHysteresis()) {
601 if (!this->
sgmax_.empty()) {
602 sgmax = this->
sgmax_[elemIdx];
605 if (matLawManager->enableWettingHysteresis()) {
606 if (!this->
shmax_.empty()) {
607 shmax = this->
shmax_[elemIdx];
610 if (matLawManager->enablePCHysteresis()) {
611 if (!this->
somin_.empty()) {
612 somin = this->
somin_[elemIdx];
615 matLawManager->setGasOilHysteresisParams(
616 sgmax, shmax, somin, elemIdx);
621 if (simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT")) {
622 simulator.problem().materialLawManager()
623 ->applyRestartSwatInit(elemIdx, this->
ppcw_[elemIdx]);
629 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
630 updateFluidInPlace_(elemCtx, dofIdx);
635 const IntensiveQuantities& intQuants,
636 const double totVolume)
638 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
642 template <
typename T>
643 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
645 template <
typename,
class =
void>
646 struct HasGeoMech :
public std::false_type {};
648 template <
typename Problem>
650 Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
651 > :
public std::true_type {};
653 template <
typename,
class =
void>
654 struct HasGeochemistry :
public std::false_type {};
656 template <
typename Problem>
657 struct HasGeochemistry<
658 Problem, std::void_t<decltype(std::declval<Problem>().geochemistryModel())>
659 > :
public std::true_type {};
661 bool isDefunctParallelWell(
const std::string& wname)
const override
663 if (simulator_.gridView().comm().size() == 1)
665 const auto& parallelWells = simulator_.vanguard().parallelWells();
666 std::pair<std::string, bool> value {wname,
true};
667 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
668 return candidate == parallelWells.end() || *candidate != value;
671 bool isOwnedByCurrentRank(
const std::string& wname)
const override
673 return this->simulator_.problem().wellModel().isOwner(wname);
676 bool isOnCurrentRank(
const std::string& wname)
const override
678 return this->simulator_.problem().wellModel().hasLocalCells(wname);
681 void updateFluidInPlace_(
const ElementContext& elemCtx,
const unsigned dofIdx)
683 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
684 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
685 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
687 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
690 void updateFluidInPlace_(
const unsigned globalDofIdx,
691 const IntensiveQuantities& intQuants,
692 const double totVolume)
696 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
699 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
703 void createLocalRegion_(std::vector<int>& region)
709 region.resize(simulator_.gridView().size(0));
710 std::size_t elemIdx = 0;
711 for (
const auto& elem : elements(simulator_.gridView())) {
712 if (elem.partitionType() != Dune::InteriorEntity) {
720 template <
typename Flu
idState>
721 void aggregateAverageDensityContributions_(
const FluidState& fs,
722 const unsigned int globalDofIdx,
725 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
726 pvCellValue.porv = porv;
728 for (
auto phaseIdx = 0*FluidSystem::numPhases;
729 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
731 if (! FluidSystem::phaseIsActive(phaseIdx)) {
735 pvCellValue.value = getValue(fs.density(phaseIdx));
736 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
739 ->addCell(globalDofIdx,
760 data::InterRegFlowMap::FlowRates
761 getComponentSurfaceRates(
const ElementContext& elemCtx,
762 const Scalar faceArea,
763 const std::size_t scvfIdx,
764 const std::size_t timeIdx)
const
766 using Component = data::InterRegFlowMap::Component;
768 auto rates = data::InterRegFlowMap::FlowRates {};
770 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
772 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
774 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
775 const auto& up = elemCtx
776 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
778 const auto pvtReg = up.pvtRegionIndex();
780 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
781 (up.fluidState(), oilPhaseIdx, pvtReg));
783 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
785 rates[Component::Oil] += qO;
787 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
788 const auto Rs = getValue(
789 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
790 (up.fluidState(), pvtReg));
792 rates[Component::Gas] += qO *
Rs;
793 rates[Component::Disgas] += qO *
Rs;
797 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
798 const auto& up = elemCtx
799 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
801 const auto pvtReg = up.pvtRegionIndex();
803 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
804 (up.fluidState(), gasPhaseIdx, pvtReg));
806 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
808 rates[Component::Gas] += qG;
810 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
811 const auto Rv = getValue(
812 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
813 (up.fluidState(), pvtReg));
815 rates[Component::Oil] += qG *
Rv;
816 rates[Component::Vapoil] += qG *
Rv;
820 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
821 const auto& up = elemCtx
822 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
824 const auto pvtReg = up.pvtRegionIndex();
826 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
827 (up.fluidState(), waterPhaseIdx, pvtReg));
829 rates[Component::Water] +=
830 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
836 template <
typename Flu
idState>
837 Scalar hydroCarbonFraction(
const FluidState& fs)
const
839 if (this->
eclState_.runspec().co2Storage()) {
846 auto hydrocarbon = Scalar {0};
847 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
848 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
851 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
852 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
858 void updateTotalVolumesAndPressures_(
const unsigned globalDofIdx,
859 const IntensiveQuantities& intQuants,
860 const double totVolume)
862 const auto& fs = intQuants.fluidState();
864 const double pv = totVolume * intQuants.porosity().value();
865 const auto hydrocarbon = this->hydroCarbonFraction(fs);
869 totVolume * intQuants.referencePorosity());
876 !this->pressureTimesPoreVolume_.empty())
879 assert(this->
fipC_.
get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
881 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
883 getValue(fs.pressure(oilPhaseIdx)) * pv;
888 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
890 getValue(fs.pressure(gasPhaseIdx)) * pv;
895 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
897 getValue(fs.pressure(waterPhaseIdx)) * pv;
902 void updatePhaseInplaceVolumes_(
const unsigned globalDofIdx,
903 const IntensiveQuantities& intQuants,
904 const double totVolume)
906 std::array<Scalar, FluidSystem::numPhases> fip {};
907 std::array<Scalar, FluidSystem::numPhases> fipr{};
909 const auto& fs = intQuants.fluidState();
910 const auto pv = totVolume * intQuants.porosity().value();
912 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
913 if (!FluidSystem::phaseIsActive(phaseIdx)) {
917 const auto b = getValue(fs.invB(phaseIdx));
918 const auto s = getValue(fs.saturation(phaseIdx));
920 fipr[phaseIdx] = s * pv;
921 fip [phaseIdx] = b * fipr[phaseIdx];
926 fs.saltConcentration().value(),
929 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
930 FluidSystem::phaseIsActive(gasPhaseIdx))
932 this->updateOilGasDistribution(globalDofIdx, fs, fip);
935 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
936 FluidSystem::phaseIsActive(gasPhaseIdx))
938 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
941 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
944 this->updateCO2InGas(globalDofIdx, pv, intQuants);
948 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
949 FluidSystem::phaseIsActive(oilPhaseIdx)))
951 this->updateCO2InWater(globalDofIdx, pv, fs);
954 if constexpr(enableBioeffects) {
955 const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
956 getValue(fs.invB(waterPhaseIdx));
958 this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
961 this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
963 if constexpr(enableMICP) {
965 this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
968 this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
971 this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
978 this->updateWaterMass(globalDofIdx, fs, fip);
982 template <
typename Flu
idState,
typename FIPArray>
983 void updateOilGasDistribution(
const unsigned globalDofIdx,
984 const FluidState& fs,
988 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
989 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
994 template <
typename Flu
idState,
typename FIPArray>
995 void updateGasWaterDistribution(
const unsigned globalDofIdx,
996 const FluidState& fs,
1000 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
1001 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
1006 template <
typename IntensiveQuantities>
1007 void updateCO2InGas(
const unsigned globalDofIdx,
1009 const IntensiveQuantities& intQuants)
1011 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
1012 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
1014 const auto& fs = intQuants.fluidState();
1015 Scalar sgcr = scaledDrainageInfo.Sgcr;
1016 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1017 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1018 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
1021 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1022 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
1023 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
1025 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1026 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1028 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams,
true);
1032 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1033 Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
1034 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
1035 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
1037 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1038 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1039 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1040 strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1044 const typename FIPContainer<FluidSystem>::Co2InGasInput v{
1048 getValue(fs.density(gasPhaseIdx)),
1049 FluidSystem::phaseIsActive(waterPhaseIdx)
1050 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1051 : FluidSystem::convertRvToXgO(getValue(fs.
Rv()), fs.pvtRegionIndex()),
1052 FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
1053 trappedGasSaturation,
1054 strandedGasSaturation,
1060 template <
typename Flu
idState>
1061 void updateCO2InWater(
const unsigned globalDofIdx,
1063 const FluidState& fs)
1065 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1066 ? this->co2InWaterFromOil(fs, pv)
1067 : this->co2InWaterFromWater(fs, pv);
1069 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1074 template <
typename Flu
idState>
1075 Scalar co2InWaterFromWater(
const FluidState& fs,
const double pv)
const
1077 const double rhow = getValue(fs.density(waterPhaseIdx));
1078 const double sw = getValue(fs.saturation(waterPhaseIdx));
1079 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1081 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1083 return xwG * pv * rhow * sw / mM;
1086 template <
typename Flu
idState>
1087 Scalar co2InWaterFromOil(
const FluidState& fs,
const double pv)
const
1089 const double rhoo = getValue(fs.density(oilPhaseIdx));
1090 const double so = getValue(fs.saturation(oilPhaseIdx));
1091 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1093 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1095 return xoG * pv * rhoo * so / mM;
1098 template <
typename Flu
idState,
typename FIPArray>
1099 void updateWaterMass(
const unsigned globalDofIdx,
1100 const FluidState& fs,
1104 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
1109 template <
typename IntensiveQuantities>
1110 void updateMicrobialMass(
const unsigned globalDofIdx,
1111 const IntensiveQuantities& intQuants,
1112 const double surfVolWat)
1114 const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
1119 template <
typename IntensiveQuantities>
1120 void updateOxygenMass(
const unsigned globalDofIdx,
1121 const IntensiveQuantities& intQuants,
1122 const double surfVolWat)
1124 const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
1129 template <
typename IntensiveQuantities>
1130 void updateUreaMass(
const unsigned globalDofIdx,
1131 const IntensiveQuantities& intQuants,
1132 const double surfVolWat)
1134 const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
1139 template <
typename IntensiveQuantities>
1140 void updateBiofilmMass(
const unsigned globalDofIdx,
1141 const IntensiveQuantities& intQuants,
1142 const double totVolume)
1144 const Scalar mass = totVolume * intQuants.biofilmMass().value();
1149 template <
typename IntensiveQuantities>
1150 void updateCalciteMass(
const unsigned globalDofIdx,
1151 const IntensiveQuantities& intQuants,
1152 const double totVolume)
1154 const Scalar mass = totVolume * intQuants.calciteMass().value();
1160 void setupElementExtractors_()
1162 using Entry =
typename Extractor::Entry;
1163 using Context =
typename Extractor::Context;
1164 using ScalarEntry =
typename Extractor::ScalarEntry;
1165 using PhaseEntry =
typename Extractor::PhaseEntry;
1167 const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
1168 const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
1170 auto extractors = std::array{
1172 [](
const unsigned phase,
const Context& ectx)
1173 {
return getValue(ectx.fs.saturation(phase)); }
1176 Entry{PhaseEntry{&this->
invB_,
1177 [](
const unsigned phase,
const Context& ectx)
1178 {
return getValue(ectx.fs.invB(phase)); }
1182 [](
const unsigned phase,
const Context& ectx)
1183 {
return getValue(ectx.fs.density(phase)); }
1187 [](
const unsigned phase,
const Context& ectx)
1188 {
return getValue(ectx.intQuants.relativePermeability(phase)); }
1192 [
this](
const unsigned phaseIdx,
const Context& ectx)
1194 if (this->
extboC_.allocated() && phaseIdx == oilPhaseIdx) {
1195 return getValue(ectx.intQuants.oilViscosity());
1197 else if (this->
extboC_.allocated() && phaseIdx == gasPhaseIdx) {
1198 return getValue(ectx.intQuants.gasViscosity());
1201 return getValue(ectx.fs.viscosity(phaseIdx));
1207 [&modelResid = this->simulator_.model().linearizer().residual()]
1208 (
const unsigned phaseIdx,
const Context& ectx)
1210 const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
1211 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
1212 return modelResid[ectx.globalDofIdx][activeCompIdx];
1218 [&problem = this->simulator_.problem()](
const Context& ectx)
1220 return problem.template
1221 rockCompPoroMultiplier<Scalar>(ectx.intQuants,
1227 [&problem = this->simulator_.problem()](
const Context& ectx)
1230 template rockCompTransMultiplier<Scalar>(ectx.intQuants,
1235 [&problem = this->simulator_.problem()](
const Context& ectx)
1237 return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
1238 problem.minOilPressure(ectx.globalDofIdx));
1244 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1248 FluidSystem::bubblePointPressure(ectx.fs,
1249 ectx.intQuants.pvtRegionIndex())
1251 }
catch (
const NumericalProblem&) {
1252 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1253 failedCells.push_back(cartesianIdx);
1261 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1265 FluidSystem::dewPointPressure(ectx.fs,
1266 ectx.intQuants.pvtRegionIndex())
1268 }
catch (
const NumericalProblem&) {
1269 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1270 failedCells.push_back(cartesianIdx);
1277 [&problem = simulator_.problem()](
const Context& ectx)
1278 {
return problem.overburdenPressure(ectx.globalDofIdx); }
1282 [](
const Context& ectx)
1283 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }
1286 Entry{ScalarEntry{&this->
sSol_,
1287 [](
const Context& ectx)
1288 {
return getValue(ectx.intQuants.solventSaturation()); }
1291 Entry{ScalarEntry{&this->
rswSol_,
1292 [](
const Context& ectx)
1293 {
return getValue(ectx.intQuants.rsSolw()); }
1297 [](
const Context& ectx)
1298 {
return getValue(ectx.intQuants.polymerConcentration()); }
1301 Entry{ScalarEntry{&this->
cFoam_,
1302 [](
const Context& ectx)
1303 {
return getValue(ectx.intQuants.foamConcentration()); }
1306 Entry{ScalarEntry{&this->
cSalt_,
1307 [](
const Context& ectx)
1308 {
return getValue(ectx.fs.saltConcentration()); }
1311 Entry{ScalarEntry{&this->
pSalt_,
1312 [](
const Context& ectx)
1313 {
return getValue(ectx.fs.saltSaturation()); }
1317 [](
const Context& ectx)
1318 {
return getValue(ectx.intQuants.permFactor()); }
1321 Entry{ScalarEntry{&this->
rPorV_,
1322 [&model = this->simulator_.model()](
const Context& ectx)
1324 const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
1325 return totVolume * getValue(ectx.intQuants.porosity());
1329 Entry{ScalarEntry{&this->
rs_,
1330 [](
const Context& ectx)
1331 {
return getValue(ectx.fs.Rs()); }
1334 Entry{ScalarEntry{&this->
rv_,
1335 [](
const Context& ectx)
1336 {
return getValue(ectx.fs.Rv()); }
1339 Entry{ScalarEntry{&this->
rsw_,
1340 [](
const Context& ectx)
1341 {
return getValue(ectx.fs.Rsw()); }
1344 Entry{ScalarEntry{&this->
rvw_,
1345 [](
const Context& ectx)
1346 {
return getValue(ectx.fs.Rvw()); }
1349 Entry{ScalarEntry{&this->
ppcw_,
1350 [&matLawManager = *this->simulator_.problem().materialLawManager()]
1351 (
const Context& ectx)
1353 return matLawManager.
1354 oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
1359 [&problem = this->simulator_.problem()](
const Context& ectx)
1361 return problem.drsdtcon(ectx.globalDofIdx,
1366 Entry{ScalarEntry{&this->
pcgw_,
1367 [](
const Context& ectx)
1369 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1370 getValue(ectx.fs.pressure(waterPhaseIdx));
1374 Entry{ScalarEntry{&this->
pcow_,
1375 [](
const Context& ectx)
1377 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1378 getValue(ectx.fs.pressure(waterPhaseIdx));
1382 Entry{ScalarEntry{&this->
pcog_,
1383 [](
const Context& ectx)
1385 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1386 getValue(ectx.fs.pressure(oilPhaseIdx));
1391 [](
const Context& ectx)
1393 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1395 return getValue(ectx.fs.pressure(oilPhaseIdx));
1397 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1399 return getValue(ectx.fs.pressure(gasPhaseIdx));
1403 return getValue(ectx.fs.pressure(waterPhaseIdx));
1409 [&problem = this->simulator_.problem()](
const Context& ectx)
1411 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1412 return FluidSystem::template
1413 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1421 [&problem = this->simulator_.problem()](
const Context& ectx)
1423 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1424 return FluidSystem::template
1425 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1433 [&problem = this->simulator_.problem()](
const Context& ectx)
1435 const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
1436 return FluidSystem::template
1437 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1445 [](
const Context& ectx)
1447 return FluidSystem::template
1448 saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
1455 [](
const Context& ectx)
1457 return 1.0 / FluidSystem::template
1458 inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1465 [](
const Context& ectx)
1467 return 1.0 / FluidSystem::template
1468 saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1475 [](
const Context& ectx)
1477 return FluidSystem::template
1478 saturationPressure<FluidState, Scalar>(ectx.fs,
1484 Entry{ScalarEntry{&this->
soMax_,
1485 [&problem = this->simulator_.problem()](
const Context& ectx)
1487 return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
1488 problem.maxOilSaturation(ectx.globalDofIdx));
1491 !hysteresisConfig.enableHysteresis()
1493 Entry{ScalarEntry{&this->
swMax_,
1494 [&problem = this->simulator_.problem()](
const Context& ectx)
1496 return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
1497 problem.maxWaterSaturation(ectx.globalDofIdx));
1500 !hysteresisConfig.enableHysteresis()
1502 Entry{ScalarEntry{&this->
soMax_,
1503 [](
const Context& ectx)
1504 {
return ectx.hParams.somax; }
1506 hysteresisConfig.enableHysteresis() &&
1507 hysteresisConfig.enableNonWettingHysteresis() &&
1508 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1509 FluidSystem::phaseIsActive(waterPhaseIdx)
1511 Entry{ScalarEntry{&this->
swMax_,
1512 [](
const Context& ectx)
1513 {
return ectx.hParams.swmax; }
1515 hysteresisConfig.enableHysteresis() &&
1516 hysteresisConfig.enableWettingHysteresis() &&
1517 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1518 FluidSystem::phaseIsActive(waterPhaseIdx)
1520 Entry{ScalarEntry{&this->
swmin_,
1521 [](
const Context& ectx)
1522 {
return ectx.hParams.swmin; }
1524 hysteresisConfig.enableHysteresis() &&
1525 hysteresisConfig.enablePCHysteresis() &&
1526 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1527 FluidSystem::phaseIsActive(waterPhaseIdx)
1529 Entry{ScalarEntry{&this->
sgmax_,
1530 [](
const Context& ectx)
1531 {
return ectx.hParams.sgmax; }
1533 hysteresisConfig.enableHysteresis() &&
1534 hysteresisConfig.enableNonWettingHysteresis() &&
1535 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1536 FluidSystem::phaseIsActive(gasPhaseIdx)
1538 Entry{ScalarEntry{&this->
shmax_,
1539 [](
const Context& ectx)
1540 {
return ectx.hParams.shmax; }
1542 hysteresisConfig.enableHysteresis() &&
1543 hysteresisConfig.enableWettingHysteresis() &&
1544 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1545 FluidSystem::phaseIsActive(gasPhaseIdx)
1547 Entry{ScalarEntry{&this->
somin_,
1548 [](
const Context& ectx)
1549 {
return ectx.hParams.somin; }
1551 hysteresisConfig.enableHysteresis() &&
1552 hysteresisConfig.enablePCHysteresis() &&
1553 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1554 FluidSystem::phaseIsActive(gasPhaseIdx)
1556 Entry{[&model = this->simulator_.model(),
this](
const Context& ectx)
1560 const auto porv = ectx.intQuants.referencePorosity()
1561 * model.dofTotalVolume(ectx.globalDofIdx);
1563 this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
1564 static_cast<double>(porv));
1567 Entry{[&extboC = this->
extboC_](
const Context& ectx)
1569 extboC.assignVolumes(ectx.globalDofIdx,
1570 ectx.intQuants.xVolume().value(),
1571 ectx.intQuants.yVolume().value());
1572 extboC.assignZFraction(ectx.globalDofIdx,
1573 ectx.intQuants.zFraction().value());
1575 const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
1576 getValue(ectx.fs.invB(oilPhaseIdx)) +
1577 getValue(ectx.fs.saturation(gasPhaseIdx)) *
1578 getValue(ectx.fs.invB(gasPhaseIdx)) *
1579 getValue(ectx.fs.Rv());
1580 const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1581 getValue(ectx.fs.invB(gasPhaseIdx)) *
1582 (1.0 - ectx.intQuants.yVolume().value()) +
1583 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1584 getValue(ectx.fs.invB(oilPhaseIdx)) *
1585 getValue(ectx.fs.Rs()) *
1586 (1.0 - ectx.intQuants.xVolume().value());
1587 const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1588 getValue(ectx.fs.invB(gasPhaseIdx)) *
1589 ectx.intQuants.yVolume().value() +
1590 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1591 getValue(ectx.fs.invB(oilPhaseIdx)) *
1592 getValue(ectx.fs.Rs()) *
1593 ectx.intQuants.xVolume().value();
1594 const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1595 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1596 const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
1597 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
1598 extboC.assignMassFractions(ectx.globalDofIdx,
1599 stdVolGas * rhoG / stdMassTotal,
1600 stdVolOil * rhoO / stdMassTotal,
1601 stdVolCo2 * rhoCO2 / stdMassTotal);
1604 Entry{[&bioeffectsC = this->
bioeffectsC_](
const Context& ectx)
1606 bioeffectsC.assign(ectx.globalDofIdx,
1607 ectx.intQuants.microbialConcentration().value(),
1608 ectx.intQuants.biofilmVolumeFraction().value());
1609 if (Indices::enableMICP) {
1610 bioeffectsC.assign(ectx.globalDofIdx,
1611 ectx.intQuants.oxygenConcentration().value(),
1612 ectx.intQuants.ureaConcentration().value(),
1613 ectx.intQuants.calciteVolumeFraction().value());
1617 Entry{[&runspec = this->
eclState_.runspec(),
1618 &CO2H2C = this->
CO2H2C_](
const Context& ectx)
1620 const auto xwg = FluidSystem::convertRswToXwG(getValue(ectx.fs.Rsw()), ectx.pvtRegionIdx);
1621 const auto xgw = FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.pvtRegionIdx);
1622 CO2H2C.assign(ectx.globalDofIdx,
1623 FluidSystem::convertXwGToxwG(xwg, ectx.pvtRegionIdx),
1624 FluidSystem::convertXgWToxgW(xgw, ectx.pvtRegionIdx),
1625 runspec.co2Storage());
1628 Entry{[&rftC = this->
rftC_,
1629 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1631 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1632 rftC.assign(cartesianIdx,
1633 [&fs = ectx.fs]() {
return getValue(fs.pressure(oilPhaseIdx)); },
1634 [&fs = ectx.fs]() {
return getValue(fs.saturation(waterPhaseIdx)); },
1635 [&fs = ectx.fs]() {
return getValue(fs.saturation(gasPhaseIdx)); });
1639 &tM = this->simulator_.problem().tracerModel()](
const Context& ectx)
1641 tC.assignFreeConcentrations(ectx.globalDofIdx,
1642 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1643 {
return tM.freeTracerConcentration(tracerIdx, gIdx); });
1644 tC.assignSolConcentrations(ectx.globalDofIdx,
1645 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1646 {
return tM.solTracerConcentration(tracerIdx, gIdx); });
1649 Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
1651 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1653 const auto gas_idx = Indices::gasEnabled ?
1654 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1655 const auto oil_idx = Indices::oilEnabled ?
1656 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1657 const auto water_idx = Indices::waterEnabled ?
1658 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1659 const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
1660 if (!flowsC.blockFlows().empty()) {
1661 const std::vector<int>& blockIdxs = flowsC.blockFlows();
1662 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1663 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1664 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1665 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1666 for (
const auto& flowsInfo : flowsInfos) {
1667 if (flowsInfo.faceId < 0) {
1670 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1671 if (!compEnabled[ii]) {
1674 if (flowsC.hasBlockFlowValue(cartesianIdx, flowsInfo.faceId, compIdxs[ii])) {
1675 flowsC.assignBlockFlows(flowsC.blockFlowsIds(cartesianIdx, flowsInfo.faceId, compIdxs[ii]),
1678 flowsInfo.flow[conti0EqIdx
1679 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1686 for (
const auto& flowsInfo : flowsInfos) {
1687 flowsC.assignFlows(ectx.globalDofIdx,
1690 value_or_zero(gas_idx, flowsInfo.flow),
1691 value_or_zero(oil_idx, flowsInfo.flow),
1692 value_or_zero(water_idx, flowsInfo.flow));
1695 }, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
1697 Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
1698 &flowsC = this->
flowsC_](
const Context& ectx)
1700 const auto gas_idx = Indices::gasEnabled ?
1701 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1702 const auto oil_idx = Indices::oilEnabled ?
1703 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1704 const auto water_idx = Indices::waterEnabled ?
1705 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1706 const auto& floresInfos = floresInf[ectx.globalDofIdx];
1707 for (
const auto& floresInfo : floresInfos) {
1708 flowsC.assignFlores(ectx.globalDofIdx,
1711 value_or_zero(gas_idx, floresInfo.flow),
1712 value_or_zero(oil_idx, floresInfo.flow),
1713 value_or_zero(water_idx, floresInfo.flow));
1715 }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
1717 Entry{[&velocityInf = this->simulator_.problem().model().linearizer().getVelocityInfo(),
1719 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1721 const auto& velocityInfos = velocityInf[ectx.globalDofIdx];
1722 const std::vector<int>& blockIdxs = flowsC.blockVelocity();
1723 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1724 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1725 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1726 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1727 for (
const auto& velocityInfo : velocityInfos) {
1728 if (velocityInfo.faceId < 0) {
1731 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1732 if (!compEnabled[ii]) {
1735 if (flowsC.hasBlockVelocityValue(cartesianIdx, velocityInfo.faceId, compIdxs[ii])) {
1736 flowsC.assignBlockVelocity(flowsC.blockVelocityIds(cartesianIdx, velocityInfo.faceId, compIdxs[ii]),
1737 velocityInfo.faceId,
1739 velocityInfo.velocity[conti0EqIdx
1740 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1746 !this->simulator_.problem().model().linearizer().getVelocityInfo().empty()
1753 Entry{ScalarEntry{&this->
rv_,
1754 [&problem = this->simulator_.problem()](
const Context& ectx)
1755 {
return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
1757 simulator_.episodeIndex() < 0 &&
1758 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1759 FluidSystem::phaseIsActive(gasPhaseIdx)
1761 Entry{ScalarEntry{&this->
rs_,
1762 [&problem = this->simulator_.problem()](
const Context& ectx)
1763 {
return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
1765 simulator_.episodeIndex() < 0 &&
1766 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1767 FluidSystem::phaseIsActive(gasPhaseIdx)
1769 Entry{ScalarEntry{&this->
rsw_,
1770 [&problem = this->simulator_.problem()](
const Context& ectx)
1771 {
return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
1773 simulator_.episodeIndex() < 0 &&
1774 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1775 FluidSystem::phaseIsActive(gasPhaseIdx)
1777 Entry{ScalarEntry{&this->
rvw_,
1778 [&problem = this->simulator_.problem()](
const Context& ectx)
1779 {
return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
1781 simulator_.episodeIndex() < 0 &&
1782 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1783 FluidSystem::phaseIsActive(gasPhaseIdx)
1787 [&problem = this->simulator_.problem()](
const unsigned phase,
1788 const Context& ectx)
1790 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1791 return FluidSystem::density(fsInitial,
1793 ectx.intQuants.pvtRegionIndex());
1796 simulator_.episodeIndex() < 0 &&
1797 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1798 FluidSystem::phaseIsActive(gasPhaseIdx)
1800 Entry{PhaseEntry{&this->
invB_,
1801 [&problem = this->simulator_.problem()](
const unsigned phase,
1802 const Context& ectx)
1804 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1805 return FluidSystem::inverseFormationVolumeFactor(fsInitial,
1807 ectx.intQuants.pvtRegionIndex());
1810 simulator_.episodeIndex() < 0 &&
1811 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1812 FluidSystem::phaseIsActive(gasPhaseIdx)
1815 [&problem = this->simulator_.problem()](
const unsigned phase,
1816 const Context& ectx)
1818 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1819 return FluidSystem::viscosity(fsInitial,
1821 ectx.intQuants.pvtRegionIndex());
1824 simulator_.episodeIndex() < 0 &&
1825 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1826 FluidSystem::phaseIsActive(gasPhaseIdx)
1834 if constexpr (getPropValue<TypeTag, Properties::EnableGeochemistry>()) {
1836 this->extractors_.emplace_back(
1838 &gM = this->simulator_.problem().geochemistryModel()](
const Context& ectx)
1840 gC.assignSpeciesConcentrations(
1842 [gIdx = ectx.globalDofIdx, &gM](
const unsigned speciesIdx)
1843 {
return gM.speciesConcentration(speciesIdx, gIdx); }
1845 gC.assignMineralConcentrations(
1847 [gIdx = ectx.globalDofIdx, &gM](
const unsigned mineralIdx)
1848 {
return gM.mineralConcentration(mineralIdx, gIdx); }
1850 gC.assignPH(ectx.globalDofIdx, gM.PH(ectx.globalDofIdx));
1858 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
1859 if (this->
mech_.allocated()) {
1860 this->extractors_.emplace_back(
1861 [&mech = this->
mech_,
1862 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1864 mech.assignDelStress(ectx.globalDofIdx,
1865 model.delstress(ectx.globalDofIdx));
1867 mech.assignDisplacement(ectx.globalDofIdx,
1868 model.disp(ectx.globalDofIdx,
true));
1871 mech.assignFracStress(ectx.globalDofIdx,
1872 model.fractureStress(ectx.globalDofIdx));
1874 mech.assignLinStress(ectx.globalDofIdx,
1875 model.linstress(ectx.globalDofIdx));
1877 mech.assignPotentialForces(ectx.globalDofIdx,
1878 model.mechPotentialForce(ectx.globalDofIdx),
1879 model.mechPotentialPressForce(ectx.globalDofIdx),
1880 model.mechPotentialTempForce(ectx.globalDofIdx));
1882 mech.assignStrain(ectx.globalDofIdx,
1883 model.strain(ectx.globalDofIdx,
true));
1886 mech.assignStress(ectx.globalDofIdx,
1887 model.stress(ectx.globalDofIdx,
true));
1896 void setupBlockExtractors_(
const bool isSubStep,
1897 const int reportStepNum)
1900 using Context =
typename BlockExtractor::Context;
1901 using PhaseEntry =
typename BlockExtractor::PhaseEntry;
1902 using ScalarEntry =
typename BlockExtractor::ScalarEntry;
1904 using namespace std::string_view_literals;
1906 const auto pressure_handler =
1907 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1908 [](
const Context& ectx)
1910 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1911 return getValue(ectx.fs.pressure(oilPhaseIdx));
1913 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1914 return getValue(ectx.fs.pressure(gasPhaseIdx));
1917 return getValue(ectx.fs.pressure(waterPhaseIdx));
1923 const auto handlers = std::array{
1925 Entry{PhaseEntry{std::array{
1926 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1927 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1929 [](
const unsigned phaseIdx,
const Context& ectx)
1931 return getValue(ectx.fs.saturation(phaseIdx));
1935 Entry{ScalarEntry{
"BNSAT",
1936 [](
const Context& ectx)
1938 return ectx.intQuants.solventSaturation().value();
1942 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1943 [](
const Context& ectx)
1945 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1946 return getValue(ectx.fs.temperature(oilPhaseIdx));
1948 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1949 return getValue(ectx.fs.temperature(gasPhaseIdx));
1952 return getValue(ectx.fs.temperature(waterPhaseIdx));
1957 Entry{PhaseEntry{std::array{
1958 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
1959 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
1961 [](
const unsigned phaseIdx,
const Context& ectx)
1963 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
1967 Entry{ScalarEntry{
"BKROG",
1968 [&problem = this->simulator_.problem()](
const Context& ectx)
1970 const auto& materialParams =
1971 problem.materialLawParams(ectx.elemCtx,
1974 return getValue(MaterialLaw::template
1975 relpermOilInOilGasSystem<Evaluation>(materialParams,
1980 Entry{ScalarEntry{
"BKROW",
1981 [&problem = this->simulator_.problem()](
const Context& ectx)
1983 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
1986 return getValue(MaterialLaw::template
1987 relpermOilInOilWaterSystem<Evaluation>(materialParams,
1992 Entry{ScalarEntry{
"BWPC",
1993 [](
const Context& ectx)
1995 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1996 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1997 getValue(ectx.fs.pressure(waterPhaseIdx));
1999 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2000 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2001 getValue(ectx.fs.pressure(waterPhaseIdx));
2009 Entry{ScalarEntry{
"BGPC",
2010 [](
const Context& ectx)
2012 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2013 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2014 getValue(ectx.fs.pressure(oilPhaseIdx));
2016 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
2017 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2018 getValue(ectx.fs.pressure(waterPhaseIdx));
2026 Entry{ScalarEntry{
"BWPR",
2027 [](
const Context& ectx)
2029 return getValue(ectx.fs.pressure(waterPhaseIdx));
2033 Entry{ScalarEntry{
"BGPR",
2034 [](
const Context& ectx)
2036 return getValue(ectx.fs.pressure(gasPhaseIdx));
2040 Entry{PhaseEntry{std::array{
2041 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
2042 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
2044 [](
const unsigned phaseIdx,
const Context& ectx)
2046 return getValue(ectx.fs.viscosity(phaseIdx));
2050 Entry{PhaseEntry{std::array{
2051 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
2052 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
2054 [](
const unsigned phaseIdx,
const Context& ectx)
2056 return getValue(ectx.fs.density(phaseIdx));
2060 Entry{ScalarEntry{
"BFLOGI",
2062 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2064 const unsigned index = !flowsC.blockFlows().empty() ?
2065 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2066 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx) : ectx.globalDofIdx;
2067 return flowsC.getFlow(index, Dir::XPlus, gasCompIdx);
2071 Entry{ScalarEntry{
"BFLOGI-",
2073 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2075 const unsigned index = !flowsC.blockFlows().empty() ?
2076 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2077 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx) : ectx.globalDofIdx;
2078 return flowsC.getFlow(index, Dir::XMinus, gasCompIdx);
2082 Entry{ScalarEntry{
"BFLOGJ",
2084 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2086 const unsigned index = !flowsC.blockFlows().empty() ?
2087 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2088 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx) : ectx.globalDofIdx;
2089 return flowsC.getFlow(index, Dir::YPlus, gasCompIdx);
2093 Entry{ScalarEntry{
"BFLOGJ-",
2095 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2097 const unsigned index = !flowsC.blockFlows().empty() ?
2098 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2099 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx) : ectx.globalDofIdx;
2100 return flowsC.getFlow(index, Dir::YMinus, gasCompIdx);
2104 Entry{ScalarEntry{
"BFLOGK",
2106 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2108 const unsigned index = !flowsC.blockFlows().empty() ?
2109 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2110 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx) : ectx.globalDofIdx;
2111 return flowsC.getFlow(index, Dir::ZPlus, gasCompIdx);
2115 Entry{ScalarEntry{
"BFLOGK-",
2117 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2119 const unsigned index = !flowsC.blockFlows().empty() ?
2120 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2121 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx) : ectx.globalDofIdx;
2122 return flowsC.getFlow(index, Dir::ZMinus, gasCompIdx);
2126 Entry{ScalarEntry{
"BFLOOI",
2128 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2130 const unsigned index = !flowsC.blockFlows().empty() ?
2131 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2132 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx) : ectx.globalDofIdx;
2133 return flowsC.getFlow(index, Dir::XPlus, oilCompIdx);
2137 Entry{ScalarEntry{
"BFLOOI-",
2139 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2141 const unsigned index = !flowsC.blockFlows().empty() ?
2142 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2143 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx) : ectx.globalDofIdx;
2144 return flowsC.getFlow(index, Dir::XMinus, oilCompIdx);
2148 Entry{ScalarEntry{
"BFLOOJ",
2150 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2152 const unsigned index = !flowsC.blockFlows().empty() ?
2153 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2154 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx) : ectx.globalDofIdx;
2155 return flowsC.getFlow(index, Dir::YPlus, oilCompIdx);
2159 Entry{ScalarEntry{
"BFLOOJ-",
2161 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2163 const unsigned index = !flowsC.blockFlows().empty() ?
2164 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2165 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx) : ectx.globalDofIdx;
2166 return flowsC.getFlow(index, Dir::YMinus, oilCompIdx);
2170 Entry{ScalarEntry{
"BFLOOK",
2172 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2174 const unsigned index = !flowsC.blockFlows().empty() ?
2175 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2176 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx) : ectx.globalDofIdx;
2177 return flowsC.getFlow(index, Dir::ZPlus, oilCompIdx);
2181 Entry{ScalarEntry{
"BFLOOK-",
2183 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2185 const unsigned index = !flowsC.blockFlows().empty() ?
2186 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2187 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx) : ectx.globalDofIdx;
2188 return flowsC.getFlow(index, Dir::ZMinus, oilCompIdx);
2192 Entry{ScalarEntry{
"BFLOWI",
2194 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2196 const unsigned index = !flowsC.blockFlows().empty() ?
2197 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2198 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx) : ectx.globalDofIdx;
2199 return flowsC.getFlow(index, Dir::XPlus, waterCompIdx);
2203 Entry{ScalarEntry{
"BFLOWI-",
2205 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2207 const unsigned index = !flowsC.blockFlows().empty() ?
2208 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2209 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx) : ectx.globalDofIdx;
2210 return flowsC.getFlow(index, Dir::XMinus, waterCompIdx);
2214 Entry{ScalarEntry{
"BFLOWJ",
2216 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2218 const unsigned index = !flowsC.blockFlows().empty() ?
2219 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2220 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx) : ectx.globalDofIdx;
2221 return flowsC.getFlow(index, Dir::YPlus, waterCompIdx);
2225 Entry{ScalarEntry{
"BFLOWJ-",
2227 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2229 const unsigned index = !flowsC.blockFlows().empty() ?
2230 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2231 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx) : ectx.globalDofIdx;
2232 return flowsC.getFlow(index, Dir::YMinus, waterCompIdx);
2236 Entry{ScalarEntry{
"BFLOWK",
2238 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2240 const unsigned index = !flowsC.blockFlows().empty() ?
2241 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2242 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx) : ectx.globalDofIdx;
2243 return flowsC.getFlow(index, Dir::ZPlus, waterCompIdx);
2247 Entry{ScalarEntry{
"BFLOWK-",
2249 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2251 const unsigned index = !flowsC.blockFlows().empty() ?
2252 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2253 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx) : ectx.globalDofIdx;
2254 return flowsC.getFlow(index, Dir::ZMinus, waterCompIdx);
2258 Entry{ScalarEntry{
"BVELGI",
2260 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2262 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2263 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx);
2264 return flowsC.getVelocity(index, Dir::XPlus, gasCompIdx);
2268 Entry{ScalarEntry{
"BVELGI-",
2270 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2272 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2273 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx);
2274 return flowsC.getVelocity(index, Dir::XMinus, gasCompIdx);
2278 Entry{ScalarEntry{
"BVELGJ",
2280 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2282 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2283 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx);
2284 return flowsC.getVelocity(index, Dir::YPlus, gasCompIdx);
2288 Entry{ScalarEntry{
"BVELGJ-",
2290 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2292 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2293 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx);
2294 return flowsC.getVelocity(index, Dir::YMinus, gasCompIdx);
2298 Entry{ScalarEntry{
"BVELGK",
2300 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2302 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2303 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx);
2304 return flowsC.getVelocity(index, Dir::ZPlus, gasCompIdx);
2308 Entry{ScalarEntry{
"BVELGK-",
2310 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2312 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2313 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx);
2314 return flowsC.getVelocity(index, Dir::ZMinus, gasCompIdx);
2318 Entry{ScalarEntry{
"BVELOI",
2320 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2322 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2323 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx);
2324 return flowsC.getVelocity(index, Dir::XPlus, oilCompIdx);
2328 Entry{ScalarEntry{
"BVELOI-",
2330 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2332 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2333 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx);
2334 return flowsC.getVelocity(index, Dir::XMinus, oilCompIdx);
2338 Entry{ScalarEntry{
"BVELOJ",
2340 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2342 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2343 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx);
2344 return flowsC.getVelocity(index, Dir::YPlus, oilCompIdx);
2348 Entry{ScalarEntry{
"BVELOJ-",
2350 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2352 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2353 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx);
2354 return flowsC.getVelocity(index, Dir::YMinus, oilCompIdx);
2358 Entry{ScalarEntry{
"BVELOK",
2360 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2362 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2363 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx);
2364 return flowsC.getVelocity(index, Dir::ZPlus, oilCompIdx);
2368 Entry{ScalarEntry{
"BVELOK-",
2370 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2372 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2373 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx);
2374 return flowsC.getVelocity(index, Dir::ZMinus, oilCompIdx);
2378 Entry{ScalarEntry{
"BVELWI",
2380 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2382 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2383 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx);
2384 return flowsC.getVelocity(index, Dir::XPlus, waterCompIdx);
2388 Entry{ScalarEntry{
"BVELWI-",
2390 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2392 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2393 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx);
2394 return flowsC.getVelocity(index, Dir::XMinus, waterCompIdx);
2398 Entry{ScalarEntry{
"BVELWJ",
2400 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2402 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2403 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx);
2404 return flowsC.getVelocity(index, Dir::YPlus, waterCompIdx);
2408 Entry{ScalarEntry{
"BVELWJ-",
2410 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2412 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2413 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx);
2414 return flowsC.getVelocity(index, Dir::YMinus, waterCompIdx);
2418 Entry{ScalarEntry{
"BVELWK",
2420 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2422 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2423 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx);
2424 return flowsC.getVelocity(index, Dir::ZPlus, waterCompIdx);
2428 Entry{ScalarEntry{
"BVELWK-",
2430 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2432 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2433 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx);
2434 return flowsC.getVelocity(index, Dir::ZMinus, waterCompIdx);
2438 Entry{ScalarEntry{
"BRPV",
2439 [&model = this->simulator_.model()](
const Context& ectx)
2441 return getValue(ectx.intQuants.porosity()) *
2442 model.dofTotalVolume(ectx.globalDofIdx);
2446 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
2447 [&model = this->simulator_.model()](
const unsigned phaseIdx,
2448 const Context& ectx)
2450 return getValue(ectx.fs.saturation(phaseIdx)) *
2451 getValue(ectx.intQuants.porosity()) *
2452 model.dofTotalVolume(ectx.globalDofIdx);
2456 Entry{ScalarEntry{
"BRS",
2457 [](
const Context& ectx)
2459 return getValue(ectx.fs.Rs());
2463 Entry{ScalarEntry{
"BRV",
2464 [](
const Context& ectx)
2466 return getValue(ectx.fs.Rv());
2470 Entry{ScalarEntry{
"BOIP",
2471 [&model = this->simulator_.model()](
const Context& ectx)
2473 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
2474 getValue(ectx.fs.saturation(oilPhaseIdx)) +
2475 getValue(ectx.fs.Rv()) *
2476 getValue(ectx.fs.invB(gasPhaseIdx)) *
2477 getValue(ectx.fs.saturation(gasPhaseIdx))) *
2478 model.dofTotalVolume(ectx.globalDofIdx) *
2479 getValue(ectx.intQuants.porosity());
2483 Entry{ScalarEntry{
"BGIP",
2484 [&model = this->simulator_.model()](
const Context& ectx)
2486 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2487 getValue(ectx.fs.saturation(gasPhaseIdx));
2489 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2490 result += getValue(ectx.fs.Rs()) *
2491 getValue(ectx.fs.invB(oilPhaseIdx)) *
2492 getValue(ectx.fs.saturation(oilPhaseIdx));
2495 result += getValue(ectx.fs.Rsw()) *
2496 getValue(ectx.fs.invB(waterPhaseIdx)) *
2497 getValue(ectx.fs.saturation(waterPhaseIdx));
2501 model.dofTotalVolume(ectx.globalDofIdx) *
2502 getValue(ectx.intQuants.porosity());
2506 Entry{ScalarEntry{
"BWIP",
2507 [&model = this->simulator_.model()](
const Context& ectx)
2509 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2510 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2511 model.dofTotalVolume(ectx.globalDofIdx) *
2512 getValue(ectx.intQuants.porosity());
2516 Entry{ScalarEntry{
"BOIPL",
2517 [&model = this->simulator_.model()](
const Context& ectx)
2519 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2520 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2521 model.dofTotalVolume(ectx.globalDofIdx) *
2522 getValue(ectx.intQuants.porosity());
2526 Entry{ScalarEntry{
"BGIPL",
2527 [&model = this->simulator_.model()](
const Context& ectx)
2530 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2531 result = getValue(ectx.fs.Rs()) *
2532 getValue(ectx.fs.invB(oilPhaseIdx)) *
2533 getValue(ectx.fs.saturation(oilPhaseIdx));
2536 result = getValue(ectx.fs.Rsw()) *
2537 getValue(ectx.fs.invB(waterPhaseIdx)) *
2538 getValue(ectx.fs.saturation(waterPhaseIdx));
2541 model.dofTotalVolume(ectx.globalDofIdx) *
2542 getValue(ectx.intQuants.porosity());
2546 Entry{ScalarEntry{
"BGIPG",
2547 [&model = this->simulator_.model()](
const Context& ectx)
2549 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2550 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2551 model.dofTotalVolume(ectx.globalDofIdx) *
2552 getValue(ectx.intQuants.porosity());
2556 Entry{ScalarEntry{
"BOIPG",
2557 [&model = this->simulator_.model()](
const Context& ectx)
2559 return getValue(ectx.fs.Rv()) *
2560 getValue(ectx.fs.invB(gasPhaseIdx)) *
2561 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2562 model.dofTotalVolume(ectx.globalDofIdx) *
2563 getValue(ectx.intQuants.porosity());
2567 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2568 [&simConfig = this->
eclState_.getSimulationConfig(),
2569 &grav = this->simulator_.problem().gravity(),
2571 &problem = this->simulator_.problem(),
2572 ®ions = this->
regions_](
const unsigned phaseIdx,
const Context& ectx)
2575 phase.ix = phaseIdx;
2584 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2587 const auto region = RegionPhasePoreVolAverage::Region {
2588 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2591 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2593 const auto press = getValue(ectx.fs.pressure(phase.ix));
2594 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2595 return press - density*dz*grav[GridView::dimensionworld - 1];
2599 Entry{ScalarEntry{
"BAMIP",
2600 [&model = this->simulator_.model()](
const Context& ectx)
2602 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2603 ectx.intQuants.pvtRegionIndex());
2604 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2605 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2607 model.dofTotalVolume(ectx.globalDofIdx) *
2608 getValue(ectx.intQuants.porosity());
2612 Entry{ScalarEntry{
"BMMIP",
2613 [&model = this->simulator_.model()](
const Context& ectx)
2615 return getValue(ectx.intQuants.microbialConcentration()) *
2616 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2617 getValue(ectx.intQuants.porosity()) *
2618 model.dofTotalVolume(ectx.globalDofIdx);
2622 Entry{ScalarEntry{
"BMOIP",
2623 [&model = this->simulator_.model()](
const Context& ectx)
2625 return getValue(ectx.intQuants.oxygenConcentration()) *
2626 getValue(ectx.intQuants.porosity()) *
2627 model.dofTotalVolume(ectx.globalDofIdx);
2631 Entry{ScalarEntry{
"BMUIP",
2632 [&model = this->simulator_.model()](
const Context& ectx)
2634 return getValue(ectx.intQuants.ureaConcentration()) *
2635 getValue(ectx.intQuants.porosity()) *
2636 model.dofTotalVolume(ectx.globalDofIdx) * 1;
2640 Entry{ScalarEntry{
"BMBIP",
2641 [&model = this->simulator_.model()](
const Context& ectx)
2643 return model.dofTotalVolume(ectx.globalDofIdx) *
2644 getValue(ectx.intQuants.biofilmMass());
2648 Entry{ScalarEntry{
"BMCIP",
2649 [&model = this->simulator_.model()](
const Context& ectx)
2651 return model.dofTotalVolume(ectx.globalDofIdx) *
2652 getValue(ectx.intQuants.calciteMass());
2656 Entry{ScalarEntry{
"BGMIP",
2657 [&model = this->simulator_.model()](
const Context& ectx)
2659 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2660 getValue(ectx.fs.saturation(gasPhaseIdx));
2662 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2663 result += getValue(ectx.fs.Rs()) *
2664 getValue(ectx.fs.invB(oilPhaseIdx)) *
2665 getValue(ectx.fs.saturation(oilPhaseIdx));
2668 result += getValue(ectx.fs.Rsw()) *
2669 getValue(ectx.fs.invB(waterPhaseIdx)) *
2670 getValue(ectx.fs.saturation(waterPhaseIdx));
2672 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2673 ectx.intQuants.pvtRegionIndex());
2675 model.dofTotalVolume(ectx.globalDofIdx) *
2676 getValue(ectx.intQuants.porosity()) *
2681 Entry{ScalarEntry{
"BGMGP",
2682 [&model = this->simulator_.model()](
const Context& ectx)
2684 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2685 ectx.intQuants.pvtRegionIndex());
2686 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2687 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2688 model.dofTotalVolume(ectx.globalDofIdx) *
2689 getValue(ectx.intQuants.porosity()) *
2694 Entry{ScalarEntry{
"BGMDS",
2695 [&model = this->simulator_.model()](
const Context& ectx)
2698 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2699 result = getValue(ectx.fs.Rs()) *
2700 getValue(ectx.fs.invB(oilPhaseIdx)) *
2701 getValue(ectx.fs.saturation(oilPhaseIdx));
2704 result = getValue(ectx.fs.Rsw()) *
2705 getValue(ectx.fs.invB(waterPhaseIdx)) *
2706 getValue(ectx.fs.saturation(waterPhaseIdx));
2708 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2709 ectx.intQuants.pvtRegionIndex());
2711 model.dofTotalVolume(ectx.globalDofIdx) *
2712 getValue(ectx.intQuants.porosity()) *
2717 Entry{ScalarEntry{
"BGMST",
2718 [&model = this->simulator_.model(),
2719 &problem = this->simulator_.problem()](
const Context& ectx)
2721 const auto& scaledDrainageInfo = problem.materialLawManager()
2722 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2723 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2724 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2725 if (problem.materialLawManager()->enableHysteresis()) {
2726 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2727 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2728 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2730 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2731 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2732 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2733 return (1.0 - xgW) *
2734 model.dofTotalVolume(ectx.globalDofIdx) *
2735 getValue(ectx.intQuants.porosity()) *
2736 getValue(ectx.fs.density(gasPhaseIdx)) *
2737 std::min(strandedGas, sg);
2741 Entry{ScalarEntry{
"BGMUS",
2742 [&model = this->simulator_.model(),
2743 &problem = this->simulator_.problem()](
const Context& ectx)
2745 const auto& scaledDrainageInfo = problem.materialLawManager()
2746 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2747 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2748 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2749 if (problem.materialLawManager()->enableHysteresis()) {
2750 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2751 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2752 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2754 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2755 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2756 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2757 return (1.0 - xgW) *
2758 model.dofTotalVolume(ectx.globalDofIdx) *
2759 getValue(ectx.intQuants.porosity()) *
2760 getValue(ectx.fs.density(gasPhaseIdx)) *
2761 std::max(Scalar{0.0}, sg - strandedGas);
2765 Entry{ScalarEntry{
"BGMTR",
2766 [&model = this->simulator_.model(),
2767 &problem = this->simulator_.problem()](
const Context& ectx)
2769 const auto& scaledDrainageInfo = problem.materialLawManager()
2770 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2771 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2772 if (problem.materialLawManager()->enableHysteresis()) {
2773 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2774 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2776 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2777 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2778 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2779 return (1.0 - xgW) *
2780 model.dofTotalVolume(ectx.globalDofIdx) *
2781 getValue(ectx.intQuants.porosity()) *
2782 getValue(ectx.fs.density(gasPhaseIdx)) *
2783 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2787 Entry{ScalarEntry{
"BGMMO",
2788 [&model = this->simulator_.model(),
2789 &problem = this->simulator_.problem()](
const Context& ectx)
2791 const auto& scaledDrainageInfo = problem.materialLawManager()
2792 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2793 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2794 if (problem.materialLawManager()->enableHysteresis()) {
2795 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2796 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2798 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2799 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2800 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2801 return (1.0 - xgW) *
2802 model.dofTotalVolume(ectx.globalDofIdx) *
2803 getValue(ectx.intQuants.porosity()) *
2804 getValue(ectx.fs.density(gasPhaseIdx)) *
2805 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2809 Entry{ScalarEntry{
"BGKTR",
2810 [&model = this->simulator_.model(),
2811 &problem = this->simulator_.problem()](
const Context& ectx)
2813 const auto& scaledDrainageInfo = problem.materialLawManager()
2814 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2815 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2816 Scalar sgcr = scaledDrainageInfo.Sgcr;
2817 if (problem.materialLawManager()->enableHysteresis()) {
2818 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2819 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2825 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2826 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2827 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2828 return (1.0 - xgW) *
2829 model.dofTotalVolume(ectx.globalDofIdx) *
2830 getValue(ectx.intQuants.porosity()) *
2831 getValue(ectx.fs.density(gasPhaseIdx)) *
2832 getValue(ectx.fs.saturation(gasPhaseIdx));
2837 Entry{ScalarEntry{
"BGKMO",
2838 [&model = this->simulator_.model(),
2839 &problem = this->simulator_.problem()](
const Context& ectx)
2841 const auto& scaledDrainageInfo = problem.materialLawManager()
2842 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2843 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2844 Scalar sgcr = scaledDrainageInfo.Sgcr;
2845 if (problem.materialLawManager()->enableHysteresis()) {
2846 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2847 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2853 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2854 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2855 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2856 return (1.0 - xgW) *
2857 model.dofTotalVolume(ectx.globalDofIdx) *
2858 getValue(ectx.intQuants.porosity()) *
2859 getValue(ectx.fs.density(gasPhaseIdx)) *
2860 getValue(ectx.fs.saturation(gasPhaseIdx));
2865 Entry{ScalarEntry{
"BGCDI",
2866 [&model = this->simulator_.model(),
2867 &problem = this->simulator_.problem()](
const Context& ectx)
2869 const auto& scaledDrainageInfo = problem.materialLawManager()
2870 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2871 Scalar sgcr = scaledDrainageInfo.Sgcr;
2872 if (problem.materialLawManager()->enableHysteresis()) {
2873 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2874 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2876 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2877 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2878 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2879 return (1.0 - xgW) *
2880 model.dofTotalVolume(ectx.globalDofIdx) *
2881 getValue(ectx.intQuants.porosity()) *
2882 getValue(ectx.fs.density(gasPhaseIdx)) *
2883 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2884 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2888 Entry{ScalarEntry{
"BGCDM",
2889 [&model = this->simulator_.model(),
2890 &problem = this->simulator_.problem()](
const Context& ectx)
2892 const auto& scaledDrainageInfo = problem.materialLawManager()
2893 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2894 Scalar sgcr = scaledDrainageInfo.Sgcr;
2895 if (problem.materialLawManager()->enableHysteresis()) {
2896 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2897 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2899 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2900 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2901 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2902 return (1.0 - xgW) *
2903 model.dofTotalVolume(ectx.globalDofIdx) *
2904 getValue(ectx.intQuants.porosity()) *
2905 getValue(ectx.fs.density(gasPhaseIdx)) *
2906 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2907 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2911 Entry{ScalarEntry{
"BGKDI",
2912 [&model = this->simulator_.model(),
2913 &problem = this->simulator_.problem()](
const Context& ectx)
2915 const auto& scaledDrainageInfo = problem.materialLawManager()
2916 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2917 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2918 Scalar sgcr = scaledDrainageInfo.Sgcr;
2919 if (problem.materialLawManager()->enableHysteresis()) {
2920 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2921 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2927 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2928 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2929 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2930 return (1.0 - xgW) *
2931 model.dofTotalVolume(ectx.globalDofIdx) *
2932 getValue(ectx.intQuants.porosity()) *
2933 getValue(ectx.fs.density(gasPhaseIdx)) *
2934 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2935 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2940 Entry{ScalarEntry{
"BGKDM",
2941 [&model = this->simulator_.model(),
2942 &problem = this->simulator_.problem()](
const Context& ectx)
2944 const auto& scaledDrainageInfo = problem.materialLawManager()
2945 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2946 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2947 Scalar sgcr = scaledDrainageInfo.Sgcr;
2948 if (problem.materialLawManager()->enableHysteresis()) {
2949 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2950 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2956 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2957 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2958 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2959 return (1.0 - xgW) *
2960 model.dofTotalVolume(ectx.globalDofIdx) *
2961 getValue(ectx.intQuants.porosity()) *
2962 getValue(ectx.fs.density(gasPhaseIdx)) *
2963 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2964 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2969 Entry{ScalarEntry{
"BWCD",
2970 [&model = this->simulator_.model()](
const Context& ectx)
2973 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2974 result = getValue(ectx.fs.Rs()) *
2975 getValue(ectx.fs.invB(oilPhaseIdx)) *
2976 getValue(ectx.fs.saturation(oilPhaseIdx));
2979 result = getValue(ectx.fs.Rsw()) *
2980 getValue(ectx.fs.invB(waterPhaseIdx)) *
2981 getValue(ectx.fs.saturation(waterPhaseIdx));
2983 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2984 ectx.intQuants.pvtRegionIndex());
2986 model.dofTotalVolume(ectx.globalDofIdx) *
2987 getValue(ectx.intQuants.porosity()) *
2989 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2993 Entry{ScalarEntry{
"BWIPG",
2994 [&model = this->simulator_.model()](
const Context& ectx)
2996 Scalar result = 0.0;
2997 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2998 result = getValue(ectx.fs.Rvw()) *
2999 getValue(ectx.fs.invB(gasPhaseIdx)) *
3000 getValue(ectx.fs.saturation(gasPhaseIdx));
3003 model.dofTotalVolume(ectx.globalDofIdx) *
3004 getValue(ectx.intQuants.porosity());
3008 Entry{ScalarEntry{
"BWIPL",
3009 [&model = this->simulator_.model()](
const Context& ectx)
3011 return getValue(ectx.fs.invB(waterPhaseIdx)) *
3012 getValue(ectx.fs.saturation(waterPhaseIdx)) *
3013 model.dofTotalVolume(ectx.globalDofIdx) *
3014 getValue(ectx.intQuants.porosity());
3023 if (reportStepNum > 0 && !isSubStep) {
3025 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
3026 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
3028 [&c = this->collectOnIORank_](
const int idx)
3029 {
return c.isCartIdxOnThisRank(idx); });
3031 const auto extraHandlers = std::array{
3040 const Simulator& simulator_;
3041 const CollectDataOnIORankType& collectOnIORank_;
3042 std::vector<typename Extractor::Entry> extractors_;
Contains the classes required to extend the black-oil model by energy.
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:86
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition: OutputBlackoilModule.hpp:242
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:486
void setupExtractors(const bool isSubStep, const int reportStepNum)
Setup list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:223
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:201
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:449
void clearExtractors()
Clear list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:231
void outputFipAndResvLogToCSV(const std::size_t reportStepNum, const bool substep, const Parallel::Communication &comm)
Definition: OutputBlackoilModule.hpp:383
void assignToFluidState(FluidState &fs, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:510
void initHysteresisParams(Simulator &simulator, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:562
void updateFluidInPlace(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:627
OutputBlackOilModule(const Simulator &simulator, const SummaryConfig &smryCfg, const CollectDataOnIORankType &collectOnIORank)
Definition: OutputBlackoilModule.hpp:134
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:332
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputBlackoilModule.hpp:504
void processElementBlockData(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:288
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputBlackoilModule.hpp:496
void updateFluidInPlace(const unsigned globalDofIdx, const IntensiveQuantities &intQuants, const double totVolume)
Definition: OutputBlackoilModule.hpp:634
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:156
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