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_.push_back(
1839 &gM = this->simulator_.problem().geochemistryModel()](
const Context& ectx)
1841 gC.assignSpeciesConcentrations(
1843 [gIdx = ectx.globalDofIdx, &gM](
const unsigned speciesIdx)
1844 {
return gM.speciesConcentration(speciesIdx, gIdx); }
1846 gC.assignMineralConcentrations(
1848 [gIdx = ectx.globalDofIdx, &gM](
const unsigned mineralIdx)
1849 {
return gM.mineralConcentration(mineralIdx, gIdx); }
1851 gC.assignPH(ectx.globalDofIdx, gM.PH(ectx.globalDofIdx));
1859 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
1860 if (this->
mech_.allocated()) {
1861 this->extractors_.push_back(
1862 Entry{[&mech = this->
mech_,
1863 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1865 mech.assignDelStress(ectx.globalDofIdx,
1866 model.delstress(ectx.globalDofIdx));
1868 mech.assignDisplacement(ectx.globalDofIdx,
1869 model.disp(ectx.globalDofIdx,
true));
1872 mech.assignFracStress(ectx.globalDofIdx,
1873 model.fractureStress(ectx.globalDofIdx));
1875 mech.assignLinStress(ectx.globalDofIdx,
1876 model.linstress(ectx.globalDofIdx));
1878 mech.assignPotentialForces(ectx.globalDofIdx,
1879 model.mechPotentialForce(ectx.globalDofIdx),
1880 model.mechPotentialPressForce(ectx.globalDofIdx),
1881 model.mechPotentialTempForce(ectx.globalDofIdx));
1883 mech.assignStrain(ectx.globalDofIdx,
1884 model.strain(ectx.globalDofIdx,
true));
1887 mech.assignStress(ectx.globalDofIdx,
1888 model.stress(ectx.globalDofIdx,
true));
1897 void setupBlockExtractors_(
const bool isSubStep,
1898 const int reportStepNum)
1901 using Context =
typename BlockExtractor::Context;
1902 using PhaseEntry =
typename BlockExtractor::PhaseEntry;
1903 using ScalarEntry =
typename BlockExtractor::ScalarEntry;
1905 using namespace std::string_view_literals;
1907 const auto pressure_handler =
1908 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1909 [](
const Context& ectx)
1911 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1912 return getValue(ectx.fs.pressure(oilPhaseIdx));
1914 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1915 return getValue(ectx.fs.pressure(gasPhaseIdx));
1918 return getValue(ectx.fs.pressure(waterPhaseIdx));
1924 const auto handlers = std::array{
1926 Entry{PhaseEntry{std::array{
1927 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1928 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1930 [](
const unsigned phaseIdx,
const Context& ectx)
1932 return getValue(ectx.fs.saturation(phaseIdx));
1936 Entry{ScalarEntry{
"BNSAT",
1937 [](
const Context& ectx)
1939 return ectx.intQuants.solventSaturation().value();
1943 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1944 [](
const Context& ectx)
1946 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1947 return getValue(ectx.fs.temperature(oilPhaseIdx));
1949 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1950 return getValue(ectx.fs.temperature(gasPhaseIdx));
1953 return getValue(ectx.fs.temperature(waterPhaseIdx));
1958 Entry{PhaseEntry{std::array{
1959 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
1960 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
1962 [](
const unsigned phaseIdx,
const Context& ectx)
1964 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
1968 Entry{ScalarEntry{
"BKROG",
1969 [&problem = this->simulator_.problem()](
const Context& ectx)
1971 const auto& materialParams =
1972 problem.materialLawParams(ectx.elemCtx,
1975 return getValue(MaterialLaw::template
1976 relpermOilInOilGasSystem<Evaluation>(materialParams,
1981 Entry{ScalarEntry{
"BKROW",
1982 [&problem = this->simulator_.problem()](
const Context& ectx)
1984 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
1987 return getValue(MaterialLaw::template
1988 relpermOilInOilWaterSystem<Evaluation>(materialParams,
1993 Entry{ScalarEntry{
"BWPC",
1994 [](
const Context& ectx)
1996 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1997 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1998 getValue(ectx.fs.pressure(waterPhaseIdx));
2000 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2001 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2002 getValue(ectx.fs.pressure(waterPhaseIdx));
2010 Entry{ScalarEntry{
"BGPC",
2011 [](
const Context& ectx)
2013 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2014 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2015 getValue(ectx.fs.pressure(oilPhaseIdx));
2017 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
2018 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2019 getValue(ectx.fs.pressure(waterPhaseIdx));
2027 Entry{ScalarEntry{
"BWPR",
2028 [](
const Context& ectx)
2030 return getValue(ectx.fs.pressure(waterPhaseIdx));
2034 Entry{ScalarEntry{
"BGPR",
2035 [](
const Context& ectx)
2037 return getValue(ectx.fs.pressure(gasPhaseIdx));
2041 Entry{PhaseEntry{std::array{
2042 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
2043 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
2045 [](
const unsigned phaseIdx,
const Context& ectx)
2047 return getValue(ectx.fs.viscosity(phaseIdx));
2051 Entry{PhaseEntry{std::array{
2052 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
2053 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
2055 [](
const unsigned phaseIdx,
const Context& ectx)
2057 return getValue(ectx.fs.density(phaseIdx));
2061 Entry{ScalarEntry{
"BFLOGI",
2063 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2065 const unsigned index = !flowsC.blockFlows().empty() ?
2066 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2067 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx) : ectx.globalDofIdx;
2068 return flowsC.getFlow(index, Dir::XPlus, gasCompIdx);
2072 Entry{ScalarEntry{
"BFLOGI-",
2074 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2076 const unsigned index = !flowsC.blockFlows().empty() ?
2077 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2078 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx) : ectx.globalDofIdx;
2079 return flowsC.getFlow(index, Dir::XMinus, gasCompIdx);
2083 Entry{ScalarEntry{
"BFLOGJ",
2085 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2087 const unsigned index = !flowsC.blockFlows().empty() ?
2088 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2089 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx) : ectx.globalDofIdx;
2090 return flowsC.getFlow(index, Dir::YPlus, gasCompIdx);
2094 Entry{ScalarEntry{
"BFLOGJ-",
2096 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2098 const unsigned index = !flowsC.blockFlows().empty() ?
2099 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2100 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx) : ectx.globalDofIdx;
2101 return flowsC.getFlow(index, Dir::YMinus, gasCompIdx);
2105 Entry{ScalarEntry{
"BFLOGK",
2107 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2109 const unsigned index = !flowsC.blockFlows().empty() ?
2110 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2111 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx) : ectx.globalDofIdx;
2112 return flowsC.getFlow(index, Dir::ZPlus, gasCompIdx);
2116 Entry{ScalarEntry{
"BFLOGK-",
2118 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2120 const unsigned index = !flowsC.blockFlows().empty() ?
2121 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2122 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx) : ectx.globalDofIdx;
2123 return flowsC.getFlow(index, Dir::ZMinus, gasCompIdx);
2127 Entry{ScalarEntry{
"BFLOOI",
2129 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2131 const unsigned index = !flowsC.blockFlows().empty() ?
2132 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2133 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx) : ectx.globalDofIdx;
2134 return flowsC.getFlow(index, Dir::XPlus, oilCompIdx);
2138 Entry{ScalarEntry{
"BFLOOI-",
2140 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2142 const unsigned index = !flowsC.blockFlows().empty() ?
2143 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2144 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx) : ectx.globalDofIdx;
2145 return flowsC.getFlow(index, Dir::XMinus, oilCompIdx);
2149 Entry{ScalarEntry{
"BFLOOJ",
2151 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2153 const unsigned index = !flowsC.blockFlows().empty() ?
2154 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2155 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx) : ectx.globalDofIdx;
2156 return flowsC.getFlow(index, Dir::YPlus, oilCompIdx);
2160 Entry{ScalarEntry{
"BFLOOJ-",
2162 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2164 const unsigned index = !flowsC.blockFlows().empty() ?
2165 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2166 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx) : ectx.globalDofIdx;
2167 return flowsC.getFlow(index, Dir::YMinus, oilCompIdx);
2171 Entry{ScalarEntry{
"BFLOOK",
2173 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2175 const unsigned index = !flowsC.blockFlows().empty() ?
2176 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2177 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx) : ectx.globalDofIdx;
2178 return flowsC.getFlow(index, Dir::ZPlus, oilCompIdx);
2182 Entry{ScalarEntry{
"BFLOOK-",
2184 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2186 const unsigned index = !flowsC.blockFlows().empty() ?
2187 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2188 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx) : ectx.globalDofIdx;
2189 return flowsC.getFlow(index, Dir::ZMinus, oilCompIdx);
2193 Entry{ScalarEntry{
"BFLOWI",
2195 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2197 const unsigned index = !flowsC.blockFlows().empty() ?
2198 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2199 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx) : ectx.globalDofIdx;
2200 return flowsC.getFlow(index, Dir::XPlus, waterCompIdx);
2204 Entry{ScalarEntry{
"BFLOWI-",
2206 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2208 const unsigned index = !flowsC.blockFlows().empty() ?
2209 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2210 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx) : ectx.globalDofIdx;
2211 return flowsC.getFlow(index, Dir::XMinus, waterCompIdx);
2215 Entry{ScalarEntry{
"BFLOWJ",
2217 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2219 const unsigned index = !flowsC.blockFlows().empty() ?
2220 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2221 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx) : ectx.globalDofIdx;
2222 return flowsC.getFlow(index, Dir::YPlus, waterCompIdx);
2226 Entry{ScalarEntry{
"BFLOWJ-",
2228 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2230 const unsigned index = !flowsC.blockFlows().empty() ?
2231 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2232 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx) : ectx.globalDofIdx;
2233 return flowsC.getFlow(index, Dir::YMinus, waterCompIdx);
2237 Entry{ScalarEntry{
"BFLOWK",
2239 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2241 const unsigned index = !flowsC.blockFlows().empty() ?
2242 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2243 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx) : ectx.globalDofIdx;
2244 return flowsC.getFlow(index, Dir::ZPlus, waterCompIdx);
2248 Entry{ScalarEntry{
"BFLOWK-",
2250 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2252 const unsigned index = !flowsC.blockFlows().empty() ?
2253 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2254 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx) : ectx.globalDofIdx;
2255 return flowsC.getFlow(index, Dir::ZMinus, waterCompIdx);
2259 Entry{ScalarEntry{
"BVELGI",
2261 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2263 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2264 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx);
2265 return flowsC.getVelocity(index, Dir::XPlus, gasCompIdx);
2269 Entry{ScalarEntry{
"BVELGI-",
2271 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2273 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2274 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx);
2275 return flowsC.getVelocity(index, Dir::XMinus, gasCompIdx);
2279 Entry{ScalarEntry{
"BVELGJ",
2281 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2283 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2284 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx);
2285 return flowsC.getVelocity(index, Dir::YPlus, gasCompIdx);
2289 Entry{ScalarEntry{
"BVELGJ-",
2291 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2293 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2294 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx);
2295 return flowsC.getVelocity(index, Dir::YMinus, gasCompIdx);
2299 Entry{ScalarEntry{
"BVELGK",
2301 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2303 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2304 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx);
2305 return flowsC.getVelocity(index, Dir::ZPlus, gasCompIdx);
2309 Entry{ScalarEntry{
"BVELGK-",
2311 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2313 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2314 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx);
2315 return flowsC.getVelocity(index, Dir::ZMinus, gasCompIdx);
2319 Entry{ScalarEntry{
"BVELOI",
2321 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2323 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2324 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx);
2325 return flowsC.getVelocity(index, Dir::XPlus, oilCompIdx);
2329 Entry{ScalarEntry{
"BVELOI-",
2331 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2333 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2334 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx);
2335 return flowsC.getVelocity(index, Dir::XMinus, oilCompIdx);
2339 Entry{ScalarEntry{
"BVELOJ",
2341 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2343 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2344 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx);
2345 return flowsC.getVelocity(index, Dir::YPlus, oilCompIdx);
2349 Entry{ScalarEntry{
"BVELOJ-",
2351 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2353 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2354 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx);
2355 return flowsC.getVelocity(index, Dir::YMinus, oilCompIdx);
2359 Entry{ScalarEntry{
"BVELOK",
2361 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2363 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2364 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx);
2365 return flowsC.getVelocity(index, Dir::ZPlus, oilCompIdx);
2369 Entry{ScalarEntry{
"BVELOK-",
2371 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2373 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2374 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx);
2375 return flowsC.getVelocity(index, Dir::ZMinus, oilCompIdx);
2379 Entry{ScalarEntry{
"BVELWI",
2381 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2383 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2384 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx);
2385 return flowsC.getVelocity(index, Dir::XPlus, waterCompIdx);
2389 Entry{ScalarEntry{
"BVELWI-",
2391 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2393 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2394 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx);
2395 return flowsC.getVelocity(index, Dir::XMinus, waterCompIdx);
2399 Entry{ScalarEntry{
"BVELWJ",
2401 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2403 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2404 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx);
2405 return flowsC.getVelocity(index, Dir::YPlus, waterCompIdx);
2409 Entry{ScalarEntry{
"BVELWJ-",
2411 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2413 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2414 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx);
2415 return flowsC.getVelocity(index, Dir::YMinus, waterCompIdx);
2419 Entry{ScalarEntry{
"BVELWK",
2421 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2423 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2424 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx);
2425 return flowsC.getVelocity(index, Dir::ZPlus, waterCompIdx);
2429 Entry{ScalarEntry{
"BVELWK-",
2431 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2433 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2434 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx);
2435 return flowsC.getVelocity(index, Dir::ZMinus, waterCompIdx);
2439 Entry{ScalarEntry{
"BRPV",
2440 [&model = this->simulator_.model()](
const Context& ectx)
2442 return getValue(ectx.intQuants.porosity()) *
2443 model.dofTotalVolume(ectx.globalDofIdx);
2447 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
2448 [&model = this->simulator_.model()](
const unsigned phaseIdx,
2449 const Context& ectx)
2451 return getValue(ectx.fs.saturation(phaseIdx)) *
2452 getValue(ectx.intQuants.porosity()) *
2453 model.dofTotalVolume(ectx.globalDofIdx);
2457 Entry{ScalarEntry{
"BRS",
2458 [](
const Context& ectx)
2460 return getValue(ectx.fs.Rs());
2464 Entry{ScalarEntry{
"BRV",
2465 [](
const Context& ectx)
2467 return getValue(ectx.fs.Rv());
2471 Entry{ScalarEntry{
"BOIP",
2472 [&model = this->simulator_.model()](
const Context& ectx)
2474 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
2475 getValue(ectx.fs.saturation(oilPhaseIdx)) +
2476 getValue(ectx.fs.Rv()) *
2477 getValue(ectx.fs.invB(gasPhaseIdx)) *
2478 getValue(ectx.fs.saturation(gasPhaseIdx))) *
2479 model.dofTotalVolume(ectx.globalDofIdx) *
2480 getValue(ectx.intQuants.porosity());
2484 Entry{ScalarEntry{
"BGIP",
2485 [&model = this->simulator_.model()](
const Context& ectx)
2487 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2488 getValue(ectx.fs.saturation(gasPhaseIdx));
2490 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2491 result += getValue(ectx.fs.Rs()) *
2492 getValue(ectx.fs.invB(oilPhaseIdx)) *
2493 getValue(ectx.fs.saturation(oilPhaseIdx));
2496 result += getValue(ectx.fs.Rsw()) *
2497 getValue(ectx.fs.invB(waterPhaseIdx)) *
2498 getValue(ectx.fs.saturation(waterPhaseIdx));
2502 model.dofTotalVolume(ectx.globalDofIdx) *
2503 getValue(ectx.intQuants.porosity());
2507 Entry{ScalarEntry{
"BWIP",
2508 [&model = this->simulator_.model()](
const Context& ectx)
2510 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2511 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2512 model.dofTotalVolume(ectx.globalDofIdx) *
2513 getValue(ectx.intQuants.porosity());
2517 Entry{ScalarEntry{
"BOIPL",
2518 [&model = this->simulator_.model()](
const Context& ectx)
2520 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2521 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2522 model.dofTotalVolume(ectx.globalDofIdx) *
2523 getValue(ectx.intQuants.porosity());
2527 Entry{ScalarEntry{
"BGIPL",
2528 [&model = this->simulator_.model()](
const Context& ectx)
2531 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2532 result = getValue(ectx.fs.Rs()) *
2533 getValue(ectx.fs.invB(oilPhaseIdx)) *
2534 getValue(ectx.fs.saturation(oilPhaseIdx));
2537 result = getValue(ectx.fs.Rsw()) *
2538 getValue(ectx.fs.invB(waterPhaseIdx)) *
2539 getValue(ectx.fs.saturation(waterPhaseIdx));
2542 model.dofTotalVolume(ectx.globalDofIdx) *
2543 getValue(ectx.intQuants.porosity());
2547 Entry{ScalarEntry{
"BGIPG",
2548 [&model = this->simulator_.model()](
const Context& ectx)
2550 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2551 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2552 model.dofTotalVolume(ectx.globalDofIdx) *
2553 getValue(ectx.intQuants.porosity());
2557 Entry{ScalarEntry{
"BOIPG",
2558 [&model = this->simulator_.model()](
const Context& ectx)
2560 return getValue(ectx.fs.Rv()) *
2561 getValue(ectx.fs.invB(gasPhaseIdx)) *
2562 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2563 model.dofTotalVolume(ectx.globalDofIdx) *
2564 getValue(ectx.intQuants.porosity());
2568 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2569 [&simConfig = this->
eclState_.getSimulationConfig(),
2570 &grav = this->simulator_.problem().gravity(),
2572 &problem = this->simulator_.problem(),
2573 ®ions = this->
regions_](
const unsigned phaseIdx,
const Context& ectx)
2576 phase.ix = phaseIdx;
2585 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2588 const auto region = RegionPhasePoreVolAverage::Region {
2589 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2592 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2594 const auto press = getValue(ectx.fs.pressure(phase.ix));
2595 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2596 return press - density*dz*grav[GridView::dimensionworld - 1];
2600 Entry{ScalarEntry{
"BAMIP",
2601 [&model = this->simulator_.model()](
const Context& ectx)
2603 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2604 ectx.intQuants.pvtRegionIndex());
2605 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2606 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2608 model.dofTotalVolume(ectx.globalDofIdx) *
2609 getValue(ectx.intQuants.porosity());
2613 Entry{ScalarEntry{
"BMMIP",
2614 [&model = this->simulator_.model()](
const Context& ectx)
2616 return getValue(ectx.intQuants.microbialConcentration()) *
2617 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2618 getValue(ectx.intQuants.porosity()) *
2619 model.dofTotalVolume(ectx.globalDofIdx);
2623 Entry{ScalarEntry{
"BMOIP",
2624 [&model = this->simulator_.model()](
const Context& ectx)
2626 return getValue(ectx.intQuants.oxygenConcentration()) *
2627 getValue(ectx.intQuants.porosity()) *
2628 model.dofTotalVolume(ectx.globalDofIdx);
2632 Entry{ScalarEntry{
"BMUIP",
2633 [&model = this->simulator_.model()](
const Context& ectx)
2635 return getValue(ectx.intQuants.ureaConcentration()) *
2636 getValue(ectx.intQuants.porosity()) *
2637 model.dofTotalVolume(ectx.globalDofIdx) * 1;
2641 Entry{ScalarEntry{
"BMBIP",
2642 [&model = this->simulator_.model()](
const Context& ectx)
2644 return model.dofTotalVolume(ectx.globalDofIdx) *
2645 getValue(ectx.intQuants.biofilmMass());
2649 Entry{ScalarEntry{
"BMCIP",
2650 [&model = this->simulator_.model()](
const Context& ectx)
2652 return model.dofTotalVolume(ectx.globalDofIdx) *
2653 getValue(ectx.intQuants.calciteMass());
2657 Entry{ScalarEntry{
"BGMIP",
2658 [&model = this->simulator_.model()](
const Context& ectx)
2660 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2661 getValue(ectx.fs.saturation(gasPhaseIdx));
2663 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2664 result += getValue(ectx.fs.Rs()) *
2665 getValue(ectx.fs.invB(oilPhaseIdx)) *
2666 getValue(ectx.fs.saturation(oilPhaseIdx));
2669 result += getValue(ectx.fs.Rsw()) *
2670 getValue(ectx.fs.invB(waterPhaseIdx)) *
2671 getValue(ectx.fs.saturation(waterPhaseIdx));
2673 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2674 ectx.intQuants.pvtRegionIndex());
2676 model.dofTotalVolume(ectx.globalDofIdx) *
2677 getValue(ectx.intQuants.porosity()) *
2682 Entry{ScalarEntry{
"BGMGP",
2683 [&model = this->simulator_.model()](
const Context& ectx)
2685 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2686 ectx.intQuants.pvtRegionIndex());
2687 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2688 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2689 model.dofTotalVolume(ectx.globalDofIdx) *
2690 getValue(ectx.intQuants.porosity()) *
2695 Entry{ScalarEntry{
"BGMDS",
2696 [&model = this->simulator_.model()](
const Context& ectx)
2699 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2700 result = getValue(ectx.fs.Rs()) *
2701 getValue(ectx.fs.invB(oilPhaseIdx)) *
2702 getValue(ectx.fs.saturation(oilPhaseIdx));
2705 result = getValue(ectx.fs.Rsw()) *
2706 getValue(ectx.fs.invB(waterPhaseIdx)) *
2707 getValue(ectx.fs.saturation(waterPhaseIdx));
2709 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2710 ectx.intQuants.pvtRegionIndex());
2712 model.dofTotalVolume(ectx.globalDofIdx) *
2713 getValue(ectx.intQuants.porosity()) *
2718 Entry{ScalarEntry{
"BGMST",
2719 [&model = this->simulator_.model(),
2720 &problem = this->simulator_.problem()](
const Context& ectx)
2722 const auto& scaledDrainageInfo = problem.materialLawManager()
2723 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2724 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2725 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2726 if (problem.materialLawManager()->enableHysteresis()) {
2727 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2728 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2729 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2731 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2732 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2733 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2734 return (1.0 - xgW) *
2735 model.dofTotalVolume(ectx.globalDofIdx) *
2736 getValue(ectx.intQuants.porosity()) *
2737 getValue(ectx.fs.density(gasPhaseIdx)) *
2738 std::min(strandedGas, sg);
2742 Entry{ScalarEntry{
"BGMUS",
2743 [&model = this->simulator_.model(),
2744 &problem = this->simulator_.problem()](
const Context& ectx)
2746 const auto& scaledDrainageInfo = problem.materialLawManager()
2747 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2748 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2749 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2750 if (problem.materialLawManager()->enableHysteresis()) {
2751 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2752 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2753 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2755 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2756 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2757 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2758 return (1.0 - xgW) *
2759 model.dofTotalVolume(ectx.globalDofIdx) *
2760 getValue(ectx.intQuants.porosity()) *
2761 getValue(ectx.fs.density(gasPhaseIdx)) *
2762 std::max(Scalar{0.0}, sg - strandedGas);
2766 Entry{ScalarEntry{
"BGMTR",
2767 [&model = this->simulator_.model(),
2768 &problem = this->simulator_.problem()](
const Context& ectx)
2770 const auto& scaledDrainageInfo = problem.materialLawManager()
2771 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2772 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2773 if (problem.materialLawManager()->enableHysteresis()) {
2774 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2775 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2777 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2778 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2779 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2780 return (1.0 - xgW) *
2781 model.dofTotalVolume(ectx.globalDofIdx) *
2782 getValue(ectx.intQuants.porosity()) *
2783 getValue(ectx.fs.density(gasPhaseIdx)) *
2784 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2788 Entry{ScalarEntry{
"BGMMO",
2789 [&model = this->simulator_.model(),
2790 &problem = this->simulator_.problem()](
const Context& ectx)
2792 const auto& scaledDrainageInfo = problem.materialLawManager()
2793 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2794 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2795 if (problem.materialLawManager()->enableHysteresis()) {
2796 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2797 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2799 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2800 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2801 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2802 return (1.0 - xgW) *
2803 model.dofTotalVolume(ectx.globalDofIdx) *
2804 getValue(ectx.intQuants.porosity()) *
2805 getValue(ectx.fs.density(gasPhaseIdx)) *
2806 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2810 Entry{ScalarEntry{
"BGKTR",
2811 [&model = this->simulator_.model(),
2812 &problem = this->simulator_.problem()](
const Context& ectx)
2814 const auto& scaledDrainageInfo = problem.materialLawManager()
2815 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2816 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2817 Scalar sgcr = scaledDrainageInfo.Sgcr;
2818 if (problem.materialLawManager()->enableHysteresis()) {
2819 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2820 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2826 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2827 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2828 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2829 return (1.0 - xgW) *
2830 model.dofTotalVolume(ectx.globalDofIdx) *
2831 getValue(ectx.intQuants.porosity()) *
2832 getValue(ectx.fs.density(gasPhaseIdx)) *
2833 getValue(ectx.fs.saturation(gasPhaseIdx));
2838 Entry{ScalarEntry{
"BGKMO",
2839 [&model = this->simulator_.model(),
2840 &problem = this->simulator_.problem()](
const Context& ectx)
2842 const auto& scaledDrainageInfo = problem.materialLawManager()
2843 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2844 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2845 Scalar sgcr = scaledDrainageInfo.Sgcr;
2846 if (problem.materialLawManager()->enableHysteresis()) {
2847 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2848 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2854 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2855 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2856 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2857 return (1.0 - xgW) *
2858 model.dofTotalVolume(ectx.globalDofIdx) *
2859 getValue(ectx.intQuants.porosity()) *
2860 getValue(ectx.fs.density(gasPhaseIdx)) *
2861 getValue(ectx.fs.saturation(gasPhaseIdx));
2866 Entry{ScalarEntry{
"BGCDI",
2867 [&model = this->simulator_.model(),
2868 &problem = this->simulator_.problem()](
const Context& ectx)
2870 const auto& scaledDrainageInfo = problem.materialLawManager()
2871 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2872 Scalar sgcr = scaledDrainageInfo.Sgcr;
2873 if (problem.materialLawManager()->enableHysteresis()) {
2874 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2875 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2877 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2878 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2879 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2880 return (1.0 - xgW) *
2881 model.dofTotalVolume(ectx.globalDofIdx) *
2882 getValue(ectx.intQuants.porosity()) *
2883 getValue(ectx.fs.density(gasPhaseIdx)) *
2884 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2885 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2889 Entry{ScalarEntry{
"BGCDM",
2890 [&model = this->simulator_.model(),
2891 &problem = this->simulator_.problem()](
const Context& ectx)
2893 const auto& scaledDrainageInfo = problem.materialLawManager()
2894 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2895 Scalar sgcr = scaledDrainageInfo.Sgcr;
2896 if (problem.materialLawManager()->enableHysteresis()) {
2897 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2898 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2900 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2901 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2902 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2903 return (1.0 - xgW) *
2904 model.dofTotalVolume(ectx.globalDofIdx) *
2905 getValue(ectx.intQuants.porosity()) *
2906 getValue(ectx.fs.density(gasPhaseIdx)) *
2907 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2908 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2912 Entry{ScalarEntry{
"BGKDI",
2913 [&model = this->simulator_.model(),
2914 &problem = this->simulator_.problem()](
const Context& ectx)
2916 const auto& scaledDrainageInfo = problem.materialLawManager()
2917 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2918 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2919 Scalar sgcr = scaledDrainageInfo.Sgcr;
2920 if (problem.materialLawManager()->enableHysteresis()) {
2921 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2922 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2928 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2929 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2930 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2931 return (1.0 - xgW) *
2932 model.dofTotalVolume(ectx.globalDofIdx) *
2933 getValue(ectx.intQuants.porosity()) *
2934 getValue(ectx.fs.density(gasPhaseIdx)) *
2935 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2936 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2941 Entry{ScalarEntry{
"BGKDM",
2942 [&model = this->simulator_.model(),
2943 &problem = this->simulator_.problem()](
const Context& ectx)
2945 const auto& scaledDrainageInfo = problem.materialLawManager()
2946 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2947 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2948 Scalar sgcr = scaledDrainageInfo.Sgcr;
2949 if (problem.materialLawManager()->enableHysteresis()) {
2950 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2951 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2957 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2958 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2959 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2960 return (1.0 - xgW) *
2961 model.dofTotalVolume(ectx.globalDofIdx) *
2962 getValue(ectx.intQuants.porosity()) *
2963 getValue(ectx.fs.density(gasPhaseIdx)) *
2964 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2965 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2970 Entry{ScalarEntry{
"BWCD",
2971 [&model = this->simulator_.model()](
const Context& ectx)
2974 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2975 result = getValue(ectx.fs.Rs()) *
2976 getValue(ectx.fs.invB(oilPhaseIdx)) *
2977 getValue(ectx.fs.saturation(oilPhaseIdx));
2980 result = getValue(ectx.fs.Rsw()) *
2981 getValue(ectx.fs.invB(waterPhaseIdx)) *
2982 getValue(ectx.fs.saturation(waterPhaseIdx));
2984 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2985 ectx.intQuants.pvtRegionIndex());
2987 model.dofTotalVolume(ectx.globalDofIdx) *
2988 getValue(ectx.intQuants.porosity()) *
2990 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2994 Entry{ScalarEntry{
"BWIPG",
2995 [&model = this->simulator_.model()](
const Context& ectx)
2997 Scalar result = 0.0;
2998 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2999 result = getValue(ectx.fs.Rvw()) *
3000 getValue(ectx.fs.invB(gasPhaseIdx)) *
3001 getValue(ectx.fs.saturation(gasPhaseIdx));
3004 model.dofTotalVolume(ectx.globalDofIdx) *
3005 getValue(ectx.intQuants.porosity());
3009 Entry{ScalarEntry{
"BWIPL",
3010 [&model = this->simulator_.model()](
const Context& ectx)
3012 return getValue(ectx.fs.invB(waterPhaseIdx)) *
3013 getValue(ectx.fs.saturation(waterPhaseIdx)) *
3014 model.dofTotalVolume(ectx.globalDofIdx) *
3015 getValue(ectx.intQuants.porosity());
3024 if (reportStepNum > 0 && !isSubStep) {
3026 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
3027 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
3029 [&c = this->collectOnIORank_](
const int idx)
3030 {
return c.isCartIdxOnThisRank(idx); });
3032 const auto extraHandlers = std::array{
3041 const Simulator& simulator_;
3042 const CollectDataOnIORankType& collectOnIORank_;
3043 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