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