Loading...
Searching...
No Matches
OutputBlackoilModule.hpp
Go to the documentation of this file.
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
#ifndef OPM_OUTPUT_BLACK_OIL_MODULE_HPP
#define OPM_OUTPUT_BLACK_OIL_MODULE_HPP
#include <dune/common/fvector.hh>
#include <opm/simulators/utils/moduleVersion.hpp>
#include <opm/common/Exceptions.hpp>
#include <opm/common/TimingMacros.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/common/utility/Visitor.hpp>
#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
#include <opm/material/common/Valgrind.hpp>
#include <opm/material/fluidmatrixinteractions/EclEpsScalingPoints.hpp>
#include <opm/material/fluidstates/BlackOilFluidState.hpp>
#include <opm/material/fluidsystems/BlackOilFluidSystem.hpp>
#include <opm/models/blackoil/blackoilproperties.hh>
#include <opm/models/discretization/common/fvbaseproperties.hh>
#include <opm/models/utils/parametersystem.hpp>
#include <opm/models/utils/propertysystem.hh>
#include <opm/output/data/Cells.hpp>
#include <opm/output/eclipse/EclipseIO.hpp>
#include <opm/output/eclipse/Inplace.hpp>
#include <opm/simulators/flow/CollectDataOnIORank.hpp>
#include <opm/simulators/flow/FlowBaseVanguard.hpp>
#include <opm/simulators/flow/GenericOutputBlackoilModule.hpp>
#include <opm/simulators/flow/OutputExtractor.hpp>
#include <algorithm>
#include <array>
#include <cassert>
#include <cstddef>
#include <functional>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
namespace Opm {
// forward declaration
template <class TypeTag>
class EcfvDiscretization;
template <class TypeTag>
class OutputBlackOilModule : public GenericOutputBlackoilModule<GetPropType<TypeTag, Properties::FluidSystem>>
{
using Simulator = GetPropType<TypeTag, Properties::Simulator>;
using Discretization = GetPropType<TypeTag, Properties::Discretization>;
using Scalar = GetPropType<TypeTag, Properties::Scalar>;
using Evaluation = GetPropType<TypeTag, Properties::Evaluation>;
using ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
using MaterialLaw = GetPropType<TypeTag, Properties::MaterialLaw>;
using MaterialLawParams = GetPropType<TypeTag, Properties::MaterialLawParams>;
using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
using FluidState = typename IntensiveQuantities::FluidState;
using GridView = GetPropType<TypeTag, Properties::GridView>;
using Element = typename GridView::template Codim<0>::Entity;
using ElementIterator = typename GridView::template Codim<0>::Iterator;
using BaseType = GenericOutputBlackoilModule<FluidSystem>;
using Indices = GetPropType<TypeTag, Properties::Indices>;
using Dir = FaceDir::DirEnum;
using BlockExtractor = detail::BlockExtractor<TypeTag>;
using Extractor = detail::Extractor<TypeTag>;
using Grid = GetPropType<TypeTag, Properties::Grid>;
using EquilGrid = GetPropType<TypeTag, Properties::EquilGrid>;
using CollectDataOnIORankType = CollectDataOnIORank<Grid,EquilGrid,GridView>;
static constexpr int conti0EqIdx = Indices::conti0EqIdx;
static constexpr int numPhases = FluidSystem::numPhases;
static constexpr int oilPhaseIdx = FluidSystem::oilPhaseIdx;
static constexpr int gasPhaseIdx = FluidSystem::gasPhaseIdx;
static constexpr int waterPhaseIdx = FluidSystem::waterPhaseIdx;
static constexpr int gasCompIdx = FluidSystem::gasCompIdx;
static constexpr int oilCompIdx = FluidSystem::oilCompIdx;
static constexpr int waterCompIdx = FluidSystem::waterCompIdx;
enum { enableEnergy = getPropValue<TypeTag, Properties::EnableEnergy>() };
enum { enableBioeffects = getPropValue<TypeTag, Properties::EnableBioeffects>() };
enum { enableMICP = Indices::enableMICP };
enum { enableVapwat = getPropValue<TypeTag, Properties::EnableVapwat>() };
enum { enableDisgasInWater = getPropValue<TypeTag, Properties::EnableDisgasInWater>() };
enum { enableDissolvedGas = Indices::compositionSwitchIdx >= 0 };
template<class VectorType>
static Scalar value_or_zero(int idx, const VectorType& v)
{
if (idx == -1) {
return 0.0;
}
return v.empty() ? 0.0 : v[idx];
}
public:
OutputBlackOilModule(const Simulator& simulator,
const SummaryConfig& smryCfg,
const CollectDataOnIORankType& collectOnIORank)
: BaseType(simulator.vanguard().eclState(),
simulator.vanguard().schedule(),
smryCfg,
simulator.vanguard().summaryState(),
moduleVersionName(),
[this](const int idx)
{ return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
simulator.vanguard().grid().comm(),
getPropValue<TypeTag, Properties::EnableEnergy>(),
getPropValue<TypeTag, Properties::EnableTemperature>(),
getPropValue<TypeTag, Properties::EnableMech>(),
getPropValue<TypeTag, Properties::EnableSolvent>(),
getPropValue<TypeTag, Properties::EnablePolymer>(),
getPropValue<TypeTag, Properties::EnableFoam>(),
getPropValue<TypeTag, Properties::EnableBrine>(),
getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
getPropValue<TypeTag, Properties::EnableExtbo>(),
getPropValue<TypeTag, Properties::EnableBioeffects>())
, simulator_(simulator)
, collectOnIORank_(collectOnIORank)
{
for (auto& region_pair : this->regions_) {
this->createLocalRegion_(region_pair.second);
}
auto isCartIdxOnThisRank = [&collectOnIORank](const int idx) {
return collectOnIORank.isCartIdxOnThisRank(idx);
};
this->setupBlockData(isCartIdxOnThisRank);
if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
const std::string msg = "The output code does not support --owner-cells-first=false.";
if (collectOnIORank.isIORank()) {
OpmLog::error(msg);
}
OPM_THROW_NOLOG(std::runtime_error, msg);
}
if (smryCfg.match("[FB]PP[OGW]") || smryCfg.match("RPP[OGW]*")) {
auto rset = this->eclState_.fieldProps().fip_regions();
rset.push_back("PVTNUM");
// Note: We explicitly use decltype(auto) here because the
// default scheme (-> auto) will deduce an undesirable type. We
// need the "reference to vector" semantics in this instance.
this->regionAvgDensity_
.emplace(this->simulator_.gridView().comm(),
FluidSystem::numPhases, rset,
[fp = std::cref(this->eclState_.fieldProps())]
(const std::string& rsetName) -> decltype(auto)
{ return fp.get().get_int(rsetName); });
}
}
void
allocBuffers(const unsigned bufferSize,
const unsigned reportStepNum,
const bool substep,
const bool log,
const bool isRestart)
{
if (! std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value) {
return;
}
const auto& problem = this->simulator_.problem();
this->doAllocBuffers(bufferSize,
reportStepNum,
substep,
log,
isRestart,
&problem.materialLawManager()->hysteresisConfig(),
problem.eclWriter().getOutputNnc().size());
}
void setupExtractors(const bool isSubStep,
const int reportStepNum)
{
this->setupElementExtractors_();
this->setupBlockExtractors_(isSubStep, reportStepNum);
}
void clearExtractors()
{
this->extractors_.clear();
this->blockExtractors_.clear();
this->extraBlockExtractors_.clear();
}
void processElement(const ElementContext& elemCtx)
{
OPM_TIMEBLOCK_LOCAL(processElement, Subsystem::Output);
if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value) {
return;
}
if (this->extractors_.empty()) {
assert(0);
}
const auto& matLawManager = simulator_.problem().materialLawManager();
typename Extractor::HysteresisParams hysterParams;
for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const typename Extractor::Context ectx{
elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0),
elemCtx.primaryVars(dofIdx, /*timeIdx=*/0).pvtRegionIndex(),
elemCtx.simulator().episodeIndex(),
fs,
intQuants,
hysterParams
};
if (matLawManager->enableHysteresis()) {
if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(waterPhaseIdx)) {
matLawManager->oilWaterHysteresisParams(hysterParams.somax,
hysterParams.swmax,
hysterParams.swmin,
ectx.globalDofIdx);
}
if (FluidSystem::phaseIsActive(oilPhaseIdx) && FluidSystem::phaseIsActive(gasPhaseIdx)) {
matLawManager->gasOilHysteresisParams(hysterParams.sgmax,
hysterParams.shmax,
hysterParams.somin,
ectx.globalDofIdx);
}
}
Extractor::process(ectx, extractors_);
}
}
void processElementBlockData(const ElementContext& elemCtx)
{
OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value) {
return;
}
if (this->blockExtractors_.empty() && this->extraBlockExtractors_.empty()) {
return;
}
for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
// Adding block data
const auto globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
const auto cartesianIdx = elemCtx.simulator().vanguard().cartesianIndex(globalDofIdx);
const auto be_it = this->blockExtractors_.find(cartesianIdx);
const auto bee_it = this->extraBlockExtractors_.find(cartesianIdx);
if (be_it == this->blockExtractors_.end() &&
bee_it == this->extraBlockExtractors_.end())
{
continue;
}
const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const typename BlockExtractor::Context ectx{
globalDofIdx,
dofIdx,
fs,
intQuants,
elemCtx,
};
if (be_it != this->blockExtractors_.end()) {
BlockExtractor::process(be_it->second, ectx);
}
if (bee_it != this->extraBlockExtractors_.end()) {
BlockExtractor::process(bee_it->second, ectx);
}
}
}
void outputFipAndResvLog(const Inplace& inplace,
const std::size_t reportStepNum,
double elapsed,
boost::posix_time::ptime currentDate,
const bool substep,
const Parallel::Communication& comm)
{
if (comm.rank() != 0) {
return;
}
// For report step 0 we use the RPTSOL config, else derive from RPTSCHED
std::unique_ptr<FIPConfig> fipSched;
if (reportStepNum > 0) {
const auto& rpt = this->schedule_[reportStepNum-1].rpt_config.get();
fipSched = std::make_unique<FIPConfig>(rpt);
}
const FIPConfig& fipc = reportStepNum == 0 ? this->eclState_.getEclipseConfig().fip()
: *fipSched;
if (!substep && !this->forceDisableFipOutput_ && fipc.output(FIPConfig::OutputField::FIELD)) {
this->logOutput_.timeStamp("BALANCE", elapsed, reportStepNum, currentDate);
const auto& initial_inplace = this->initialInplace().value();
this->logOutput_.fip(inplace, initial_inplace, "");
if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
this->logOutput_.fip(inplace, initial_inplace, "FIPNUM");
if (fipc.output(FIPConfig::OutputField::RESV))
this->logOutput_.fipResv(inplace, "FIPNUM");
}
if (fipc.output(FIPConfig::OutputField::FIP)) {
for (const auto& reg : this->regions_) {
if (reg.first != "FIPNUM") {
std::ostringstream ss;
ss << "BAL" << reg.first.substr(3);
this->logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
this->logOutput_.fip(inplace, initial_inplace, reg.first);
if (fipc.output(FIPConfig::OutputField::RESV))
this->logOutput_.fipResv(inplace, reg.first);
}
}
}
}
}
void outputFipAndResvLogToCSV(const std::size_t reportStepNum,
const bool substep,
const Parallel::Communication& comm)
{
if (comm.rank() != 0) {
return;
}
if ((reportStepNum == 0) && (!substep) &&
(this->schedule_.initialReportConfiguration().has_value()) &&
(this->schedule_.initialReportConfiguration()->contains("CSVFIP"))) {
std::ostringstream csv_stream;
this->logOutput_.csv_header(csv_stream);
const auto& initial_inplace = this->initialInplace().value();
this->logOutput_.fip_csv(csv_stream, initial_inplace, "FIPNUM");
for (const auto& reg : this->regions_) {
if (reg.first != "FIPNUM") {
this->logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
}
}
const IOConfig& io = this->eclState_.getIOConfig();
auto csv_fname = io.getOutputDir() + "/" + io.getBaseName() + ".CSV";
std::ofstream outputFile(csv_fname);
outputFile << csv_stream.str();
outputFile.close();
}
}
template <class ActiveIndex, class CartesianIndex>
void processFluxes(const ElementContext& elemCtx,
ActiveIndex&& activeIndex,
CartesianIndex&& cartesianIndex)
{
OPM_TIMEBLOCK_LOCAL(processFluxes, Subsystem::Output);
const auto identifyCell = [&activeIndex, &cartesianIndex](const Element& elem)
-> InterRegFlowMap::Cell
{
const auto cellIndex = activeIndex(elem);
return {
static_cast<int>(cellIndex),
cartesianIndex(cellIndex),
elem.partitionType() == Dune::InteriorEntity
};
};
const auto timeIdx = 0u;
const auto& stencil = elemCtx.stencil(timeIdx);
const auto numInteriorFaces = elemCtx.numInteriorFaces(timeIdx);
for (auto scvfIdx = 0 * numInteriorFaces; scvfIdx < numInteriorFaces; ++scvfIdx) {
const auto& face = stencil.interiorFace(scvfIdx);
const auto left = identifyCell(stencil.element(face.interiorIndex()));
const auto right = identifyCell(stencil.element(face.exteriorIndex()));
const auto rates = this->
getComponentSurfaceRates(elemCtx, face.area(), scvfIdx, timeIdx);
this->interRegionFlows_.addConnection(left, right, rates);
}
}
void initializeFluxData()
{
// Inter-region flow rates. Note: ".clear()" prepares to accumulate
// contributions per bulk connection between FIP regions.
this->interRegionFlows_.clear();
}
void finalizeFluxData()
{
this->interRegionFlows_.compress();
}
const InterRegFlowMap& getInterRegFlows() const
{
return this->interRegionFlows_;
}
template <class FluidState>
void assignToFluidState(FluidState& fs, unsigned elemIdx) const
{
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
if (this->saturation_[phaseIdx].empty())
continue;
fs.setSaturation(phaseIdx, this->saturation_[phaseIdx][elemIdx]);
}
if (!this->fluidPressure_.empty()) {
// this assumes that capillary pressures only depend on the phase saturations
// and possibly on temperature. (this is always the case for ECL problems.)
std::array<Scalar, numPhases> pc = {0};
const MaterialLawParams& matParams = simulator_.problem().materialLawParams(elemIdx);
MaterialLaw::capillaryPressures(pc, matParams, fs);
Valgrind::CheckDefined(this->fluidPressure_[elemIdx]);
Valgrind::CheckDefined(pc);
const auto& pressure = this->fluidPressure_[elemIdx];
for (unsigned phaseIdx = 0; phaseIdx < numPhases; ++phaseIdx) {
if (!FluidSystem::phaseIsActive(phaseIdx))
continue;
if (Indices::oilEnabled)
fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[oilPhaseIdx]));
else if (Indices::gasEnabled)
fs.setPressure(phaseIdx, pressure + (pc[phaseIdx] - pc[gasPhaseIdx]));
else if (Indices::waterEnabled)
//single (water) phase
fs.setPressure(phaseIdx, pressure);
}
}
if (!this->temperature_.empty())
fs.setTemperature(this->temperature_[elemIdx]);
if constexpr (enableDissolvedGas) {
if (!this->rs_.empty())
fs.setRs(this->rs_[elemIdx]);
if (!this->rv_.empty())
fs.setRv(this->rv_[elemIdx]);
}
if constexpr (enableDisgasInWater) {
if (!this->rsw_.empty())
fs.setRsw(this->rsw_[elemIdx]);
}
if constexpr (enableVapwat) {
if (!this->rvw_.empty())
fs.setRvw(this->rvw_[elemIdx]);
}
}
void initHysteresisParams(Simulator& simulator, unsigned elemIdx) const
{
if (!this->soMax_.empty())
simulator.problem().setMaxOilSaturation(elemIdx, this->soMax_[elemIdx]);
if (simulator.problem().materialLawManager()->enableHysteresis()) {
auto matLawManager = simulator.problem().materialLawManager();
if (FluidSystem::phaseIsActive(oilPhaseIdx)
&& FluidSystem::phaseIsActive(waterPhaseIdx)) {
Scalar somax = 2.0;
Scalar swmax = -2.0;
Scalar swmin = 2.0;
if (matLawManager->enableNonWettingHysteresis()) {
if (!this->soMax_.empty()) {
somax = this->soMax_[elemIdx];
}
}
if (matLawManager->enableWettingHysteresis()) {
if (!this->swMax_.empty()) {
swmax = this->swMax_[elemIdx];
}
}
if (matLawManager->enablePCHysteresis()) {
if (!this->swmin_.empty()) {
swmin = this->swmin_[elemIdx];
}
}
matLawManager->setOilWaterHysteresisParams(
somax, swmax, swmin, elemIdx);
}
if (FluidSystem::phaseIsActive(oilPhaseIdx)
&& FluidSystem::phaseIsActive(gasPhaseIdx)) {
Scalar sgmax = 2.0;
Scalar shmax = -2.0;
Scalar somin = 2.0;
if (matLawManager->enableNonWettingHysteresis()) {
if (!this->sgmax_.empty()) {
sgmax = this->sgmax_[elemIdx];
}
}
if (matLawManager->enableWettingHysteresis()) {
if (!this->shmax_.empty()) {
shmax = this->shmax_[elemIdx];
}
}
if (matLawManager->enablePCHysteresis()) {
if (!this->somin_.empty()) {
somin = this->somin_[elemIdx];
}
}
matLawManager->setGasOilHysteresisParams(
sgmax, shmax, somin, elemIdx);
}
}
if (simulator_.vanguard().eclState().fieldProps().has_double("SWATINIT")) {
simulator.problem().materialLawManager()
->applyRestartSwatInit(elemIdx, this->ppcw_[elemIdx]);
}
}
void updateFluidInPlace(const ElementContext& elemCtx)
{
for (unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(/*timeIdx=*/0); ++dofIdx) {
updateFluidInPlace_(elemCtx, dofIdx);
}
}
void updateFluidInPlace(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
}
private:
template <typename T>
using RemoveCVR = std::remove_cv_t<std::remove_reference_t<T>>;
template <typename, class = void>
struct HasGeoMech : public std::false_type {};
template <typename Problem>
struct HasGeoMech<
Problem, std::void_t<decltype(std::declval<Problem>().geoMechModel())>
> : public std::true_type {};
bool isDefunctParallelWell(const std::string& wname) const override
{
if (simulator_.gridView().comm().size() == 1)
return false;
const auto& parallelWells = simulator_.vanguard().parallelWells();
std::pair<std::string, bool> value {wname, true};
auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
return candidate == parallelWells.end() || *candidate != value;
}
bool isOwnedByCurrentRank(const std::string& wname) const override
{
return this->simulator_.problem().wellModel().isOwner(wname);
}
bool isOnCurrentRank(const std::string& wname) const override
{
return this->simulator_.problem().wellModel().hasLocalCells(wname);
}
void updateFluidInPlace_(const ElementContext& elemCtx, const unsigned dofIdx)
{
const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, /*timeIdx=*/0);
const unsigned globalDofIdx = elemCtx.globalSpaceIndex(dofIdx, /*timeIdx=*/0);
const auto totVolume = elemCtx.simulator().model().dofTotalVolume(globalDofIdx);
this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
}
void updateFluidInPlace_(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
OPM_TIMEBLOCK_LOCAL(updateFluidInPlace, Subsystem::Output);
this->updateTotalVolumesAndPressures_(globalDofIdx, intQuants, totVolume);
if (this->computeFip_) {
this->updatePhaseInplaceVolumes_(globalDofIdx, intQuants, totVolume);
}
}
void createLocalRegion_(std::vector<int>& region)
{
// For CpGrid with LGRs, where level zero grid has been distributed,
// resize region is needed, since in this case the total amount of
// element - per process - in level zero grid and leaf grid do not
// coincide, in general.
region.resize(simulator_.gridView().size(0));
std::size_t elemIdx = 0;
for (const auto& elem : elements(simulator_.gridView())) {
if (elem.partitionType() != Dune::InteriorEntity) {
region[elemIdx] = 0;
}
++elemIdx;
}
}
template <typename FluidState>
void aggregateAverageDensityContributions_(const FluidState& fs,
const unsigned int globalDofIdx,
const double porv)
{
auto pvCellValue = RegionPhasePoreVolAverage::CellValue{};
pvCellValue.porv = porv;
for (auto phaseIdx = 0*FluidSystem::numPhases;
phaseIdx < FluidSystem::numPhases; ++phaseIdx)
{
if (! FluidSystem::phaseIsActive(phaseIdx)) {
continue;
}
pvCellValue.value = getValue(fs.density(phaseIdx));
pvCellValue.sat = getValue(fs.saturation(phaseIdx));
this->regionAvgDensity_
->addCell(globalDofIdx,
RegionPhasePoreVolAverage::Phase { phaseIdx },
pvCellValue);
}
}
data::InterRegFlowMap::FlowRates
getComponentSurfaceRates(const ElementContext& elemCtx,
const Scalar faceArea,
const std::size_t scvfIdx,
const std::size_t timeIdx) const
{
using Component = data::InterRegFlowMap::Component;
auto rates = data::InterRegFlowMap::FlowRates {};
const auto& extQuant = elemCtx.extensiveQuantities(scvfIdx, timeIdx);
const auto alpha = getValue(extQuant.extrusionFactor()) * faceArea;
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
const auto& up = elemCtx
.intensiveQuantities(extQuant.upstreamIndex(oilPhaseIdx), timeIdx);
const auto pvtReg = up.pvtRegionIndex();
const auto bO = getValue(getInvB_<FluidSystem, FluidState, Scalar>
(up.fluidState(), oilPhaseIdx, pvtReg));
const auto qO = alpha * bO * getValue(extQuant.volumeFlux(oilPhaseIdx));
rates[Component::Oil] += qO;
if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
const auto Rs = getValue(
BlackOil::getRs_<FluidSystem, FluidState, Scalar>
(up.fluidState(), pvtReg));
rates[Component::Gas] += qO * Rs;
rates[Component::Disgas] += qO * Rs;
}
}
if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
const auto& up = elemCtx
.intensiveQuantities(extQuant.upstreamIndex(gasPhaseIdx), timeIdx);
const auto pvtReg = up.pvtRegionIndex();
const auto bG = getValue(getInvB_<FluidSystem, FluidState, Scalar>
(up.fluidState(), gasPhaseIdx, pvtReg));
const auto qG = alpha * bG * getValue(extQuant.volumeFlux(gasPhaseIdx));
rates[Component::Gas] += qG;
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
const auto Rv = getValue(
BlackOil::getRv_<FluidSystem, FluidState, Scalar>
(up.fluidState(), pvtReg));
rates[Component::Oil] += qG * Rv;
rates[Component::Vapoil] += qG * Rv;
}
}
if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
const auto& up = elemCtx
.intensiveQuantities(extQuant.upstreamIndex(waterPhaseIdx), timeIdx);
const auto pvtReg = up.pvtRegionIndex();
const auto bW = getValue(getInvB_<FluidSystem, FluidState, Scalar>
(up.fluidState(), waterPhaseIdx, pvtReg));
rates[Component::Water] +=
alpha * bW * getValue(extQuant.volumeFlux(waterPhaseIdx));
}
return rates;
}
template <typename FluidState>
Scalar hydroCarbonFraction(const FluidState& fs) const
{
if (this->eclState_.runspec().co2Storage()) {
// CO2 storage: Hydrocarbon volume is full pore-volume.
return 1.0;
}
// Common case. Hydrocarbon volume is fraction occupied by actual
// hydrocarbons.
auto hydrocarbon = Scalar {0};
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
hydrocarbon += getValue(fs.saturation(oilPhaseIdx));
}
if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
hydrocarbon += getValue(fs.saturation(gasPhaseIdx));
}
return hydrocarbon;
}
void updateTotalVolumesAndPressures_(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
const auto& fs = intQuants.fluidState();
const double pv = totVolume * intQuants.porosity().value();
const auto hydrocarbon = this->hydroCarbonFraction(fs);
if (! this->hydrocarbonPoreVolume_.empty()) {
this->fipC_.assignPoreVolume(globalDofIdx,
totVolume * intQuants.referencePorosity());
this->dynamicPoreVolume_[globalDofIdx] = pv;
this->hydrocarbonPoreVolume_[globalDofIdx] = pv * hydrocarbon;
}
if (!this->pressureTimesHydrocarbonVolume_.empty() &&
!this->pressureTimesPoreVolume_.empty())
{
assert(this->hydrocarbonPoreVolume_.size() == this->pressureTimesHydrocarbonVolume_.size());
assert(this->fipC_.get(Inplace::Phase::PoreVolume).size() == this->pressureTimesPoreVolume_.size());
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
this->pressureTimesPoreVolume_[globalDofIdx] =
getValue(fs.pressure(oilPhaseIdx)) * pv;
this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
}
else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
this->pressureTimesPoreVolume_[globalDofIdx] =
getValue(fs.pressure(gasPhaseIdx)) * pv;
this->pressureTimesHydrocarbonVolume_[globalDofIdx] =
this->pressureTimesPoreVolume_[globalDofIdx] * hydrocarbon;
}
else if (FluidSystem::phaseIsActive(waterPhaseIdx)) {
this->pressureTimesPoreVolume_[globalDofIdx] =
getValue(fs.pressure(waterPhaseIdx)) * pv;
}
}
}
void updatePhaseInplaceVolumes_(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
std::array<Scalar, FluidSystem::numPhases> fip {};
std::array<Scalar, FluidSystem::numPhases> fipr{}; // at reservoir condition
const auto& fs = intQuants.fluidState();
const auto pv = totVolume * intQuants.porosity().value();
for (unsigned phaseIdx = 0; phaseIdx < FluidSystem::numPhases; ++phaseIdx) {
if (!FluidSystem::phaseIsActive(phaseIdx)) {
continue;
}
const auto b = getValue(fs.invB(phaseIdx));
const auto s = getValue(fs.saturation(phaseIdx));
fipr[phaseIdx] = s * pv;
fip [phaseIdx] = b * fipr[phaseIdx];
}
this->fipC_.assignVolumesSurface(globalDofIdx, fip);
this->fipC_.assignVolumesReservoir(globalDofIdx,
fs.saltConcentration().value(),
fipr);
if (FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx))
{
this->updateOilGasDistribution(globalDofIdx, fs, fip);
}
if (FluidSystem::phaseIsActive(waterPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx))
{
this->updateGasWaterDistribution(globalDofIdx, fs, fip);
}
if (FluidSystem::phaseIsActive(gasPhaseIdx) &&
this->fipC_.hasCo2InGas())
{
this->updateCO2InGas(globalDofIdx, pv, intQuants);
}
if (this->fipC_.hasCo2InWater() &&
(FluidSystem::phaseIsActive(waterPhaseIdx) ||
FluidSystem::phaseIsActive(oilPhaseIdx)))
{
this->updateCO2InWater(globalDofIdx, pv, fs);
}
if constexpr(enableBioeffects) {
const auto surfVolWat = pv * getValue(fs.saturation(waterPhaseIdx)) *
getValue(fs.invB(waterPhaseIdx));
if (this->fipC_.hasMicrobialMass()) {
this->updateMicrobialMass(globalDofIdx, intQuants, surfVolWat);
}
if (this->fipC_.hasBiofilmMass()) {
this->updateBiofilmMass(globalDofIdx, intQuants, totVolume);
}
if constexpr(enableMICP) {
if (this->fipC_.hasOxygenMass()) {
this->updateOxygenMass(globalDofIdx, intQuants, surfVolWat);
}
if (this->fipC_.hasUreaMass()) {
this->updateUreaMass(globalDofIdx, intQuants, surfVolWat);
}
if (this->fipC_.hasCalciteMass()) {
this->updateCalciteMass(globalDofIdx, intQuants, totVolume);
}
}
}
if (this->fipC_.hasWaterMass() && FluidSystem::phaseIsActive(waterPhaseIdx))
{
this->updateWaterMass(globalDofIdx, fs, fip);
}
}
template <typename FluidState, typename FIPArray>
void updateOilGasDistribution(const unsigned globalDofIdx,
const FluidState& fs,
const FIPArray& fip)
{
// Gas dissolved in oil and vaporized oil
const auto gasInPlaceLiquid = getValue(fs.Rs()) * fip[oilPhaseIdx];
const auto oilInPlaceGas = getValue(fs.Rv()) * fip[gasPhaseIdx];
this->fipC_.assignOilGasDistribution(globalDofIdx, gasInPlaceLiquid, oilInPlaceGas);
}
template <typename FluidState, typename FIPArray>
void updateGasWaterDistribution(const unsigned globalDofIdx,
const FluidState& fs,
const FIPArray& fip)
{
// Gas dissolved in water and vaporized water
const auto gasInPlaceWater = getValue(fs.Rsw()) * fip[waterPhaseIdx];
const auto waterInPlaceGas = getValue(fs.Rvw()) * fip[gasPhaseIdx];
this->fipC_.assignGasWater(globalDofIdx, fip, gasInPlaceWater, waterInPlaceGas);
}
template <typename IntensiveQuantities>
void updateCO2InGas(const unsigned globalDofIdx,
const double pv,
const IntensiveQuantities& intQuants)
{
const auto& scaledDrainageInfo = this->simulator_.problem().materialLawManager()
->oilWaterScaledEpsInfoDrainage(globalDofIdx);
const auto& fs = intQuants.fluidState();
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maximumTrapping*/false);
}
Scalar trappedGasSaturation = scaledDrainageInfo.Sgcr;
if (this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumTrapped) ||
this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseMaximumUnTrapped))
{
if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
// Get the maximum trapped gas saturation
trappedGasSaturation = MaterialLaw::trappedGasSaturation(matParams, /*maximumTrapping*/true);
}
}
const Scalar sg = getValue(fs.saturation(gasPhaseIdx));
Scalar strandedGasSaturation = scaledDrainageInfo.Sgcr;
if (this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveTrapped) ||
this->fipC_.has(Inplace::Phase::CO2MassInGasPhaseEffectiveUnTrapped))
{
if (this->simulator_.problem().materialLawManager()->enableHysteresis()) {
const auto& matParams = simulator_.problem().materialLawParams(globalDofIdx);
const double krg = getValue(intQuants.relativePermeability(gasPhaseIdx));
strandedGasSaturation = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
}
}
const typename FIPContainer<FluidSystem>::Co2InGasInput v{
pv,
sg,
sgcr,
getValue(fs.density(gasPhaseIdx)),
FluidSystem::phaseIsActive(waterPhaseIdx)
? FluidSystem::convertRvwToXgW(getValue(fs.Rvw()), fs.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(fs.Rv()), fs.pvtRegionIndex()),
FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex()),
trappedGasSaturation,
strandedGasSaturation,
};
this->fipC_.assignCo2InGas(globalDofIdx, v);
}
template <typename FluidState>
void updateCO2InWater(const unsigned globalDofIdx,
const double pv,
const FluidState& fs)
{
const auto co2InWater = FluidSystem::phaseIsActive(oilPhaseIdx)
? this->co2InWaterFromOil(fs, pv)
: this->co2InWaterFromWater(fs, pv);
const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
this->fipC_.assignCo2InWater(globalDofIdx, co2InWater, mM);
}
template <typename FluidState>
Scalar co2InWaterFromWater(const FluidState& fs, const double pv) const
{
const double rhow = getValue(fs.density(waterPhaseIdx));
const double sw = getValue(fs.saturation(waterPhaseIdx));
const double xwG = FluidSystem::convertRswToXwG(getValue(fs.Rsw()), fs.pvtRegionIndex());
const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
return xwG * pv * rhow * sw / mM;
}
template <typename FluidState>
Scalar co2InWaterFromOil(const FluidState& fs, const double pv) const
{
const double rhoo = getValue(fs.density(oilPhaseIdx));
const double so = getValue(fs.saturation(oilPhaseIdx));
const double xoG = FluidSystem::convertRsToXoG(getValue(fs.Rs()), fs.pvtRegionIndex());
const Scalar mM = FluidSystem::molarMass(gasCompIdx, fs.pvtRegionIndex());
return xoG * pv * rhoo * so / mM;
}
template <typename FluidState, typename FIPArray>
void updateWaterMass(const unsigned globalDofIdx,
const FluidState& fs,
const FIPArray& fip
)
{
const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx, fs.pvtRegionIndex());
this->fipC_.assignWaterMass(globalDofIdx, fip, rhoW);
}
template <typename IntensiveQuantities>
void updateMicrobialMass(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double surfVolWat)
{
const Scalar mass = surfVolWat * intQuants.microbialConcentration().value();
this->fipC_.assignMicrobialMass(globalDofIdx, mass);
}
template <typename IntensiveQuantities>
void updateOxygenMass(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double surfVolWat)
{
const Scalar mass = surfVolWat * intQuants.oxygenConcentration().value();
this->fipC_.assignOxygenMass(globalDofIdx, mass);
}
template <typename IntensiveQuantities>
void updateUreaMass(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double surfVolWat)
{
const Scalar mass = surfVolWat * intQuants.ureaConcentration().value();
this->fipC_.assignUreaMass(globalDofIdx, mass);
}
template <typename IntensiveQuantities>
void updateBiofilmMass(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
const Scalar mass = totVolume * intQuants.biofilmMass().value();
this->fipC_.assignBiofilmMass(globalDofIdx, mass);
}
template <typename IntensiveQuantities>
void updateCalciteMass(const unsigned globalDofIdx,
const IntensiveQuantities& intQuants,
const double totVolume)
{
const Scalar mass = totVolume * intQuants.calciteMass().value();
this->fipC_.assignCalciteMass(globalDofIdx, mass);
}
void setupElementExtractors_()
{
using Entry = typename Extractor::Entry;
using Context = typename Extractor::Context;
using ScalarEntry = typename Extractor::ScalarEntry;
using PhaseEntry = typename Extractor::PhaseEntry;
const bool hasResidual = simulator_.model().linearizer().residual().size() > 0;
const auto& hysteresisConfig = simulator_.problem().materialLawManager()->hysteresisConfig();
auto extractors = std::array{
Entry{PhaseEntry{&this->saturation_,
[](const unsigned phase, const Context& ectx)
{ return getValue(ectx.fs.saturation(phase)); }
}
},
Entry{PhaseEntry{&this->invB_,
[](const unsigned phase, const Context& ectx)
{ return getValue(ectx.fs.invB(phase)); }
}
},
Entry{PhaseEntry{&this->density_,
[](const unsigned phase, const Context& ectx)
{ return getValue(ectx.fs.density(phase)); }
}
},
Entry{PhaseEntry{&this->relativePermeability_,
[](const unsigned phase, const Context& ectx)
{ return getValue(ectx.intQuants.relativePermeability(phase)); }
}
},
Entry{PhaseEntry{&this->viscosity_,
[this](const unsigned phaseIdx, const Context& ectx)
{
if (this->extboC_.allocated() && phaseIdx == oilPhaseIdx) {
return getValue(ectx.intQuants.oilViscosity());
}
else if (this->extboC_.allocated() && phaseIdx == gasPhaseIdx) {
return getValue(ectx.intQuants.gasViscosity());
}
else {
return getValue(ectx.fs.viscosity(phaseIdx));
}
}
}
},
Entry{PhaseEntry{&this->residual_,
[&modelResid = this->simulator_.model().linearizer().residual()]
(const unsigned phaseIdx, const Context& ectx)
{
const unsigned sIdx = FluidSystem::solventComponentIndex(phaseIdx);
const unsigned activeCompIdx = FluidSystem::canonicalToActiveCompIdx(sIdx);
return modelResid[ectx.globalDofIdx][activeCompIdx];
}
},
hasResidual
},
Entry{ScalarEntry{&this->rockCompPorvMultiplier_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return problem.template
rockCompPoroMultiplier<Scalar>(ectx.intQuants,
ectx.globalDofIdx);
}
}
},
Entry{ScalarEntry{&this->rockCompTransMultiplier_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return problem.
template rockCompTransMultiplier<Scalar>(ectx.intQuants,
ectx.globalDofIdx);
}}
},
Entry{ScalarEntry{&this->minimumOilPressure_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return std::min(getValue(ectx.fs.pressure(oilPhaseIdx)),
problem.minOilPressure(ectx.globalDofIdx));
}
}
},
Entry{ScalarEntry{&this->bubblePointPressure_,
[&failedCells = this->failedCellsPb_,
&vanguard = this->simulator_.vanguard()](const Context& ectx)
{
try {
return getValue(
FluidSystem::bubblePointPressure(ectx.fs,
ectx.intQuants.pvtRegionIndex())
);
} catch (const NumericalProblem&) {
const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
failedCells.push_back(cartesianIdx);
return Scalar{0};
}
}
}
},
Entry{ScalarEntry{&this->dewPointPressure_,
[&failedCells = this->failedCellsPd_,
&vanguard = this->simulator_.vanguard()](const Context& ectx)
{
try {
return getValue(
FluidSystem::dewPointPressure(ectx.fs,
ectx.intQuants.pvtRegionIndex())
);
} catch (const NumericalProblem&) {
const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
failedCells.push_back(cartesianIdx);
return Scalar{0};
}
}
}
},
Entry{ScalarEntry{&this->overburdenPressure_,
[&problem = simulator_.problem()](const Context& ectx)
{ return problem.overburdenPressure(ectx.globalDofIdx); }
}
},
Entry{ScalarEntry{&this->temperature_,
[](const Context& ectx)
{ return getValue(ectx.fs.temperature(oilPhaseIdx)); }
}
},
Entry{ScalarEntry{&this->sSol_,
[](const Context& ectx)
{ return getValue(ectx.intQuants.solventSaturation()); }
}
},
Entry{ScalarEntry{&this->rswSol_,
[](const Context& ectx)
{ return getValue(ectx.intQuants.rsSolw()); }
}
},
Entry{ScalarEntry{&this->cPolymer_,
[](const Context& ectx)
{ return getValue(ectx.intQuants.polymerConcentration()); }
}
},
Entry{ScalarEntry{&this->cFoam_,
[](const Context& ectx)
{ return getValue(ectx.intQuants.foamConcentration()); }
}
},
Entry{ScalarEntry{&this->cSalt_,
[](const Context& ectx)
{ return getValue(ectx.fs.saltConcentration()); }
}
},
Entry{ScalarEntry{&this->pSalt_,
[](const Context& ectx)
{ return getValue(ectx.fs.saltSaturation()); }
}
},
Entry{ScalarEntry{&this->permFact_,
[](const Context& ectx)
{ return getValue(ectx.intQuants.permFactor()); }
}
},
Entry{ScalarEntry{&this->rPorV_,
[&model = this->simulator_.model()](const Context& ectx)
{
const auto totVolume = model.dofTotalVolume(ectx.globalDofIdx);
return totVolume * getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{&this->rs_,
[](const Context& ectx)
{ return getValue(ectx.fs.Rs()); }
}
},
Entry{ScalarEntry{&this->rv_,
[](const Context& ectx)
{ return getValue(ectx.fs.Rv()); }
}
},
Entry{ScalarEntry{&this->rsw_,
[](const Context& ectx)
{ return getValue(ectx.fs.Rsw()); }
}
},
Entry{ScalarEntry{&this->rvw_,
[](const Context& ectx)
{ return getValue(ectx.fs.Rvw()); }
}
},
Entry{ScalarEntry{&this->ppcw_,
[&matLawManager = *this->simulator_.problem().materialLawManager()]
(const Context& ectx)
{
return matLawManager.
oilWaterScaledEpsInfoDrainage(ectx.globalDofIdx).maxPcow;
}
}
},
Entry{ScalarEntry{&this->drsdtcon_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return problem.drsdtcon(ectx.globalDofIdx,
ectx.episodeIndex);
}
}
},
Entry{ScalarEntry{&this->pcgw_,
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(gasPhaseIdx)) -
getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
},
Entry{ScalarEntry{&this->pcow_,
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(oilPhaseIdx)) -
getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
},
Entry{ScalarEntry{&this->pcog_,
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(gasPhaseIdx)) -
getValue(ectx.fs.pressure(oilPhaseIdx));
}
}
},
Entry{ScalarEntry{&this->fluidPressure_,
[](const Context& ectx)
{
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
// Output oil pressure as default
return getValue(ectx.fs.pressure(oilPhaseIdx));
}
else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
// Output gas if oil is not present
return getValue(ectx.fs.pressure(gasPhaseIdx));
}
else {
// Output water if neither oil nor gas is present
return getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
}
},
Entry{ScalarEntry{&this->gasDissolutionFactor_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
return FluidSystem::template
saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
oilPhaseIdx,
ectx.pvtRegionIdx,
SoMax);
}
}
},
Entry{ScalarEntry{&this->oilVaporizationFactor_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
const Scalar SoMax = problem.maxOilSaturation(ectx.globalDofIdx);
return FluidSystem::template
saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
gasPhaseIdx,
ectx.pvtRegionIdx,
SoMax);
}
}
},
Entry{ScalarEntry{&this->gasDissolutionFactorInWater_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
const Scalar SwMax = problem.maxWaterSaturation(ectx.globalDofIdx);
return FluidSystem::template
saturatedDissolutionFactor<FluidState, Scalar>(ectx.fs,
waterPhaseIdx,
ectx.pvtRegionIdx,
SwMax);
}
}
},
Entry{ScalarEntry{&this->waterVaporizationFactor_,
[](const Context& ectx)
{
return FluidSystem::template
saturatedVaporizationFactor<FluidState, Scalar>(ectx.fs,
gasPhaseIdx,
ectx.pvtRegionIdx);
}
}
},
Entry{ScalarEntry{&this->gasFormationVolumeFactor_,
[](const Context& ectx)
{
return 1.0 / FluidSystem::template
inverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
gasPhaseIdx,
ectx.pvtRegionIdx);
}
}
},
Entry{ScalarEntry{&this->saturatedOilFormationVolumeFactor_,
[](const Context& ectx)
{
return 1.0 / FluidSystem::template
saturatedInverseFormationVolumeFactor<FluidState, Scalar>(ectx.fs,
oilPhaseIdx,
ectx.pvtRegionIdx);
}
}
},
Entry{ScalarEntry{&this->oilSaturationPressure_,
[](const Context& ectx)
{
return FluidSystem::template
saturationPressure<FluidState, Scalar>(ectx.fs,
oilPhaseIdx,
ectx.pvtRegionIdx);
}
}
},
Entry{ScalarEntry{&this->soMax_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return std::max(getValue(ectx.fs.saturation(oilPhaseIdx)),
problem.maxOilSaturation(ectx.globalDofIdx));
}
},
!hysteresisConfig.enableHysteresis()
},
Entry{ScalarEntry{&this->swMax_,
[&problem = this->simulator_.problem()](const Context& ectx)
{
return std::max(getValue(ectx.fs.saturation(waterPhaseIdx)),
problem.maxWaterSaturation(ectx.globalDofIdx));
}
},
!hysteresisConfig.enableHysteresis()
},
Entry{ScalarEntry{&this->soMax_,
[](const Context& ectx)
{ return ectx.hParams.somax; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enableNonWettingHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(waterPhaseIdx)
},
Entry{ScalarEntry{&this->swMax_,
[](const Context& ectx)
{ return ectx.hParams.swmax; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enableWettingHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(waterPhaseIdx)
},
Entry{ScalarEntry{&this->swmin_,
[](const Context& ectx)
{ return ectx.hParams.swmin; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enablePCHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(waterPhaseIdx)
},
Entry{ScalarEntry{&this->sgmax_,
[](const Context& ectx)
{ return ectx.hParams.sgmax; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enableNonWettingHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{ScalarEntry{&this->shmax_,
[](const Context& ectx)
{ return ectx.hParams.shmax; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enableWettingHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{ScalarEntry{&this->somin_,
[](const Context& ectx)
{ return ectx.hParams.somin; }
},
hysteresisConfig.enableHysteresis() &&
hysteresisConfig.enablePCHysteresis() &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{[&model = this->simulator_.model(), this](const Context& ectx)
{
// Note: We intentionally exclude effects of rock
// compressibility by using referencePorosity() here.
const auto porv = ectx.intQuants.referencePorosity()
* model.dofTotalVolume(ectx.globalDofIdx);
this->aggregateAverageDensityContributions_(ectx.fs, ectx.globalDofIdx,
static_cast<double>(porv));
}, this->regionAvgDensity_.has_value()
},
Entry{[&extboC = this->extboC_](const Context& ectx)
{
extboC.assignVolumes(ectx.globalDofIdx,
ectx.intQuants.xVolume().value(),
ectx.intQuants.yVolume().value());
extboC.assignZFraction(ectx.globalDofIdx,
ectx.intQuants.zFraction().value());
const Scalar stdVolOil = getValue(ectx.fs.saturation(oilPhaseIdx)) *
getValue(ectx.fs.invB(oilPhaseIdx)) +
getValue(ectx.fs.saturation(gasPhaseIdx)) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.Rv());
const Scalar stdVolGas = getValue(ectx.fs.saturation(gasPhaseIdx)) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
(1.0 - ectx.intQuants.yVolume().value()) +
getValue(ectx.fs.saturation(oilPhaseIdx)) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.Rs()) *
(1.0 - ectx.intQuants.xVolume().value());
const Scalar stdVolCo2 = getValue(ectx.fs.saturation(gasPhaseIdx)) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
ectx.intQuants.yVolume().value() +
getValue(ectx.fs.saturation(oilPhaseIdx)) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.Rs()) *
ectx.intQuants.xVolume().value();
const Scalar rhoO = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx, ectx.pvtRegionIdx);
const Scalar rhoCO2 = ectx.intQuants.zRefDensity();
const Scalar stdMassTotal = 1.0e-10 + stdVolOil * rhoO + stdVolGas * rhoG + stdVolCo2 * rhoCO2;
extboC.assignMassFractions(ectx.globalDofIdx,
stdVolGas * rhoG / stdMassTotal,
stdVolOil * rhoO / stdMassTotal,
stdVolCo2 * rhoCO2 / stdMassTotal);
}, this->extboC_.allocated()
},
Entry{[&bioeffectsC = this->bioeffectsC_](const Context& ectx)
{
bioeffectsC.assign(ectx.globalDofIdx,
ectx.intQuants.microbialConcentration().value(),
ectx.intQuants.biofilmVolumeFraction().value());
if (Indices::enableMICP) {
bioeffectsC.assign(ectx.globalDofIdx,
ectx.intQuants.oxygenConcentration().value(),
ectx.intQuants.ureaConcentration().value(),
ectx.intQuants.calciteVolumeFraction().value());
}
}, this->bioeffectsC_.allocated()
},
Entry{[&rftC = this->rftC_,
&vanguard = this->simulator_.vanguard()](const Context& ectx)
{
const auto cartesianIdx = vanguard.cartesianIndex(ectx.globalDofIdx);
rftC.assign(cartesianIdx,
[&fs = ectx.fs]() { return getValue(fs.pressure(oilPhaseIdx)); },
[&fs = ectx.fs]() { return getValue(fs.saturation(waterPhaseIdx)); },
[&fs = ectx.fs]() { return getValue(fs.saturation(gasPhaseIdx)); });
}
},
Entry{[&tC = this->tracerC_,
&tM = this->simulator_.problem().tracerModel()](const Context& ectx)
{
tC.assignFreeConcentrations(ectx.globalDofIdx,
[gIdx = ectx.globalDofIdx, &tM](const unsigned tracerIdx)
{ return tM.freeTracerConcentration(tracerIdx, gIdx); });
tC.assignSolConcentrations(ectx.globalDofIdx,
[gIdx = ectx.globalDofIdx, &tM](const unsigned tracerIdx)
{ return tM.solTracerConcentration(tracerIdx, gIdx); });
}
},
Entry{[&flowsInf = this->simulator_.problem().model().linearizer().getFlowsInfo(),
&flowsC = this->flowsC_](const Context& ectx)
{
const auto gas_idx = Indices::gasEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
const auto oil_idx = Indices::oilEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
const auto water_idx = Indices::waterEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
const auto& flowsInfos = flowsInf[ectx.globalDofIdx];
for (const auto& flowsInfo : flowsInfos) {
flowsC.assignFlows(ectx.globalDofIdx,
flowsInfo.faceId,
flowsInfo.nncId,
value_or_zero(gas_idx, flowsInfo.flow),
value_or_zero(oil_idx, flowsInfo.flow),
value_or_zero(water_idx, flowsInfo.flow));
}
}, !this->simulator_.problem().model().linearizer().getFlowsInfo().empty()
},
Entry{[&floresInf = this->simulator_.problem().model().linearizer().getFloresInfo(),
&flowsC = this->flowsC_](const Context& ectx)
{
const auto gas_idx = Indices::gasEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(gasCompIdx) : -1;
const auto oil_idx = Indices::oilEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(oilCompIdx) : -1;
const auto water_idx = Indices::waterEnabled ?
conti0EqIdx + FluidSystem::canonicalToActiveCompIdx(waterCompIdx) : -1;
const auto& floresInfos = floresInf[ectx.globalDofIdx];
for (const auto& floresInfo : floresInfos) {
flowsC.assignFlores(ectx.globalDofIdx,
floresInfo.faceId,
floresInfo.nncId,
value_or_zero(gas_idx, floresInfo.flow),
value_or_zero(oil_idx, floresInfo.flow),
value_or_zero(water_idx, floresInfo.flow));
}
}, !this->simulator_.problem().model().linearizer().getFloresInfo().empty()
},
// hack to make the intial output of rs and rv Ecl compatible.
// For cells with swat == 1 Ecl outputs; rs = rsSat and rv=rvSat, in all but the initial step
// where it outputs rs and rv values calculated by the initialization. To be compatible we overwrite
// rs and rv with the values computed in the initially.
// Volume factors, densities and viscosities need to be recalculated with the updated rs and rv values.
Entry{ScalarEntry{&this->rv_,
[&problem = this->simulator_.problem()](const Context& ectx)
{ return problem.initialFluidState(ectx.globalDofIdx).Rv(); }
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{ScalarEntry{&this->rs_,
[&problem = this->simulator_.problem()](const Context& ectx)
{ return problem.initialFluidState(ectx.globalDofIdx).Rs(); }
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{ScalarEntry{&this->rsw_,
[&problem = this->simulator_.problem()](const Context& ectx)
{ return problem.initialFluidState(ectx.globalDofIdx).Rsw(); }
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{ScalarEntry{&this->rvw_,
[&problem = this->simulator_.problem()](const Context& ectx)
{ return problem.initialFluidState(ectx.globalDofIdx).Rvw(); }
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
// re-compute the volume factors, viscosities and densities if asked for
Entry{PhaseEntry{&this->density_,
[&problem = this->simulator_.problem()](const unsigned phase,
const Context& ectx)
{
const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
return FluidSystem::density(fsInitial,
phase,
ectx.intQuants.pvtRegionIndex());
}
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{PhaseEntry{&this->invB_,
[&problem = this->simulator_.problem()](const unsigned phase,
const Context& ectx)
{
const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
return FluidSystem::inverseFormationVolumeFactor(fsInitial,
phase,
ectx.intQuants.pvtRegionIndex());
}
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
Entry{PhaseEntry{&this->viscosity_,
[&problem = this->simulator_.problem()](const unsigned phase,
const Context& ectx)
{
const auto& fsInitial = problem.initialFluidState(ectx.globalDofIdx);
return FluidSystem::viscosity(fsInitial,
phase,
ectx.intQuants.pvtRegionIndex());
}
},
simulator_.episodeIndex() < 0 &&
FluidSystem::phaseIsActive(oilPhaseIdx) &&
FluidSystem::phaseIsActive(gasPhaseIdx)
},
};
// Setup active extractors
this->extractors_ = Extractor::removeInactive(extractors);
if constexpr (getPropValue<TypeTag, Properties::EnableMech>()) {
if (this->mech_.allocated()) {
this->extractors_.push_back(
Entry{[&mech = this->mech_,
&model = simulator_.problem().geoMechModel()](const Context& ectx)
{
mech.assignDelStress(ectx.globalDofIdx,
model.delstress(ectx.globalDofIdx));
mech.assignDisplacement(ectx.globalDofIdx,
model.disp(ectx.globalDofIdx, /*include_fracture*/true));
// is the tresagii stress which make rock fracture
mech.assignFracStress(ectx.globalDofIdx,
model.fractureStress(ectx.globalDofIdx));
mech.assignLinStress(ectx.globalDofIdx,
model.linstress(ectx.globalDofIdx));
mech.assignPotentialForces(ectx.globalDofIdx,
model.mechPotentialForce(ectx.globalDofIdx),
model.mechPotentialPressForce(ectx.globalDofIdx),
model.mechPotentialTempForce(ectx.globalDofIdx));
mech.assignStrain(ectx.globalDofIdx,
model.strain(ectx.globalDofIdx, /*include_fracture*/true));
// Total stress is not stored but calculated result is Voigt notation
mech.assignStress(ectx.globalDofIdx,
model.stress(ectx.globalDofIdx, /*include_fracture*/true));
}
}
);
}
}
}
void setupBlockExtractors_(const bool isSubStep,
const int reportStepNum)
{
using Entry = typename BlockExtractor::Entry;
using Context = typename BlockExtractor::Context;
using PhaseEntry = typename BlockExtractor::PhaseEntry;
using ScalarEntry = typename BlockExtractor::ScalarEntry;
using namespace std::string_view_literals;
const auto pressure_handler =
Entry{ScalarEntry{std::vector{"BPR"sv, "BPRESSUR"sv},
[](const Context& ectx)
{
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
return getValue(ectx.fs.pressure(oilPhaseIdx));
}
else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
return getValue(ectx.fs.pressure(gasPhaseIdx));
}
else { //if (FluidSystem::phaseIsActive(waterPhaseIdx))
return getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
}
};
const auto handlers = std::array{
pressure_handler,
Entry{PhaseEntry{std::array{
std::array{"BWSAT"sv, "BOSAT"sv, "BGSAT"sv},
std::array{"BSWAT"sv, "BSOIL"sv, "BSGAS"sv}
},
[](const unsigned phaseIdx, const Context& ectx)
{
return getValue(ectx.fs.saturation(phaseIdx));
}
}
},
Entry{ScalarEntry{"BNSAT",
[](const Context& ectx)
{
return ectx.intQuants.solventSaturation().value();
}
}
},
Entry{ScalarEntry{std::vector{"BTCNFHEA"sv, "BTEMP"sv},
[](const Context& ectx)
{
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
return getValue(ectx.fs.temperature(oilPhaseIdx));
}
else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
return getValue(ectx.fs.temperature(gasPhaseIdx));
}
else { //if (FluidSystem::phaseIsActive(waterPhaseIdx))
return getValue(ectx.fs.temperature(waterPhaseIdx));
}
}
}
},
Entry{PhaseEntry{std::array{
std::array{"BWKR"sv, "BOKR"sv, "BGKR"sv},
std::array{"BKRW"sv, "BKRO"sv, "BKRG"sv}
},
[](const unsigned phaseIdx, const Context& ectx)
{
return getValue(ectx.intQuants.relativePermeability(phaseIdx));
}
}
},
Entry{ScalarEntry{"BKROG",
[&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& materialParams =
problem.materialLawParams(ectx.elemCtx,
ectx.dofIdx,
/* timeIdx = */ 0);
return getValue(MaterialLaw::template
relpermOilInOilGasSystem<Evaluation>(materialParams,
ectx.fs));
}
}
},
Entry{ScalarEntry{"BKROW",
[&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& materialParams = problem.materialLawParams(ectx.elemCtx,
ectx.dofIdx,
/* timeIdx = */ 0);
return getValue(MaterialLaw::template
relpermOilInOilWaterSystem<Evaluation>(materialParams,
ectx.fs));
}
}
},
Entry{ScalarEntry{"BWPC",
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(oilPhaseIdx)) -
getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
},
Entry{ScalarEntry{"BGPC",
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(gasPhaseIdx)) -
getValue(ectx.fs.pressure(oilPhaseIdx));
}
}
},
Entry{ScalarEntry{"BWPR",
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(waterPhaseIdx));
}
}
},
Entry{ScalarEntry{"BGPR",
[](const Context& ectx)
{
return getValue(ectx.fs.pressure(gasPhaseIdx));
}
}
},
Entry{PhaseEntry{std::array{
std::array{"BVWAT"sv, "BVOIL"sv, "BVGAS"sv},
std::array{"BWVIS"sv, "BOVIS"sv, "BGVIS"sv}
},
[](const unsigned phaseIdx, const Context& ectx)
{
return getValue(ectx.fs.viscosity(phaseIdx));
}
}
},
Entry{PhaseEntry{std::array{
std::array{"BWDEN"sv, "BODEN"sv, "BGDEN"sv},
std::array{"BDENW"sv, "BDENO"sv, "BDENG"sv}
},
[](const unsigned phaseIdx, const Context& ectx)
{
return getValue(ectx.fs.density(phaseIdx));
}
}
},
Entry{ScalarEntry{"BFLOWI",
[&flowsC = this->flowsC_](const Context& ectx)
{
return flowsC.getFlow(ectx.globalDofIdx, Dir::XPlus, waterCompIdx);
}
}
},
Entry{ScalarEntry{"BFLOWJ",
[&flowsC = this->flowsC_](const Context& ectx)
{
return flowsC.getFlow(ectx.globalDofIdx, Dir::YPlus, waterCompIdx);
}
}
},
Entry{ScalarEntry{"BFLOWK",
[&flowsC = this->flowsC_](const Context& ectx)
{
return flowsC.getFlow(ectx.globalDofIdx, Dir::ZPlus, waterCompIdx);
}
}
},
Entry{ScalarEntry{"BRPV",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.intQuants.porosity()) *
model.dofTotalVolume(ectx.globalDofIdx);
}
}
},
Entry{PhaseEntry{std::array{"BWPV"sv, "BOPV"sv, "BGPV"sv},
[&model = this->simulator_.model()](const unsigned phaseIdx,
const Context& ectx)
{
return getValue(ectx.fs.saturation(phaseIdx)) *
getValue(ectx.intQuants.porosity()) *
model.dofTotalVolume(ectx.globalDofIdx);
}
}
},
Entry{ScalarEntry{"BRS",
[](const Context& ectx)
{
return getValue(ectx.fs.Rs());
}
}
},
Entry{ScalarEntry{"BRV",
[](const Context& ectx)
{
return getValue(ectx.fs.Rv());
}
}
},
Entry{ScalarEntry{"BOIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return (getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx)) +
getValue(ectx.fs.Rv()) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx))) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BGIP",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx));
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
result += getValue(ectx.fs.Rs()) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx));
}
else {
result += getValue(ectx.fs.Rsw()) *
getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx));
}
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BWIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BOIPL",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BGIPL",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result;
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
result = getValue(ectx.fs.Rs()) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx));
}
else {
result = getValue(ectx.fs.Rsw()) *
getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx));
}
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BGIPG",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BOIPG",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.fs.Rv()) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{PhaseEntry{std::array{"BPPW"sv, "BPPO"sv, "BPPG"sv},
[&simConfig = this->eclState_.getSimulationConfig(),
&grav = this->simulator_.problem().gravity(),
&regionAvgDensity = this->regionAvgDensity_,
&problem = this->simulator_.problem(),
&regions = this->regions_](const unsigned phaseIdx, const Context& ectx)
{
auto phase = RegionPhasePoreVolAverage::Phase{};
phase.ix = phaseIdx;
// Note different region handling here. FIPNUM is
// one-based, but we need zero-based lookup in
// DatumDepth. On the other hand, pvtRegionIndex is
// zero-based but we need one-based lookup in
// RegionPhasePoreVolAverage.
// Subtract one to convert FIPNUM to region index.
const auto datum = simConfig.datumDepths()(regions["FIPNUM"][ectx.dofIdx] - 1);
// Add one to convert region index to region ID.
const auto region = RegionPhasePoreVolAverage::Region {
ectx.elemCtx.primaryVars(ectx.dofIdx, /*timeIdx=*/0).pvtRegionIndex() + 1
};
const auto density = regionAvgDensity->value("PVTNUM", phase, region);
const auto press = getValue(ectx.fs.pressure(phase.ix));
const auto dz = problem.dofCenterDepth(ectx.globalDofIdx) - datum;
return press - density*dz*grav[GridView::dimensionworld - 1];
}
}
},
Entry{ScalarEntry{"BAMIP",
[&model = this->simulator_.model()](const Context& ectx)
{
const Scalar rhoW = FluidSystem::referenceDensity(waterPhaseIdx,
ectx.intQuants.pvtRegionIndex());
return getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx)) *
rhoW *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BMMIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.intQuants.microbialConcentration()) *
getValue(ectx.fs.saturation(waterPhaseIdx)) *
getValue(ectx.intQuants.porosity()) *
model.dofTotalVolume(ectx.globalDofIdx);
}
}
},
Entry{ScalarEntry{"BMOIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.intQuants.oxygenConcentration()) *
getValue(ectx.intQuants.porosity()) *
model.dofTotalVolume(ectx.globalDofIdx);
}
}
},
Entry{ScalarEntry{"BMUIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.intQuants.ureaConcentration()) *
getValue(ectx.intQuants.porosity()) *
model.dofTotalVolume(ectx.globalDofIdx) * 1;
}
}
},
Entry{ScalarEntry{"BMBIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.biofilmMass());
}
}
},
Entry{ScalarEntry{"BMCIP",
[&model = this->simulator_.model()](const Context& ectx)
{
return model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.calciteMass());
}
}
},
Entry{ScalarEntry{"BGMIP",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result = getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx));
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
result += getValue(ectx.fs.Rs()) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx));
}
else {
result += getValue(ectx.fs.Rsw()) *
getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx));
}
const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
ectx.intQuants.pvtRegionIndex());
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
rhoG;
}
}
},
Entry{ScalarEntry{"BGMGP",
[&model = this->simulator_.model()](const Context& ectx)
{
const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
ectx.intQuants.pvtRegionIndex());
return getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
rhoG;
}
}
},
Entry{ScalarEntry{"BGMDS",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result;
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
result = getValue(ectx.fs.Rs()) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx));
}
else {
result = getValue(ectx.fs.Rsw()) *
getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx));
}
const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
ectx.intQuants.pvtRegionIndex());
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
rhoG;
}
}
},
Entry{ScalarEntry{"BGMST",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar strandedGas = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::min(strandedGas, sg);
}
}
},
Entry{ScalarEntry{"BGMUS",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar strandedGas = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
const Scalar krg = getValue(ectx.intQuants.relativePermeability(gasPhaseIdx));
strandedGas = MaterialLaw::strandedGasSaturation(matParams, sg, krg);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::max(Scalar{0.0}, sg - strandedGas);
}
}
},
Entry{ScalarEntry{"BGMTR",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
Scalar trappedGas = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
trappedGas = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/true);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::min(trappedGas, getValue(ectx.fs.saturation(gasPhaseIdx)));
}
}
},
Entry{ScalarEntry{"BGMMO",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
Scalar trappedGas = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
trappedGas = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/true);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - trappedGas);
}
}
},
Entry{ScalarEntry{"BGKTR",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
if (sg > sgcr) {
return 0.0;
}
else {
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx));
}
}
}
},
Entry{ScalarEntry{"BGKMO",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
if (sgcr >= sg) {
return 0.0;
}
else {
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx));
}
}
}
},
Entry{ScalarEntry{"BGCDI",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::min(sgcr, getValue(ectx.fs.saturation(gasPhaseIdx))) /
FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
}
}
},
Entry{ScalarEntry{"BGCDM",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
std::max(Scalar{0.0}, getValue(ectx.fs.saturation(gasPhaseIdx)) - sgcr) /
FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
}
}
},
Entry{ScalarEntry{"BGKDI",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
if (sg > sgcr) {
return 0.0;
}
else {
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx)) /
FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
}
}
}
},
Entry{ScalarEntry{"BGKDM",
[&model = this->simulator_.model(),
&problem = this->simulator_.problem()](const Context& ectx)
{
const auto& scaledDrainageInfo = problem.materialLawManager()
->oilWaterScaledEpsInfoDrainage(ectx.dofIdx);
const Scalar sg = getValue(ectx.fs.saturation(gasPhaseIdx));
Scalar sgcr = scaledDrainageInfo.Sgcr;
if (problem.materialLawManager()->enableHysteresis()) {
const auto& matParams = problem.materialLawParams(ectx.dofIdx);
sgcr = MaterialLaw::trappedGasSaturation(matParams, /*maxTrapping*/false);
}
if (sgcr >= sg) {
return 0.0;
}
else {
const Scalar xgW = FluidSystem::phaseIsActive(waterPhaseIdx) ?
FluidSystem::convertRvwToXgW(getValue(ectx.fs.Rvw()), ectx.intQuants.pvtRegionIndex())
: FluidSystem::convertRvToXgO(getValue(ectx.fs.Rv()), ectx.intQuants.pvtRegionIndex());
return (1.0 - xgW) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
getValue(ectx.fs.density(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx)) /
FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
}
}
}
},
Entry{ScalarEntry{"BWCD",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result;
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
result = getValue(ectx.fs.Rs()) *
getValue(ectx.fs.invB(oilPhaseIdx)) *
getValue(ectx.fs.saturation(oilPhaseIdx));
}
else {
result = getValue(ectx.fs.Rsw()) *
getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx));
}
const Scalar rhoG = FluidSystem::referenceDensity(gasPhaseIdx,
ectx.intQuants.pvtRegionIndex());
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity()) *
rhoG /
FluidSystem::molarMass(gasCompIdx, ectx.intQuants.pvtRegionIndex());
}
}
},
Entry{ScalarEntry{"BWIPG",
[&model = this->simulator_.model()](const Context& ectx)
{
Scalar result = 0.0;
if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
result = getValue(ectx.fs.Rvw()) *
getValue(ectx.fs.invB(gasPhaseIdx)) *
getValue(ectx.fs.saturation(gasPhaseIdx));
}
return result *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
Entry{ScalarEntry{"BWIPL",
[&model = this->simulator_.model()](const Context& ectx)
{
return getValue(ectx.fs.invB(waterPhaseIdx)) *
getValue(ectx.fs.saturation(waterPhaseIdx)) *
model.dofTotalVolume(ectx.globalDofIdx) *
getValue(ectx.intQuants.porosity());
}
}
},
};
this->blockExtractors_ = BlockExtractor::setupExecMap(this->blockData_, handlers);
this->extraBlockData_.clear();
if (reportStepNum > 0 && !isSubStep) {
// check we need extra block pressures for RPTSCHED
const auto& rpt = this->schedule_[reportStepNum - 1].rpt_config.get();
if (rpt.contains("WELLS") && rpt.at("WELLS") > 1) {
this->setupExtraBlockData(reportStepNum,
[&c = this->collectOnIORank_](const int idx)
{ return c.isCartIdxOnThisRank(idx); });
const auto extraHandlers = std::array{
pressure_handler,
};
this->extraBlockExtractors_ = BlockExtractor::setupExecMap(this->extraBlockData_, extraHandlers);
}
}
}
const Simulator& simulator_;
const CollectDataOnIORankType& collectOnIORank_;
std::vector<typename Extractor::Entry> extractors_;
typename BlockExtractor::ExecMap blockExtractors_;
typename BlockExtractor::ExecMap extraBlockExtractors_;
};
} // namespace Opm
#endif // OPM_OUTPUT_BLACK_OIL_MODULE_HPP
FlowBaseVanguard.hpp
Helper class for grid instantiation of ECL file-format using problems.
GenericOutputBlackoilModule.hpp
Output module for the results black oil model writing in ECL binary format.
OutputExtractor.hpp
Output module for the results black oil model writing in ECL binary format.
blackoilproperties.hh
Declares the properties required by the black oil model.
Opm::CollectDataOnIORank
Definition CollectDataOnIORank.hpp:56
Opm::EcfvDiscretization
The base class for the element-centered finite-volume discretization scheme.
Definition ecfvdiscretization.hh:160
Opm::InterRegFlowMap
Inter-region flow accumulation maps for all region definition arrays.
Definition InterRegFlows.hpp:179
Opm::InterRegFlowMap::Cell
InterRegFlowMapSingleFIP::Cell Cell
Characteristics of a cell from a simulation grid.
Definition InterRegFlows.hpp:193
Opm::OutputBlackOilModule::processElement
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition OutputBlackoilModule.hpp:237
Opm::OutputBlackOilModule::initializeFluxData
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition OutputBlackoilModule.hpp:481
Opm::OutputBlackOilModule::setupExtractors
void setupExtractors(const bool isSubStep, const int reportStepNum)
Setup list of active element-level data extractors.
Definition OutputBlackoilModule.hpp:218
Opm::OutputBlackOilModule::allocBuffers
void allocBuffers(const unsigned bufferSize, const unsigned reportStepNum, const bool substep, const bool log, const bool isRestart)
Allocate memory for the scalar fields we would like to write to ECL output files.
Definition OutputBlackoilModule.hpp:196
Opm::OutputBlackOilModule::processFluxes
void processFluxes(const ElementContext &elemCtx, ActiveIndex &&activeIndex, CartesianIndex &&cartesianIndex)
Capture connection fluxes, particularly to account for inter-region flows.
Definition OutputBlackoilModule.hpp:444
Opm::OutputBlackOilModule::clearExtractors
void clearExtractors()
Clear list of active element-level data extractors.
Definition OutputBlackoilModule.hpp:226
Opm::OutputBlackOilModule::getInterRegFlows
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition OutputBlackoilModule.hpp:499
Opm::OutputBlackOilModule::finalizeFluxData
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition OutputBlackoilModule.hpp:491
fvbaseproperties.hh
Declare the properties used by the infrastructure code of the finite volume discretizations.
Opm
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:43
Opm::GetPropType
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition propertysystem.hh:233
Opm::moduleVersionName
std::string moduleVersionName()
Return the version name of the module, for example "2015.10" (for a release branch) or "2016....
Definition moduleVersion.cpp:34
Opm::getPropValue
constexpr auto getPropValue()
get the value data member of a property
Definition propertysystem.hh:240
parametersystem.hpp
This file provides the infrastructure to retrieve run-time parameters.
Opm::Parameters::Get
auto Get(bool errorIfNotRegistered=true)
Retrieve a runtime parameter.
Definition parametersystem.hpp:187
propertysystem.hh
The Opm property system, traits with inheritance.
Opm::detail::BlockExtractor::Context
Context passed to element extractor functions.
Definition OutputExtractor.hpp:206
Opm::detail::BlockExtractor::PhaseEntry
Definition OutputExtractor.hpp:235
Opm::detail::BlockExtractor::ScalarEntry
Definition OutputExtractor.hpp:226
Opm::detail::BlockExtractor
Wrapping struct holding types used for block-level data extraction.
Definition OutputExtractor.hpp:193
Opm::detail::BlockExtractor::ExecMap
std::unordered_map< int, std::vector< Exec > > ExecMap
A map of extraction executors, keyed by cartesian cell index.
Definition OutputExtractor.hpp:260
Opm::detail::BlockExtractor::Entry
std::variant< ScalarEntry, PhaseEntry > Entry
Descriptor for extractors.
Definition OutputExtractor.hpp:245
Opm::detail::BlockExtractor::setupExecMap
static ExecMap setupExecMap(std::map< std::pair< std::string, int >, double > &blockData, const std::array< Entry, size > &handlers)
Setup an extractor executor map from a map of evaluations to perform.
Definition OutputExtractor.hpp:264
Opm::detail::BlockExtractor::process
static void process(const std::vector< Exec > &blockExtractors, const Context &ectx)
Process a list of block extractors.
Definition OutputExtractor.hpp:367
Opm::detail::Extractor::Context
Context passed to extractor functions.
Definition OutputExtractor.hpp:74
Opm::detail::Extractor::Context::globalDofIdx
unsigned globalDofIdx
Global degree-of-freedom index.
Definition OutputExtractor.hpp:75
Opm::detail::Extractor::Entry
Descriptor for extractors.
Definition OutputExtractor.hpp:113
Opm::detail::Extractor::HysteresisParams
Struct holding hysteresis parameters.
Definition OutputExtractor.hpp:63
Opm::detail::Extractor::HysteresisParams::somin
Scalar somin
Min oil saturation.
Definition OutputExtractor.hpp:69
Opm::detail::Extractor::HysteresisParams::swmin
Scalar swmin
Min water saturation.
Definition OutputExtractor.hpp:66
Opm::detail::Extractor::HysteresisParams::swmax
Scalar swmax
Max water saturation.
Definition OutputExtractor.hpp:65
Opm::detail::Extractor::HysteresisParams::shmax
Scalar shmax
Max something.
Definition OutputExtractor.hpp:68
Opm::detail::Extractor::HysteresisParams::sgmax
Scalar sgmax
Max gas saturation.
Definition OutputExtractor.hpp:67
Opm::detail::Extractor::HysteresisParams::somax
Scalar somax
Max oil saturation.
Definition OutputExtractor.hpp:64
Opm::detail::Extractor::PhaseEntry
A phase buffer extractor descriptor.
Definition OutputExtractor.hpp:106
Opm::detail::Extractor::ScalarEntry
A scalar extractor descriptor.
Definition OutputExtractor.hpp:99
Opm::detail::Extractor
Wrapping struct holding types used for element-level data extraction.
Definition OutputExtractor.hpp:54
Opm::detail::Extractor::process
static void process(const Context &ectx, const std::vector< Entry > &extractors)
Process the given extractor entries.
Definition OutputExtractor.hpp:158
Opm::detail::Extractor::removeInactive
static std::vector< Entry > removeInactive(std::array< Entry, size > &input)
Obtain vector of active extractors from an array of extractors.
Definition OutputExtractor.hpp:120