27#ifndef OPM_OUTPUT_BLACK_OIL_MODULE_HPP
28#define OPM_OUTPUT_BLACK_OIL_MODULE_HPP
30#include <dune/common/fvector.hh>
34#include <opm/common/Exceptions.hpp>
35#include <opm/common/TimingMacros.hpp>
36#include <opm/common/OpmLog/OpmLog.hpp>
37#include <opm/common/utility/Visitor.hpp>
39#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
41#include <opm/material/common/Valgrind.hpp>
42#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
43#include <opm/material/fluidstates/BlackOilFluidState.hpp>
44#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
51#include <opm/output/data/Cells.hpp>
52#include <opm/output/eclipse/EclipseIO.hpp>
53#include <opm/output/eclipse/Inplace.hpp>
74template <
class TypeTag>
75class EcfvDiscretization;
83template <
class TypeTag>
95 using FluidState =
typename IntensiveQuantities::FluidState;
97 using Element =
typename GridView::template Codim<0>::Entity;
98 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
101 using Dir = FaceDir::DirEnum;
108 static constexpr int conti0EqIdx = Indices::conti0EqIdx;
109 static constexpr int numPhases = FluidSystem::numPhases;
110 static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
111 static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
112 static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
113 static constexpr int gasCompIdx = FluidSystem::gasCompIdx;
114 static constexpr int oilCompIdx = FluidSystem::oilCompIdx;
115 static constexpr int waterCompIdx = FluidSystem::waterCompIdx;
116 enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
117 enum { enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>() };
118 enum { enableMICP = Indices::enableMICP };
119 enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
120 enum { enableDisgasInWater = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
121 enum { enableDissolvedGas = Indices::compositionSwitchIdx >= 0 };
123 template<
class VectorType>
124 static Scalar value_or_zero(
int idx,
const VectorType& v)
129 return v.empty() ? 0.0 : v[idx];
134 const SummaryConfig& smryCfg,
136 :
BaseType(simulator.vanguard().eclState(),
137 simulator.vanguard().schedule(),
139 simulator.vanguard().summaryState(),
141 [this](const int idx)
142 {
return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
143 simulator.vanguard().grid().comm(),
144 getPropValue<TypeTag, Properties::EnableEnergy>(),
145 getPropValue<TypeTag, Properties::EnableTemperature>(),
146 getPropValue<TypeTag, Properties::EnableMech>(),
147 getPropValue<TypeTag, Properties::EnableSolvent>(),
148 getPropValue<TypeTag, Properties::EnablePolymer>(),
149 getPropValue<TypeTag, Properties::EnableFoam>(),
150 getPropValue<TypeTag, Properties::EnableBrine>(),
151 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
152 getPropValue<TypeTag, Properties::EnableExtbo>(),
153 getPropValue<TypeTag, Properties::EnableBioeffects>())
154 , simulator_(simulator)
155 , collectOnIORank_(collectOnIORank)
157 for (
auto& region_pair : this->
regions_) {
158 this->createLocalRegion_(region_pair.second);
161 auto isCartIdxOnThisRank = [&collectOnIORank](
const int idx) {
162 return collectOnIORank.isCartIdxOnThisRank(idx);
167 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
168 const std::string msg =
"The output code does not support --owner-cells-first=false.";
169 if (collectOnIORank.isIORank()) {
172 OPM_THROW_NOLOG(std::runtime_error, msg);
175 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
176 auto rset = this->
eclState_.fieldProps().fip_regions();
177 rset.push_back(
"PVTNUM");
183 .emplace(this->simulator_.gridView().comm(),
184 FluidSystem::numPhases, rset,
185 [fp = std::cref(this->eclState_.fieldProps())]
186 (
const std::string& rsetName) ->
decltype(
auto)
187 { return fp.get().get_int(rsetName); });
197 const unsigned reportStepNum,
200 const bool isRestart)
206 const auto& problem = this->simulator_.problem();
213 &problem.materialLawManager()->hysteresisConfig(),
214 problem.eclWriter().getOutputNnc().size());
219 const int reportStepNum)
221 this->setupElementExtractors_();
222 this->setupBlockExtractors_(isSubStep, reportStepNum);
228 this->extractors_.clear();
229 this->blockExtractors_.clear();
230 this->extraBlockExtractors_.clear();
244 if (this->extractors_.empty()) {
248 const auto& matLawManager = simulator_.problem().materialLawManager();
251 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
252 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
253 const auto& fs = intQuants.fluidState();
256 elemCtx.globalSpaceIndex(dofIdx, 0),
257 elemCtx.primaryVars(dofIdx, 0).pvtRegionIndex(),
264 if (matLawManager->enableHysteresis()) {
265 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
266 matLawManager->oilWaterHysteresisParams(hysterParams.
somax,
271 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
272 matLawManager->gasOilHysteresisParams(hysterParams.
sgmax,
290 if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
294 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
296 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
297 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
299 const auto be_it = this->blockExtractors_.find(cartesianIdx);
300 const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
301 if (be_it == this->blockExtractors_.end() &&
302 bee_it == this->extraBlockExtractors_.end())
307 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
308 const auto& fs = intQuants.fluidState();
318 if (be_it != this->blockExtractors_.end()) {
321 if (bee_it != this->extraBlockExtractors_.end()) {
328 const std::size_t reportStepNum,
330 boost::posix_time::ptime currentDate,
335 if (comm.rank() != 0) {
340 std::unique_ptr<FIPConfig> fipSched;
341 if (reportStepNum > 0) {
342 const auto& rpt = this->
schedule_[reportStepNum-1].rpt_config.get();
343 fipSched = std::make_unique<FIPConfig>(rpt);
345 const FIPConfig& fipc = reportStepNum == 0 ? this->
eclState_.getEclipseConfig().fip()
350 this->
logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
353 this->
logOutput_.fip(inplace, initial_inplace,
"");
355 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
356 this->
logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
358 if (fipc.output(FIPConfig::OutputField::RESV))
362 if (fipc.output(FIPConfig::OutputField::FIP)) {
363 for (
const auto& reg : this->regions_) {
364 if (reg.first !=
"FIPNUM") {
365 std::ostringstream ss;
366 ss <<
"BAL" << reg.first.substr(3);
367 this->
logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
368 this->
logOutput_.fip(inplace, initial_inplace, reg.first);
370 if (fipc.output(FIPConfig::OutputField::RESV))
382 if (comm.rank() != 0) {
386 if ((reportStepNum == 0) && (!substep) &&
387 (this->
schedule_.initialReportConfiguration().has_value()) &&
388 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
390 std::ostringstream csv_stream;
396 this->
logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
398 for (
const auto& reg : this->regions_) {
399 if (reg.first !=
"FIPNUM") {
400 this->
logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
404 const IOConfig& io = this->
eclState_.getIOConfig();
405 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
407 std::ofstream outputFile(csv_fname);
409 outputFile << csv_stream.str();
443 template <
class ActiveIndex,
class CartesianIndex>
445 ActiveIndex&& activeIndex,
446 CartesianIndex&& cartesianIndex)
449 const auto identifyCell = [&activeIndex, &cartesianIndex](
const Element& elem)
452 const auto cellIndex = activeIndex(elem);
455 static_cast<int>(cellIndex),
456 cartesianIndex(cellIndex),
457 elem.partitionType() == Dune::InteriorEntity
461 const auto timeIdx = 0u;
462 const auto& stencil = elemCtx.stencil(timeIdx);
463 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
465 for (
auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
466 const auto& face = stencil.interiorFace(scvfIdx);
467 const auto left = identifyCell(stencil.element(face.interiorIndex()));
468 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
470 const auto rates = this->
471 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
504 template <
class Flu
idState>
507 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
511 fs.setSaturation(phaseIdx, this->
saturation_[phaseIdx][elemIdx]);
517 std::array<Scalar, numPhases> pc = {0};
518 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
519 MaterialLaw::capillaryPressures(pc, matParams, fs);
521 Valgrind::CheckDefined(pc);
523 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
524 if (!FluidSystem::phaseIsActive(phaseIdx))
527 if (Indices::oilEnabled)
528 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
529 else if (Indices::gasEnabled)
530 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
531 else if (Indices::waterEnabled)
533 fs.setPressure(phaseIdx, pressure);
539 if constexpr (enableDissolvedGas) {
540 if (!this->
rs_.empty())
541 fs.setRs(this->rs_[elemIdx]);
542 if (!this->
rv_.empty())
543 fs.setRv(this->rv_[elemIdx]);
545 if constexpr (enableDisgasInWater) {
546 if (!this->
rsw_.empty())
547 fs.setRsw(this->rsw_[elemIdx]);
549 if constexpr (enableVapwat) {
550 if (!this->
rvw_.empty())
551 fs.setRvw(this->rvw_[elemIdx]);
557 if (!this->
soMax_.empty())
558 simulator.problem().setMaxOilSaturation(elemIdx, this->
soMax_[elemIdx]);
560 if (simulator.problem().materialLawManager()->enableHysteresis()) {
561 auto matLawManager = simulator.problem().materialLawManager();
563 if (FluidSystem::phaseIsActive(oilPhaseIdx)
564 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
569 if (matLawManager->enableNonWettingHysteresis()) {
570 if (!this->
soMax_.empty()) {
571 somax = this->
soMax_[elemIdx];
574 if (matLawManager->enableWettingHysteresis()) {
575 if (!this->
swMax_.empty()) {
576 swmax = this->
swMax_[elemIdx];
579 if (matLawManager->enablePCHysteresis()) {
580 if (!this->
swmin_.empty()) {
581 swmin = this->
swmin_[elemIdx];
584 matLawManager->setOilWaterHysteresisParams(
585 somax, swmax, swmin, elemIdx);
587 if (FluidSystem::phaseIsActive(oilPhaseIdx)
588 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
593 if (matLawManager->enableNonWettingHysteresis()) {
594 if (!this->
sgmax_.empty()) {
595 sgmax = this->
sgmax_[elemIdx];
598 if (matLawManager->enableWettingHysteresis()) {
599 if (!this->
shmax_.empty()) {
600 shmax = this->
shmax_[elemIdx];
603 if (matLawManager->enablePCHysteresis()) {
604 if (!this->
somin_.empty()) {
605 somin = this->
somin_[elemIdx];
608 matLawManager->setGasOilHysteresisParams(
609 sgmax, shmax, somin, elemIdx);
614 if (simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT")) {
615 simulator.problem().materialLawManager()
616 ->applyRestartSwatInit(elemIdx, this->
ppcw_[elemIdx]);
622 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
623 updateFluidInPlace_(elemCtx, dofIdx);
628 const IntensiveQuantities& intQuants,
629 const double totVolume)
631 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
635 template <
typename T>
636 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
638 template <
typename,
class =
void>
639 struct HasGeoMech :
public std::false_type {};
641 template <
typename Problem>
643 Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
644 > :
public std::true_type {};
646 bool isDefunctParallelWell(
const std::string& wname)
const override
648 if (simulator_.gridView().comm().size() == 1)
650 const auto& parallelWells = simulator_.vanguard().parallelWells();
651 std::pair<std::string, bool> value {wname,
true};
652 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
653 return candidate == parallelWells.end() || *candidate != value;
656 bool isOwnedByCurrentRank(
const std::string& wname)
const override
658 return this->simulator_.problem().wellModel().isOwner(wname);
661 bool isOnCurrentRank(
const std::string& wname)
const override
663 return this->simulator_.problem().wellModel().hasLocalCells(wname);
666 void updateFluidInPlace_(
const ElementContext& elemCtx,
const unsigned dofIdx)
668 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
669 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
670 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
672 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
675 void updateFluidInPlace_(
const unsigned globalDofIdx,
676 const IntensiveQuantities& intQuants,
677 const double totVolume)
681 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
684 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
688 void createLocalRegion_(std::vector<int>& region)
694 region.resize(simulator_.gridView().size(0));
695 std::size_t elemIdx = 0;
696 for (
const auto& elem : elements(simulator_.gridView())) {
697 if (elem.partitionType() != Dune::InteriorEntity) {
705 template <
typename Flu
idState>
706 void aggregateAverageDensityContributions_(
const FluidState& fs,
707 const unsigned int globalDofIdx,
710 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
711 pvCellValue.porv = porv;
713 for (
auto phaseIdx = 0*FluidSystem::numPhases;
714 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
716 if (! FluidSystem::phaseIsActive(phaseIdx)) {
720 pvCellValue.value = getValue(fs.density(phaseIdx));
721 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
724 ->addCell(globalDofIdx,
725 RegionPhasePoreVolAverage::Phase { phaseIdx },
745 data::InterRegFlowMap::FlowRates
746 getComponentSurfaceRates(
const ElementContext& elemCtx,
747 const Scalar faceArea,
748 const std::size_t scvfIdx,
749 const std::size_t timeIdx)
const
751 using Component = data::InterRegFlowMap::Component;
753 auto rates = data::InterRegFlowMap::FlowRates {};
755 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
757 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
759 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
760 const auto& up = elemCtx
761 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
763 const auto pvtReg = up.pvtRegionIndex();
765 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
766 (up.fluidState(), oilPhaseIdx, pvtReg));
768 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
770 rates[Component::Oil] += qO;
772 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
773 const auto Rs = getValue(
774 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
775 (up.fluidState(), pvtReg));
777 rates[Component::Gas] += qO * Rs;
778 rates[Component::Disgas] += qO * Rs;
782 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
783 const auto& up = elemCtx
784 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
786 const auto pvtReg = up.pvtRegionIndex();
788 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
789 (up.fluidState(), gasPhaseIdx, pvtReg));
791 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
793 rates[Component::Gas] += qG;
795 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
796 const auto Rv = getValue(
797 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
798 (up.fluidState(), pvtReg));
800 rates[Component::Oil] += qG * Rv;
801 rates[Component::Vapoil] += qG * Rv;
805 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
806 const auto& up = elemCtx
807 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
809 const auto pvtReg = up.pvtRegionIndex();
811 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
812 (up.fluidState(), waterPhaseIdx, pvtReg));
814 rates[Component::Water] +=
815 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
821 template <
typename Flu
idState>
822 Scalar hydroCarbonFraction(
const FluidState& fs)
const
824 if (this->
eclState_.runspec().co2Storage()) {
831 auto hydrocarbon = Scalar {0};
832 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
833 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
836 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
837 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
843 void updateTotalVolumesAndPressures_(
const unsigned globalDofIdx,
844 const IntensiveQuantities& intQuants,
845 const double totVolume)
847 const auto& fs = intQuants.fluidState();
849 const double pv = totVolume * intQuants.porosity().value();
850 const auto hydrocarbon = this->hydroCarbonFraction(fs);
854 totVolume * intQuants.referencePorosity());
861 !this->pressureTimesPoreVolume_.empty())
864 assert(this->
fipC_.
get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
866 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
868 getValue(fs.pressure(oilPhaseIdx)) * pv;
873 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
875 getValue(fs.pressure(gasPhaseIdx)) * pv;
880 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
882 getValue(fs.pressure(waterPhaseIdx)) * pv;
887 void updatePhaseInplaceVolumes_(
const unsigned globalDofIdx,
888 const IntensiveQuantities& intQuants,
889 const double totVolume)
891 std::array<Scalar, FluidSystem::numPhases> fip {};
892 std::array<Scalar, FluidSystem::numPhases> fipr{};
894 const auto& fs = intQuants.fluidState();
895 const auto pv = totVolume * intQuants.porosity().value();
897 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
898 if (!FluidSystem::phaseIsActive(phaseIdx)) {
902 const auto b = getValue(fs.invB(phaseIdx));
903 const auto s = getValue(fs.saturation(phaseIdx));
905 fipr[phaseIdx] = s * pv;
906 fip [phaseIdx] = b * fipr[phaseIdx];
911 fs.saltConcentration().value(),
914 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
915 FluidSystem::phaseIsActive(gasPhaseIdx))
917 this->updateOilGasDistribution(globalDofIdx, fs, fip);
920 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
921 FluidSystem::phaseIsActive(gasPhaseIdx))
923 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
926 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
929 this->updateCO2InGas(globalDofIdx, pv, intQuants);
933 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
934 FluidSystem::phaseIsActive(oilPhaseIdx)))
936 this->updateCO2InWater(globalDofIdx, pv, fs);
939 if constexpr(enableBioeffects) {
940 const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
941 getValue(fs.invB(waterPhaseIdx));
943 this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
946 this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
948 if constexpr(enableMICP) {
950 this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
953 this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
956 this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
963 this->updateWaterMass(globalDofIdx, fs, fip);
967 template <
typename Flu
idState,
typename FIPArray>
968 void updateOilGasDistribution(
const unsigned globalDofIdx,
969 const FluidState& fs,
973 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
974 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
979 template <
typename Flu
idState,
typename FIPArray>
980 void updateGasWaterDistribution(
const unsigned globalDofIdx,
981 const FluidState& fs,
985 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
986 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
991 template <
typename IntensiveQuantities>
992 void updateCO2InGas(
const unsigned globalDofIdx,
994 const IntensiveQuantities& intQuants)
996 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
997 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
999 const auto& fs = intQuants.fluidState();
1000 Scalar sgcr = scaledDrainageInfo.Sgcr;
1001 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1002 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1003 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
1006 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1007 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
1008 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
1010 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1011 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1013 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams,
true);
1017 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1018 Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
1019 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
1020 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
1022 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1023 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1024 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1025 strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1029 const typename FIPContainer<FluidSystem>::Co2InGasInput v{
1033 getValue(fs.density(gasPhaseIdx)),
1034 FluidSystem::phaseIsActive(waterPhaseIdx)
1035 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1036 : FluidSystem::convertRvToXgO(getValue(fs.Rv()), fs.pvtRegionIndex()),
1037 FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
1038 trappedGasSaturation,
1039 strandedGasSaturation,
1045 template <
typename Flu
idState>
1046 void updateCO2InWater(
const unsigned globalDofIdx,
1048 const FluidState& fs)
1050 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1051 ? this->co2InWaterFromOil(fs, pv)
1052 : this->co2InWaterFromWater(fs, pv);
1054 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1059 template <
typename Flu
idState>
1060 Scalar co2InWaterFromWater(
const FluidState& fs,
const double pv)
const
1062 const double rhow = getValue(fs.density(waterPhaseIdx));
1063 const double sw = getValue(fs.saturation(waterPhaseIdx));
1064 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1066 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1068 return xwG * pv * rhow * sw / mM;
1071 template <
typename Flu
idState>
1072 Scalar co2InWaterFromOil(
const FluidState& fs,
const double pv)
const
1074 const double rhoo = getValue(fs.density(oilPhaseIdx));
1075 const double so = getValue(fs.saturation(oilPhaseIdx));
1076 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1078 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1080 return xoG * pv * rhoo * so / mM;
1083 template <
typename Flu
idState,
typename FIPArray>
1084 void updateWaterMass(
const unsigned globalDofIdx,
1085 const FluidState& fs,
1089 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
1094 template <
typename IntensiveQuantities>
1095 void updateMicrobialMass(
const unsigned globalDofIdx,
1096 const IntensiveQuantities& intQuants,
1097 const double surfVolWat)
1099 const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
1104 template <
typename IntensiveQuantities>
1105 void updateOxygenMass(
const unsigned globalDofIdx,
1106 const IntensiveQuantities& intQuants,
1107 const double surfVolWat)
1109 const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
1114 template <
typename IntensiveQuantities>
1115 void updateUreaMass(
const unsigned globalDofIdx,
1116 const IntensiveQuantities& intQuants,
1117 const double surfVolWat)
1119 const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
1124 template <
typename IntensiveQuantities>
1125 void updateBiofilmMass(
const unsigned globalDofIdx,
1126 const IntensiveQuantities& intQuants,
1127 const double totVolume)
1129 const Scalar mass = totVolume * intQuants.biofilmMass().value();
1134 template <
typename IntensiveQuantities>
1135 void updateCalciteMass(
const unsigned globalDofIdx,
1136 const IntensiveQuantities& intQuants,
1137 const double totVolume)
1139 const Scalar mass = totVolume * intQuants.calciteMass().value();
1145 void setupElementExtractors_()
1147 using Entry =
typename Extractor::Entry;
1148 using Context =
typename Extractor::Context;
1149 using ScalarEntry =
typename Extractor::ScalarEntry;
1150 using PhaseEntry =
typename Extractor::PhaseEntry;
1152 const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
1153 const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
1155 auto extractors = std::array{
1157 [](
const unsigned phase,
const Context& ectx)
1158 {
return getValue(ectx.fs.saturation(phase)); }
1161 Entry{PhaseEntry{&this->
invB_,
1162 [](
const unsigned phase,
const Context& ectx)
1163 {
return getValue(ectx.fs.invB(phase)); }
1167 [](
const unsigned phase,
const Context& ectx)
1168 {
return getValue(ectx.fs.density(phase)); }
1172 [](
const unsigned phase,
const Context& ectx)
1173 {
return getValue(ectx.intQuants.relativePermeability(phase)); }
1177 [
this](
const unsigned phaseIdx,
const Context& ectx)
1179 if (this->
extboC_.allocated() && phaseIdx == oilPhaseIdx) {
1180 return getValue(ectx.intQuants.oilViscosity());
1182 else if (this->
extboC_.allocated() && phaseIdx == gasPhaseIdx) {
1183 return getValue(ectx.intQuants.gasViscosity());
1186 return getValue(ectx.fs.viscosity(phaseIdx));
1192 [&modelResid = this->simulator_.model().linearizer().residual()]
1193 (
const unsigned phaseIdx,
const Context& ectx)
1195 const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
1196 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
1197 return modelResid[ectx.globalDofIdx][activeCompIdx];
1203 [&problem = this->simulator_.problem()](
const Context& ectx)
1205 return problem.template
1206 rockCompPoroMultiplier<Scalar>(ectx.intQuants,
1212 [&problem = this->simulator_.problem()](
const Context& ectx)
1215 template rockCompTransMultiplier<Scalar>(ectx.intQuants,
1220 [&problem = this->simulator_.problem()](
const Context& ectx)
1222 return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
1223 problem.minOilPressure(ectx.globalDofIdx));
1229 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1233 FluidSystem::bubblePointPressure(ectx.fs,
1234 ectx.intQuants.pvtRegionIndex())
1236 }
catch (
const NumericalProblem&) {
1237 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1238 failedCells.push_back(cartesianIdx);
1246 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1250 FluidSystem::dewPointPressure(ectx.fs,
1251 ectx.intQuants.pvtRegionIndex())
1253 }
catch (
const NumericalProblem&) {
1254 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1255 failedCells.push_back(cartesianIdx);
1262 [&problem = simulator_.problem()](
const Context& ectx)
1263 {
return problem.overburdenPressure(ectx.globalDofIdx); }
1267 [](
const Context& ectx)
1268 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }
1271 Entry{ScalarEntry{&this->
sSol_,
1272 [](
const Context& ectx)
1273 {
return getValue(ectx.intQuants.solventSaturation()); }
1276 Entry{ScalarEntry{&this->
rswSol_,
1277 [](
const Context& ectx)
1278 {
return getValue(ectx.intQuants.rsSolw()); }
1282 [](
const Context& ectx)
1283 {
return getValue(ectx.intQuants.polymerConcentration()); }
1286 Entry{ScalarEntry{&this->
cFoam_,
1287 [](
const Context& ectx)
1288 {
return getValue(ectx.intQuants.foamConcentration()); }
1291 Entry{ScalarEntry{&this->
cSalt_,
1292 [](
const Context& ectx)
1293 {
return getValue(ectx.fs.saltConcentration()); }
1296 Entry{ScalarEntry{&this->
pSalt_,
1297 [](
const Context& ectx)
1298 {
return getValue(ectx.fs.saltSaturation()); }
1302 [](
const Context& ectx)
1303 {
return getValue(ectx.intQuants.permFactor()); }
1306 Entry{ScalarEntry{&this->
rPorV_,
1307 [&model = this->simulator_.model()](
const Context& ectx)
1309 const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
1310 return totVolume * getValue(ectx.intQuants.porosity());
1314 Entry{ScalarEntry{&this->
rs_,
1315 [](
const Context& ectx)
1316 {
return getValue(ectx.fs.Rs()); }
1319 Entry{ScalarEntry{&this->
rv_,
1320 [](
const Context& ectx)
1321 {
return getValue(ectx.fs.Rv()); }
1324 Entry{ScalarEntry{&this->
rsw_,
1325 [](
const Context& ectx)
1326 {
return getValue(ectx.fs.Rsw()); }
1329 Entry{ScalarEntry{&this->
rvw_,
1330 [](
const Context& ectx)
1331 {
return getValue(ectx.fs.Rvw()); }
1334 Entry{ScalarEntry{&this->
ppcw_,
1335 [&matLawManager = *this->simulator_.problem().materialLawManager()]
1336 (
const Context& ectx)
1338 return matLawManager.
1339 oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
1344 [&problem = this->simulator_.problem()](
const Context& ectx)
1346 return problem.drsdtcon(ectx.globalDofIdx,
1351 Entry{ScalarEntry{&this->
pcgw_,
1352 [](
const Context& ectx)
1354 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1355 getValue(ectx.fs.pressure(waterPhaseIdx));
1359 Entry{ScalarEntry{&this->
pcow_,
1360 [](
const Context& ectx)
1362 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1363 getValue(ectx.fs.pressure(waterPhaseIdx));
1367 Entry{ScalarEntry{&this->
pcog_,
1368 [](
const Context& ectx)
1370 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1371 getValue(ectx.fs.pressure(oilPhaseIdx));
1376 [](
const Context& ectx)
1378 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1380 return getValue(ectx.fs.pressure(oilPhaseIdx));
1382 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1384 return getValue(ectx.fs.pressure(gasPhaseIdx));
1388 return getValue(ectx.fs.pressure(waterPhaseIdx));
1394 [&problem = this->simulator_.problem()](
const Context& ectx)
1396 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1397 return FluidSystem::template
1398 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1406 [&problem = this->simulator_.problem()](
const Context& ectx)
1408 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1409 return FluidSystem::template
1410 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1418 [&problem = this->simulator_.problem()](
const Context& ectx)
1420 const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
1421 return FluidSystem::template
1422 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1430 [](
const Context& ectx)
1432 return FluidSystem::template
1433 saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
1440 [](
const Context& ectx)
1442 return 1.0 / FluidSystem::template
1443 inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1450 [](
const Context& ectx)
1452 return 1.0 / FluidSystem::template
1453 saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1460 [](
const Context& ectx)
1462 return FluidSystem::template
1463 saturationPressure<FluidState, Scalar>(ectx.fs,
1469 Entry{ScalarEntry{&this->
soMax_,
1470 [&problem = this->simulator_.problem()](
const Context& ectx)
1472 return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
1473 problem.maxOilSaturation(ectx.globalDofIdx));
1476 !hysteresisConfig.enableHysteresis()
1478 Entry{ScalarEntry{&this->
swMax_,
1479 [&problem = this->simulator_.problem()](
const Context& ectx)
1481 return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
1482 problem.maxWaterSaturation(ectx.globalDofIdx));
1485 !hysteresisConfig.enableHysteresis()
1487 Entry{ScalarEntry{&this->
soMax_,
1488 [](
const Context& ectx)
1489 {
return ectx.hParams.somax; }
1491 hysteresisConfig.enableHysteresis() &&
1492 hysteresisConfig.enableNonWettingHysteresis() &&
1493 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1494 FluidSystem::phaseIsActive(waterPhaseIdx)
1496 Entry{ScalarEntry{&this->
swMax_,
1497 [](
const Context& ectx)
1498 {
return ectx.hParams.swmax; }
1500 hysteresisConfig.enableHysteresis() &&
1501 hysteresisConfig.enableWettingHysteresis() &&
1502 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1503 FluidSystem::phaseIsActive(waterPhaseIdx)
1505 Entry{ScalarEntry{&this->
swmin_,
1506 [](
const Context& ectx)
1507 {
return ectx.hParams.swmin; }
1509 hysteresisConfig.enableHysteresis() &&
1510 hysteresisConfig.enablePCHysteresis() &&
1511 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1512 FluidSystem::phaseIsActive(waterPhaseIdx)
1514 Entry{ScalarEntry{&this->
sgmax_,
1515 [](
const Context& ectx)
1516 {
return ectx.hParams.sgmax; }
1518 hysteresisConfig.enableHysteresis() &&
1519 hysteresisConfig.enableNonWettingHysteresis() &&
1520 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1521 FluidSystem::phaseIsActive(gasPhaseIdx)
1523 Entry{ScalarEntry{&this->
shmax_,
1524 [](
const Context& ectx)
1525 {
return ectx.hParams.shmax; }
1527 hysteresisConfig.enableHysteresis() &&
1528 hysteresisConfig.enableWettingHysteresis() &&
1529 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1530 FluidSystem::phaseIsActive(gasPhaseIdx)
1532 Entry{ScalarEntry{&this->
somin_,
1533 [](
const Context& ectx)
1534 {
return ectx.hParams.somin; }
1536 hysteresisConfig.enableHysteresis() &&
1537 hysteresisConfig.enablePCHysteresis() &&
1538 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1539 FluidSystem::phaseIsActive(gasPhaseIdx)
1541 Entry{[&model = this->simulator_.model(),
this](
const Context& ectx)
1545 const auto porv = ectx.intQuants.referencePorosity()
1546 * model.dofTotalVolume(ectx.globalDofIdx);
1548 this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
1549 static_cast<double>(porv));
1552 Entry{[&extboC = this->
extboC_](
const Context& ectx)
1554 extboC.assignVolumes(ectx.globalDofIdx,
1555 ectx.intQuants.xVolume().value(),
1556 ectx.intQuants.yVolume().value());
1557 extboC.assignZFraction(ectx.globalDofIdx,
1558 ectx.intQuants.zFraction().value());
1560 const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
1561 getValue(ectx.fs.invB(oilPhaseIdx)) +
1562 getValue(ectx.fs.saturation(gasPhaseIdx)) *
1563 getValue(ectx.fs.invB(gasPhaseIdx)) *
1564 getValue(ectx.fs.Rv());
1565 const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1566 getValue(ectx.fs.invB(gasPhaseIdx)) *
1567 (1.0 - ectx.intQuants.yVolume().value()) +
1568 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1569 getValue(ectx.fs.invB(oilPhaseIdx)) *
1570 getValue(ectx.fs.Rs()) *
1571 (1.0 - ectx.intQuants.xVolume().value());
1572 const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1573 getValue(ectx.fs.invB(gasPhaseIdx)) *
1574 ectx.intQuants.yVolume().value() +
1575 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1576 getValue(ectx.fs.invB(oilPhaseIdx)) *
1577 getValue(ectx.fs.Rs()) *
1578 ectx.intQuants.xVolume().value();
1579 const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1580 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1581 const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
1582 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
1583 extboC.assignMassFractions(ectx.globalDofIdx,
1584 stdVolGas * rhoG / stdMassTotal,
1585 stdVolOil * rhoO / stdMassTotal,
1586 stdVolCo2 * rhoCO2 / stdMassTotal);
1589 Entry{[&bioeffectsC = this->
bioeffectsC_](
const Context& ectx)
1591 bioeffectsC.assign(ectx.globalDofIdx,
1592 ectx.intQuants.microbialConcentration().value(),
1593 ectx.intQuants.biofilmVolumeFraction().value());
1594 if (Indices::enableMICP) {
1595 bioeffectsC.assign(ectx.globalDofIdx,
1596 ectx.intQuants.oxygenConcentration().value(),
1597 ectx.intQuants.ureaConcentration().value(),
1598 ectx.intQuants.calciteVolumeFraction().value());
1602 Entry{[&rftC = this->
rftC_,
1603 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1605 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1606 rftC.assign(cartesianIdx,
1607 [&fs = ectx.fs]() {
return getValue(fs.pressure(oilPhaseIdx)); },
1608 [&fs = ectx.fs]() {
return getValue(fs.saturation(waterPhaseIdx)); },
1609 [&fs = ectx.fs]() {
return getValue(fs.saturation(gasPhaseIdx)); });
1613 &tM = this->simulator_.problem().tracerModel()](
const Context& ectx)
1615 tC.assignFreeConcentrations(ectx.globalDofIdx,
1616 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1617 {
return tM.freeTracerConcentration(tracerIdx, gIdx); });
1618 tC.assignSolConcentrations(ectx.globalDofIdx,
1619 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1620 {
return tM.solTracerConcentration(tracerIdx, gIdx); });
1623 Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
1624 &flowsC = this->
flowsC_](
const Context& ectx)
1626 const auto gas_idx = Indices::gasEnabled ?
1627 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1628 const auto oil_idx = Indices::oilEnabled ?
1629 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1630 const auto water_idx = Indices::waterEnabled ?
1631 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1632 const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
1633 for (
const auto& flowsInfo : flowsInfos) {
1634 flowsC.assignFlows(ectx.globalDofIdx,
1637 value_or_zero(gas_idx, flowsInfo.flow),
1638 value_or_zero(oil_idx, flowsInfo.flow),
1639 value_or_zero(water_idx, flowsInfo.flow));
1641 }, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
1643 Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
1644 &flowsC = this->
flowsC_](
const Context& ectx)
1646 const auto gas_idx = Indices::gasEnabled ?
1647 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1648 const auto oil_idx = Indices::oilEnabled ?
1649 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1650 const auto water_idx = Indices::waterEnabled ?
1651 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1652 const auto& floresInfos = floresInf[ectx.globalDofIdx];
1653 for (
const auto& floresInfo : floresInfos) {
1654 flowsC.assignFlores(ectx.globalDofIdx,
1657 value_or_zero(gas_idx, floresInfo.flow),
1658 value_or_zero(oil_idx, floresInfo.flow),
1659 value_or_zero(water_idx, floresInfo.flow));
1661 }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
1668 Entry{ScalarEntry{&this->
rv_,
1669 [&problem = this->simulator_.problem()](
const Context& ectx)
1670 {
return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
1672 simulator_.episodeIndex() < 0 &&
1673 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1674 FluidSystem::phaseIsActive(gasPhaseIdx)
1676 Entry{ScalarEntry{&this->
rs_,
1677 [&problem = this->simulator_.problem()](
const Context& ectx)
1678 {
return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
1680 simulator_.episodeIndex() < 0 &&
1681 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1682 FluidSystem::phaseIsActive(gasPhaseIdx)
1684 Entry{ScalarEntry{&this->
rsw_,
1685 [&problem = this->simulator_.problem()](
const Context& ectx)
1686 {
return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
1688 simulator_.episodeIndex() < 0 &&
1689 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1690 FluidSystem::phaseIsActive(gasPhaseIdx)
1692 Entry{ScalarEntry{&this->
rvw_,
1693 [&problem = this->simulator_.problem()](
const Context& ectx)
1694 {
return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
1696 simulator_.episodeIndex() < 0 &&
1697 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1698 FluidSystem::phaseIsActive(gasPhaseIdx)
1702 [&problem = this->simulator_.problem()](
const unsigned phase,
1703 const Context& ectx)
1705 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1706 return FluidSystem::density(fsInitial,
1708 ectx.intQuants.pvtRegionIndex());
1711 simulator_.episodeIndex() < 0 &&
1712 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1713 FluidSystem::phaseIsActive(gasPhaseIdx)
1715 Entry{PhaseEntry{&this->
invB_,
1716 [&problem = this->simulator_.problem()](
const unsigned phase,
1717 const Context& ectx)
1719 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1720 return FluidSystem::inverseFormationVolumeFactor(fsInitial,
1722 ectx.intQuants.pvtRegionIndex());
1725 simulator_.episodeIndex() < 0 &&
1726 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1727 FluidSystem::phaseIsActive(gasPhaseIdx)
1730 [&problem = this->simulator_.problem()](
const unsigned phase,
1731 const Context& ectx)
1733 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1734 return FluidSystem::viscosity(fsInitial,
1736 ectx.intQuants.pvtRegionIndex());
1739 simulator_.episodeIndex() < 0 &&
1740 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1741 FluidSystem::phaseIsActive(gasPhaseIdx)
1748 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
1749 if (this->
mech_.allocated()) {
1750 this->extractors_.push_back(
1751 Entry{[&mech = this->
mech_,
1752 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1754 mech.assignDelStress(ectx.globalDofIdx,
1755 model.delstress(ectx.globalDofIdx));
1757 mech.assignDisplacement(ectx.globalDofIdx,
1758 model.disp(ectx.globalDofIdx,
true));
1761 mech.assignFracStress(ectx.globalDofIdx,
1762 model.fractureStress(ectx.globalDofIdx));
1764 mech.assignLinStress(ectx.globalDofIdx,
1765 model.linstress(ectx.globalDofIdx));
1767 mech.assignPotentialForces(ectx.globalDofIdx,
1768 model.mechPotentialForce(ectx.globalDofIdx),
1769 model.mechPotentialPressForce(ectx.globalDofIdx),
1770 model.mechPotentialTempForce(ectx.globalDofIdx));
1772 mech.assignStrain(ectx.globalDofIdx,
1773 model.strain(ectx.globalDofIdx,
true));
1776 mech.assignStress(ectx.globalDofIdx,
1777 model.stress(ectx.globalDofIdx,
true));
1786 void setupBlockExtractors_(
const bool isSubStep,
1787 const int reportStepNum)
1790 using Context =
typename BlockExtractor::Context;
1791 using PhaseEntry =
typename BlockExtractor::PhaseEntry;
1792 using ScalarEntry =
typename BlockExtractor::ScalarEntry;
1794 using namespace std::string_view_literals;
1796 const auto pressure_handler =
1797 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1798 [](
const Context& ectx)
1800 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1801 return getValue(ectx.fs.pressure(oilPhaseIdx));
1803 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1804 return getValue(ectx.fs.pressure(gasPhaseIdx));
1807 return getValue(ectx.fs.pressure(waterPhaseIdx));
1813 const auto handlers = std::array{
1815 Entry{PhaseEntry{std::array{
1816 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1817 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1819 [](
const unsigned phaseIdx,
const Context& ectx)
1821 return getValue(ectx.fs.saturation(phaseIdx));
1825 Entry{ScalarEntry{
"BNSAT",
1826 [](
const Context& ectx)
1828 return ectx.intQuants.solventSaturation().value();
1832 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1833 [](
const Context& ectx)
1835 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1836 return getValue(ectx.fs.temperature(oilPhaseIdx));
1838 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1839 return getValue(ectx.fs.temperature(gasPhaseIdx));
1842 return getValue(ectx.fs.temperature(waterPhaseIdx));
1847 Entry{PhaseEntry{std::array{
1848 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
1849 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
1851 [](
const unsigned phaseIdx,
const Context& ectx)
1853 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
1857 Entry{ScalarEntry{
"BKROG",
1858 [&problem = this->simulator_.problem()](
const Context& ectx)
1860 const auto& materialParams =
1861 problem.materialLawParams(ectx.elemCtx,
1864 return getValue(MaterialLaw::template
1865 relpermOilInOilGasSystem<Evaluation>(materialParams,
1870 Entry{ScalarEntry{
"BKROW",
1871 [&problem = this->simulator_.problem()](
const Context& ectx)
1873 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
1876 return getValue(MaterialLaw::template
1877 relpermOilInOilWaterSystem<Evaluation>(materialParams,
1882 Entry{ScalarEntry{
"BWPC",
1883 [](
const Context& ectx)
1885 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1886 getValue(ectx.fs.pressure(waterPhaseIdx));
1890 Entry{ScalarEntry{
"BGPC",
1891 [](
const Context& ectx)
1893 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1894 getValue(ectx.fs.pressure(oilPhaseIdx));
1898 Entry{ScalarEntry{
"BWPR",
1899 [](
const Context& ectx)
1901 return getValue(ectx.fs.pressure(waterPhaseIdx));
1905 Entry{ScalarEntry{
"BGPR",
1906 [](
const Context& ectx)
1908 return getValue(ectx.fs.pressure(gasPhaseIdx));
1912 Entry{PhaseEntry{std::array{
1913 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
1914 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
1916 [](
const unsigned phaseIdx,
const Context& ectx)
1918 return getValue(ectx.fs.viscosity(phaseIdx));
1922 Entry{PhaseEntry{std::array{
1923 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
1924 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
1926 [](
const unsigned phaseIdx,
const Context& ectx)
1928 return getValue(ectx.fs.density(phaseIdx));
1932 Entry{ScalarEntry{
"BFLOWI",
1933 [&flowsC = this->
flowsC_](
const Context& ectx)
1935 return flowsC.getFlow(ectx.globalDofIdx, Dir::XPlus, waterCompIdx);
1939 Entry{ScalarEntry{
"BFLOWJ",
1940 [&flowsC = this->
flowsC_](
const Context& ectx)
1942 return flowsC.getFlow(ectx.globalDofIdx, Dir::YPlus, waterCompIdx);
1946 Entry{ScalarEntry{
"BFLOWK",
1947 [&flowsC = this->
flowsC_](
const Context& ectx)
1949 return flowsC.getFlow(ectx.globalDofIdx, Dir::ZPlus, waterCompIdx);
1953 Entry{ScalarEntry{
"BRPV",
1954 [&model = this->simulator_.model()](
const Context& ectx)
1956 return getValue(ectx.intQuants.porosity()) *
1957 model.dofTotalVolume(ectx.globalDofIdx);
1961 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
1962 [&model = this->simulator_.model()](
const unsigned phaseIdx,
1963 const Context& ectx)
1965 return getValue(ectx.fs.saturation(phaseIdx)) *
1966 getValue(ectx.intQuants.porosity()) *
1967 model.dofTotalVolume(ectx.globalDofIdx);
1971 Entry{ScalarEntry{
"BRS",
1972 [](
const Context& ectx)
1974 return getValue(ectx.fs.Rs());
1978 Entry{ScalarEntry{
"BRV",
1979 [](
const Context& ectx)
1981 return getValue(ectx.fs.Rv());
1985 Entry{ScalarEntry{
"BOIP",
1986 [&model = this->simulator_.model()](
const Context& ectx)
1988 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
1989 getValue(ectx.fs.saturation(oilPhaseIdx)) +
1990 getValue(ectx.fs.Rv()) *
1991 getValue(ectx.fs.invB(gasPhaseIdx)) *
1992 getValue(ectx.fs.saturation(gasPhaseIdx))) *
1993 model.dofTotalVolume(ectx.globalDofIdx) *
1994 getValue(ectx.intQuants.porosity());
1998 Entry{ScalarEntry{
"BGIP",
1999 [&model = this->simulator_.model()](
const Context& ectx)
2001 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2002 getValue(ectx.fs.saturation(gasPhaseIdx));
2004 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2005 result += getValue(ectx.fs.Rs()) *
2006 getValue(ectx.fs.invB(oilPhaseIdx)) *
2007 getValue(ectx.fs.saturation(oilPhaseIdx));
2010 result += getValue(ectx.fs.Rsw()) *
2011 getValue(ectx.fs.invB(waterPhaseIdx)) *
2012 getValue(ectx.fs.saturation(waterPhaseIdx));
2016 model.dofTotalVolume(ectx.globalDofIdx) *
2017 getValue(ectx.intQuants.porosity());
2021 Entry{ScalarEntry{
"BWIP",
2022 [&model = this->simulator_.model()](
const Context& ectx)
2024 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2025 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2026 model.dofTotalVolume(ectx.globalDofIdx) *
2027 getValue(ectx.intQuants.porosity());
2031 Entry{ScalarEntry{
"BOIPL",
2032 [&model = this->simulator_.model()](
const Context& ectx)
2034 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2035 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2036 model.dofTotalVolume(ectx.globalDofIdx) *
2037 getValue(ectx.intQuants.porosity());
2041 Entry{ScalarEntry{
"BGIPL",
2042 [&model = this->simulator_.model()](
const Context& ectx)
2045 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2046 result = getValue(ectx.fs.Rs()) *
2047 getValue(ectx.fs.invB(oilPhaseIdx)) *
2048 getValue(ectx.fs.saturation(oilPhaseIdx));
2051 result = getValue(ectx.fs.Rsw()) *
2052 getValue(ectx.fs.invB(waterPhaseIdx)) *
2053 getValue(ectx.fs.saturation(waterPhaseIdx));
2056 model.dofTotalVolume(ectx.globalDofIdx) *
2057 getValue(ectx.intQuants.porosity());
2061 Entry{ScalarEntry{
"BGIPG",
2062 [&model = this->simulator_.model()](
const Context& ectx)
2064 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2065 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2066 model.dofTotalVolume(ectx.globalDofIdx) *
2067 getValue(ectx.intQuants.porosity());
2071 Entry{ScalarEntry{
"BOIPG",
2072 [&model = this->simulator_.model()](
const Context& ectx)
2074 return getValue(ectx.fs.Rv()) *
2075 getValue(ectx.fs.invB(gasPhaseIdx)) *
2076 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2077 model.dofTotalVolume(ectx.globalDofIdx) *
2078 getValue(ectx.intQuants.porosity());
2082 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2083 [&simConfig = this->
eclState_.getSimulationConfig(),
2084 &grav = this->simulator_.problem().gravity(),
2086 &problem = this->simulator_.problem(),
2087 ®ions = this->
regions_](
const unsigned phaseIdx,
const Context& ectx)
2089 auto phase = RegionPhasePoreVolAverage::Phase{};
2090 phase.ix = phaseIdx;
2099 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2102 const auto region = RegionPhasePoreVolAverage::Region {
2103 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2106 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2108 const auto press = getValue(ectx.fs.pressure(phase.ix));
2109 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2110 return press - density*dz*grav[GridView::dimensionworld - 1];
2114 Entry{ScalarEntry{
"BAMIP",
2115 [&model = this->simulator_.model()](
const Context& ectx)
2117 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2118 ectx.intQuants.pvtRegionIndex());
2119 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2120 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2122 model.dofTotalVolume(ectx.globalDofIdx) *
2123 getValue(ectx.intQuants.porosity());
2127 Entry{ScalarEntry{
"BMMIP",
2128 [&model = this->simulator_.model()](
const Context& ectx)
2130 return getValue(ectx.intQuants.microbialConcentration()) *
2131 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2132 getValue(ectx.intQuants.porosity()) *
2133 model.dofTotalVolume(ectx.globalDofIdx);
2137 Entry{ScalarEntry{
"BMOIP",
2138 [&model = this->simulator_.model()](
const Context& ectx)
2140 return getValue(ectx.intQuants.oxygenConcentration()) *
2141 getValue(ectx.intQuants.porosity()) *
2142 model.dofTotalVolume(ectx.globalDofIdx);
2146 Entry{ScalarEntry{
"BMUIP",
2147 [&model = this->simulator_.model()](
const Context& ectx)
2149 return getValue(ectx.intQuants.ureaConcentration()) *
2150 getValue(ectx.intQuants.porosity()) *
2151 model.dofTotalVolume(ectx.globalDofIdx) * 1;
2155 Entry{ScalarEntry{
"BMBIP",
2156 [&model = this->simulator_.model()](
const Context& ectx)
2158 return model.dofTotalVolume(ectx.globalDofIdx) *
2159 getValue(ectx.intQuants.biofilmMass());
2163 Entry{ScalarEntry{
"BMCIP",
2164 [&model = this->simulator_.model()](
const Context& ectx)
2166 return model.dofTotalVolume(ectx.globalDofIdx) *
2167 getValue(ectx.intQuants.calciteMass());
2171 Entry{ScalarEntry{
"BGMIP",
2172 [&model = this->simulator_.model()](
const Context& ectx)
2174 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2175 getValue(ectx.fs.saturation(gasPhaseIdx));
2177 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2178 result += getValue(ectx.fs.Rs()) *
2179 getValue(ectx.fs.invB(oilPhaseIdx)) *
2180 getValue(ectx.fs.saturation(oilPhaseIdx));
2183 result += getValue(ectx.fs.Rsw()) *
2184 getValue(ectx.fs.invB(waterPhaseIdx)) *
2185 getValue(ectx.fs.saturation(waterPhaseIdx));
2187 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2188 ectx.intQuants.pvtRegionIndex());
2190 model.dofTotalVolume(ectx.globalDofIdx) *
2191 getValue(ectx.intQuants.porosity()) *
2196 Entry{ScalarEntry{
"BGMGP",
2197 [&model = this->simulator_.model()](
const Context& ectx)
2199 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2200 ectx.intQuants.pvtRegionIndex());
2201 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2202 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2203 model.dofTotalVolume(ectx.globalDofIdx) *
2204 getValue(ectx.intQuants.porosity()) *
2209 Entry{ScalarEntry{
"BGMDS",
2210 [&model = this->simulator_.model()](
const Context& ectx)
2213 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2214 result = getValue(ectx.fs.Rs()) *
2215 getValue(ectx.fs.invB(oilPhaseIdx)) *
2216 getValue(ectx.fs.saturation(oilPhaseIdx));
2219 result = getValue(ectx.fs.Rsw()) *
2220 getValue(ectx.fs.invB(waterPhaseIdx)) *
2221 getValue(ectx.fs.saturation(waterPhaseIdx));
2223 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2224 ectx.intQuants.pvtRegionIndex());
2226 model.dofTotalVolume(ectx.globalDofIdx) *
2227 getValue(ectx.intQuants.porosity()) *
2232 Entry{ScalarEntry{
"BGMST",
2233 [&model = this->simulator_.model(),
2234 &problem = this->simulator_.problem()](
const Context& ectx)
2236 const auto& scaledDrainageInfo = problem.materialLawManager()
2237 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2238 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2239 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2240 if (problem.materialLawManager()->enableHysteresis()) {
2241 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2242 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2243 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2245 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2246 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2247 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2248 return (1.0 - xgW) *
2249 model.dofTotalVolume(ectx.globalDofIdx) *
2250 getValue(ectx.intQuants.porosity()) *
2251 getValue(ectx.fs.density(gasPhaseIdx)) *
2252 std::min(strandedGas, sg);
2256 Entry{ScalarEntry{
"BGMUS",
2257 [&model = this->simulator_.model(),
2258 &problem = this->simulator_.problem()](
const Context& ectx)
2260 const auto& scaledDrainageInfo = problem.materialLawManager()
2261 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2262 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2263 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2264 if (problem.materialLawManager()->enableHysteresis()) {
2265 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2266 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2267 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2269 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2270 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2271 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2272 return (1.0 - xgW) *
2273 model.dofTotalVolume(ectx.globalDofIdx) *
2274 getValue(ectx.intQuants.porosity()) *
2275 getValue(ectx.fs.density(gasPhaseIdx)) *
2276 std::max(Scalar{0.0}, sg - strandedGas);
2280 Entry{ScalarEntry{
"BGMTR",
2281 [&model = this->simulator_.model(),
2282 &problem = this->simulator_.problem()](
const Context& ectx)
2284 const auto& scaledDrainageInfo = problem.materialLawManager()
2285 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2286 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2287 if (problem.materialLawManager()->enableHysteresis()) {
2288 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2289 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2291 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2292 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2293 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2294 return (1.0 - xgW) *
2295 model.dofTotalVolume(ectx.globalDofIdx) *
2296 getValue(ectx.intQuants.porosity()) *
2297 getValue(ectx.fs.density(gasPhaseIdx)) *
2298 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2302 Entry{ScalarEntry{
"BGMMO",
2303 [&model = this->simulator_.model(),
2304 &problem = this->simulator_.problem()](
const Context& ectx)
2306 const auto& scaledDrainageInfo = problem.materialLawManager()
2307 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2308 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2309 if (problem.materialLawManager()->enableHysteresis()) {
2310 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2311 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2313 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2314 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2315 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2316 return (1.0 - xgW) *
2317 model.dofTotalVolume(ectx.globalDofIdx) *
2318 getValue(ectx.intQuants.porosity()) *
2319 getValue(ectx.fs.density(gasPhaseIdx)) *
2320 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2324 Entry{ScalarEntry{
"BGKTR",
2325 [&model = this->simulator_.model(),
2326 &problem = this->simulator_.problem()](
const Context& ectx)
2328 const auto& scaledDrainageInfo = problem.materialLawManager()
2329 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2330 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2331 Scalar sgcr = scaledDrainageInfo.Sgcr;
2332 if (problem.materialLawManager()->enableHysteresis()) {
2333 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2334 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2340 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2341 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2342 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2343 return (1.0 - xgW) *
2344 model.dofTotalVolume(ectx.globalDofIdx) *
2345 getValue(ectx.intQuants.porosity()) *
2346 getValue(ectx.fs.density(gasPhaseIdx)) *
2347 getValue(ectx.fs.saturation(gasPhaseIdx));
2352 Entry{ScalarEntry{
"BGKMO",
2353 [&model = this->simulator_.model(),
2354 &problem = this->simulator_.problem()](
const Context& ectx)
2356 const auto& scaledDrainageInfo = problem.materialLawManager()
2357 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2358 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2359 Scalar sgcr = scaledDrainageInfo.Sgcr;
2360 if (problem.materialLawManager()->enableHysteresis()) {
2361 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2362 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2368 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2369 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2370 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2371 return (1.0 - xgW) *
2372 model.dofTotalVolume(ectx.globalDofIdx) *
2373 getValue(ectx.intQuants.porosity()) *
2374 getValue(ectx.fs.density(gasPhaseIdx)) *
2375 getValue(ectx.fs.saturation(gasPhaseIdx));
2380 Entry{ScalarEntry{
"BGCDI",
2381 [&model = this->simulator_.model(),
2382 &problem = this->simulator_.problem()](
const Context& ectx)
2384 const auto& scaledDrainageInfo = problem.materialLawManager()
2385 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2386 Scalar sgcr = scaledDrainageInfo.Sgcr;
2387 if (problem.materialLawManager()->enableHysteresis()) {
2388 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2389 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2391 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2392 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2393 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2394 return (1.0 - xgW) *
2395 model.dofTotalVolume(ectx.globalDofIdx) *
2396 getValue(ectx.intQuants.porosity()) *
2397 getValue(ectx.fs.density(gasPhaseIdx)) *
2398 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2399 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2403 Entry{ScalarEntry{
"BGCDM",
2404 [&model = this->simulator_.model(),
2405 &problem = this->simulator_.problem()](
const Context& ectx)
2407 const auto& scaledDrainageInfo = problem.materialLawManager()
2408 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2409 Scalar sgcr = scaledDrainageInfo.Sgcr;
2410 if (problem.materialLawManager()->enableHysteresis()) {
2411 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2412 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2414 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2415 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2416 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2417 return (1.0 - xgW) *
2418 model.dofTotalVolume(ectx.globalDofIdx) *
2419 getValue(ectx.intQuants.porosity()) *
2420 getValue(ectx.fs.density(gasPhaseIdx)) *
2421 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2422 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2426 Entry{ScalarEntry{
"BGKDI",
2427 [&model = this->simulator_.model(),
2428 &problem = this->simulator_.problem()](
const Context& ectx)
2430 const auto& scaledDrainageInfo = problem.materialLawManager()
2431 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2432 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2433 Scalar sgcr = scaledDrainageInfo.Sgcr;
2434 if (problem.materialLawManager()->enableHysteresis()) {
2435 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2436 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2442 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2443 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2444 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2445 return (1.0 - xgW) *
2446 model.dofTotalVolume(ectx.globalDofIdx) *
2447 getValue(ectx.intQuants.porosity()) *
2448 getValue(ectx.fs.density(gasPhaseIdx)) *
2449 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2450 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2455 Entry{ScalarEntry{
"BGKDM",
2456 [&model = this->simulator_.model(),
2457 &problem = this->simulator_.problem()](
const Context& ectx)
2459 const auto& scaledDrainageInfo = problem.materialLawManager()
2460 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2461 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2462 Scalar sgcr = scaledDrainageInfo.Sgcr;
2463 if (problem.materialLawManager()->enableHysteresis()) {
2464 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2465 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2471 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2472 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2473 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2474 return (1.0 - xgW) *
2475 model.dofTotalVolume(ectx.globalDofIdx) *
2476 getValue(ectx.intQuants.porosity()) *
2477 getValue(ectx.fs.density(gasPhaseIdx)) *
2478 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2479 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2484 Entry{ScalarEntry{
"BWCD",
2485 [&model = this->simulator_.model()](
const Context& ectx)
2488 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2489 result = getValue(ectx.fs.Rs()) *
2490 getValue(ectx.fs.invB(oilPhaseIdx)) *
2491 getValue(ectx.fs.saturation(oilPhaseIdx));
2494 result = getValue(ectx.fs.Rsw()) *
2495 getValue(ectx.fs.invB(waterPhaseIdx)) *
2496 getValue(ectx.fs.saturation(waterPhaseIdx));
2498 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2499 ectx.intQuants.pvtRegionIndex());
2501 model.dofTotalVolume(ectx.globalDofIdx) *
2502 getValue(ectx.intQuants.porosity()) *
2504 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2508 Entry{ScalarEntry{
"BWIPG",
2509 [&model = this->simulator_.model()](
const Context& ectx)
2511 Scalar result = 0.0;
2512 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2513 result = getValue(ectx.fs.Rvw()) *
2514 getValue(ectx.fs.invB(gasPhaseIdx)) *
2515 getValue(ectx.fs.saturation(gasPhaseIdx));
2518 model.dofTotalVolume(ectx.globalDofIdx) *
2519 getValue(ectx.intQuants.porosity());
2523 Entry{ScalarEntry{
"BWIPL",
2524 [&model = this->simulator_.model()](
const Context& ectx)
2526 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2527 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2528 model.dofTotalVolume(ectx.globalDofIdx) *
2529 getValue(ectx.intQuants.porosity());
2538 if (reportStepNum > 0 && !isSubStep) {
2540 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
2541 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
2543 [&c = this->collectOnIORank_](
const int idx)
2544 {
return c.isCartIdxOnThisRank(idx); });
2546 const auto extraHandlers = std::array{
2555 const Simulator& simulator_;
2556 const CollectDataOnIORankType& collectOnIORank_;
2557 std::vector<typename Extractor::Entry> extractors_;
Declares the properties required by the black oil model.
Definition: CollectDataOnIORank.hpp:56
The base class for the element-centered finite-volume discretization scheme.
Definition: ecfvdiscretization.hh:160
void assignMicrobialMass(const unsigned globalDofIdx, const Scalar microbialMass)
void assignCalciteMass(const unsigned globalDofIdx, const Scalar calciteMass)
void assignCo2InWater(const unsigned globalDofIdx, const Scalar co2InWater, const Scalar mM)
void assignVolumesSurface(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip)
bool has(const Inplace::Phase phase) const
bool hasMicrobialMass() const
void assignWaterMass(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip, const Scalar rhoW)
void assignCo2InGas(const unsigned globalDofIdx, const Co2InGasInput &v)
bool hasOxygenMass() const
void assignVolumesReservoir(const unsigned globalDofIdx, const Scalar saltConcentration, const std::array< Scalar, numPhases > &fipr)
void assignPoreVolume(const unsigned globalDofIdx, const Scalar value)
void assignOxygenMass(const unsigned globalDofIdx, const Scalar oxygenMass)
void assignOilGasDistribution(const unsigned globalDofIdx, const Scalar gasInPlaceLiquid, const Scalar oilInPlaceGas)
void assignBiofilmMass(const unsigned globalDofIdx, const Scalar biofilmMass)
bool hasWaterMass() const
bool hasCo2InWater() const
void assignUreaMass(const unsigned globalDofIdx, const Scalar ureaMass)
bool hasCalciteMass() const
bool hasBiofilmMass() const
const std::vector< Scalar > & get(const Inplace::Phase phase) const
void assignGasWater(const unsigned globalDofIdx, const std::array< Scalar, numPhases > &fip, const Scalar gasInPlaceWater, const Scalar waterInPlaceGas)
Definition: GenericOutputBlackoilModule.hpp:76
std::map< std::pair< std::string, int >, double > blockData_
Definition: GenericOutputBlackoilModule.hpp:435
std::array< ScalarBuffer, numPhases > relativePermeability_
Definition: GenericOutputBlackoilModule.hpp:424
ScalarBuffer fluidPressure_
Definition: GenericOutputBlackoilModule.hpp:378
std::array< ScalarBuffer, numPhases > density_
Definition: GenericOutputBlackoilModule.hpp:422
ScalarBuffer saturatedOilFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:410
ScalarBuffer overburdenPressure_
Definition: GenericOutputBlackoilModule.hpp:384
ScalarBuffer gasDissolutionFactorInWater_
Definition: GenericOutputBlackoilModule.hpp:404
const EclipseState & eclState_
Definition: GenericOutputBlackoilModule.hpp:337
ScalarBuffer swmin_
Definition: GenericOutputBlackoilModule.hpp:400
ScalarBuffer rockCompPorvMultiplier_
Definition: GenericOutputBlackoilModule.hpp:408
RFTContainer< GetPropType< TypeTag, Properties::FluidSystem > > rftC_
Definition: GenericOutputBlackoilModule.hpp:432
bool computeFip_
Definition: GenericOutputBlackoilModule.hpp:360
ScalarBuffer dewPointPressure_
Definition: GenericOutputBlackoilModule.hpp:407
LogOutputHelper< Scalar > logOutput_
Definition: GenericOutputBlackoilModule.hpp:344
std::vector< int > failedCellsPb_
Definition: GenericOutputBlackoilModule.hpp:369
ScalarBuffer permFact_
Definition: GenericOutputBlackoilModule.hpp:393
ScalarBuffer rsw_
Definition: GenericOutputBlackoilModule.hpp:381
ScalarBuffer pcog_
Definition: GenericOutputBlackoilModule.hpp:415
std::optional< RegionPhasePoreVolAverage > regionAvgDensity_
Definition: GenericOutputBlackoilModule.hpp:443
std::array< ScalarBuffer, numPhases > invB_
Definition: GenericOutputBlackoilModule.hpp:421
ScalarBuffer pSalt_
Definition: GenericOutputBlackoilModule.hpp:392
ScalarBuffer cFoam_
Definition: GenericOutputBlackoilModule.hpp:390
ScalarBuffer bubblePointPressure_
Definition: GenericOutputBlackoilModule.hpp:406
ScalarBuffer temperature_
Definition: GenericOutputBlackoilModule.hpp:379
ScalarBuffer ppcw_
Definition: GenericOutputBlackoilModule.hpp:401
FIPContainer< GetPropType< TypeTag, Properties::FluidSystem > > fipC_
Definition: GenericOutputBlackoilModule.hpp:362
ScalarBuffer rockCompTransMultiplier_
Definition: GenericOutputBlackoilModule.hpp:411
MechContainer< Scalar > mech_
Definition: GenericOutputBlackoilModule.hpp:418
ScalarBuffer dynamicPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:376
ScalarBuffer minimumOilPressure_
Definition: GenericOutputBlackoilModule.hpp:409
ScalarBuffer gasFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:372
std::array< ScalarBuffer, numPhases > residual_
Definition: GenericOutputBlackoilModule.hpp:428
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:398
BioeffectsContainer< Scalar > bioeffectsC_
Definition: GenericOutputBlackoilModule.hpp:412
const Schedule & schedule_
Definition: GenericOutputBlackoilModule.hpp:338
FlowsContainer< GetPropType< TypeTag, Properties::FluidSystem > > flowsC_
Definition: GenericOutputBlackoilModule.hpp:430
ExtboContainer< Scalar > extboC_
Definition: GenericOutputBlackoilModule.hpp:394
void setupExtraBlockData(const std::size_t reportStepNum, std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer oilSaturationPressure_
Definition: GenericOutputBlackoilModule.hpp:385
InterRegFlowMap interRegionFlows_
Definition: GenericOutputBlackoilModule.hpp:343
ScalarBuffer pcgw_
Definition: GenericOutputBlackoilModule.hpp:413
ScalarBuffer cPolymer_
Definition: GenericOutputBlackoilModule.hpp:389
void setupBlockData(std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer rvw_
Definition: GenericOutputBlackoilModule.hpp:383
std::array< ScalarBuffer, numPhases > saturation_
Definition: GenericOutputBlackoilModule.hpp:420
std::unordered_map< std::string, std::vector< int > > regions_
Definition: GenericOutputBlackoilModule.hpp:363
ScalarBuffer rPorV_
Definition: GenericOutputBlackoilModule.hpp:377
ScalarBuffer oilVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:403
std::vector< int > failedCellsPd_
Definition: GenericOutputBlackoilModule.hpp:370
ScalarBuffer rs_
Definition: GenericOutputBlackoilModule.hpp:380
ScalarBuffer drsdtcon_
Definition: GenericOutputBlackoilModule.hpp:386
ScalarBuffer sSol_
Definition: GenericOutputBlackoilModule.hpp:387
std::map< std::pair< std::string, int >, double > extraBlockData_
Definition: GenericOutputBlackoilModule.hpp:438
ScalarBuffer pressureTimesPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:374
ScalarBuffer gasDissolutionFactor_
Definition: GenericOutputBlackoilModule.hpp:402
std::array< ScalarBuffer, numPhases > viscosity_
Definition: GenericOutputBlackoilModule.hpp:423
bool forceDisableFipOutput_
Definition: GenericOutputBlackoilModule.hpp:358
ScalarBuffer soMax_
Definition: GenericOutputBlackoilModule.hpp:395
ScalarBuffer sgmax_
Definition: GenericOutputBlackoilModule.hpp:397
ScalarBuffer somin_
Definition: GenericOutputBlackoilModule.hpp:399
ScalarBuffer hydrocarbonPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:373
const std::optional< Inplace > & initialInplace() const
Definition: GenericOutputBlackoilModule.hpp:225
ScalarBuffer waterVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:405
ScalarBuffer cSalt_
Definition: GenericOutputBlackoilModule.hpp:391
TracerContainer< GetPropType< TypeTag, Properties::FluidSystem > > tracerC_
Definition: GenericOutputBlackoilModule.hpp:426
ScalarBuffer rv_
Definition: GenericOutputBlackoilModule.hpp:382
ScalarBuffer pcow_
Definition: GenericOutputBlackoilModule.hpp:414
ScalarBuffer swMax_
Definition: GenericOutputBlackoilModule.hpp:396
ScalarBuffer pressureTimesHydrocarbonVolume_
Definition: GenericOutputBlackoilModule.hpp:375
ScalarBuffer rswSol_
Definition: GenericOutputBlackoilModule.hpp:388
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:85
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition: OutputBlackoilModule.hpp:237
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:481
void setupExtractors(const bool isSubStep, const int reportStepNum)
Setup list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:218
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:196
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:444
void clearExtractors()
Clear list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:226
void outputFipAndResvLogToCSV(const std::size_t reportStepNum, const bool substep, const Parallel::Communication &comm)
Definition: OutputBlackoilModule.hpp:378
void assignToFluidState(FluidState &fs, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:505
void initHysteresisParams(Simulator &simulator, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:555
void updateFluidInPlace(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:620
OutputBlackOilModule(const Simulator &simulator, const SummaryConfig &smryCfg, const CollectDataOnIORankType &collectOnIORank)
Definition: OutputBlackoilModule.hpp:133
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:327
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputBlackoilModule.hpp:499
void processElementBlockData(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:283
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputBlackoilModule.hpp:491
void updateFluidInPlace(const unsigned globalDofIdx, const IntensiveQuantities &intQuants, const double totVolume)
Definition: OutputBlackoilModule.hpp:627
Declare the properties used by the infrastructure code of the finite volume discretizations.
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilbioeffectsmodules.hh:43
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