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 simulator.vanguard().grid().comm(),
145 energyModuleType == EnergyModules::FullyImplicitThermal ||
146 energyModuleType == EnergyModules::SequentialImplicitThermal,
147 energyModuleType == EnergyModules::ConstantTemperature,
148 getPropValue<TypeTag, Properties::EnableMech>(),
149 getPropValue<TypeTag, Properties::EnableSolvent>(),
150 getPropValue<TypeTag, Properties::EnablePolymer>(),
151 getPropValue<TypeTag, Properties::EnableFoam>(),
152 getPropValue<TypeTag, Properties::EnableBrine>(),
153 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
154 getPropValue<TypeTag, Properties::EnableExtbo>(),
155 getPropValue<TypeTag, Properties::EnableBioeffects>())
156 , simulator_(simulator)
157 , collectOnIORank_(collectOnIORank)
159 for (
auto& region_pair : this->
regions_) {
160 this->createLocalRegion_(region_pair.second);
163 auto isCartIdxOnThisRank = [&collectOnIORank](
const int idx) {
164 return collectOnIORank.isCartIdxOnThisRank(idx);
169 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
170 const std::string msg =
"The output code does not support --owner-cells-first=false.";
171 if (collectOnIORank.isIORank()) {
174 OPM_THROW_NOLOG(std::runtime_error, msg);
177 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
178 auto rset = this->
eclState_.fieldProps().fip_regions();
179 rset.push_back(
"PVTNUM");
185 .emplace(this->simulator_.gridView().comm(),
186 FluidSystem::numPhases, rset,
187 [fp = std::cref(this->eclState_.fieldProps())]
188 (
const std::string& rsetName) ->
decltype(
auto)
189 { return fp.get().get_int(rsetName); });
199 const unsigned reportStepNum,
202 const bool isRestart)
208 const auto& problem = this->simulator_.problem();
215 &problem.materialLawManager()->hysteresisConfig(),
216 problem.eclWriter().getOutputNnc().size());
221 const int reportStepNum)
223 this->setupElementExtractors_();
224 this->setupBlockExtractors_(isSubStep, reportStepNum);
230 this->extractors_.clear();
231 this->blockExtractors_.clear();
232 this->extraBlockExtractors_.clear();
246 if (this->extractors_.empty()) {
250 const auto& matLawManager = simulator_.problem().materialLawManager();
253 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
254 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
255 const auto& fs = intQuants.fluidState();
258 elemCtx.globalSpaceIndex(dofIdx, 0),
259 elemCtx.primaryVars(dofIdx, 0).pvtRegionIndex(),
266 if (matLawManager->enableHysteresis()) {
267 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
268 matLawManager->oilWaterHysteresisParams(hysterParams.
somax,
273 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
274 matLawManager->gasOilHysteresisParams(hysterParams.
sgmax,
292 if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
296 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
298 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
299 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
301 const auto be_it = this->blockExtractors_.find(cartesianIdx);
302 const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
303 if (be_it == this->blockExtractors_.end() &&
304 bee_it == this->extraBlockExtractors_.end())
309 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
310 const auto& fs = intQuants.fluidState();
320 if (be_it != this->blockExtractors_.end()) {
323 if (bee_it != this->extraBlockExtractors_.end()) {
330 const std::size_t reportStepNum,
332 boost::posix_time::ptime currentDate,
337 if (comm.rank() != 0) {
342 std::unique_ptr<FIPConfig> fipSched;
343 if (reportStepNum > 0) {
344 const auto& rpt = this->
schedule_[reportStepNum-1].rpt_config.get();
345 fipSched = std::make_unique<FIPConfig>(rpt);
347 const FIPConfig& fipc = reportStepNum == 0 ? this->
eclState_.getEclipseConfig().fip()
352 this->
logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
355 this->
logOutput_.fip(inplace, initial_inplace,
"");
357 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
358 this->
logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
360 if (fipc.output(FIPConfig::OutputField::RESV))
364 if (fipc.output(FIPConfig::OutputField::FIP)) {
365 for (
const auto& reg : this->regions_) {
366 if (reg.first !=
"FIPNUM") {
367 std::ostringstream ss;
368 ss <<
"BAL" << reg.first.substr(3);
369 this->
logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
370 this->
logOutput_.fip(inplace, initial_inplace, reg.first);
372 if (fipc.output(FIPConfig::OutputField::RESV))
384 if (comm.rank() != 0) {
388 if ((reportStepNum == 0) && (!substep) &&
389 (this->
schedule_.initialReportConfiguration().has_value()) &&
390 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
392 std::ostringstream csv_stream;
398 this->
logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
400 for (
const auto& reg : this->regions_) {
401 if (reg.first !=
"FIPNUM") {
402 this->
logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
406 const IOConfig& io = this->
eclState_.getIOConfig();
407 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
409 std::ofstream outputFile(csv_fname);
411 outputFile << csv_stream.str();
445 template <
class ActiveIndex,
class CartesianIndex>
447 ActiveIndex&& activeIndex,
448 CartesianIndex&& cartesianIndex)
451 const auto identifyCell = [&activeIndex, &cartesianIndex](
const Element& elem)
454 const auto cellIndex = activeIndex(elem);
457 static_cast<int>(cellIndex),
458 cartesianIndex(cellIndex),
459 elem.partitionType() == Dune::InteriorEntity
463 const auto timeIdx = 0u;
464 const auto& stencil = elemCtx.stencil(timeIdx);
465 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
467 for (
auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
468 const auto& face = stencil.interiorFace(scvfIdx);
469 const auto left = identifyCell(stencil.element(face.interiorIndex()));
470 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
472 const auto rates = this->
473 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
506 template <
class Flu
idState>
509 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
513 fs.setSaturation(phaseIdx, this->
saturation_[phaseIdx][elemIdx]);
519 std::array<Scalar, numPhases> pc = {0};
520 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
521 MaterialLaw::capillaryPressures(pc, matParams, fs);
523 Valgrind::CheckDefined(pc);
525 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
526 if (!FluidSystem::phaseIsActive(phaseIdx))
529 if (Indices::oilEnabled)
530 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
531 else if (Indices::gasEnabled)
532 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
533 else if (Indices::waterEnabled)
535 fs.setPressure(phaseIdx, pressure);
539 if constexpr (energyModuleType != EnergyModules::NoTemperature) {
541 fs.setTemperature(this->temperature_[elemIdx]);
543 if constexpr (enableDissolvedGas) {
544 if (!this->
rs_.empty())
545 fs.setRs(this->rs_[elemIdx]);
546 if (!this->
rv_.empty())
547 fs.setRv(this->rv_[elemIdx]);
549 if constexpr (enableDisgasInWater) {
550 if (!this->
rsw_.empty())
551 fs.setRsw(this->rsw_[elemIdx]);
553 if constexpr (enableVapwat) {
554 if (!this->
rvw_.empty())
555 fs.setRvw(this->rvw_[elemIdx]);
561 if (!this->
soMax_.empty())
562 simulator.problem().setMaxOilSaturation(elemIdx, this->
soMax_[elemIdx]);
564 if (simulator.problem().materialLawManager()->enableHysteresis()) {
565 auto matLawManager = simulator.problem().materialLawManager();
567 if (FluidSystem::phaseIsActive(oilPhaseIdx)
568 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
573 if (matLawManager->enableNonWettingHysteresis()) {
574 if (!this->
soMax_.empty()) {
575 somax = this->
soMax_[elemIdx];
578 if (matLawManager->enableWettingHysteresis()) {
579 if (!this->
swMax_.empty()) {
580 swmax = this->
swMax_[elemIdx];
583 if (matLawManager->enablePCHysteresis()) {
584 if (!this->
swmin_.empty()) {
585 swmin = this->
swmin_[elemIdx];
588 matLawManager->setOilWaterHysteresisParams(
589 somax, swmax, swmin, elemIdx);
591 if (FluidSystem::phaseIsActive(oilPhaseIdx)
592 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
597 if (matLawManager->enableNonWettingHysteresis()) {
598 if (!this->
sgmax_.empty()) {
599 sgmax = this->
sgmax_[elemIdx];
602 if (matLawManager->enableWettingHysteresis()) {
603 if (!this->
shmax_.empty()) {
604 shmax = this->
shmax_[elemIdx];
607 if (matLawManager->enablePCHysteresis()) {
608 if (!this->
somin_.empty()) {
609 somin = this->
somin_[elemIdx];
612 matLawManager->setGasOilHysteresisParams(
613 sgmax, shmax, somin, elemIdx);
618 if (simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT")) {
619 simulator.problem().materialLawManager()
620 ->applyRestartSwatInit(elemIdx, this->
ppcw_[elemIdx]);
626 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
627 updateFluidInPlace_(elemCtx, dofIdx);
632 const IntensiveQuantities& intQuants,
633 const double totVolume)
635 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
639 template <
typename T>
640 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
642 template <
typename,
class =
void>
643 struct HasGeoMech :
public std::false_type {};
645 template <
typename Problem>
647 Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
648 > :
public std::true_type {};
650 bool isDefunctParallelWell(
const std::string& wname)
const override
652 if (simulator_.gridView().comm().size() == 1)
654 const auto& parallelWells = simulator_.vanguard().parallelWells();
655 std::pair<std::string, bool> value {wname,
true};
656 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
657 return candidate == parallelWells.end() || *candidate != value;
660 bool isOwnedByCurrentRank(
const std::string& wname)
const override
662 return this->simulator_.problem().wellModel().isOwner(wname);
665 bool isOnCurrentRank(
const std::string& wname)
const override
667 return this->simulator_.problem().wellModel().hasLocalCells(wname);
670 void updateFluidInPlace_(
const ElementContext& elemCtx,
const unsigned dofIdx)
672 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
673 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
674 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
676 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
679 void updateFluidInPlace_(
const unsigned globalDofIdx,
680 const IntensiveQuantities& intQuants,
681 const double totVolume)
685 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
688 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
692 void createLocalRegion_(std::vector<int>& region)
698 region.resize(simulator_.gridView().size(0));
699 std::size_t elemIdx = 0;
700 for (
const auto& elem : elements(simulator_.gridView())) {
701 if (elem.partitionType() != Dune::InteriorEntity) {
709 template <
typename Flu
idState>
710 void aggregateAverageDensityContributions_(
const FluidState& fs,
711 const unsigned int globalDofIdx,
714 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
715 pvCellValue.porv = porv;
717 for (
auto phaseIdx = 0*FluidSystem::numPhases;
718 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
720 if (! FluidSystem::phaseIsActive(phaseIdx)) {
724 pvCellValue.value = getValue(fs.density(phaseIdx));
725 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
728 ->addCell(globalDofIdx,
749 data::InterRegFlowMap::FlowRates
750 getComponentSurfaceRates(
const ElementContext& elemCtx,
751 const Scalar faceArea,
752 const std::size_t scvfIdx,
753 const std::size_t timeIdx)
const
755 using Component = data::InterRegFlowMap::Component;
757 auto rates = data::InterRegFlowMap::FlowRates {};
759 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
761 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
763 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
764 const auto& up = elemCtx
765 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
767 const auto pvtReg = up.pvtRegionIndex();
769 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
770 (up.fluidState(), oilPhaseIdx, pvtReg));
772 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
774 rates[Component::Oil] += qO;
776 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
777 const auto Rs = getValue(
778 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
779 (up.fluidState(), pvtReg));
781 rates[Component::Gas] += qO *
Rs;
782 rates[Component::Disgas] += qO *
Rs;
786 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
787 const auto& up = elemCtx
788 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
790 const auto pvtReg = up.pvtRegionIndex();
792 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
793 (up.fluidState(), gasPhaseIdx, pvtReg));
795 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
797 rates[Component::Gas] += qG;
799 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
800 const auto Rv = getValue(
801 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
802 (up.fluidState(), pvtReg));
804 rates[Component::Oil] += qG *
Rv;
805 rates[Component::Vapoil] += qG *
Rv;
809 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
810 const auto& up = elemCtx
811 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
813 const auto pvtReg = up.pvtRegionIndex();
815 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
816 (up.fluidState(), waterPhaseIdx, pvtReg));
818 rates[Component::Water] +=
819 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
825 template <
typename Flu
idState>
826 Scalar hydroCarbonFraction(
const FluidState& fs)
const
828 if (this->
eclState_.runspec().co2Storage()) {
835 auto hydrocarbon = Scalar {0};
836 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
837 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
840 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
841 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
847 void updateTotalVolumesAndPressures_(
const unsigned globalDofIdx,
848 const IntensiveQuantities& intQuants,
849 const double totVolume)
851 const auto& fs = intQuants.fluidState();
853 const double pv = totVolume * intQuants.porosity().value();
854 const auto hydrocarbon = this->hydroCarbonFraction(fs);
858 totVolume * intQuants.referencePorosity());
865 !this->pressureTimesPoreVolume_.empty())
868 assert(this->
fipC_.
get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
870 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
872 getValue(fs.pressure(oilPhaseIdx)) * pv;
877 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
879 getValue(fs.pressure(gasPhaseIdx)) * pv;
884 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
886 getValue(fs.pressure(waterPhaseIdx)) * pv;
891 void updatePhaseInplaceVolumes_(
const unsigned globalDofIdx,
892 const IntensiveQuantities& intQuants,
893 const double totVolume)
895 std::array<Scalar, FluidSystem::numPhases> fip {};
896 std::array<Scalar, FluidSystem::numPhases> fipr{};
898 const auto& fs = intQuants.fluidState();
899 const auto pv = totVolume * intQuants.porosity().value();
901 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
902 if (!FluidSystem::phaseIsActive(phaseIdx)) {
906 const auto b = getValue(fs.invB(phaseIdx));
907 const auto s = getValue(fs.saturation(phaseIdx));
909 fipr[phaseIdx] = s * pv;
910 fip [phaseIdx] = b * fipr[phaseIdx];
915 fs.saltConcentration().value(),
918 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
919 FluidSystem::phaseIsActive(gasPhaseIdx))
921 this->updateOilGasDistribution(globalDofIdx, fs, fip);
924 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
925 FluidSystem::phaseIsActive(gasPhaseIdx))
927 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
930 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
933 this->updateCO2InGas(globalDofIdx, pv, intQuants);
937 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
938 FluidSystem::phaseIsActive(oilPhaseIdx)))
940 this->updateCO2InWater(globalDofIdx, pv, fs);
943 if constexpr(enableBioeffects) {
944 const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
945 getValue(fs.invB(waterPhaseIdx));
947 this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
950 this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
952 if constexpr(enableMICP) {
954 this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
957 this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
960 this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
967 this->updateWaterMass(globalDofIdx, fs, fip);
971 template <
typename Flu
idState,
typename FIPArray>
972 void updateOilGasDistribution(
const unsigned globalDofIdx,
973 const FluidState& fs,
977 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
978 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
983 template <
typename Flu
idState,
typename FIPArray>
984 void updateGasWaterDistribution(
const unsigned globalDofIdx,
985 const FluidState& fs,
989 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
990 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
995 template <
typename IntensiveQuantities>
996 void updateCO2InGas(
const unsigned globalDofIdx,
998 const IntensiveQuantities& intQuants)
1000 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
1001 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
1003 const auto& fs = intQuants.fluidState();
1004 Scalar sgcr = scaledDrainageInfo.Sgcr;
1005 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1006 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1007 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
1010 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1011 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
1012 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
1014 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1015 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1017 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams,
true);
1021 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1022 Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
1023 if (this->
fipC_.
has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
1024 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
1026 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1027 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1028 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1029 strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1033 const typename FIPContainer<FluidSystem>::Co2InGasInput v{
1037 getValue(fs.density(gasPhaseIdx)),
1038 FluidSystem::phaseIsActive(waterPhaseIdx)
1039 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1040 : FluidSystem::convertRvToXgO(getValue(fs.
Rv()), fs.pvtRegionIndex()),
1041 FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
1042 trappedGasSaturation,
1043 strandedGasSaturation,
1049 template <
typename Flu
idState>
1050 void updateCO2InWater(
const unsigned globalDofIdx,
1052 const FluidState& fs)
1054 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1055 ? this->co2InWaterFromOil(fs, pv)
1056 : this->co2InWaterFromWater(fs, pv);
1058 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1063 template <
typename Flu
idState>
1064 Scalar co2InWaterFromWater(
const FluidState& fs,
const double pv)
const
1066 const double rhow = getValue(fs.density(waterPhaseIdx));
1067 const double sw = getValue(fs.saturation(waterPhaseIdx));
1068 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1070 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1072 return xwG * pv * rhow * sw / mM;
1075 template <
typename Flu
idState>
1076 Scalar co2InWaterFromOil(
const FluidState& fs,
const double pv)
const
1078 const double rhoo = getValue(fs.density(oilPhaseIdx));
1079 const double so = getValue(fs.saturation(oilPhaseIdx));
1080 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1082 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1084 return xoG * pv * rhoo * so / mM;
1087 template <
typename Flu
idState,
typename FIPArray>
1088 void updateWaterMass(
const unsigned globalDofIdx,
1089 const FluidState& fs,
1093 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
1098 template <
typename IntensiveQuantities>
1099 void updateMicrobialMass(
const unsigned globalDofIdx,
1100 const IntensiveQuantities& intQuants,
1101 const double surfVolWat)
1103 const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
1108 template <
typename IntensiveQuantities>
1109 void updateOxygenMass(
const unsigned globalDofIdx,
1110 const IntensiveQuantities& intQuants,
1111 const double surfVolWat)
1113 const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
1118 template <
typename IntensiveQuantities>
1119 void updateUreaMass(
const unsigned globalDofIdx,
1120 const IntensiveQuantities& intQuants,
1121 const double surfVolWat)
1123 const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
1128 template <
typename IntensiveQuantities>
1129 void updateBiofilmMass(
const unsigned globalDofIdx,
1130 const IntensiveQuantities& intQuants,
1131 const double totVolume)
1133 const Scalar mass = totVolume * intQuants.biofilmMass().value();
1138 template <
typename IntensiveQuantities>
1139 void updateCalciteMass(
const unsigned globalDofIdx,
1140 const IntensiveQuantities& intQuants,
1141 const double totVolume)
1143 const Scalar mass = totVolume * intQuants.calciteMass().value();
1149 void setupElementExtractors_()
1151 using Entry =
typename Extractor::Entry;
1152 using Context =
typename Extractor::Context;
1153 using ScalarEntry =
typename Extractor::ScalarEntry;
1154 using PhaseEntry =
typename Extractor::PhaseEntry;
1156 const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
1157 const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
1159 auto extractors = std::array{
1161 [](
const unsigned phase,
const Context& ectx)
1162 {
return getValue(ectx.fs.saturation(phase)); }
1165 Entry{PhaseEntry{&this->
invB_,
1166 [](
const unsigned phase,
const Context& ectx)
1167 {
return getValue(ectx.fs.invB(phase)); }
1171 [](
const unsigned phase,
const Context& ectx)
1172 {
return getValue(ectx.fs.density(phase)); }
1176 [](
const unsigned phase,
const Context& ectx)
1177 {
return getValue(ectx.intQuants.relativePermeability(phase)); }
1181 [
this](
const unsigned phaseIdx,
const Context& ectx)
1183 if (this->
extboC_.allocated() && phaseIdx == oilPhaseIdx) {
1184 return getValue(ectx.intQuants.oilViscosity());
1186 else if (this->
extboC_.allocated() && phaseIdx == gasPhaseIdx) {
1187 return getValue(ectx.intQuants.gasViscosity());
1190 return getValue(ectx.fs.viscosity(phaseIdx));
1196 [&modelResid = this->simulator_.model().linearizer().residual()]
1197 (
const unsigned phaseIdx,
const Context& ectx)
1199 const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
1200 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
1201 return modelResid[ectx.globalDofIdx][activeCompIdx];
1207 [&problem = this->simulator_.problem()](
const Context& ectx)
1209 return problem.template
1210 rockCompPoroMultiplier<Scalar>(ectx.intQuants,
1216 [&problem = this->simulator_.problem()](
const Context& ectx)
1219 template rockCompTransMultiplier<Scalar>(ectx.intQuants,
1224 [&problem = this->simulator_.problem()](
const Context& ectx)
1226 return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
1227 problem.minOilPressure(ectx.globalDofIdx));
1233 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1237 FluidSystem::bubblePointPressure(ectx.fs,
1238 ectx.intQuants.pvtRegionIndex())
1240 }
catch (
const NumericalProblem&) {
1241 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1242 failedCells.push_back(cartesianIdx);
1250 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1254 FluidSystem::dewPointPressure(ectx.fs,
1255 ectx.intQuants.pvtRegionIndex())
1257 }
catch (
const NumericalProblem&) {
1258 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1259 failedCells.push_back(cartesianIdx);
1266 [&problem = simulator_.problem()](
const Context& ectx)
1267 {
return problem.overburdenPressure(ectx.globalDofIdx); }
1271 [](
const Context& ectx)
1272 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }
1275 Entry{ScalarEntry{&this->
sSol_,
1276 [](
const Context& ectx)
1277 {
return getValue(ectx.intQuants.solventSaturation()); }
1280 Entry{ScalarEntry{&this->
rswSol_,
1281 [](
const Context& ectx)
1282 {
return getValue(ectx.intQuants.rsSolw()); }
1286 [](
const Context& ectx)
1287 {
return getValue(ectx.intQuants.polymerConcentration()); }
1290 Entry{ScalarEntry{&this->
cFoam_,
1291 [](
const Context& ectx)
1292 {
return getValue(ectx.intQuants.foamConcentration()); }
1295 Entry{ScalarEntry{&this->
cSalt_,
1296 [](
const Context& ectx)
1297 {
return getValue(ectx.fs.saltConcentration()); }
1300 Entry{ScalarEntry{&this->
pSalt_,
1301 [](
const Context& ectx)
1302 {
return getValue(ectx.fs.saltSaturation()); }
1306 [](
const Context& ectx)
1307 {
return getValue(ectx.intQuants.permFactor()); }
1310 Entry{ScalarEntry{&this->
rPorV_,
1311 [&model = this->simulator_.model()](
const Context& ectx)
1313 const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
1314 return totVolume * getValue(ectx.intQuants.porosity());
1318 Entry{ScalarEntry{&this->
rs_,
1319 [](
const Context& ectx)
1320 {
return getValue(ectx.fs.Rs()); }
1323 Entry{ScalarEntry{&this->
rv_,
1324 [](
const Context& ectx)
1325 {
return getValue(ectx.fs.Rv()); }
1328 Entry{ScalarEntry{&this->
rsw_,
1329 [](
const Context& ectx)
1330 {
return getValue(ectx.fs.Rsw()); }
1333 Entry{ScalarEntry{&this->
rvw_,
1334 [](
const Context& ectx)
1335 {
return getValue(ectx.fs.Rvw()); }
1338 Entry{ScalarEntry{&this->
ppcw_,
1339 [&matLawManager = *this->simulator_.problem().materialLawManager()]
1340 (
const Context& ectx)
1342 return matLawManager.
1343 oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
1348 [&problem = this->simulator_.problem()](
const Context& ectx)
1350 return problem.drsdtcon(ectx.globalDofIdx,
1355 Entry{ScalarEntry{&this->
pcgw_,
1356 [](
const Context& ectx)
1358 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1359 getValue(ectx.fs.pressure(waterPhaseIdx));
1363 Entry{ScalarEntry{&this->
pcow_,
1364 [](
const Context& ectx)
1366 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1367 getValue(ectx.fs.pressure(waterPhaseIdx));
1371 Entry{ScalarEntry{&this->
pcog_,
1372 [](
const Context& ectx)
1374 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1375 getValue(ectx.fs.pressure(oilPhaseIdx));
1380 [](
const Context& ectx)
1382 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1384 return getValue(ectx.fs.pressure(oilPhaseIdx));
1386 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1388 return getValue(ectx.fs.pressure(gasPhaseIdx));
1392 return getValue(ectx.fs.pressure(waterPhaseIdx));
1398 [&problem = this->simulator_.problem()](
const Context& ectx)
1400 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1401 return FluidSystem::template
1402 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1410 [&problem = this->simulator_.problem()](
const Context& ectx)
1412 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1413 return FluidSystem::template
1414 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1422 [&problem = this->simulator_.problem()](
const Context& ectx)
1424 const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
1425 return FluidSystem::template
1426 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1434 [](
const Context& ectx)
1436 return FluidSystem::template
1437 saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
1444 [](
const Context& ectx)
1446 return 1.0 / FluidSystem::template
1447 inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1454 [](
const Context& ectx)
1456 return 1.0 / FluidSystem::template
1457 saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1464 [](
const Context& ectx)
1466 return FluidSystem::template
1467 saturationPressure<FluidState, Scalar>(ectx.fs,
1473 Entry{ScalarEntry{&this->
soMax_,
1474 [&problem = this->simulator_.problem()](
const Context& ectx)
1476 return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
1477 problem.maxOilSaturation(ectx.globalDofIdx));
1480 !hysteresisConfig.enableHysteresis()
1482 Entry{ScalarEntry{&this->
swMax_,
1483 [&problem = this->simulator_.problem()](
const Context& ectx)
1485 return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
1486 problem.maxWaterSaturation(ectx.globalDofIdx));
1489 !hysteresisConfig.enableHysteresis()
1491 Entry{ScalarEntry{&this->
soMax_,
1492 [](
const Context& ectx)
1493 {
return ectx.hParams.somax; }
1495 hysteresisConfig.enableHysteresis() &&
1496 hysteresisConfig.enableNonWettingHysteresis() &&
1497 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1498 FluidSystem::phaseIsActive(waterPhaseIdx)
1500 Entry{ScalarEntry{&this->
swMax_,
1501 [](
const Context& ectx)
1502 {
return ectx.hParams.swmax; }
1504 hysteresisConfig.enableHysteresis() &&
1505 hysteresisConfig.enableWettingHysteresis() &&
1506 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1507 FluidSystem::phaseIsActive(waterPhaseIdx)
1509 Entry{ScalarEntry{&this->
swmin_,
1510 [](
const Context& ectx)
1511 {
return ectx.hParams.swmin; }
1513 hysteresisConfig.enableHysteresis() &&
1514 hysteresisConfig.enablePCHysteresis() &&
1515 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1516 FluidSystem::phaseIsActive(waterPhaseIdx)
1518 Entry{ScalarEntry{&this->
sgmax_,
1519 [](
const Context& ectx)
1520 {
return ectx.hParams.sgmax; }
1522 hysteresisConfig.enableHysteresis() &&
1523 hysteresisConfig.enableNonWettingHysteresis() &&
1524 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1525 FluidSystem::phaseIsActive(gasPhaseIdx)
1527 Entry{ScalarEntry{&this->
shmax_,
1528 [](
const Context& ectx)
1529 {
return ectx.hParams.shmax; }
1531 hysteresisConfig.enableHysteresis() &&
1532 hysteresisConfig.enableWettingHysteresis() &&
1533 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1534 FluidSystem::phaseIsActive(gasPhaseIdx)
1536 Entry{ScalarEntry{&this->
somin_,
1537 [](
const Context& ectx)
1538 {
return ectx.hParams.somin; }
1540 hysteresisConfig.enableHysteresis() &&
1541 hysteresisConfig.enablePCHysteresis() &&
1542 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1543 FluidSystem::phaseIsActive(gasPhaseIdx)
1545 Entry{[&model = this->simulator_.model(),
this](
const Context& ectx)
1549 const auto porv = ectx.intQuants.referencePorosity()
1550 * model.dofTotalVolume(ectx.globalDofIdx);
1552 this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
1553 static_cast<double>(porv));
1556 Entry{[&extboC = this->
extboC_](
const Context& ectx)
1558 extboC.assignVolumes(ectx.globalDofIdx,
1559 ectx.intQuants.xVolume().value(),
1560 ectx.intQuants.yVolume().value());
1561 extboC.assignZFraction(ectx.globalDofIdx,
1562 ectx.intQuants.zFraction().value());
1564 const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
1565 getValue(ectx.fs.invB(oilPhaseIdx)) +
1566 getValue(ectx.fs.saturation(gasPhaseIdx)) *
1567 getValue(ectx.fs.invB(gasPhaseIdx)) *
1568 getValue(ectx.fs.Rv());
1569 const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1570 getValue(ectx.fs.invB(gasPhaseIdx)) *
1571 (1.0 - ectx.intQuants.yVolume().value()) +
1572 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1573 getValue(ectx.fs.invB(oilPhaseIdx)) *
1574 getValue(ectx.fs.Rs()) *
1575 (1.0 - ectx.intQuants.xVolume().value());
1576 const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1577 getValue(ectx.fs.invB(gasPhaseIdx)) *
1578 ectx.intQuants.yVolume().value() +
1579 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1580 getValue(ectx.fs.invB(oilPhaseIdx)) *
1581 getValue(ectx.fs.Rs()) *
1582 ectx.intQuants.xVolume().value();
1583 const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1584 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1585 const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
1586 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
1587 extboC.assignMassFractions(ectx.globalDofIdx,
1588 stdVolGas * rhoG / stdMassTotal,
1589 stdVolOil * rhoO / stdMassTotal,
1590 stdVolCo2 * rhoCO2 / stdMassTotal);
1593 Entry{[&bioeffectsC = this->
bioeffectsC_](
const Context& ectx)
1595 bioeffectsC.assign(ectx.globalDofIdx,
1596 ectx.intQuants.microbialConcentration().value(),
1597 ectx.intQuants.biofilmVolumeFraction().value());
1598 if (Indices::enableMICP) {
1599 bioeffectsC.assign(ectx.globalDofIdx,
1600 ectx.intQuants.oxygenConcentration().value(),
1601 ectx.intQuants.ureaConcentration().value(),
1602 ectx.intQuants.calciteVolumeFraction().value());
1606 Entry{[&rftC = this->
rftC_,
1607 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1609 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1610 rftC.assign(cartesianIdx,
1611 [&fs = ectx.fs]() {
return getValue(fs.pressure(oilPhaseIdx)); },
1612 [&fs = ectx.fs]() {
return getValue(fs.saturation(waterPhaseIdx)); },
1613 [&fs = ectx.fs]() {
return getValue(fs.saturation(gasPhaseIdx)); });
1617 &tM = this->simulator_.problem().tracerModel()](
const Context& ectx)
1619 tC.assignFreeConcentrations(ectx.globalDofIdx,
1620 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1621 {
return tM.freeTracerConcentration(tracerIdx, gIdx); });
1622 tC.assignSolConcentrations(ectx.globalDofIdx,
1623 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1624 {
return tM.solTracerConcentration(tracerIdx, gIdx); });
1627 Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
1628 &flowsC = this->
flowsC_](
const Context& ectx)
1630 const auto gas_idx = Indices::gasEnabled ?
1631 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1632 const auto oil_idx = Indices::oilEnabled ?
1633 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1634 const auto water_idx = Indices::waterEnabled ?
1635 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1636 const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
1637 for (
const auto& flowsInfo : flowsInfos) {
1638 flowsC.assignFlows(ectx.globalDofIdx,
1641 value_or_zero(gas_idx, flowsInfo.flow),
1642 value_or_zero(oil_idx, flowsInfo.flow),
1643 value_or_zero(water_idx, flowsInfo.flow));
1645 }, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
1647 Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
1648 &flowsC = this->
flowsC_](
const Context& ectx)
1650 const auto gas_idx = Indices::gasEnabled ?
1651 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1652 const auto oil_idx = Indices::oilEnabled ?
1653 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1654 const auto water_idx = Indices::waterEnabled ?
1655 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1656 const auto& floresInfos = floresInf[ectx.globalDofIdx];
1657 for (
const auto& floresInfo : floresInfos) {
1658 flowsC.assignFlores(ectx.globalDofIdx,
1661 value_or_zero(gas_idx, floresInfo.flow),
1662 value_or_zero(oil_idx, floresInfo.flow),
1663 value_or_zero(water_idx, floresInfo.flow));
1665 }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
1672 Entry{ScalarEntry{&this->
rv_,
1673 [&problem = this->simulator_.problem()](
const Context& ectx)
1674 {
return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
1676 simulator_.episodeIndex() < 0 &&
1677 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1678 FluidSystem::phaseIsActive(gasPhaseIdx)
1680 Entry{ScalarEntry{&this->
rs_,
1681 [&problem = this->simulator_.problem()](
const Context& ectx)
1682 {
return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
1684 simulator_.episodeIndex() < 0 &&
1685 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1686 FluidSystem::phaseIsActive(gasPhaseIdx)
1688 Entry{ScalarEntry{&this->
rsw_,
1689 [&problem = this->simulator_.problem()](
const Context& ectx)
1690 {
return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
1692 simulator_.episodeIndex() < 0 &&
1693 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1694 FluidSystem::phaseIsActive(gasPhaseIdx)
1696 Entry{ScalarEntry{&this->
rvw_,
1697 [&problem = this->simulator_.problem()](
const Context& ectx)
1698 {
return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
1700 simulator_.episodeIndex() < 0 &&
1701 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1702 FluidSystem::phaseIsActive(gasPhaseIdx)
1706 [&problem = this->simulator_.problem()](
const unsigned phase,
1707 const Context& ectx)
1709 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1710 return FluidSystem::density(fsInitial,
1712 ectx.intQuants.pvtRegionIndex());
1715 simulator_.episodeIndex() < 0 &&
1716 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1717 FluidSystem::phaseIsActive(gasPhaseIdx)
1719 Entry{PhaseEntry{&this->
invB_,
1720 [&problem = this->simulator_.problem()](
const unsigned phase,
1721 const Context& ectx)
1723 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1724 return FluidSystem::inverseFormationVolumeFactor(fsInitial,
1726 ectx.intQuants.pvtRegionIndex());
1729 simulator_.episodeIndex() < 0 &&
1730 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1731 FluidSystem::phaseIsActive(gasPhaseIdx)
1734 [&problem = this->simulator_.problem()](
const unsigned phase,
1735 const Context& ectx)
1737 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1738 return FluidSystem::viscosity(fsInitial,
1740 ectx.intQuants.pvtRegionIndex());
1743 simulator_.episodeIndex() < 0 &&
1744 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1745 FluidSystem::phaseIsActive(gasPhaseIdx)
1752 if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
1753 if (this->
mech_.allocated()) {
1754 this->extractors_.push_back(
1755 Entry{[&mech = this->
mech_,
1756 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1758 mech.assignDelStress(ectx.globalDofIdx,
1759 model.delstress(ectx.globalDofIdx));
1761 mech.assignDisplacement(ectx.globalDofIdx,
1762 model.disp(ectx.globalDofIdx,
true));
1765 mech.assignFracStress(ectx.globalDofIdx,
1766 model.fractureStress(ectx.globalDofIdx));
1768 mech.assignLinStress(ectx.globalDofIdx,
1769 model.linstress(ectx.globalDofIdx));
1771 mech.assignPotentialForces(ectx.globalDofIdx,
1772 model.mechPotentialForce(ectx.globalDofIdx),
1773 model.mechPotentialPressForce(ectx.globalDofIdx),
1774 model.mechPotentialTempForce(ectx.globalDofIdx));
1776 mech.assignStrain(ectx.globalDofIdx,
1777 model.strain(ectx.globalDofIdx,
true));
1780 mech.assignStress(ectx.globalDofIdx,
1781 model.stress(ectx.globalDofIdx,
true));
1790 void setupBlockExtractors_(
const bool isSubStep,
1791 const int reportStepNum)
1794 using Context =
typename BlockExtractor::Context;
1795 using PhaseEntry =
typename BlockExtractor::PhaseEntry;
1796 using ScalarEntry =
typename BlockExtractor::ScalarEntry;
1798 using namespace std::string_view_literals;
1800 const auto pressure_handler =
1801 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1802 [](
const Context& ectx)
1804 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1805 return getValue(ectx.fs.pressure(oilPhaseIdx));
1807 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1808 return getValue(ectx.fs.pressure(gasPhaseIdx));
1811 return getValue(ectx.fs.pressure(waterPhaseIdx));
1817 const auto handlers = std::array{
1819 Entry{PhaseEntry{std::array{
1820 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1821 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1823 [](
const unsigned phaseIdx,
const Context& ectx)
1825 return getValue(ectx.fs.saturation(phaseIdx));
1829 Entry{ScalarEntry{
"BNSAT",
1830 [](
const Context& ectx)
1832 return ectx.intQuants.solventSaturation().value();
1836 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1837 [](
const Context& ectx)
1839 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1840 return getValue(ectx.fs.temperature(oilPhaseIdx));
1842 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1843 return getValue(ectx.fs.temperature(gasPhaseIdx));
1846 return getValue(ectx.fs.temperature(waterPhaseIdx));
1851 Entry{PhaseEntry{std::array{
1852 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
1853 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
1855 [](
const unsigned phaseIdx,
const Context& ectx)
1857 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
1861 Entry{ScalarEntry{
"BKROG",
1862 [&problem = this->simulator_.problem()](
const Context& ectx)
1864 const auto& materialParams =
1865 problem.materialLawParams(ectx.elemCtx,
1868 return getValue(MaterialLaw::template
1869 relpermOilInOilGasSystem<Evaluation>(materialParams,
1874 Entry{ScalarEntry{
"BKROW",
1875 [&problem = this->simulator_.problem()](
const Context& ectx)
1877 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
1880 return getValue(MaterialLaw::template
1881 relpermOilInOilWaterSystem<Evaluation>(materialParams,
1886 Entry{ScalarEntry{
"BWPC",
1887 [](
const Context& ectx)
1889 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1890 getValue(ectx.fs.pressure(waterPhaseIdx));
1894 Entry{ScalarEntry{
"BGPC",
1895 [](
const Context& ectx)
1897 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1898 getValue(ectx.fs.pressure(oilPhaseIdx));
1902 Entry{ScalarEntry{
"BWPR",
1903 [](
const Context& ectx)
1905 return getValue(ectx.fs.pressure(waterPhaseIdx));
1909 Entry{ScalarEntry{
"BGPR",
1910 [](
const Context& ectx)
1912 return getValue(ectx.fs.pressure(gasPhaseIdx));
1916 Entry{PhaseEntry{std::array{
1917 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
1918 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
1920 [](
const unsigned phaseIdx,
const Context& ectx)
1922 return getValue(ectx.fs.viscosity(phaseIdx));
1926 Entry{PhaseEntry{std::array{
1927 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
1928 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
1930 [](
const unsigned phaseIdx,
const Context& ectx)
1932 return getValue(ectx.fs.density(phaseIdx));
1936 Entry{ScalarEntry{
"BFLOWI",
1937 [&flowsC = this->
flowsC_](
const Context& ectx)
1939 return flowsC.getFlow(ectx.globalDofIdx, Dir::XPlus, waterCompIdx);
1943 Entry{ScalarEntry{
"BFLOWJ",
1944 [&flowsC = this->
flowsC_](
const Context& ectx)
1946 return flowsC.getFlow(ectx.globalDofIdx, Dir::YPlus, waterCompIdx);
1950 Entry{ScalarEntry{
"BFLOWK",
1951 [&flowsC = this->
flowsC_](
const Context& ectx)
1953 return flowsC.getFlow(ectx.globalDofIdx, Dir::ZPlus, waterCompIdx);
1957 Entry{ScalarEntry{
"BRPV",
1958 [&model = this->simulator_.model()](
const Context& ectx)
1960 return getValue(ectx.intQuants.porosity()) *
1961 model.dofTotalVolume(ectx.globalDofIdx);
1965 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
1966 [&model = this->simulator_.model()](
const unsigned phaseIdx,
1967 const Context& ectx)
1969 return getValue(ectx.fs.saturation(phaseIdx)) *
1970 getValue(ectx.intQuants.porosity()) *
1971 model.dofTotalVolume(ectx.globalDofIdx);
1975 Entry{ScalarEntry{
"BRS",
1976 [](
const Context& ectx)
1978 return getValue(ectx.fs.Rs());
1982 Entry{ScalarEntry{
"BRV",
1983 [](
const Context& ectx)
1985 return getValue(ectx.fs.Rv());
1989 Entry{ScalarEntry{
"BOIP",
1990 [&model = this->simulator_.model()](
const Context& ectx)
1992 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
1993 getValue(ectx.fs.saturation(oilPhaseIdx)) +
1994 getValue(ectx.fs.Rv()) *
1995 getValue(ectx.fs.invB(gasPhaseIdx)) *
1996 getValue(ectx.fs.saturation(gasPhaseIdx))) *
1997 model.dofTotalVolume(ectx.globalDofIdx) *
1998 getValue(ectx.intQuants.porosity());
2002 Entry{ScalarEntry{
"BGIP",
2003 [&model = this->simulator_.model()](
const Context& ectx)
2005 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2006 getValue(ectx.fs.saturation(gasPhaseIdx));
2008 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2009 result += getValue(ectx.fs.Rs()) *
2010 getValue(ectx.fs.invB(oilPhaseIdx)) *
2011 getValue(ectx.fs.saturation(oilPhaseIdx));
2014 result += getValue(ectx.fs.Rsw()) *
2015 getValue(ectx.fs.invB(waterPhaseIdx)) *
2016 getValue(ectx.fs.saturation(waterPhaseIdx));
2020 model.dofTotalVolume(ectx.globalDofIdx) *
2021 getValue(ectx.intQuants.porosity());
2025 Entry{ScalarEntry{
"BWIP",
2026 [&model = this->simulator_.model()](
const Context& ectx)
2028 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2029 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2030 model.dofTotalVolume(ectx.globalDofIdx) *
2031 getValue(ectx.intQuants.porosity());
2035 Entry{ScalarEntry{
"BOIPL",
2036 [&model = this->simulator_.model()](
const Context& ectx)
2038 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2039 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2040 model.dofTotalVolume(ectx.globalDofIdx) *
2041 getValue(ectx.intQuants.porosity());
2045 Entry{ScalarEntry{
"BGIPL",
2046 [&model = this->simulator_.model()](
const Context& ectx)
2049 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2050 result = getValue(ectx.fs.Rs()) *
2051 getValue(ectx.fs.invB(oilPhaseIdx)) *
2052 getValue(ectx.fs.saturation(oilPhaseIdx));
2055 result = getValue(ectx.fs.Rsw()) *
2056 getValue(ectx.fs.invB(waterPhaseIdx)) *
2057 getValue(ectx.fs.saturation(waterPhaseIdx));
2060 model.dofTotalVolume(ectx.globalDofIdx) *
2061 getValue(ectx.intQuants.porosity());
2065 Entry{ScalarEntry{
"BGIPG",
2066 [&model = this->simulator_.model()](
const Context& ectx)
2068 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2069 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2070 model.dofTotalVolume(ectx.globalDofIdx) *
2071 getValue(ectx.intQuants.porosity());
2075 Entry{ScalarEntry{
"BOIPG",
2076 [&model = this->simulator_.model()](
const Context& ectx)
2078 return getValue(ectx.fs.Rv()) *
2079 getValue(ectx.fs.invB(gasPhaseIdx)) *
2080 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2081 model.dofTotalVolume(ectx.globalDofIdx) *
2082 getValue(ectx.intQuants.porosity());
2086 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2087 [&simConfig = this->
eclState_.getSimulationConfig(),
2088 &grav = this->simulator_.problem().gravity(),
2090 &problem = this->simulator_.problem(),
2091 ®ions = this->
regions_](
const unsigned phaseIdx,
const Context& ectx)
2094 phase.ix = phaseIdx;
2103 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2106 const auto region = RegionPhasePoreVolAverage::Region {
2107 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2110 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2112 const auto press = getValue(ectx.fs.pressure(phase.ix));
2113 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2114 return press - density*dz*grav[GridView::dimensionworld - 1];
2118 Entry{ScalarEntry{
"BAMIP",
2119 [&model = this->simulator_.model()](
const Context& ectx)
2121 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2122 ectx.intQuants.pvtRegionIndex());
2123 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2124 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2126 model.dofTotalVolume(ectx.globalDofIdx) *
2127 getValue(ectx.intQuants.porosity());
2131 Entry{ScalarEntry{
"BMMIP",
2132 [&model = this->simulator_.model()](
const Context& ectx)
2134 return getValue(ectx.intQuants.microbialConcentration()) *
2135 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2136 getValue(ectx.intQuants.porosity()) *
2137 model.dofTotalVolume(ectx.globalDofIdx);
2141 Entry{ScalarEntry{
"BMOIP",
2142 [&model = this->simulator_.model()](
const Context& ectx)
2144 return getValue(ectx.intQuants.oxygenConcentration()) *
2145 getValue(ectx.intQuants.porosity()) *
2146 model.dofTotalVolume(ectx.globalDofIdx);
2150 Entry{ScalarEntry{
"BMUIP",
2151 [&model = this->simulator_.model()](
const Context& ectx)
2153 return getValue(ectx.intQuants.ureaConcentration()) *
2154 getValue(ectx.intQuants.porosity()) *
2155 model.dofTotalVolume(ectx.globalDofIdx) * 1;
2159 Entry{ScalarEntry{
"BMBIP",
2160 [&model = this->simulator_.model()](
const Context& ectx)
2162 return model.dofTotalVolume(ectx.globalDofIdx) *
2163 getValue(ectx.intQuants.biofilmMass());
2167 Entry{ScalarEntry{
"BMCIP",
2168 [&model = this->simulator_.model()](
const Context& ectx)
2170 return model.dofTotalVolume(ectx.globalDofIdx) *
2171 getValue(ectx.intQuants.calciteMass());
2175 Entry{ScalarEntry{
"BGMIP",
2176 [&model = this->simulator_.model()](
const Context& ectx)
2178 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2179 getValue(ectx.fs.saturation(gasPhaseIdx));
2181 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2182 result += getValue(ectx.fs.Rs()) *
2183 getValue(ectx.fs.invB(oilPhaseIdx)) *
2184 getValue(ectx.fs.saturation(oilPhaseIdx));
2187 result += getValue(ectx.fs.Rsw()) *
2188 getValue(ectx.fs.invB(waterPhaseIdx)) *
2189 getValue(ectx.fs.saturation(waterPhaseIdx));
2191 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2192 ectx.intQuants.pvtRegionIndex());
2194 model.dofTotalVolume(ectx.globalDofIdx) *
2195 getValue(ectx.intQuants.porosity()) *
2200 Entry{ScalarEntry{
"BGMGP",
2201 [&model = this->simulator_.model()](
const Context& ectx)
2203 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2204 ectx.intQuants.pvtRegionIndex());
2205 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2206 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2207 model.dofTotalVolume(ectx.globalDofIdx) *
2208 getValue(ectx.intQuants.porosity()) *
2213 Entry{ScalarEntry{
"BGMDS",
2214 [&model = this->simulator_.model()](
const Context& ectx)
2217 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2218 result = getValue(ectx.fs.Rs()) *
2219 getValue(ectx.fs.invB(oilPhaseIdx)) *
2220 getValue(ectx.fs.saturation(oilPhaseIdx));
2223 result = getValue(ectx.fs.Rsw()) *
2224 getValue(ectx.fs.invB(waterPhaseIdx)) *
2225 getValue(ectx.fs.saturation(waterPhaseIdx));
2227 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2228 ectx.intQuants.pvtRegionIndex());
2230 model.dofTotalVolume(ectx.globalDofIdx) *
2231 getValue(ectx.intQuants.porosity()) *
2236 Entry{ScalarEntry{
"BGMST",
2237 [&model = this->simulator_.model(),
2238 &problem = this->simulator_.problem()](
const Context& ectx)
2240 const auto& scaledDrainageInfo = problem.materialLawManager()
2241 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2242 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2243 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2244 if (problem.materialLawManager()->enableHysteresis()) {
2245 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2246 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2247 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2249 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2250 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2251 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2252 return (1.0 - xgW) *
2253 model.dofTotalVolume(ectx.globalDofIdx) *
2254 getValue(ectx.intQuants.porosity()) *
2255 getValue(ectx.fs.density(gasPhaseIdx)) *
2256 std::min(strandedGas, sg);
2260 Entry{ScalarEntry{
"BGMUS",
2261 [&model = this->simulator_.model(),
2262 &problem = this->simulator_.problem()](
const Context& ectx)
2264 const auto& scaledDrainageInfo = problem.materialLawManager()
2265 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2266 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2267 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2268 if (problem.materialLawManager()->enableHysteresis()) {
2269 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2270 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2271 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2273 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2274 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2275 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2276 return (1.0 - xgW) *
2277 model.dofTotalVolume(ectx.globalDofIdx) *
2278 getValue(ectx.intQuants.porosity()) *
2279 getValue(ectx.fs.density(gasPhaseIdx)) *
2280 std::max(Scalar{0.0}, sg - strandedGas);
2284 Entry{ScalarEntry{
"BGMTR",
2285 [&model = this->simulator_.model(),
2286 &problem = this->simulator_.problem()](
const Context& ectx)
2288 const auto& scaledDrainageInfo = problem.materialLawManager()
2289 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2290 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2291 if (problem.materialLawManager()->enableHysteresis()) {
2292 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2293 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2295 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2296 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2297 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2298 return (1.0 - xgW) *
2299 model.dofTotalVolume(ectx.globalDofIdx) *
2300 getValue(ectx.intQuants.porosity()) *
2301 getValue(ectx.fs.density(gasPhaseIdx)) *
2302 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2306 Entry{ScalarEntry{
"BGMMO",
2307 [&model = this->simulator_.model(),
2308 &problem = this->simulator_.problem()](
const Context& ectx)
2310 const auto& scaledDrainageInfo = problem.materialLawManager()
2311 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2312 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2313 if (problem.materialLawManager()->enableHysteresis()) {
2314 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2315 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2317 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2318 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2319 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2320 return (1.0 - xgW) *
2321 model.dofTotalVolume(ectx.globalDofIdx) *
2322 getValue(ectx.intQuants.porosity()) *
2323 getValue(ectx.fs.density(gasPhaseIdx)) *
2324 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2328 Entry{ScalarEntry{
"BGKTR",
2329 [&model = this->simulator_.model(),
2330 &problem = this->simulator_.problem()](
const Context& ectx)
2332 const auto& scaledDrainageInfo = problem.materialLawManager()
2333 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2334 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2335 Scalar sgcr = scaledDrainageInfo.Sgcr;
2336 if (problem.materialLawManager()->enableHysteresis()) {
2337 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2338 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2344 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2345 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2346 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2347 return (1.0 - xgW) *
2348 model.dofTotalVolume(ectx.globalDofIdx) *
2349 getValue(ectx.intQuants.porosity()) *
2350 getValue(ectx.fs.density(gasPhaseIdx)) *
2351 getValue(ectx.fs.saturation(gasPhaseIdx));
2356 Entry{ScalarEntry{
"BGKMO",
2357 [&model = this->simulator_.model(),
2358 &problem = this->simulator_.problem()](
const Context& ectx)
2360 const auto& scaledDrainageInfo = problem.materialLawManager()
2361 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2362 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2363 Scalar sgcr = scaledDrainageInfo.Sgcr;
2364 if (problem.materialLawManager()->enableHysteresis()) {
2365 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2366 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2372 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2373 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2374 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2375 return (1.0 - xgW) *
2376 model.dofTotalVolume(ectx.globalDofIdx) *
2377 getValue(ectx.intQuants.porosity()) *
2378 getValue(ectx.fs.density(gasPhaseIdx)) *
2379 getValue(ectx.fs.saturation(gasPhaseIdx));
2384 Entry{ScalarEntry{
"BGCDI",
2385 [&model = this->simulator_.model(),
2386 &problem = this->simulator_.problem()](
const Context& ectx)
2388 const auto& scaledDrainageInfo = problem.materialLawManager()
2389 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2390 Scalar sgcr = scaledDrainageInfo.Sgcr;
2391 if (problem.materialLawManager()->enableHysteresis()) {
2392 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2393 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2395 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2396 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2397 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2398 return (1.0 - xgW) *
2399 model.dofTotalVolume(ectx.globalDofIdx) *
2400 getValue(ectx.intQuants.porosity()) *
2401 getValue(ectx.fs.density(gasPhaseIdx)) *
2402 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2403 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2407 Entry{ScalarEntry{
"BGCDM",
2408 [&model = this->simulator_.model(),
2409 &problem = this->simulator_.problem()](
const Context& ectx)
2411 const auto& scaledDrainageInfo = problem.materialLawManager()
2412 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2413 Scalar sgcr = scaledDrainageInfo.Sgcr;
2414 if (problem.materialLawManager()->enableHysteresis()) {
2415 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2416 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2418 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2419 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2420 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2421 return (1.0 - xgW) *
2422 model.dofTotalVolume(ectx.globalDofIdx) *
2423 getValue(ectx.intQuants.porosity()) *
2424 getValue(ectx.fs.density(gasPhaseIdx)) *
2425 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2426 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2430 Entry{ScalarEntry{
"BGKDI",
2431 [&model = this->simulator_.model(),
2432 &problem = this->simulator_.problem()](
const Context& ectx)
2434 const auto& scaledDrainageInfo = problem.materialLawManager()
2435 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2436 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2437 Scalar sgcr = scaledDrainageInfo.Sgcr;
2438 if (problem.materialLawManager()->enableHysteresis()) {
2439 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2440 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2446 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2447 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2448 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2449 return (1.0 - xgW) *
2450 model.dofTotalVolume(ectx.globalDofIdx) *
2451 getValue(ectx.intQuants.porosity()) *
2452 getValue(ectx.fs.density(gasPhaseIdx)) *
2453 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2454 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2459 Entry{ScalarEntry{
"BGKDM",
2460 [&model = this->simulator_.model(),
2461 &problem = this->simulator_.problem()](
const Context& ectx)
2463 const auto& scaledDrainageInfo = problem.materialLawManager()
2464 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2465 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2466 Scalar sgcr = scaledDrainageInfo.Sgcr;
2467 if (problem.materialLawManager()->enableHysteresis()) {
2468 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2469 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2475 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2476 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2477 : FluidSystem::convertRvToXgO(getValue(ectx.fs.
Rv()), ectx.intQuants.pvtRegionIndex());
2478 return (1.0 - xgW) *
2479 model.dofTotalVolume(ectx.globalDofIdx) *
2480 getValue(ectx.intQuants.porosity()) *
2481 getValue(ectx.fs.density(gasPhaseIdx)) *
2482 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2483 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2488 Entry{ScalarEntry{
"BWCD",
2489 [&model = this->simulator_.model()](
const Context& ectx)
2492 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2493 result = getValue(ectx.fs.Rs()) *
2494 getValue(ectx.fs.invB(oilPhaseIdx)) *
2495 getValue(ectx.fs.saturation(oilPhaseIdx));
2498 result = getValue(ectx.fs.Rsw()) *
2499 getValue(ectx.fs.invB(waterPhaseIdx)) *
2500 getValue(ectx.fs.saturation(waterPhaseIdx));
2502 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2503 ectx.intQuants.pvtRegionIndex());
2505 model.dofTotalVolume(ectx.globalDofIdx) *
2506 getValue(ectx.intQuants.porosity()) *
2508 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2512 Entry{ScalarEntry{
"BWIPG",
2513 [&model = this->simulator_.model()](
const Context& ectx)
2515 Scalar result = 0.0;
2516 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2517 result = getValue(ectx.fs.Rvw()) *
2518 getValue(ectx.fs.invB(gasPhaseIdx)) *
2519 getValue(ectx.fs.saturation(gasPhaseIdx));
2522 model.dofTotalVolume(ectx.globalDofIdx) *
2523 getValue(ectx.intQuants.porosity());
2527 Entry{ScalarEntry{
"BWIPL",
2528 [&model = this->simulator_.model()](
const Context& ectx)
2530 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2531 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2532 model.dofTotalVolume(ectx.globalDofIdx) *
2533 getValue(ectx.intQuants.porosity());
2542 if (reportStepNum > 0 && !isSubStep) {
2544 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
2545 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
2547 [&c = this->collectOnIORank_](
const int idx)
2548 {
return c.isCartIdxOnThisRank(idx); });
2550 const auto extraHandlers = std::array{
2559 const Simulator& simulator_;
2560 const CollectDataOnIORankType& collectOnIORank_;
2561 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)
Definition: GenericOutputBlackoilModule.hpp:76
std::map< std::pair< std::string, int >, double > blockData_
Definition: GenericOutputBlackoilModule.hpp:456
std::array< ScalarBuffer, numPhases > relativePermeability_
Definition: GenericOutputBlackoilModule.hpp:445
ScalarBuffer fluidPressure_
Definition: GenericOutputBlackoilModule.hpp:399
std::array< ScalarBuffer, numPhases > density_
Definition: GenericOutputBlackoilModule.hpp:443
ScalarBuffer saturatedOilFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:431
ScalarBuffer overburdenPressure_
Definition: GenericOutputBlackoilModule.hpp:405
ScalarBuffer gasDissolutionFactorInWater_
Definition: GenericOutputBlackoilModule.hpp:425
const EclipseState & eclState_
Definition: GenericOutputBlackoilModule.hpp:358
ScalarBuffer swmin_
Definition: GenericOutputBlackoilModule.hpp:421
ScalarBuffer rockCompPorvMultiplier_
Definition: GenericOutputBlackoilModule.hpp:429
RFTContainer< GetPropType< TypeTag, Properties::FluidSystem > > rftC_
Definition: GenericOutputBlackoilModule.hpp:453
bool computeFip_
Definition: GenericOutputBlackoilModule.hpp:381
ScalarBuffer dewPointPressure_
Definition: GenericOutputBlackoilModule.hpp:428
LogOutputHelper< Scalar > logOutput_
Definition: GenericOutputBlackoilModule.hpp:365
std::vector< int > failedCellsPb_
Definition: GenericOutputBlackoilModule.hpp:390
ScalarBuffer permFact_
Definition: GenericOutputBlackoilModule.hpp:414
ScalarBuffer rsw_
Definition: GenericOutputBlackoilModule.hpp:402
ScalarBuffer pcog_
Definition: GenericOutputBlackoilModule.hpp:436
std::optional< RegionPhasePoreVolAverage > regionAvgDensity_
Definition: GenericOutputBlackoilModule.hpp:464
std::array< ScalarBuffer, numPhases > invB_
Definition: GenericOutputBlackoilModule.hpp:442
ScalarBuffer pSalt_
Definition: GenericOutputBlackoilModule.hpp:413
ScalarBuffer cFoam_
Definition: GenericOutputBlackoilModule.hpp:411
ScalarBuffer bubblePointPressure_
Definition: GenericOutputBlackoilModule.hpp:427
ScalarBuffer temperature_
Definition: GenericOutputBlackoilModule.hpp:400
ScalarBuffer ppcw_
Definition: GenericOutputBlackoilModule.hpp:422
FIPContainer< GetPropType< TypeTag, Properties::FluidSystem > > fipC_
Definition: GenericOutputBlackoilModule.hpp:383
ScalarBuffer rockCompTransMultiplier_
Definition: GenericOutputBlackoilModule.hpp:432
MechContainer< Scalar > mech_
Definition: GenericOutputBlackoilModule.hpp:439
ScalarBuffer dynamicPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:397
ScalarBuffer minimumOilPressure_
Definition: GenericOutputBlackoilModule.hpp:430
ScalarBuffer gasFormationVolumeFactor_
Definition: GenericOutputBlackoilModule.hpp:393
std::array< ScalarBuffer, numPhases > residual_
Definition: GenericOutputBlackoilModule.hpp:449
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:419
BioeffectsContainer< Scalar > bioeffectsC_
Definition: GenericOutputBlackoilModule.hpp:433
const Schedule & schedule_
Definition: GenericOutputBlackoilModule.hpp:359
FlowsContainer< GetPropType< TypeTag, Properties::FluidSystem > > flowsC_
Definition: GenericOutputBlackoilModule.hpp:451
ExtboContainer< Scalar > extboC_
Definition: GenericOutputBlackoilModule.hpp:415
void setupExtraBlockData(const std::size_t reportStepNum, std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer oilSaturationPressure_
Definition: GenericOutputBlackoilModule.hpp:406
InterRegFlowMap interRegionFlows_
Definition: GenericOutputBlackoilModule.hpp:364
ScalarBuffer pcgw_
Definition: GenericOutputBlackoilModule.hpp:434
ScalarBuffer cPolymer_
Definition: GenericOutputBlackoilModule.hpp:410
void setupBlockData(std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer rvw_
Definition: GenericOutputBlackoilModule.hpp:404
std::array< ScalarBuffer, numPhases > saturation_
Definition: GenericOutputBlackoilModule.hpp:441
std::unordered_map< std::string, std::vector< int > > regions_
Definition: GenericOutputBlackoilModule.hpp:384
ScalarBuffer rPorV_
Definition: GenericOutputBlackoilModule.hpp:398
ScalarBuffer oilVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:424
std::vector< int > failedCellsPd_
Definition: GenericOutputBlackoilModule.hpp:391
ScalarBuffer rs_
Definition: GenericOutputBlackoilModule.hpp:401
ScalarBuffer drsdtcon_
Definition: GenericOutputBlackoilModule.hpp:407
ScalarBuffer sSol_
Definition: GenericOutputBlackoilModule.hpp:408
std::map< std::pair< std::string, int >, double > extraBlockData_
Definition: GenericOutputBlackoilModule.hpp:459
ScalarBuffer pressureTimesPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:395
ScalarBuffer gasDissolutionFactor_
Definition: GenericOutputBlackoilModule.hpp:423
std::array< ScalarBuffer, numPhases > viscosity_
Definition: GenericOutputBlackoilModule.hpp:444
bool forceDisableFipOutput_
Definition: GenericOutputBlackoilModule.hpp:379
ScalarBuffer soMax_
Definition: GenericOutputBlackoilModule.hpp:416
ScalarBuffer sgmax_
Definition: GenericOutputBlackoilModule.hpp:418
ScalarBuffer somin_
Definition: GenericOutputBlackoilModule.hpp:420
ScalarBuffer hydrocarbonPoreVolume_
Definition: GenericOutputBlackoilModule.hpp:394
const std::optional< Inplace > & initialInplace() const
Definition: GenericOutputBlackoilModule.hpp:246
ScalarBuffer waterVaporizationFactor_
Definition: GenericOutputBlackoilModule.hpp:426
ScalarBuffer cSalt_
Definition: GenericOutputBlackoilModule.hpp:412
TracerContainer< GetPropType< TypeTag, Properties::FluidSystem > > tracerC_
Definition: GenericOutputBlackoilModule.hpp:447
ScalarBuffer rv_
Definition: GenericOutputBlackoilModule.hpp:403
ScalarBuffer pcow_
Definition: GenericOutputBlackoilModule.hpp:435
ScalarBuffer swMax_
Definition: GenericOutputBlackoilModule.hpp:417
ScalarBuffer pressureTimesHydrocarbonVolume_
Definition: GenericOutputBlackoilModule.hpp:396
ScalarBuffer rswSol_
Definition: GenericOutputBlackoilModule.hpp:409
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:239
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:483
void setupExtractors(const bool isSubStep, const int reportStepNum)
Setup list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:220
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:198
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputBlackoilModule.hpp:446
void clearExtractors()
Clear list of active element-level data extractors.
Definition: OutputBlackoilModule.hpp:228
void outputFipAndResvLogToCSV(const std::size_t reportStepNum, const bool substep, const Parallel::Communication &comm)
Definition: OutputBlackoilModule.hpp:380
void assignToFluidState(FluidState &fs, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:507
void initHysteresisParams(Simulator &simulator, unsigned elemIdx) const
Definition: OutputBlackoilModule.hpp:559
void updateFluidInPlace(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:624
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:329
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputBlackoilModule.hpp:501
void processElementBlockData(const ElementContext &elemCtx)
Definition: OutputBlackoilModule.hpp:285
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputBlackoilModule.hpp:493
void updateFluidInPlace(const unsigned globalDofIdx, const IntensiveQuantities &intQuants, const double totVolume)
Definition: OutputBlackoilModule.hpp:631
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:141
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