85class OutputBlackOilModule :
public GenericOutputBlackoilModule<GetPropType<TypeTag, Properties::FluidSystem>>
96 using FluidState =
typename IntensiveQuantities::FluidState;
98 using Element =
typename GridView::template Codim<0>::Entity;
99 using ElementIterator =
typename GridView::template Codim<0>::Iterator;
100 using BaseType = GenericOutputBlackoilModule<FluidSystem>;
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;
119 enum { enableMICP = Indices::enableMICP };
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];
134 OutputBlackOilModule(
const Simulator& simulator,
135 const SummaryConfig& smryCfg,
136 const CollectDataOnIORankType& collectOnIORank)
137 : BaseType(simulator.vanguard().eclState(),
138 simulator.vanguard().schedule(),
140 simulator.vanguard().summaryState(),
142 [
this](
const int idx)
143 {
return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
144 [&collectOnIORank](
const int idx)
145 {
return collectOnIORank.isCartIdxOnThisRank(idx); },
146 simulator.vanguard().grid().comm(),
147 energyModuleType == EnergyModules::FullyImplicitThermal ||
148 energyModuleType == EnergyModules::SequentialImplicitThermal,
149 energyModuleType == EnergyModules::ConstantTemperature,
159 , simulator_(simulator)
160 , collectOnIORank_(collectOnIORank)
162 for (
auto& region_pair : this->regions_) {
163 this->createLocalRegion_(region_pair.second);
166 auto isCartIdxOnThisRank = [&collectOnIORank](
const int idx) {
167 return collectOnIORank.isCartIdxOnThisRank(idx);
170 this->setupBlockData(isCartIdxOnThisRank);
173 const std::string msg =
"The output code does not support --owner-cells-first=false.";
174 if (collectOnIORank.isIORank()) {
177 OPM_THROW_NOLOG(std::runtime_error, msg);
180 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
181 auto rset = this->eclState_.fieldProps().fip_regions();
182 rset.push_back(
"PVTNUM");
187 this->regionAvgDensity_
188 .emplace(this->simulator_.gridView().comm(),
189 FluidSystem::numPhases, rset,
190 [fp = std::cref(this->eclState_.fieldProps())]
191 (
const std::string& rsetName) ->
decltype(
auto)
192 { return fp.get().get_int(rsetName); });
202 const unsigned reportStepNum,
205 const bool isRestart)
211 const auto& problem = this->simulator_.problem();
213 this->doAllocBuffers(bufferSize,
218 &problem.materialLawManager()->hysteresisConfig(),
219 problem.eclWriter().getOutputNnc().front().size());
224 const int reportStepNum)
226 this->setupElementExtractors_();
227 this->setupBlockExtractors_(isSubStep, reportStepNum);
233 this->extractors_.clear();
234 this->blockExtractors_.clear();
235 this->extraBlockExtractors_.clear();
249 if (this->extractors_.empty()) {
253 const auto& matLawManager = simulator_.problem().materialLawManager();
256 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
257 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
258 const auto& fs = intQuants.fluidState();
261 elemCtx.globalSpaceIndex(dofIdx, 0),
262 elemCtx.primaryVars(dofIdx, 0).pvtRegionIndex(),
263 elemCtx.simulator().episodeIndex(),
269 if (matLawManager->enableHysteresis()) {
270 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
271 matLawManager->oilWaterHysteresisParams(hysterParams.
somax,
276 if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
277 matLawManager->gasOilHysteresisParams(hysterParams.
sgmax,
288 void processElementBlockData(
const ElementContext& elemCtx)
290 OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
295 if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
299 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
301 const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
302 const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
304 const auto be_it = this->blockExtractors_.find(cartesianIdx);
305 const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
306 if (be_it == this->blockExtractors_.end() &&
307 bee_it == this->extraBlockExtractors_.end())
312 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
313 const auto& fs = intQuants.fluidState();
323 if (be_it != this->blockExtractors_.end()) {
326 if (bee_it != this->extraBlockExtractors_.end()) {
332 void outputFipAndResvLog(
const Inplace& inplace,
333 const std::size_t reportStepNum,
335 boost::posix_time::ptime currentDate,
337 const Parallel::Communication& comm)
340 if (comm.rank() != 0) {
345 std::unique_ptr<FIPConfig> fipSched;
346 if (reportStepNum > 0) {
347 const auto& rpt = this->schedule_[reportStepNum-1].rpt_config.get();
348 fipSched = std::make_unique<FIPConfig>(rpt);
350 const FIPConfig& fipc = reportStepNum == 0 ? this->eclState_.getEclipseConfig().fip()
353 if (!substep && !this->forceDisableFipOutput_ && fipc.output(FIPConfig::OutputField::FIELD)) {
355 this->logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
357 const auto& initial_inplace = *this->initialInplace();
358 this->logOutput_.fip(inplace, initial_inplace,
"");
360 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
361 this->logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
363 if (fipc.output(FIPConfig::OutputField::RESV))
364 this->logOutput_.fipResv(inplace,
"FIPNUM");
367 if (fipc.output(FIPConfig::OutputField::FIP)) {
368 for (
const auto& reg : this->regions_) {
369 if (reg.first !=
"FIPNUM") {
370 std::ostringstream ss;
371 ss <<
"BAL" << reg.first.substr(3);
372 this->logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
373 this->logOutput_.fip(inplace, initial_inplace, reg.first);
375 if (fipc.output(FIPConfig::OutputField::RESV))
376 this->logOutput_.fipResv(inplace, reg.first);
383 void outputFipAndResvLogToCSV(
const std::size_t reportStepNum,
385 const Parallel::Communication& comm)
387 if (comm.rank() != 0) {
391 if ((reportStepNum == 0) && (!substep) &&
392 (this->schedule_.initialReportConfiguration().has_value()) &&
393 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
395 std::ostringstream csv_stream;
397 this->logOutput_.csv_header(csv_stream);
399 const auto& initial_inplace = *this->initialInplace();
401 this->logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
403 for (
const auto& reg : this->regions_) {
404 if (reg.first !=
"FIPNUM") {
405 this->logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
409 const IOConfig& io = this->eclState_.getIOConfig();
410 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
412 std::ofstream outputFile(csv_fname);
414 outputFile << csv_stream.str();
448 template <
class ActiveIndex,
class CartesianIndex>
450 ActiveIndex&& activeIndex,
451 CartesianIndex&& cartesianIndex)
454 const auto identifyCell = [&activeIndex, &cartesianIndex](
const Element& elem)
457 const auto cellIndex = activeIndex(elem);
460 static_cast<int>(cellIndex),
461 cartesianIndex(cellIndex),
462 elem.partitionType() == Dune::InteriorEntity
466 const auto timeIdx = 0u;
467 const auto& stencil = elemCtx.stencil(timeIdx);
468 const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
470 for (
auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
471 const auto& face = stencil.interiorFace(scvfIdx);
472 const auto left = identifyCell(stencil.element(face.interiorIndex()));
473 const auto right = identifyCell(stencil.element(face.exteriorIndex()));
475 const auto rates = this->
476 getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
478 this->interRegionFlows_.addConnection(left, right, rates);
490 this->interRegionFlows_.clear();
498 this->interRegionFlows_.compress();
506 return this->interRegionFlows_;
509 template <
class Flu
idState>
510 void assignToFluidState(FluidState& fs,
unsigned elemIdx)
const
512 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
513 if (this->saturation_[phaseIdx].empty())
516 fs.setSaturation(phaseIdx, this->saturation_[phaseIdx][elemIdx]);
519 if (!this->fluidPressure_.empty()) {
522 std::array<Scalar, numPhases> pc = {0};
523 const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
524 MaterialLaw::capillaryPressures(pc, matParams, fs);
525 Valgrind::CheckDefined(this->fluidPressure_[elemIdx]);
526 Valgrind::CheckDefined(pc);
527 const auto& pressure = this->fluidPressure_[elemIdx];
528 for (
unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
529 if (!FluidSystem::phaseIsActive(phaseIdx))
532 if (Indices::oilEnabled)
533 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
534 else if (Indices::gasEnabled)
535 fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
536 else if (Indices::waterEnabled)
538 fs.setPressure(phaseIdx, pressure);
542 if constexpr (energyModuleType != EnergyModules::NoTemperature) {
543 if (!this->temperature_.empty())
544 fs.setTemperature(this->temperature_[elemIdx]);
546 if constexpr (enableDissolvedGas) {
547 if (!this->rs_.empty())
548 fs.setRs(this->rs_[elemIdx]);
549 if (!this->rv_.empty())
550 fs.setRv(this->rv_[elemIdx]);
552 if constexpr (enableDisgasInWater) {
553 if (!this->rsw_.empty())
554 fs.setRsw(this->rsw_[elemIdx]);
556 if constexpr (enableVapwat) {
557 if (!this->rvw_.empty())
558 fs.setRvw(this->rvw_[elemIdx]);
562 void initHysteresisParams(Simulator& simulator,
unsigned elemIdx)
const
564 if (!this->soMax_.empty())
565 simulator.problem().setMaxOilSaturation(elemIdx, this->soMax_[elemIdx]);
567 if (simulator.problem().materialLawManager()->enableHysteresis()) {
568 auto matLawManager = simulator.problem().materialLawManager();
570 if (FluidSystem::phaseIsActive(oilPhaseIdx)
571 && FluidSystem::phaseIsActive(waterPhaseIdx)) {
576 if (matLawManager->enableNonWettingHysteresis()) {
577 if (!this->soMax_.empty()) {
578 somax = this->soMax_[elemIdx];
581 if (matLawManager->enableWettingHysteresis()) {
582 if (!this->swMax_.empty()) {
583 swmax = this->swMax_[elemIdx];
586 if (matLawManager->enablePCHysteresis()) {
587 if (!this->swmin_.empty()) {
588 swmin = this->swmin_[elemIdx];
591 matLawManager->setOilWaterHysteresisParams(
592 somax, swmax, swmin, elemIdx);
594 if (FluidSystem::phaseIsActive(oilPhaseIdx)
595 && FluidSystem::phaseIsActive(gasPhaseIdx)) {
600 if (matLawManager->enableNonWettingHysteresis()) {
601 if (!this->sgmax_.empty()) {
602 sgmax = this->sgmax_[elemIdx];
605 if (matLawManager->enableWettingHysteresis()) {
606 if (!this->shmax_.empty()) {
607 shmax = this->shmax_[elemIdx];
610 if (matLawManager->enablePCHysteresis()) {
611 if (!this->somin_.empty()) {
612 somin = this->somin_[elemIdx];
615 matLawManager->setGasOilHysteresisParams(
616 sgmax, shmax, somin, elemIdx);
621 if (simulator_.vanguard().eclState().fieldProps().has_double(
"SWATINIT")) {
622 simulator.problem().materialLawManager()
623 ->applyRestartSwatInit(elemIdx, this->ppcw_[elemIdx]);
627 void updateFluidInPlace(
const ElementContext& elemCtx)
629 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
630 updateFluidInPlace_(elemCtx, dofIdx);
634 void updateFluidInPlace(
const unsigned globalDofIdx,
635 const IntensiveQuantities& intQuants,
636 const double totVolume)
638 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
642 template <
typename T>
643 using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
645 template <
typename,
class =
void>
646 struct HasGeoMech :
public std::false_type {};
648 template <
typename Problem>
650 Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
651 > :
public std::true_type {};
653 template <
typename,
class =
void>
654 struct HasGeochemistry :
public std::false_type {};
656 template <
typename Problem>
657 struct HasGeochemistry<
658 Problem, std::void_t<decltype(std::declval<Problem>().geochemistryModel())>
659 > :
public std::true_type {};
661 bool isDefunctParallelWell(
const std::string& wname)
const override
663 if (simulator_.gridView().comm().size() == 1)
665 const auto& parallelWells = simulator_.vanguard().parallelWells();
666 std::pair<std::string, bool> value {wname,
true};
667 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
668 return candidate == parallelWells.end() || *candidate != value;
671 bool isOwnedByCurrentRank(
const std::string& wname)
const override
673 return this->simulator_.problem().wellModel().isOwner(wname);
676 bool isOnCurrentRank(
const std::string& wname)
const override
678 return this->simulator_.problem().wellModel().hasLocalCells(wname);
681 void updateFluidInPlace_(
const ElementContext& elemCtx,
const unsigned dofIdx)
683 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
684 const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, 0);
685 const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
687 this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
690 void updateFluidInPlace_(
const unsigned globalDofIdx,
691 const IntensiveQuantities& intQuants,
692 const double totVolume)
694 OPM_TIMEBLOCK_LOCAL(updateFluidInPlace, Subsystem::Output);
696 this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
698 if (this->computeFip_) {
699 this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
703 void createLocalRegion_(std::vector<int>& region)
709 region.resize(simulator_.gridView().size(0));
710 std::size_t elemIdx = 0;
711 for (
const auto& elem : elements(simulator_.gridView())) {
712 if (elem.partitionType() != Dune::InteriorEntity) {
720 template <
typename Flu
idState>
721 void aggregateAverageDensityContributions_(
const FluidState& fs,
722 const unsigned int globalDofIdx,
725 auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
726 pvCellValue.porv = porv;
728 for (
auto phaseIdx = 0*FluidSystem::numPhases;
729 phaseIdx < FluidSystem::numPhases; ++phaseIdx)
731 if (! FluidSystem::phaseIsActive(phaseIdx)) {
735 pvCellValue.value = getValue(fs.density(phaseIdx));
736 pvCellValue.sat = getValue(fs.saturation(phaseIdx));
738 this->regionAvgDensity_
739 ->addCell(globalDofIdx,
740 RegionPhasePoreVolAverage::Phase { phaseIdx },
760 data::InterRegFlowMap::FlowRates
761 getComponentSurfaceRates(
const ElementContext& elemCtx,
762 const Scalar faceArea,
763 const std::size_t scvfIdx,
764 const std::size_t timeIdx)
const
766 using Component = data::InterRegFlowMap::Component;
768 auto rates = data::InterRegFlowMap::FlowRates {};
770 const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
772 const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
774 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
775 const auto& up = elemCtx
776 .intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
778 const auto pvtReg = up.pvtRegionIndex();
780 const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
781 (up.fluidState(), oilPhaseIdx, pvtReg));
783 const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
785 rates[Component::Oil] += qO;
787 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
788 const auto Rs = getValue(
789 BlackOil::getRs_<FluidSystem, FluidState, Scalar>
790 (up.fluidState(), pvtReg));
792 rates[Component::Gas] += qO * Rs;
793 rates[Component::Disgas] += qO * Rs;
797 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
798 const auto& up = elemCtx
799 .intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
801 const auto pvtReg = up.pvtRegionIndex();
803 const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
804 (up.fluidState(), gasPhaseIdx, pvtReg));
806 const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
808 rates[Component::Gas] += qG;
810 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
811 const auto Rv = getValue(
812 BlackOil::getRv_<FluidSystem, FluidState, Scalar>
813 (up.fluidState(), pvtReg));
815 rates[Component::Oil] += qG * Rv;
816 rates[Component::Vapoil] += qG * Rv;
820 if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
821 const auto& up = elemCtx
822 .intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
824 const auto pvtReg = up.pvtRegionIndex();
826 const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
827 (up.fluidState(), waterPhaseIdx, pvtReg));
829 rates[Component::Water] +=
830 alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
836 template <
typename Flu
idState>
837 Scalar hydroCarbonFraction(
const FluidState& fs)
const
839 if (this->eclState_.runspec().co2Storage()) {
846 auto hydrocarbon = Scalar {0};
847 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
848 hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
851 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
852 hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
858 void updateTotalVolumesAndPressures_(
const unsigned globalDofIdx,
859 const IntensiveQuantities& intQuants,
860 const double totVolume)
862 const auto& fs = intQuants.fluidState();
864 const double pv = totVolume * intQuants.porosity().value();
865 const auto hydrocarbon = this->hydroCarbonFraction(fs);
867 if (! this->hydrocarbonPoreVolume_.empty()) {
868 this->fipC_.assignPoreVolume(globalDofIdx,
869 totVolume * intQuants.referencePorosity());
871 this->dynamicPoreVolume_[globalDofIdx] = pv;
872 this->hydrocarbonPoreVolume_[globalDofIdx] = pv * hydrocarbon;
875 if (!this->pressureTimesHydrocarbonVolume_.empty() &&
876 !this->pressureTimesPoreVolume_.empty())
878 assert(this->hydrocarbonPoreVolume_.size() == this->pressureTimesHydrocarbonVolume_.size());
879 assert(this->fipC_.get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
881 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
882 this->pressureTimesPoreVolume_[globalDofIdx] =
883 getValue(fs.pressure(oilPhaseIdx)) * pv;
885 this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
886 this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
888 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
889 this->pressureTimesPoreVolume_[globalDofIdx] =
890 getValue(fs.pressure(gasPhaseIdx)) * pv;
892 this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
893 this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
895 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
896 this->pressureTimesPoreVolume_[globalDofIdx] =
897 getValue(fs.pressure(waterPhaseIdx)) * pv;
902 void updatePhaseInplaceVolumes_(
const unsigned globalDofIdx,
903 const IntensiveQuantities& intQuants,
904 const double totVolume)
906 std::array<Scalar, FluidSystem::numPhases> fip {};
907 std::array<Scalar, FluidSystem::numPhases> fipr{};
909 const auto& fs = intQuants.fluidState();
910 const auto pv = totVolume * intQuants.porosity().value();
912 for (
unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
913 if (!FluidSystem::phaseIsActive(phaseIdx)) {
917 const auto b = getValue(fs.invB(phaseIdx));
918 const auto s = getValue(fs.saturation(phaseIdx));
920 fipr[phaseIdx] = s * pv;
921 fip [phaseIdx] = b * fipr[phaseIdx];
924 this->fipC_.assignVolumesSurface(globalDofIdx, fip);
925 this->fipC_.assignVolumesReservoir(globalDofIdx,
926 fs.saltConcentration().value(),
929 if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
930 FluidSystem::phaseIsActive(gasPhaseIdx))
932 this->updateOilGasDistribution(globalDofIdx, fs, fip);
935 if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
936 FluidSystem::phaseIsActive(gasPhaseIdx))
938 this->updateGasWaterDistribution(globalDofIdx, fs, fip);
941 if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
942 this->fipC_.hasCo2InGas())
944 this->updateCO2InGas(globalDofIdx, pv, intQuants);
947 if (this->fipC_.hasCo2InWater() &&
948 (FluidSystem::phaseIsActive(waterPhaseIdx) ||
949 FluidSystem::phaseIsActive(oilPhaseIdx)))
951 this->updateCO2InWater(globalDofIdx, pv, fs);
954 if constexpr(enableBioeffects) {
955 const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
956 getValue(fs.invB(waterPhaseIdx));
957 if (this->fipC_.hasMicrobialMass()) {
958 this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
960 if (this->fipC_.hasBiofilmMass()) {
961 this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
963 if constexpr(enableMICP) {
964 if (this->fipC_.hasOxygenMass()) {
965 this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
967 if (this->fipC_.hasUreaMass()) {
968 this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
970 if (this->fipC_.hasCalciteMass()) {
971 this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
976 if (this->fipC_.hasWaterMass() && FluidSystem::phaseIsActive(waterPhaseIdx))
978 this->updateWaterMass(globalDofIdx, fs, fip);
982 template <
typename Flu
idState,
typename FIPArray>
983 void updateOilGasDistribution(
const unsigned globalDofIdx,
984 const FluidState& fs,
988 const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
989 const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
991 this->fipC_.assignOilGasDistribution(globalDofIdx, gasInPlaceLiquid, oilInPlaceGas);
994 template <
typename Flu
idState,
typename FIPArray>
995 void updateGasWaterDistribution(
const unsigned globalDofIdx,
996 const FluidState& fs,
1000 const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
1001 const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
1003 this->fipC_.assignGasWater(globalDofIdx, fip, gasInPlaceWater, waterInPlaceGas);
1006 template <
typename IntensiveQuantities>
1007 void updateCO2InGas(
const unsigned globalDofIdx,
1009 const IntensiveQuantities& intQuants)
1011 const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
1012 ->oilWaterScaledEpsInfoDrainage(globalDofIdx);
1014 const auto& fs = intQuants.fluidState();
1015 Scalar sgcr = scaledDrainageInfo.Sgcr;
1016 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1017 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1018 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
1021 Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
1022 if (this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
1023 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
1025 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1026 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1028 trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams,
true);
1032 const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
1033 Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
1034 if (this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
1035 this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
1037 if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
1038 const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
1039 const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
1040 strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
1044 const typename FIPContainer<FluidSystem>::Co2InGasInput v{
1048 getValue(fs.density(gasPhaseIdx)),
1049 FluidSystem::phaseIsActive(waterPhaseIdx)
1050 ? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
1051 : FluidSystem::convertRvToXgO(getValue(fs.Rv()), fs.pvtRegionIndex()),
1052 FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
1053 trappedGasSaturation,
1054 strandedGasSaturation,
1057 this->fipC_.assignCo2InGas(globalDofIdx, v);
1060 template <
typename Flu
idState>
1061 void updateCO2InWater(
const unsigned globalDofIdx,
1063 const FluidState& fs)
1065 const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
1066 ? this->co2InWaterFromOil(fs, pv)
1067 : this->co2InWaterFromWater(fs, pv);
1069 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1071 this->fipC_.assignCo2InWater(globalDofIdx, co2InWater, mM);
1074 template <
typename Flu
idState>
1075 Scalar co2InWaterFromWater(
const FluidState& fs,
const double pv)
const
1077 const double rhow = getValue(fs.density(waterPhaseIdx));
1078 const double sw = getValue(fs.saturation(waterPhaseIdx));
1079 const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
1081 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1083 return xwG * pv * rhow * sw / mM;
1086 template <
typename Flu
idState>
1087 Scalar co2InWaterFromOil(
const FluidState& fs,
const double pv)
const
1089 const double rhoo = getValue(fs.density(oilPhaseIdx));
1090 const double so = getValue(fs.saturation(oilPhaseIdx));
1091 const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
1093 const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
1095 return xoG * pv * rhoo * so / mM;
1098 template <
typename Flu
idState,
typename FIPArray>
1099 void updateWaterMass(
const unsigned globalDofIdx,
1100 const FluidState& fs,
1104 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
1106 this->fipC_.assignWaterMass(globalDofIdx, fip, rhoW);
1109 template <
typename IntensiveQuantities>
1110 void updateMicrobialMass(
const unsigned globalDofIdx,
1111 const IntensiveQuantities& intQuants,
1112 const double surfVolWat)
1114 const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
1116 this->fipC_.assignMicrobialMass(globalDofIdx, mass);
1119 template <
typename IntensiveQuantities>
1120 void updateOxygenMass(
const unsigned globalDofIdx,
1121 const IntensiveQuantities& intQuants,
1122 const double surfVolWat)
1124 const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
1126 this->fipC_.assignOxygenMass(globalDofIdx, mass);
1129 template <
typename IntensiveQuantities>
1130 void updateUreaMass(
const unsigned globalDofIdx,
1131 const IntensiveQuantities& intQuants,
1132 const double surfVolWat)
1134 const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
1136 this->fipC_.assignUreaMass(globalDofIdx, mass);
1139 template <
typename IntensiveQuantities>
1140 void updateBiofilmMass(
const unsigned globalDofIdx,
1141 const IntensiveQuantities& intQuants,
1142 const double totVolume)
1144 const Scalar mass = totVolume * intQuants.biofilmMass().value();
1146 this->fipC_.assignBiofilmMass(globalDofIdx, mass);
1149 template <
typename IntensiveQuantities>
1150 void updateCalciteMass(
const unsigned globalDofIdx,
1151 const IntensiveQuantities& intQuants,
1152 const double totVolume)
1154 const Scalar mass = totVolume * intQuants.calciteMass().value();
1156 this->fipC_.assignCalciteMass(globalDofIdx, mass);
1160 void setupElementExtractors_()
1167 const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
1168 const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
1170 auto extractors = std::array{
1171 Entry{PhaseEntry{&this->saturation_,
1172 [](
const unsigned phase,
const Context& ectx)
1173 {
return getValue(ectx.fs.saturation(phase)); }
1176 Entry{PhaseEntry{&this->invB_,
1177 [](
const unsigned phase,
const Context& ectx)
1178 {
return getValue(ectx.fs.invB(phase)); }
1181 Entry{PhaseEntry{&this->density_,
1182 [](
const unsigned phase,
const Context& ectx)
1183 {
return getValue(ectx.fs.density(phase)); }
1186 Entry{PhaseEntry{&this->relativePermeability_,
1187 [](
const unsigned phase,
const Context& ectx)
1188 {
return getValue(ectx.intQuants.relativePermeability(phase)); }
1191 Entry{PhaseEntry{&this->viscosity_,
1192 [
this](
const unsigned phaseIdx,
const Context& ectx)
1194 if (this->extboC_.allocated() && phaseIdx == oilPhaseIdx) {
1195 return getValue(ectx.intQuants.oilViscosity());
1197 else if (this->extboC_.allocated() && phaseIdx == gasPhaseIdx) {
1198 return getValue(ectx.intQuants.gasViscosity());
1201 return getValue(ectx.fs.viscosity(phaseIdx));
1206 Entry{PhaseEntry{&this->residual_,
1207 [&modelResid = this->simulator_.model().linearizer().residual()]
1208 (
const unsigned phaseIdx,
const Context& ectx)
1210 const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
1211 const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
1212 return modelResid[ectx.globalDofIdx][activeCompIdx];
1217 Entry{ScalarEntry{&this->rockCompPorvMultiplier_,
1218 [&problem = this->simulator_.problem()](
const Context& ectx)
1220 return problem.template
1221 rockCompPoroMultiplier<Scalar>(ectx.intQuants,
1226 Entry{ScalarEntry{&this->rockCompTransMultiplier_,
1227 [&problem = this->simulator_.problem()](
const Context& ectx)
1230 template rockCompTransMultiplier<Scalar>(ectx.intQuants,
1234 Entry{ScalarEntry{&this->minimumOilPressure_,
1235 [&problem = this->simulator_.problem()](
const Context& ectx)
1237 return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
1238 problem.minOilPressure(ectx.globalDofIdx));
1242 Entry{ScalarEntry{&this->bubblePointPressure_,
1243 [&failedCells = this->failedCellsPb_,
1244 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1248 FluidSystem::bubblePointPressure(ectx.fs,
1249 ectx.intQuants.pvtRegionIndex())
1251 }
catch (
const NumericalProblem&) {
1252 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1253 failedCells.push_back(cartesianIdx);
1259 Entry{ScalarEntry{&this->dewPointPressure_,
1260 [&failedCells = this->failedCellsPd_,
1261 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1265 FluidSystem::dewPointPressure(ectx.fs,
1266 ectx.intQuants.pvtRegionIndex())
1268 }
catch (
const NumericalProblem&) {
1269 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1270 failedCells.push_back(cartesianIdx);
1276 Entry{ScalarEntry{&this->overburdenPressure_,
1277 [&problem = simulator_.problem()](
const Context& ectx)
1278 {
return problem.overburdenPressure(ectx.globalDofIdx); }
1281 Entry{ScalarEntry{&this->temperature_,
1282 [](
const Context& ectx)
1283 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }
1286 Entry{ScalarEntry{&this->sSol_,
1287 [](
const Context& ectx)
1288 {
return getValue(ectx.intQuants.solventSaturation()); }
1291 Entry{ScalarEntry{&this->rswSol_,
1292 [](
const Context& ectx)
1293 {
return getValue(ectx.intQuants.rsSolw()); }
1296 Entry{ScalarEntry{&this->cPolymer_,
1297 [](
const Context& ectx)
1298 {
return getValue(ectx.intQuants.polymerConcentration()); }
1301 Entry{ScalarEntry{&this->cFoam_,
1302 [](
const Context& ectx)
1303 {
return getValue(ectx.intQuants.foamConcentration()); }
1306 Entry{ScalarEntry{&this->cSalt_,
1307 [](
const Context& ectx)
1308 {
return getValue(ectx.fs.saltConcentration()); }
1311 Entry{ScalarEntry{&this->pSalt_,
1312 [](
const Context& ectx)
1313 {
return getValue(ectx.fs.saltSaturation()); }
1316 Entry{ScalarEntry{&this->permFact_,
1317 [](
const Context& ectx)
1318 {
return getValue(ectx.intQuants.permFactor()); }
1321 Entry{ScalarEntry{&this->rPorV_,
1322 [&model = this->simulator_.model()](
const Context& ectx)
1324 const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
1325 return totVolume * getValue(ectx.intQuants.porosity());
1329 Entry{ScalarEntry{&this->rs_,
1330 [](
const Context& ectx)
1331 {
return getValue(ectx.fs.Rs()); }
1334 Entry{ScalarEntry{&this->rv_,
1335 [](
const Context& ectx)
1336 {
return getValue(ectx.fs.Rv()); }
1339 Entry{ScalarEntry{&this->rsw_,
1340 [](
const Context& ectx)
1341 {
return getValue(ectx.fs.Rsw()); }
1344 Entry{ScalarEntry{&this->rvw_,
1345 [](
const Context& ectx)
1346 {
return getValue(ectx.fs.Rvw()); }
1349 Entry{ScalarEntry{&this->ppcw_,
1350 [&matLawManager = *this->simulator_.problem().materialLawManager()]
1351 (
const Context& ectx)
1353 return matLawManager.
1354 oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
1358 Entry{ScalarEntry{&this->drsdtcon_,
1359 [&problem = this->simulator_.problem()](
const Context& ectx)
1361 return problem.drsdtcon(ectx.globalDofIdx,
1366 Entry{ScalarEntry{&this->pcgw_,
1367 [](
const Context& ectx)
1369 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1370 getValue(ectx.fs.pressure(waterPhaseIdx));
1374 Entry{ScalarEntry{&this->pcow_,
1375 [](
const Context& ectx)
1377 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1378 getValue(ectx.fs.pressure(waterPhaseIdx));
1382 Entry{ScalarEntry{&this->pcog_,
1383 [](
const Context& ectx)
1385 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
1386 getValue(ectx.fs.pressure(oilPhaseIdx));
1390 Entry{ScalarEntry{&this->fluidPressure_,
1391 [](
const Context& ectx)
1393 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1395 return getValue(ectx.fs.pressure(oilPhaseIdx));
1397 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1399 return getValue(ectx.fs.pressure(gasPhaseIdx));
1403 return getValue(ectx.fs.pressure(waterPhaseIdx));
1408 Entry{ScalarEntry{&this->gasDissolutionFactor_,
1409 [&problem = this->simulator_.problem()](
const Context& ectx)
1411 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1412 return FluidSystem::template
1413 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1420 Entry{ScalarEntry{&this->oilVaporizationFactor_,
1421 [&problem = this->simulator_.problem()](
const Context& ectx)
1423 const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
1424 return FluidSystem::template
1425 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1432 Entry{ScalarEntry{&this->gasDissolutionFactorInWater_,
1433 [&problem = this->simulator_.problem()](
const Context& ectx)
1435 const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
1436 return FluidSystem::template
1437 saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
1444 Entry{ScalarEntry{&this->waterVaporizationFactor_,
1445 [](
const Context& ectx)
1447 return FluidSystem::template
1448 saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
1454 Entry{ScalarEntry{&this->gasFormationVolumeFactor_,
1455 [](
const Context& ectx)
1457 return 1.0 / FluidSystem::template
1458 inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1464 Entry{ScalarEntry{&this->saturatedOilFormationVolumeFactor_,
1465 [](
const Context& ectx)
1467 return 1.0 / FluidSystem::template
1468 saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
1474 Entry{ScalarEntry{&this->oilSaturationPressure_,
1475 [](
const Context& ectx)
1477 return FluidSystem::template
1478 saturationPressure<FluidState, Scalar>(ectx.fs,
1484 Entry{ScalarEntry{&this->soMax_,
1485 [&problem = this->simulator_.problem()](
const Context& ectx)
1487 return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
1488 problem.maxOilSaturation(ectx.globalDofIdx));
1491 !hysteresisConfig.enableHysteresis()
1493 Entry{ScalarEntry{&this->swMax_,
1494 [&problem = this->simulator_.problem()](
const Context& ectx)
1496 return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
1497 problem.maxWaterSaturation(ectx.globalDofIdx));
1500 !hysteresisConfig.enableHysteresis()
1502 Entry{ScalarEntry{&this->soMax_,
1503 [](
const Context& ectx)
1504 {
return ectx.hParams.somax; }
1506 hysteresisConfig.enableHysteresis() &&
1507 hysteresisConfig.enableNonWettingHysteresis() &&
1508 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1509 FluidSystem::phaseIsActive(waterPhaseIdx)
1511 Entry{ScalarEntry{&this->swMax_,
1512 [](
const Context& ectx)
1513 {
return ectx.hParams.swmax; }
1515 hysteresisConfig.enableHysteresis() &&
1516 hysteresisConfig.enableWettingHysteresis() &&
1517 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1518 FluidSystem::phaseIsActive(waterPhaseIdx)
1520 Entry{ScalarEntry{&this->swmin_,
1521 [](
const Context& ectx)
1522 {
return ectx.hParams.swmin; }
1524 hysteresisConfig.enableHysteresis() &&
1525 hysteresisConfig.enablePCHysteresis() &&
1526 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1527 FluidSystem::phaseIsActive(waterPhaseIdx)
1529 Entry{ScalarEntry{&this->sgmax_,
1530 [](
const Context& ectx)
1531 {
return ectx.hParams.sgmax; }
1533 hysteresisConfig.enableHysteresis() &&
1534 hysteresisConfig.enableNonWettingHysteresis() &&
1535 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1536 FluidSystem::phaseIsActive(gasPhaseIdx)
1538 Entry{ScalarEntry{&this->shmax_,
1539 [](
const Context& ectx)
1540 {
return ectx.hParams.shmax; }
1542 hysteresisConfig.enableHysteresis() &&
1543 hysteresisConfig.enableWettingHysteresis() &&
1544 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1545 FluidSystem::phaseIsActive(gasPhaseIdx)
1547 Entry{ScalarEntry{&this->somin_,
1548 [](
const Context& ectx)
1549 {
return ectx.hParams.somin; }
1551 hysteresisConfig.enableHysteresis() &&
1552 hysteresisConfig.enablePCHysteresis() &&
1553 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1554 FluidSystem::phaseIsActive(gasPhaseIdx)
1556 Entry{[&model = this->simulator_.model(),
this](
const Context& ectx)
1560 const auto porv = ectx.intQuants.referencePorosity()
1561 * model.dofTotalVolume(ectx.globalDofIdx);
1563 this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
1564 static_cast<double>(porv));
1565 }, this->regionAvgDensity_.has_value()
1567 Entry{[&extboC = this->extboC_](
const Context& ectx)
1569 extboC.assignVolumes(ectx.globalDofIdx,
1570 ectx.intQuants.xVolume().value(),
1571 ectx.intQuants.yVolume().value());
1572 extboC.assignZFraction(ectx.globalDofIdx,
1573 ectx.intQuants.zFraction().value());
1575 const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
1576 getValue(ectx.fs.invB(oilPhaseIdx)) +
1577 getValue(ectx.fs.saturation(gasPhaseIdx)) *
1578 getValue(ectx.fs.invB(gasPhaseIdx)) *
1579 getValue(ectx.fs.Rv());
1580 const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1581 getValue(ectx.fs.invB(gasPhaseIdx)) *
1582 (1.0 - ectx.intQuants.yVolume().value()) +
1583 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1584 getValue(ectx.fs.invB(oilPhaseIdx)) *
1585 getValue(ectx.fs.Rs()) *
1586 (1.0 - ectx.intQuants.xVolume().value());
1587 const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
1588 getValue(ectx.fs.invB(gasPhaseIdx)) *
1589 ectx.intQuants.yVolume().value() +
1590 getValue(ectx.fs.saturation(oilPhaseIdx)) *
1591 getValue(ectx.fs.invB(oilPhaseIdx)) *
1592 getValue(ectx.fs.Rs()) *
1593 ectx.intQuants.xVolume().value();
1594 const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1595 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
1596 const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
1597 const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
1598 extboC.assignMassFractions(ectx.globalDofIdx,
1599 stdVolGas * rhoG / stdMassTotal,
1600 stdVolOil * rhoO / stdMassTotal,
1601 stdVolCo2 * rhoCO2 / stdMassTotal);
1602 }, this->extboC_.allocated()
1604 Entry{[&bioeffectsC = this->bioeffectsC_](
const Context& ectx)
1606 bioeffectsC.assign(ectx.globalDofIdx,
1607 ectx.intQuants.microbialConcentration().value(),
1608 ectx.intQuants.biofilmVolumeFraction().value());
1609 if (Indices::enableMICP) {
1610 bioeffectsC.assign(ectx.globalDofIdx,
1611 ectx.intQuants.oxygenConcentration().value(),
1612 ectx.intQuants.ureaConcentration().value(),
1613 ectx.intQuants.calciteVolumeFraction().value());
1615 }, this->bioeffectsC_.allocated()
1617 Entry{[&runspec = this->eclState_.runspec(),
1618 &CO2H2C = this->CO2H2C_](
const Context& ectx)
1620 const auto xwg = FluidSystem::convertRswToXwG(getValue(ectx.fs.Rsw()), ectx.pvtRegionIdx);
1621 const auto xgw = FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.pvtRegionIdx);
1622 CO2H2C.assign(ectx.globalDofIdx,
1623 FluidSystem::convertXwGToxwG(xwg, ectx.pvtRegionIdx),
1624 FluidSystem::convertXgWToxgW(xgw, ectx.pvtRegionIdx),
1625 runspec.co2Storage());
1626 }, this->CO2H2C_.allocated()
1628 Entry{[&rftC = this->rftC_,
1629 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1631 const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1632 rftC.assign(cartesianIdx,
1633 [&fs = ectx.fs]() { return getValue(fs.pressure(oilPhaseIdx)); },
1634 [&fs = ectx.fs]() { return getValue(fs.saturation(waterPhaseIdx)); },
1635 [&fs = ectx.fs]() { return getValue(fs.saturation(gasPhaseIdx)); });
1638 Entry{[&tC = this->tracerC_,
1639 &tM = this->simulator_.problem().tracerModel()](
const Context& ectx)
1641 tC.assignFreeConcentrations(ectx.globalDofIdx,
1642 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1643 { return tM.freeTracerConcentration(tracerIdx, gIdx); });
1644 tC.assignSolConcentrations(ectx.globalDofIdx,
1645 [gIdx = ectx.globalDofIdx, &tM](
const unsigned tracerIdx)
1646 { return tM.solTracerConcentration(tracerIdx, gIdx); });
1649 Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
1650 &flowsC = this->flowsC_,
1651 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1653 const auto gas_idx = Indices::gasEnabled ?
1654 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1655 const auto oil_idx = Indices::oilEnabled ?
1656 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1657 const auto water_idx = Indices::waterEnabled ?
1658 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1659 const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
1660 if (!flowsC.blockFlows().empty()) {
1661 const std::vector<int>& blockIdxs = flowsC.blockFlows();
1662 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1663 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1664 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1665 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1666 for (
const auto& flowsInfo : flowsInfos) {
1667 if (flowsInfo.faceId < 0) {
1670 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1671 if (!compEnabled[ii]) {
1674 if (flowsC.hasBlockFlowValue(cartesianIdx, flowsInfo.faceId, compIdxs[ii])) {
1675 flowsC.assignBlockFlows(flowsC.blockFlowsIds(cartesianIdx, flowsInfo.faceId, compIdxs[ii]),
1678 flowsInfo.flow[conti0EqIdx
1679 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1686 for (
const auto& flowsInfo : flowsInfos) {
1687 flowsC.assignFlows(ectx.globalDofIdx,
1690 value_or_zero(gas_idx, flowsInfo.flow),
1691 value_or_zero(oil_idx, flowsInfo.flow),
1692 value_or_zero(water_idx, flowsInfo.flow));
1695 }, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
1697 Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
1698 &flowsC = this->flowsC_](
const Context& ectx)
1700 const auto gas_idx = Indices::gasEnabled ?
1701 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
1702 const auto oil_idx = Indices::oilEnabled ?
1703 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
1704 const auto water_idx = Indices::waterEnabled ?
1705 conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
1706 const auto& floresInfos = floresInf[ectx.globalDofIdx];
1707 for (
const auto& floresInfo : floresInfos) {
1708 flowsC.assignFlores(ectx.globalDofIdx,
1711 value_or_zero(gas_idx, floresInfo.flow),
1712 value_or_zero(oil_idx, floresInfo.flow),
1713 value_or_zero(water_idx, floresInfo.flow));
1715 }, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
1717 Entry{[&velocityInf = this->simulator_.problem().model().linearizer().getVelocityInfo(),
1718 &flowsC = this->flowsC_,
1719 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
1721 const auto& velocityInfos = velocityInf[ectx.globalDofIdx];
1722 const std::vector<int>& blockIdxs = flowsC.blockVelocity();
1723 const unsigned cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
1724 if (std::ranges::binary_search(blockIdxs, cartesianIdx)) {
1725 const auto compIdxs = std::array{ gasCompIdx, oilCompIdx, waterCompIdx };
1726 const auto compEnabled = std::array{ Indices::gasEnabled, Indices::oilEnabled, Indices::waterEnabled };
1727 for (
const auto& velocityInfo : velocityInfos) {
1728 if (velocityInfo.faceId < 0) {
1731 for (
unsigned ii = 0; ii < compIdxs.size(); ++ii) {
1732 if (!compEnabled[ii]) {
1735 if (flowsC.hasBlockVelocityValue(cartesianIdx, velocityInfo.faceId, compIdxs[ii])) {
1736 flowsC.assignBlockVelocity(flowsC.blockVelocityIds(cartesianIdx, velocityInfo.faceId, compIdxs[ii]),
1737 velocityInfo.faceId,
1739 velocityInfo.velocity[conti0EqIdx
1740 + FluidSystem::canonicalToActiveCompIdx(compIdxs[ii])]);
1745 }, !this->flowsC_.blockVelocity().empty() &&
1746 !this->simulator_.problem().model().linearizer().getVelocityInfo().empty()
1753 Entry{ScalarEntry{&this->rv_,
1754 [&problem = this->simulator_.problem()](
const Context& ectx)
1755 {
return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
1757 simulator_.episodeIndex() < 0 &&
1758 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1759 FluidSystem::phaseIsActive(gasPhaseIdx)
1761 Entry{ScalarEntry{&this->rs_,
1762 [&problem = this->simulator_.problem()](
const Context& ectx)
1763 {
return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
1765 simulator_.episodeIndex() < 0 &&
1766 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1767 FluidSystem::phaseIsActive(gasPhaseIdx)
1769 Entry{ScalarEntry{&this->rsw_,
1770 [&problem = this->simulator_.problem()](
const Context& ectx)
1771 {
return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
1773 simulator_.episodeIndex() < 0 &&
1774 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1775 FluidSystem::phaseIsActive(gasPhaseIdx)
1777 Entry{ScalarEntry{&this->rvw_,
1778 [&problem = this->simulator_.problem()](
const Context& ectx)
1779 {
return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
1781 simulator_.episodeIndex() < 0 &&
1782 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1783 FluidSystem::phaseIsActive(gasPhaseIdx)
1786 Entry{PhaseEntry{&this->density_,
1787 [&problem = this->simulator_.problem()](
const unsigned phase,
1788 const Context& ectx)
1790 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1791 return FluidSystem::density(fsInitial,
1793 ectx.intQuants.pvtRegionIndex());
1796 simulator_.episodeIndex() < 0 &&
1797 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1798 FluidSystem::phaseIsActive(gasPhaseIdx)
1800 Entry{PhaseEntry{&this->invB_,
1801 [&problem = this->simulator_.problem()](
const unsigned phase,
1802 const Context& ectx)
1804 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1805 return FluidSystem::inverseFormationVolumeFactor(fsInitial,
1807 ectx.intQuants.pvtRegionIndex());
1810 simulator_.episodeIndex() < 0 &&
1811 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1812 FluidSystem::phaseIsActive(gasPhaseIdx)
1814 Entry{PhaseEntry{&this->viscosity_,
1815 [&problem = this->simulator_.problem()](
const unsigned phase,
1816 const Context& ectx)
1818 const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
1819 return FluidSystem::viscosity(fsInitial,
1821 ectx.intQuants.pvtRegionIndex());
1824 simulator_.episodeIndex() < 0 &&
1825 FluidSystem::phaseIsActive(oilPhaseIdx) &&
1826 FluidSystem::phaseIsActive(gasPhaseIdx)
1835 if (this->geochemC_.allocated()) {
1836 this->extractors_.push_back(
1838 [&gC = this->geochemC_,
1839 &gM = this->simulator_.problem().geochemistryModel()](
const Context& ectx)
1841 gC.assignSpeciesConcentrations(
1843 [gIdx = ectx.globalDofIdx, &gM](
const unsigned speciesIdx)
1844 { return gM.speciesConcentration(speciesIdx, gIdx); }
1846 gC.assignMineralConcentrations(
1848 [gIdx = ectx.globalDofIdx, &gM](
const unsigned mineralIdx)
1849 { return gM.mineralConcentration(mineralIdx, gIdx); }
1851 gC.assignPH(ectx.globalDofIdx, gM.PH(ectx.globalDofIdx));
1860 if (this->mech_.allocated()) {
1861 this->extractors_.push_back(
1862 Entry{[&mech = this->mech_,
1863 &model = simulator_.problem().geoMechModel()](
const Context& ectx)
1865 mech.assignDelStress(ectx.globalDofIdx,
1866 model.delstress(ectx.globalDofIdx));
1868 mech.assignDisplacement(ectx.globalDofIdx,
1869 model.disp(ectx.globalDofIdx,
true));
1872 mech.assignFracStress(ectx.globalDofIdx,
1873 model.fractureStress(ectx.globalDofIdx));
1875 mech.assignLinStress(ectx.globalDofIdx,
1876 model.linstress(ectx.globalDofIdx));
1878 mech.assignPotentialForces(ectx.globalDofIdx,
1879 model.mechPotentialForce(ectx.globalDofIdx),
1880 model.mechPotentialPressForce(ectx.globalDofIdx),
1881 model.mechPotentialTempForce(ectx.globalDofIdx));
1883 mech.assignStrain(ectx.globalDofIdx,
1884 model.strain(ectx.globalDofIdx,
true));
1887 mech.assignStress(ectx.globalDofIdx,
1888 model.stress(ectx.globalDofIdx,
true));
1897 void setupBlockExtractors_(
const bool isSubStep,
1898 const int reportStepNum)
1905 using namespace std::string_view_literals;
1907 const auto pressure_handler =
1908 Entry{ScalarEntry{std::vector{
"BPR"sv,
"BPRESSUR"sv},
1909 [](
const Context& ectx)
1911 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1912 return getValue(ectx.fs.pressure(oilPhaseIdx));
1914 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1915 return getValue(ectx.fs.pressure(gasPhaseIdx));
1918 return getValue(ectx.fs.pressure(waterPhaseIdx));
1924 const auto handlers = std::array{
1926 Entry{PhaseEntry{std::array{
1927 std::array{
"BWSAT"sv,
"BOSAT"sv,
"BGSAT"sv},
1928 std::array{
"BSWAT"sv,
"BSOIL"sv,
"BSGAS"sv}
1930 [](
const unsigned phaseIdx,
const Context& ectx)
1932 return getValue(ectx.fs.saturation(phaseIdx));
1936 Entry{ScalarEntry{
"BNSAT",
1937 [](
const Context& ectx)
1939 return ectx.intQuants.solventSaturation().value();
1943 Entry{ScalarEntry{std::vector{
"BTCNFHEA"sv,
"BTEMP"sv},
1944 [](
const Context& ectx)
1946 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1947 return getValue(ectx.fs.temperature(oilPhaseIdx));
1949 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
1950 return getValue(ectx.fs.temperature(gasPhaseIdx));
1953 return getValue(ectx.fs.temperature(waterPhaseIdx));
1958 Entry{PhaseEntry{std::array{
1959 std::array{
"BWKR"sv,
"BOKR"sv,
"BGKR"sv},
1960 std::array{
"BKRW"sv,
"BKRO"sv,
"BKRG"sv}
1962 [](
const unsigned phaseIdx,
const Context& ectx)
1964 return getValue(ectx.intQuants.relativePermeability(phaseIdx));
1968 Entry{ScalarEntry{
"BKROG",
1969 [&problem = this->simulator_.problem()](
const Context& ectx)
1971 const auto& materialParams =
1972 problem.materialLawParams(ectx.elemCtx,
1975 return getValue(MaterialLaw::template
1976 relpermOilInOilGasSystem<Evaluation>(materialParams,
1981 Entry{ScalarEntry{
"BKROW",
1982 [&problem = this->simulator_.problem()](
const Context& ectx)
1984 const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
1987 return getValue(MaterialLaw::template
1988 relpermOilInOilWaterSystem<Evaluation>(materialParams,
1993 Entry{ScalarEntry{
"BWPC",
1994 [](
const Context& ectx)
1996 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
1997 return getValue(ectx.fs.pressure(oilPhaseIdx)) -
1998 getValue(ectx.fs.pressure(waterPhaseIdx));
2000 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2001 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2002 getValue(ectx.fs.pressure(waterPhaseIdx));
2010 Entry{ScalarEntry{
"BGPC",
2011 [](
const Context& ectx)
2013 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2014 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2015 getValue(ectx.fs.pressure(oilPhaseIdx));
2017 else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
2018 return getValue(ectx.fs.pressure(gasPhaseIdx)) -
2019 getValue(ectx.fs.pressure(waterPhaseIdx));
2027 Entry{ScalarEntry{
"BWPR",
2028 [](
const Context& ectx)
2030 return getValue(ectx.fs.pressure(waterPhaseIdx));
2034 Entry{ScalarEntry{
"BGPR",
2035 [](
const Context& ectx)
2037 return getValue(ectx.fs.pressure(gasPhaseIdx));
2041 Entry{PhaseEntry{std::array{
2042 std::array{
"BVWAT"sv,
"BVOIL"sv,
"BVGAS"sv},
2043 std::array{
"BWVIS"sv,
"BOVIS"sv,
"BGVIS"sv}
2045 [](
const unsigned phaseIdx,
const Context& ectx)
2047 return getValue(ectx.fs.viscosity(phaseIdx));
2051 Entry{PhaseEntry{std::array{
2052 std::array{
"BWDEN"sv,
"BODEN"sv,
"BGDEN"sv},
2053 std::array{
"BDENW"sv,
"BDENO"sv,
"BDENG"sv}
2055 [](
const unsigned phaseIdx,
const Context& ectx)
2057 return getValue(ectx.fs.density(phaseIdx));
2061 Entry{ScalarEntry{
"BFLOGI",
2062 [&flowsC = this->flowsC_,
2063 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2065 const unsigned index = !flowsC.blockFlows().empty() ?
2066 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2067 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx) : ectx.globalDofIdx;
2068 return flowsC.getFlow(index, Dir::XPlus, gasCompIdx);
2072 Entry{ScalarEntry{
"BFLOGI-",
2073 [&flowsC = this->flowsC_,
2074 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2076 const unsigned index = !flowsC.blockFlows().empty() ?
2077 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2078 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx) : ectx.globalDofIdx;
2079 return flowsC.getFlow(index, Dir::XMinus, gasCompIdx);
2083 Entry{ScalarEntry{
"BFLOGJ",
2084 [&flowsC = this->flowsC_,
2085 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2087 const unsigned index = !flowsC.blockFlows().empty() ?
2088 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2089 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx) : ectx.globalDofIdx;
2090 return flowsC.getFlow(index, Dir::YPlus, gasCompIdx);
2094 Entry{ScalarEntry{
"BFLOGJ-",
2095 [&flowsC = this->flowsC_,
2096 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2098 const unsigned index = !flowsC.blockFlows().empty() ?
2099 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2100 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx) : ectx.globalDofIdx;
2101 return flowsC.getFlow(index, Dir::YMinus, gasCompIdx);
2105 Entry{ScalarEntry{
"BFLOGK",
2106 [&flowsC = this->flowsC_,
2107 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2109 const unsigned index = !flowsC.blockFlows().empty() ?
2110 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2111 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx) : ectx.globalDofIdx;
2112 return flowsC.getFlow(index, Dir::ZPlus, gasCompIdx);
2116 Entry{ScalarEntry{
"BFLOGK-",
2117 [&flowsC = this->flowsC_,
2118 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2120 const unsigned index = !flowsC.blockFlows().empty() ?
2121 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2122 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx) : ectx.globalDofIdx;
2123 return flowsC.getFlow(index, Dir::ZMinus, gasCompIdx);
2127 Entry{ScalarEntry{
"BFLOOI",
2128 [&flowsC = this->flowsC_,
2129 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2131 const unsigned index = !flowsC.blockFlows().empty() ?
2132 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2133 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx) : ectx.globalDofIdx;
2134 return flowsC.getFlow(index, Dir::XPlus, oilCompIdx);
2138 Entry{ScalarEntry{
"BFLOOI-",
2139 [&flowsC = this->flowsC_,
2140 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2142 const unsigned index = !flowsC.blockFlows().empty() ?
2143 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2144 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx) : ectx.globalDofIdx;
2145 return flowsC.getFlow(index, Dir::XMinus, oilCompIdx);
2149 Entry{ScalarEntry{
"BFLOOJ",
2150 [&flowsC = this->flowsC_,
2151 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2153 const unsigned index = !flowsC.blockFlows().empty() ?
2154 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2155 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx) : ectx.globalDofIdx;
2156 return flowsC.getFlow(index, Dir::YPlus, oilCompIdx);
2160 Entry{ScalarEntry{
"BFLOOJ-",
2161 [&flowsC = this->flowsC_,
2162 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2164 const unsigned index = !flowsC.blockFlows().empty() ?
2165 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2166 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx) : ectx.globalDofIdx;
2167 return flowsC.getFlow(index, Dir::YMinus, oilCompIdx);
2171 Entry{ScalarEntry{
"BFLOOK",
2172 [&flowsC = this->flowsC_,
2173 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2175 const unsigned index = !flowsC.blockFlows().empty() ?
2176 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2177 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx) : ectx.globalDofIdx;
2178 return flowsC.getFlow(index, Dir::ZPlus, oilCompIdx);
2182 Entry{ScalarEntry{
"BFLOOK-",
2183 [&flowsC = this->flowsC_,
2184 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2186 const unsigned index = !flowsC.blockFlows().empty() ?
2187 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2188 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx) : ectx.globalDofIdx;
2189 return flowsC.getFlow(index, Dir::ZMinus, oilCompIdx);
2193 Entry{ScalarEntry{
"BFLOWI",
2194 [&flowsC = this->flowsC_,
2195 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2197 const unsigned index = !flowsC.blockFlows().empty() ?
2198 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2199 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx) : ectx.globalDofIdx;
2200 return flowsC.getFlow(index, Dir::XPlus, waterCompIdx);
2204 Entry{ScalarEntry{
"BFLOWI-",
2205 [&flowsC = this->flowsC_,
2206 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2208 const unsigned index = !flowsC.blockFlows().empty() ?
2209 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2210 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx) : ectx.globalDofIdx;
2211 return flowsC.getFlow(index, Dir::XMinus, waterCompIdx);
2215 Entry{ScalarEntry{
"BFLOWJ",
2216 [&flowsC = this->flowsC_,
2217 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2219 const unsigned index = !flowsC.blockFlows().empty() ?
2220 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2221 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx) : ectx.globalDofIdx;
2222 return flowsC.getFlow(index, Dir::YPlus, waterCompIdx);
2226 Entry{ScalarEntry{
"BFLOWJ-",
2227 [&flowsC = this->flowsC_,
2228 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2230 const unsigned index = !flowsC.blockFlows().empty() ?
2231 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2232 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx) : ectx.globalDofIdx;
2233 return flowsC.getFlow(index, Dir::YMinus, waterCompIdx);
2237 Entry{ScalarEntry{
"BFLOWK",
2238 [&flowsC = this->flowsC_,
2239 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2241 const unsigned index = !flowsC.blockFlows().empty() ?
2242 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2243 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx) : ectx.globalDofIdx;
2244 return flowsC.getFlow(index, Dir::ZPlus, waterCompIdx);
2248 Entry{ScalarEntry{
"BFLOWK-",
2249 [&flowsC = this->flowsC_,
2250 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2252 const unsigned index = !flowsC.blockFlows().empty() ?
2253 flowsC.blockFlowsIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2254 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx) : ectx.globalDofIdx;
2255 return flowsC.getFlow(index, Dir::ZMinus, waterCompIdx);
2259 Entry{ScalarEntry{
"BVELGI",
2260 [&flowsC = this->flowsC_,
2261 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2263 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2264 FaceDir::ToIntersectionIndex(Dir::XPlus), gasCompIdx);
2265 return flowsC.getVelocity(index, Dir::XPlus, gasCompIdx);
2269 Entry{ScalarEntry{
"BVELGI-",
2270 [&flowsC = this->flowsC_,
2271 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2273 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2274 FaceDir::ToIntersectionIndex(Dir::XMinus), gasCompIdx);
2275 return flowsC.getVelocity(index, Dir::XMinus, gasCompIdx);
2279 Entry{ScalarEntry{
"BVELGJ",
2280 [&flowsC = this->flowsC_,
2281 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2283 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2284 FaceDir::ToIntersectionIndex(Dir::YPlus), gasCompIdx);
2285 return flowsC.getVelocity(index, Dir::YPlus, gasCompIdx);
2289 Entry{ScalarEntry{
"BVELGJ-",
2290 [&flowsC = this->flowsC_,
2291 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2293 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2294 FaceDir::ToIntersectionIndex(Dir::YMinus), gasCompIdx);
2295 return flowsC.getVelocity(index, Dir::YMinus, gasCompIdx);
2299 Entry{ScalarEntry{
"BVELGK",
2300 [&flowsC = this->flowsC_,
2301 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2303 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2304 FaceDir::ToIntersectionIndex(Dir::ZPlus), gasCompIdx);
2305 return flowsC.getVelocity(index, Dir::ZPlus, gasCompIdx);
2309 Entry{ScalarEntry{
"BVELGK-",
2310 [&flowsC = this->flowsC_,
2311 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2313 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2314 FaceDir::ToIntersectionIndex(Dir::ZMinus), gasCompIdx);
2315 return flowsC.getVelocity(index, Dir::ZMinus, gasCompIdx);
2319 Entry{ScalarEntry{
"BVELOI",
2320 [&flowsC = this->flowsC_,
2321 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2323 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2324 FaceDir::ToIntersectionIndex(Dir::XPlus), oilCompIdx);
2325 return flowsC.getVelocity(index, Dir::XPlus, oilCompIdx);
2329 Entry{ScalarEntry{
"BVELOI-",
2330 [&flowsC = this->flowsC_,
2331 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2333 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2334 FaceDir::ToIntersectionIndex(Dir::XMinus), oilCompIdx);
2335 return flowsC.getVelocity(index, Dir::XMinus, oilCompIdx);
2339 Entry{ScalarEntry{
"BVELOJ",
2340 [&flowsC = this->flowsC_,
2341 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2343 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2344 FaceDir::ToIntersectionIndex(Dir::YPlus), oilCompIdx);
2345 return flowsC.getVelocity(index, Dir::YPlus, oilCompIdx);
2349 Entry{ScalarEntry{
"BVELOJ-",
2350 [&flowsC = this->flowsC_,
2351 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2353 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2354 FaceDir::ToIntersectionIndex(Dir::YMinus), oilCompIdx);
2355 return flowsC.getVelocity(index, Dir::YMinus, oilCompIdx);
2359 Entry{ScalarEntry{
"BVELOK",
2360 [&flowsC = this->flowsC_,
2361 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2363 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2364 FaceDir::ToIntersectionIndex(Dir::ZPlus), oilCompIdx);
2365 return flowsC.getVelocity(index, Dir::ZPlus, oilCompIdx);
2369 Entry{ScalarEntry{
"BVELOK-",
2370 [&flowsC = this->flowsC_,
2371 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2373 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2374 FaceDir::ToIntersectionIndex(Dir::ZMinus), oilCompIdx);
2375 return flowsC.getVelocity(index, Dir::ZMinus, oilCompIdx);
2379 Entry{ScalarEntry{
"BVELWI",
2380 [&flowsC = this->flowsC_,
2381 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2383 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2384 FaceDir::ToIntersectionIndex(Dir::XPlus), waterCompIdx);
2385 return flowsC.getVelocity(index, Dir::XPlus, waterCompIdx);
2389 Entry{ScalarEntry{
"BVELWI-",
2390 [&flowsC = this->flowsC_,
2391 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2393 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2394 FaceDir::ToIntersectionIndex(Dir::XMinus), waterCompIdx);
2395 return flowsC.getVelocity(index, Dir::XMinus, waterCompIdx);
2399 Entry{ScalarEntry{
"BVELWJ",
2400 [&flowsC = this->flowsC_,
2401 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2403 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2404 FaceDir::ToIntersectionIndex(Dir::YPlus), waterCompIdx);
2405 return flowsC.getVelocity(index, Dir::YPlus, waterCompIdx);
2409 Entry{ScalarEntry{
"BVELWJ-",
2410 [&flowsC = this->flowsC_,
2411 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2413 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2414 FaceDir::ToIntersectionIndex(Dir::YMinus), waterCompIdx);
2415 return flowsC.getVelocity(index, Dir::YMinus, waterCompIdx);
2419 Entry{ScalarEntry{
"BVELWK",
2420 [&flowsC = this->flowsC_,
2421 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2423 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2424 FaceDir::ToIntersectionIndex(Dir::ZPlus), waterCompIdx);
2425 return flowsC.getVelocity(index, Dir::ZPlus, waterCompIdx);
2429 Entry{ScalarEntry{
"BVELWK-",
2430 [&flowsC = this->flowsC_,
2431 &vanguard = this->simulator_.vanguard()](
const Context& ectx)
2433 const unsigned index = flowsC.blockVelocityIds(vanguard.cartesianIndex(ectx.globalDofIdx),
2434 FaceDir::ToIntersectionIndex(Dir::ZMinus), waterCompIdx);
2435 return flowsC.getVelocity(index, Dir::ZMinus, waterCompIdx);
2439 Entry{ScalarEntry{
"BRPV",
2440 [&model = this->simulator_.model()](
const Context& ectx)
2442 return getValue(ectx.intQuants.porosity()) *
2443 model.dofTotalVolume(ectx.globalDofIdx);
2447 Entry{PhaseEntry{std::array{
"BWPV"sv,
"BOPV"sv,
"BGPV"sv},
2448 [&model = this->simulator_.model()](
const unsigned phaseIdx,
2449 const Context& ectx)
2451 return getValue(ectx.fs.saturation(phaseIdx)) *
2452 getValue(ectx.intQuants.porosity()) *
2453 model.dofTotalVolume(ectx.globalDofIdx);
2457 Entry{ScalarEntry{
"BRS",
2458 [](
const Context& ectx)
2460 return getValue(ectx.fs.Rs());
2464 Entry{ScalarEntry{
"BRV",
2465 [](
const Context& ectx)
2467 return getValue(ectx.fs.Rv());
2471 Entry{ScalarEntry{
"BOIP",
2472 [&model = this->simulator_.model()](
const Context& ectx)
2474 return (getValue(ectx.fs.invB(oilPhaseIdx)) *
2475 getValue(ectx.fs.saturation(oilPhaseIdx)) +
2476 getValue(ectx.fs.Rv()) *
2477 getValue(ectx.fs.invB(gasPhaseIdx)) *
2478 getValue(ectx.fs.saturation(gasPhaseIdx))) *
2479 model.dofTotalVolume(ectx.globalDofIdx) *
2480 getValue(ectx.intQuants.porosity());
2484 Entry{ScalarEntry{
"BGIP",
2485 [&model = this->simulator_.model()](
const Context& ectx)
2487 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2488 getValue(ectx.fs.saturation(gasPhaseIdx));
2490 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2491 result += getValue(ectx.fs.Rs()) *
2492 getValue(ectx.fs.invB(oilPhaseIdx)) *
2493 getValue(ectx.fs.saturation(oilPhaseIdx));
2496 result += getValue(ectx.fs.Rsw()) *
2497 getValue(ectx.fs.invB(waterPhaseIdx)) *
2498 getValue(ectx.fs.saturation(waterPhaseIdx));
2502 model.dofTotalVolume(ectx.globalDofIdx) *
2503 getValue(ectx.intQuants.porosity());
2507 Entry{ScalarEntry{
"BWIP",
2508 [&model = this->simulator_.model()](
const Context& ectx)
2510 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2511 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2512 model.dofTotalVolume(ectx.globalDofIdx) *
2513 getValue(ectx.intQuants.porosity());
2517 Entry{ScalarEntry{
"BOIPL",
2518 [&model = this->simulator_.model()](
const Context& ectx)
2520 return getValue(ectx.fs.invB(oilPhaseIdx)) *
2521 getValue(ectx.fs.saturation(oilPhaseIdx)) *
2522 model.dofTotalVolume(ectx.globalDofIdx) *
2523 getValue(ectx.intQuants.porosity());
2527 Entry{ScalarEntry{
"BGIPL",
2528 [&model = this->simulator_.model()](
const Context& ectx)
2531 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2532 result = getValue(ectx.fs.Rs()) *
2533 getValue(ectx.fs.invB(oilPhaseIdx)) *
2534 getValue(ectx.fs.saturation(oilPhaseIdx));
2537 result = getValue(ectx.fs.Rsw()) *
2538 getValue(ectx.fs.invB(waterPhaseIdx)) *
2539 getValue(ectx.fs.saturation(waterPhaseIdx));
2542 model.dofTotalVolume(ectx.globalDofIdx) *
2543 getValue(ectx.intQuants.porosity());
2547 Entry{ScalarEntry{
"BGIPG",
2548 [&model = this->simulator_.model()](
const Context& ectx)
2550 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2551 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2552 model.dofTotalVolume(ectx.globalDofIdx) *
2553 getValue(ectx.intQuants.porosity());
2557 Entry{ScalarEntry{
"BOIPG",
2558 [&model = this->simulator_.model()](
const Context& ectx)
2560 return getValue(ectx.fs.Rv()) *
2561 getValue(ectx.fs.invB(gasPhaseIdx)) *
2562 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2563 model.dofTotalVolume(ectx.globalDofIdx) *
2564 getValue(ectx.intQuants.porosity());
2568 Entry{PhaseEntry{std::array{
"BPPW"sv,
"BPPO"sv,
"BPPG"sv},
2569 [&simConfig = this->eclState_.getSimulationConfig(),
2570 &grav = this->simulator_.problem().gravity(),
2571 ®ionAvgDensity = this->regionAvgDensity_,
2572 &problem = this->simulator_.problem(),
2573 ®ions = this->regions_](
const unsigned phaseIdx,
const Context& ectx)
2575 auto phase = RegionPhasePoreVolAverage::Phase{};
2576 phase.ix = phaseIdx;
2585 const auto datum = simConfig.datumDepths()(regions[
"FIPNUM"][ectx.dofIdx] - 1);
2588 const auto region = RegionPhasePoreVolAverage::Region {
2589 ectx.elemCtx.primaryVars(ectx.dofIdx, 0).pvtRegionIndex() + 1
2592 const auto density = regionAvgDensity->value(
"PVTNUM", phase, region);
2594 const auto press = getValue(ectx.fs.pressure(phase.ix));
2595 const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
2596 return press - density*dz*grav[GridView::dimensionworld - 1];
2600 Entry{ScalarEntry{
"BAMIP",
2601 [&model = this->simulator_.model()](
const Context& ectx)
2603 const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
2604 ectx.intQuants.pvtRegionIndex());
2605 return getValue(ectx.fs.invB(waterPhaseIdx)) *
2606 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2608 model.dofTotalVolume(ectx.globalDofIdx) *
2609 getValue(ectx.intQuants.porosity());
2613 Entry{ScalarEntry{
"BMMIP",
2614 [&model = this->simulator_.model()](
const Context& ectx)
2616 return getValue(ectx.intQuants.microbialConcentration()) *
2617 getValue(ectx.fs.saturation(waterPhaseIdx)) *
2618 getValue(ectx.intQuants.porosity()) *
2619 model.dofTotalVolume(ectx.globalDofIdx);
2623 Entry{ScalarEntry{
"BMOIP",
2624 [&model = this->simulator_.model()](
const Context& ectx)
2626 return getValue(ectx.intQuants.oxygenConcentration()) *
2627 getValue(ectx.intQuants.porosity()) *
2628 model.dofTotalVolume(ectx.globalDofIdx);
2632 Entry{ScalarEntry{
"BMUIP",
2633 [&model = this->simulator_.model()](
const Context& ectx)
2635 return getValue(ectx.intQuants.ureaConcentration()) *
2636 getValue(ectx.intQuants.porosity()) *
2637 model.dofTotalVolume(ectx.globalDofIdx) * 1;
2641 Entry{ScalarEntry{
"BMBIP",
2642 [&model = this->simulator_.model()](
const Context& ectx)
2644 return model.dofTotalVolume(ectx.globalDofIdx) *
2645 getValue(ectx.intQuants.biofilmMass());
2649 Entry{ScalarEntry{
"BMCIP",
2650 [&model = this->simulator_.model()](
const Context& ectx)
2652 return model.dofTotalVolume(ectx.globalDofIdx) *
2653 getValue(ectx.intQuants.calciteMass());
2657 Entry{ScalarEntry{
"BGMIP",
2658 [&model = this->simulator_.model()](
const Context& ectx)
2660 Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
2661 getValue(ectx.fs.saturation(gasPhaseIdx));
2663 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2664 result += getValue(ectx.fs.Rs()) *
2665 getValue(ectx.fs.invB(oilPhaseIdx)) *
2666 getValue(ectx.fs.saturation(oilPhaseIdx));
2669 result += getValue(ectx.fs.Rsw()) *
2670 getValue(ectx.fs.invB(waterPhaseIdx)) *
2671 getValue(ectx.fs.saturation(waterPhaseIdx));
2673 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2674 ectx.intQuants.pvtRegionIndex());
2676 model.dofTotalVolume(ectx.globalDofIdx) *
2677 getValue(ectx.intQuants.porosity()) *
2682 Entry{ScalarEntry{
"BGMGP",
2683 [&model = this->simulator_.model()](
const Context& ectx)
2685 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2686 ectx.intQuants.pvtRegionIndex());
2687 return getValue(ectx.fs.invB(gasPhaseIdx)) *
2688 getValue(ectx.fs.saturation(gasPhaseIdx)) *
2689 model.dofTotalVolume(ectx.globalDofIdx) *
2690 getValue(ectx.intQuants.porosity()) *
2695 Entry{ScalarEntry{
"BGMDS",
2696 [&model = this->simulator_.model()](
const Context& ectx)
2699 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2700 result = getValue(ectx.fs.Rs()) *
2701 getValue(ectx.fs.invB(oilPhaseIdx)) *
2702 getValue(ectx.fs.saturation(oilPhaseIdx));
2705 result = getValue(ectx.fs.Rsw()) *
2706 getValue(ectx.fs.invB(waterPhaseIdx)) *
2707 getValue(ectx.fs.saturation(waterPhaseIdx));
2709 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2710 ectx.intQuants.pvtRegionIndex());
2712 model.dofTotalVolume(ectx.globalDofIdx) *
2713 getValue(ectx.intQuants.porosity()) *
2718 Entry{ScalarEntry{
"BGMST",
2719 [&model = this->simulator_.model(),
2720 &problem = this->simulator_.problem()](
const Context& ectx)
2722 const auto& scaledDrainageInfo = problem.materialLawManager()
2723 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2724 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2725 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2726 if (problem.materialLawManager()->enableHysteresis()) {
2727 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2728 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2729 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2731 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2732 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2733 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2734 return (1.0 - xgW) *
2735 model.dofTotalVolume(ectx.globalDofIdx) *
2736 getValue(ectx.intQuants.porosity()) *
2737 getValue(ectx.fs.density(gasPhaseIdx)) *
2738 std::min(strandedGas, sg);
2742 Entry{ScalarEntry{
"BGMUS",
2743 [&model = this->simulator_.model(),
2744 &problem = this->simulator_.problem()](
const Context& ectx)
2746 const auto& scaledDrainageInfo = problem.materialLawManager()
2747 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2748 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2749 Scalar strandedGas = scaledDrainageInfo.Sgcr;
2750 if (problem.materialLawManager()->enableHysteresis()) {
2751 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2752 const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
2753 strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
2755 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2756 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2757 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2758 return (1.0 - xgW) *
2759 model.dofTotalVolume(ectx.globalDofIdx) *
2760 getValue(ectx.intQuants.porosity()) *
2761 getValue(ectx.fs.density(gasPhaseIdx)) *
2762 std::max(Scalar{0.0}, sg - strandedGas);
2766 Entry{ScalarEntry{
"BGMTR",
2767 [&model = this->simulator_.model(),
2768 &problem = this->simulator_.problem()](
const Context& ectx)
2770 const auto& scaledDrainageInfo = problem.materialLawManager()
2771 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2772 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2773 if (problem.materialLawManager()->enableHysteresis()) {
2774 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2775 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2777 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2778 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2779 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2780 return (1.0 - xgW) *
2781 model.dofTotalVolume(ectx.globalDofIdx) *
2782 getValue(ectx.intQuants.porosity()) *
2783 getValue(ectx.fs.density(gasPhaseIdx)) *
2784 std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
2788 Entry{ScalarEntry{
"BGMMO",
2789 [&model = this->simulator_.model(),
2790 &problem = this->simulator_.problem()](
const Context& ectx)
2792 const auto& scaledDrainageInfo = problem.materialLawManager()
2793 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2794 Scalar trappedGas = scaledDrainageInfo.Sgcr;
2795 if (problem.materialLawManager()->enableHysteresis()) {
2796 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2797 trappedGas = MaterialLaw::trappedGasSaturation(matParams,
true);
2799 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2800 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2801 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2802 return (1.0 - xgW) *
2803 model.dofTotalVolume(ectx.globalDofIdx) *
2804 getValue(ectx.intQuants.porosity()) *
2805 getValue(ectx.fs.density(gasPhaseIdx)) *
2806 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
2810 Entry{ScalarEntry{
"BGKTR",
2811 [&model = this->simulator_.model(),
2812 &problem = this->simulator_.problem()](
const Context& ectx)
2814 const auto& scaledDrainageInfo = problem.materialLawManager()
2815 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2816 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2817 Scalar sgcr = scaledDrainageInfo.Sgcr;
2818 if (problem.materialLawManager()->enableHysteresis()) {
2819 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2820 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2826 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2827 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2828 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2829 return (1.0 - xgW) *
2830 model.dofTotalVolume(ectx.globalDofIdx) *
2831 getValue(ectx.intQuants.porosity()) *
2832 getValue(ectx.fs.density(gasPhaseIdx)) *
2833 getValue(ectx.fs.saturation(gasPhaseIdx));
2838 Entry{ScalarEntry{
"BGKMO",
2839 [&model = this->simulator_.model(),
2840 &problem = this->simulator_.problem()](
const Context& ectx)
2842 const auto& scaledDrainageInfo = problem.materialLawManager()
2843 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2844 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2845 Scalar sgcr = scaledDrainageInfo.Sgcr;
2846 if (problem.materialLawManager()->enableHysteresis()) {
2847 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2848 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2854 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2855 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2856 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2857 return (1.0 - xgW) *
2858 model.dofTotalVolume(ectx.globalDofIdx) *
2859 getValue(ectx.intQuants.porosity()) *
2860 getValue(ectx.fs.density(gasPhaseIdx)) *
2861 getValue(ectx.fs.saturation(gasPhaseIdx));
2866 Entry{ScalarEntry{
"BGCDI",
2867 [&model = this->simulator_.model(),
2868 &problem = this->simulator_.problem()](
const Context& ectx)
2870 const auto& scaledDrainageInfo = problem.materialLawManager()
2871 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2872 Scalar sgcr = scaledDrainageInfo.Sgcr;
2873 if (problem.materialLawManager()->enableHysteresis()) {
2874 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2875 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2877 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2878 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2879 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2880 return (1.0 - xgW) *
2881 model.dofTotalVolume(ectx.globalDofIdx) *
2882 getValue(ectx.intQuants.porosity()) *
2883 getValue(ectx.fs.density(gasPhaseIdx)) *
2884 std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
2885 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2889 Entry{ScalarEntry{
"BGCDM",
2890 [&model = this->simulator_.model(),
2891 &problem = this->simulator_.problem()](
const Context& ectx)
2893 const auto& scaledDrainageInfo = problem.materialLawManager()
2894 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2895 Scalar sgcr = scaledDrainageInfo.Sgcr;
2896 if (problem.materialLawManager()->enableHysteresis()) {
2897 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2898 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2900 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2901 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2902 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2903 return (1.0 - xgW) *
2904 model.dofTotalVolume(ectx.globalDofIdx) *
2905 getValue(ectx.intQuants.porosity()) *
2906 getValue(ectx.fs.density(gasPhaseIdx)) *
2907 std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
2908 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2912 Entry{ScalarEntry{
"BGKDI",
2913 [&model = this->simulator_.model(),
2914 &problem = this->simulator_.problem()](
const Context& ectx)
2916 const auto& scaledDrainageInfo = problem.materialLawManager()
2917 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2918 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2919 Scalar sgcr = scaledDrainageInfo.Sgcr;
2920 if (problem.materialLawManager()->enableHysteresis()) {
2921 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2922 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2928 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2929 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2930 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2931 return (1.0 - xgW) *
2932 model.dofTotalVolume(ectx.globalDofIdx) *
2933 getValue(ectx.intQuants.porosity()) *
2934 getValue(ectx.fs.density(gasPhaseIdx)) *
2935 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2936 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2941 Entry{ScalarEntry{
"BGKDM",
2942 [&model = this->simulator_.model(),
2943 &problem = this->simulator_.problem()](
const Context& ectx)
2945 const auto& scaledDrainageInfo = problem.materialLawManager()
2946 ->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
2947 const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
2948 Scalar sgcr = scaledDrainageInfo.Sgcr;
2949 if (problem.materialLawManager()->enableHysteresis()) {
2950 const auto& matParams = problem.materialLawParams(ectx.dofIdx);
2951 sgcr = MaterialLaw::trappedGasSaturation(matParams,
false);
2957 const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
2958 FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
2959 : FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
2960 return (1.0 - xgW) *
2961 model.dofTotalVolume(ectx.globalDofIdx) *
2962 getValue(ectx.intQuants.porosity()) *
2963 getValue(ectx.fs.density(gasPhaseIdx)) *
2964 getValue(ectx.fs.saturation(gasPhaseIdx)) /
2965 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2970 Entry{ScalarEntry{
"BWCD",
2971 [&model = this->simulator_.model()](
const Context& ectx)
2974 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
2975 result = getValue(ectx.fs.Rs()) *
2976 getValue(ectx.fs.invB(oilPhaseIdx)) *
2977 getValue(ectx.fs.saturation(oilPhaseIdx));
2980 result = getValue(ectx.fs.Rsw()) *
2981 getValue(ectx.fs.invB(waterPhaseIdx)) *
2982 getValue(ectx.fs.saturation(waterPhaseIdx));
2984 const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
2985 ectx.intQuants.pvtRegionIndex());
2987 model.dofTotalVolume(ectx.globalDofIdx) *
2988 getValue(ectx.intQuants.porosity()) *
2990 FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
2994 Entry{ScalarEntry{
"BWIPG",
2995 [&model = this->simulator_.model()](
const Context& ectx)
2997 Scalar result = 0.0;
2998 if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
2999 result = getValue(ectx.fs.Rvw()) *
3000 getValue(ectx.fs.invB(gasPhaseIdx)) *
3001 getValue(ectx.fs.saturation(gasPhaseIdx));
3004 model.dofTotalVolume(ectx.globalDofIdx) *
3005 getValue(ectx.intQuants.porosity());
3009 Entry{ScalarEntry{
"BWIPL",
3010 [&model = this->simulator_.model()](
const Context& ectx)
3012 return getValue(ectx.fs.invB(waterPhaseIdx)) *
3013 getValue(ectx.fs.saturation(waterPhaseIdx)) *
3014 model.dofTotalVolume(ectx.globalDofIdx) *
3015 getValue(ectx.intQuants.porosity());
3023 this->extraBlockData_.clear();
3024 if (reportStepNum > 0 && !isSubStep) {
3026 const auto& rpt = this->schedule_[reportStepNum - 1].rpt_config.get();
3027 if (rpt.contains(
"WELLS") && rpt.at(
"WELLS") > 1) {
3028 this->setupExtraBlockData(reportStepNum,
3029 [&c = this->collectOnIORank_](
const int idx)
3030 {
return c.isCartIdxOnThisRank(idx); });
3032 const auto extraHandlers = std::array{
3041 const Simulator& simulator_;
3042 const CollectDataOnIORankType& collectOnIORank_;
3043 std::vector<typename Extractor::Entry> extractors_;