27#ifndef OPM_OUTPUT_COMPOSITIONAL_MODULE_HPP
28#define OPM_OUTPUT_COMPOSITIONAL_MODULE_HPP
30#include <dune/grid/common/gridenums.hh>
34#include <opm/common/Exceptions.hpp>
35#include <opm/common/ErrorMacros.hpp>
36#include <opm/common/TimingMacros.hpp>
37#include <opm/common/OpmLog/OpmLog.hpp>
39#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
41#include <opm/material/common/Valgrind.hpp>
69template <
class TypeTag>
70class EcfvDiscretization;
78template <
class TypeTag>
90 enum { numPhases = FluidSystem::numPhases };
91 enum { numComponents = FluidSystem::numComponents };
92 enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
93 enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
94 enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
103 template <
class CollectDataToIORankType>
105 const SummaryConfig& smryCfg,
106 const CollectDataToIORankType& collectToIORank)
107 :
BaseType(simulator.vanguard().eclState(),
108 simulator.vanguard().schedule(),
110 simulator.vanguard().summaryState(),
112 [this](const int idx)
113 {
return simulator_.problem().eclWriter().collectOnIORank().localIdxToGlobalIdx(idx); },
114 [&collectToIORank](
const int idx)
115 {
return collectToIORank.isCartIdxOnThisRank(idx); },
116 simulator.vanguard().grid().comm(),
117 getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::FullyImplicitThermal,
118 getPropValue<TypeTag, Properties::EnergyModuleType>() == EnergyModules::ConstantTemperature,
119 getPropValue<TypeTag, Properties::EnableMech>(),
120 getPropValue<TypeTag, Properties::EnableSolvent>(),
121 getPropValue<TypeTag, Properties::EnablePolymer>(),
122 getPropValue<TypeTag, Properties::EnableFoam>(),
123 getPropValue<TypeTag, Properties::EnableBrine>(),
124 getPropValue<TypeTag, Properties::EnableSaltPrecipitation>(),
125 getPropValue<TypeTag, Properties::EnableExtbo>(),
126 getPropValue<TypeTag, Properties::EnableBioeffects>(),
127 getPropValue<TypeTag, Properties::EnableGeochemistry>())
128 , simulator_(simulator)
130 for (
auto& region_pair : this->
regions_) {
131 this->createLocalRegion_(region_pair.second);
134 auto isCartIdxOnThisRank = [&collectToIORank](
const int idx) {
135 return collectToIORank.isCartIdxOnThisRank(idx);
145 if (! collectToIORank.isParallel()) {
151 if (! Parameters::Get<Parameters::OwnerCellsFirst>()) {
152 const std::string msg =
"The output code does not support --owner-cells-first=false.";
153 if (collectToIORank.isIORank()) {
156 OPM_THROW_NOLOG(std::runtime_error, msg);
159 if (smryCfg.match(
"[FB]PP[OGW]") || smryCfg.match(
"RPP[OGW]*")) {
160 auto rset = this->
eclState_.fieldProps().fip_regions();
161 rset.push_back(
"PVTNUM");
167 .emplace(this->simulator_.gridView().comm(),
168 FluidSystem::numPhases, rset,
169 [fp = std::cref(this->eclState_.fieldProps())]
170 (
const std::string& rsetName) ->
decltype(
auto)
171 { return fp.get().get_int(rsetName); });
181 const unsigned reportStepNum,
184 const bool isRestart)
190 auto rstKeywords = this->
schedule_.rst_keywords(reportStepNum);
191 this->compC_.allocate(bufferSize, rstKeywords);
193 this->
doAllocBuffers(bufferSize, reportStepNum, substep, log, isRestart,
196 std::move(rstKeywords));
201 this->compC_.outputRestart(sol, this->
saturation_[oilPhaseIdx]);
207 .gasDensity =
"DENG",
208 .waterDensity =
"DENW",
209 .oilViscosity =
"VOIL",
210 .gasViscosity =
"VGAS",
211 .waterViscosity =
"VWAT",
215 using M = UnitSystem::measure;
217 relativePermeability_[oilPhaseIdx], oilPhaseIdx);
219 relativePermeability_[gasPhaseIdx], gasPhaseIdx);
220 if constexpr (numPhases > 2) {
222 relativePermeability_[waterPhaseIdx], waterPhaseIdx);
227 const std::size_t reportStepNum,
229 boost::posix_time::ptime currentDate,
233 if (comm.rank() != 0) {
237 std::unique_ptr<FIPConfig> fipSched;
238 if (reportStepNum > 0) {
239 const auto& rpt = this->
schedule_[reportStepNum - 1].rpt_config.get();
240 fipSched = std::make_unique<FIPConfig>(rpt);
243 const FIPConfig& fipc = reportStepNum == 0
244 ? this->
eclState_.getEclipseConfig().fip()
248 this->
logOutput_.timeStamp(
"BALANCE", elapsed, reportStepNum, currentDate);
251 this->
logOutput_.fip(inplace, initial_inplace,
"");
253 if (fipc.output(FIPConfig::OutputField::FIPNUM)) {
254 this->
logOutput_.fip(inplace, initial_inplace,
"FIPNUM");
256 if (fipc.output(FIPConfig::OutputField::RESV)) {
261 if (fipc.output(FIPConfig::OutputField::FIP)) {
262 for (
const auto& reg : this->regions_) {
263 if (reg.first !=
"FIPNUM") {
264 std::ostringstream ss;
265 ss <<
"BAL" << reg.first.substr(3);
266 this->
logOutput_.timeStamp(ss.str(), elapsed, reportStepNum, currentDate);
267 this->
logOutput_.fip(inplace, initial_inplace, reg.first);
269 if (fipc.output(FIPConfig::OutputField::RESV)) {
282 if (comm.rank() != 0) {
286 if ((reportStepNum == 0) && (!substep) &&
287 (this->
schedule_.initialReportConfiguration().has_value()) &&
288 (this->schedule_.initialReportConfiguration()->contains(
"CSVFIP"))) {
290 std::ostringstream csv_stream;
296 this->
logOutput_.fip_csv(csv_stream, initial_inplace,
"FIPNUM");
298 for (
const auto& reg : this->regions_) {
299 if (reg.first !=
"FIPNUM") {
300 this->
logOutput_.fip_csv(csv_stream, initial_inplace, reg.first);
304 const IOConfig& io = this->
eclState_.getIOConfig();
305 auto csv_fname = io.getOutputDir() +
"/" + io.getBaseName() +
".CSV";
307 std::ofstream outputFile(csv_fname);
308 outputFile << csv_stream.str();
321 auto extractors = std::array{
323 [](
const unsigned phase,
const ExtractContext& ectx)
324 {
return getValue(ectx.fs.saturation(phase)); }}
327 [](
const ExtractContext& ectx)
329 if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
331 return getValue(ectx.fs.pressure(oilPhaseIdx));
333 else if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
335 return getValue(ectx.fs.pressure(gasPhaseIdx));
339 return getValue(ectx.fs.pressure(waterPhaseIdx));
344 [](
const ExtractContext& ectx)
345 {
return getValue(ectx.fs.temperature(oilPhaseIdx)); }}
347 Entry{[&compC = this->compC_](
const ExtractContext& ectx)
349 compC.assignMoleFractions(ectx.globalDofIdx,
350 [&fs = ectx.fs](
const unsigned compIdx)
351 {
return getValue(fs.moleFraction(compIdx)); });
352 }, this->compC_.moleFractionsAllocated()
357 Entry{[&compC = this->compC_](
const ExtractContext& ectx)
360 getValue(ectx.fs.saturation(gasPhaseIdx)) > Scalar{0};
361 compC.assignGasFractions(ectx.globalDofIdx,
362 [&fs = ectx.fs, hasGas](
const unsigned compIdx)
365 ? getValue(fs.moleFraction(gasPhaseIdx, compIdx))
368 }, FluidSystem::phaseIsActive(gasPhaseIdx) &&
369 this->compC_.gasFractionsAllocated()
371 Entry{[&compC = this->compC_](
const ExtractContext& ectx)
374 getValue(ectx.fs.saturation(oilPhaseIdx)) > Scalar{0};
375 compC.assignOilFractions(ectx.globalDofIdx,
376 [&fs = ectx.fs, hasOil](
const unsigned compIdx)
379 ? getValue(fs.moleFraction(oilPhaseIdx, compIdx))
382 }, FluidSystem::phaseIsActive(oilPhaseIdx) &&
383 this->compC_.oilFractionsAllocated()
385 Entry{[&compC = this->compC_](
const ExtractContext& ectx)
387 compC.assignPhasePressures(ectx.globalDofIdx,
388 getValue(ectx.fs.pressure(oilPhaseIdx)),
389 getValue(ectx.fs.pressure(gasPhaseIdx)));
390 }, this->compC_.phasePressuresAllocated()
393 Entry{[&compC = this->compC_](
const ExtractContext& ectx)
395 const Scalar liquidFraction = getValue(ectx.fs.L());
396 compC.assignVaporFraction(ectx.globalDofIdx,
397 std::clamp(Scalar{1} - liquidFraction,
398 Scalar{0}, Scalar{1}));
399 }, this->compC_.vaporFractionAllocated()
402 Entry{PhaseEntry{&this->relativePermeability_,
403 [](
const unsigned phaseIdx,
const ExtractContext& ectx)
404 {
return getValue(ectx.intQuants.relativePermeability(phaseIdx)); }}
407 [](
const unsigned phaseIdx,
const ExtractContext& ectx)
409 return getValue(ectx.fs.saturation(phaseIdx)) > 0.0
410 ? getValue(ectx.fs.density(phaseIdx))
415 [](
const unsigned phaseIdx,
const ExtractContext& ectx)
417 return getValue(ectx.fs.saturation(phaseIdx)) > 0.0
418 ? getValue(ectx.fs.viscosity(phaseIdx))
424 this->extractors_ = Extractor::removeInactive(extractors);
429 { this->extractors_.clear(); }
437 OPM_TIMEBLOCK_LOCAL(processElement, Subsystem::Output);
443 for (
unsigned dofIdx = 0; dofIdx < elemCtx.numPrimaryDof(0); ++dofIdx) {
444 const auto& intQuants = elemCtx.intensiveQuantities(dofIdx, 0);
445 const auto& fs = intQuants.fluidState();
448 elemCtx.globalSpaceIndex(dofIdx, 0),
456 Extractor::process(ectx, extractors_);
462 OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
469 OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
502 template <
class ActiveIndex,
class CartesianIndex>
517 this->interRegionFlows_.clear();
525 this->interRegionFlows_.compress();
533 return this->interRegionFlows_;
537 const IntensiveQuantities& ,
546 const unsigned bufferSize)
override
550 const auto named = std::array{
551 std::pair{
static_cast<unsigned>(oilPhaseIdx), std::string_view{
"KRO"}},
552 std::pair{
static_cast<unsigned>(gasPhaseIdx), std::string_view{
"KRG"}},
553 std::pair{
static_cast<unsigned>(waterPhaseIdx), std::string_view{
"KRW"}},
555 for (
const auto& [phase, kw] : named) {
556 if (phase >= numPhases || !FluidSystem::phaseIsActive(phase)) {
559 BaseType::allocBufferIfRequested(rstKeywords, bufferSize,
560 relativePermeability_[phase], kw,
true);
565 using ScalarBuffer =
typename BaseType::ScalarBuffer;
566 std::array<ScalarBuffer, numPhases> relativePermeability_;
568 bool isDefunctParallelWell(
const std::string& wname)
const override
570 if (simulator_.gridView().comm().size() == 1)
572 const auto& parallelWells = simulator_.vanguard().parallelWells();
573 std::pair<std::string, bool> value {wname,
true};
574 auto candidate = std::lower_bound(parallelWells.begin(), parallelWells.end(), value);
575 return candidate == parallelWells.end() || *candidate != value;
578 bool isOwnedByCurrentRank(
const std::string& wname)
const override
583 return ! this->isDefunctParallelWell(wname);
586 bool isOnCurrentRank(
const std::string& wname)
const override
591 return ! this->isDefunctParallelWell(wname);
594 void createLocalRegion_(std::vector<int>& region)
596 std::size_t elemIdx = 0;
597 for (
const auto& elem : elements(simulator_.gridView())) {
598 if (elem.partitionType() != Dune::InteriorEntity) {
606 const Simulator& simulator_;
607 CompositionalContainer<FluidSystem> compC_;
608 std::vector<typename Extractor::Entry> extractors_;
Restart-output buffers specific to compositional simulations.
Common output functionality shared by simulator formulations.
Declares the properties required by the black oil model.
The base class for the element-centered finite-volume discretization scheme.
Definition: ecfvdiscretization.hh:160
Definition: GenericOutputModule.hpp:83
const Schedule & schedule_
Definition: GenericOutputModule.hpp:446
bool forceDisableFipOutput_
Definition: GenericOutputModule.hpp:467
void doAllocBuffers(unsigned bufferSize, unsigned reportStepNum, const bool substep, const bool log, const bool isRestart, const EclHysteresisConfig *hysteresisConfig, unsigned numOutputNnc=0, std::map< std::string, int > rstKeywords={})
void setupBlockData(std::function< bool(int)> isCartIdxOnThisRank)
ScalarBuffer temperature_
Definition: GenericOutputModule.hpp:487
std::optional< RegionPhasePoreVolAverage > regionAvgDensity_
Definition: GenericOutputModule.hpp:556
std::array< ScalarBuffer, numPhases > viscosity_
Definition: GenericOutputModule.hpp:528
void setupLgrBlockData(const std::map< std::string, int > &lgrNameToLevel, const std::function< bool(int, int)> &isLgrCellOnThisRank)
void assignBuffer(data::Solution &sol, std::string_view name, UnitSystem::measure measure, std::vector< Scalar > &buffer)
std::unordered_map< std::string, std::vector< int > > regions_
Definition: GenericOutputModule.hpp:472
LogOutputHelper< Scalar > logOutput_
Definition: GenericOutputModule.hpp:452
void assignPhaseProperties(data::Solution &sol, const PhasePropertyNames &names)
Move the phase density and viscosity buffers to sol under names.
std::array< ScalarBuffer, numPhases > density_
Definition: GenericOutputModule.hpp:527
std::array< ScalarBuffer, numPhases > saturation_
Definition: GenericOutputModule.hpp:526
const EclipseState & eclState_
Definition: GenericOutputModule.hpp:445
virtual void assignToSolution(data::Solution &sol)
Move all buffers to data::Solution.
const Inplace * initialInplace() const
Definition: GenericOutputModule.hpp:266
static void registerParameters()
Register all run-time parameters for the Vtk output module.
ScalarBuffer fluidPressure_
Definition: GenericOutputModule.hpp:486
Inter-region flow accumulation maps for all region definition arrays.
Definition: InterRegFlows.hpp:179
Output module for compositional-model results written in ECL binary format.
Definition: OutputCompositionalModule.hpp:80
void processElementFlows(const ElementContext &)
Definition: OutputCompositionalModule.hpp:460
void clearExtractors()
Clear list of active element-level data extractors.
Definition: OutputCompositionalModule.hpp:428
static void registerParameters()
Definition: OutputCompositionalModule.hpp:97
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition: OutputCompositionalModule.hpp:513
void setupExtractors(const bool, const std::size_t)
Setup list of active element-level data extractors.
Definition: OutputCompositionalModule.hpp:313
void allocFormulationBuffers(std::map< std::string, int > &rstKeywords, const unsigned bufferSize) override
Allocate compositional relative-permeability buffers.
Definition: OutputCompositionalModule.hpp:545
void outputFipAndResvLogToCSV(const std::size_t reportStepNum, const bool substep, const Parallel::Communication &comm)
Definition: OutputCompositionalModule.hpp:278
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition: OutputCompositionalModule.hpp:523
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition: OutputCompositionalModule.hpp:435
OutputCompositionalModule(const Simulator &simulator, const SummaryConfig &smryCfg, const CollectDataToIORankType &collectToIORank)
Definition: OutputCompositionalModule.hpp:104
void assignToSolution(data::Solution &sol) override
Move all buffers to data::Solution.
Definition: OutputCompositionalModule.hpp:199
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: OutputCompositionalModule.hpp:180
void processElementBlockData(const ElementContext &)
Definition: OutputCompositionalModule.hpp:467
void processFluxes(const ElementContext &, ActiveIndex &&, CartesianIndex &&)
Capture connection fluxes, particularly to account for inter-region flows.
Definition: OutputCompositionalModule.hpp:503
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition: OutputCompositionalModule.hpp:531
void outputFipAndResvLog(const Inplace &inplace, const std::size_t reportStepNum, double elapsed, boost::posix_time::ptime currentDate, const bool substep, const Parallel::Communication &comm)
Definition: OutputCompositionalModule.hpp:226
void updateFluidInPlace(const unsigned, const IntensiveQuantities &, const double)
Definition: OutputCompositionalModule.hpp:536
Defines the common properties required by the porous medium multi-phase models.
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Definition: blackoilbioeffectsmodules.hh:45
std::string moduleVersionName()
typename Properties::Detail::GetPropImpl< TypeTag, Property >::type::type GetPropType
get the type alias defined in the property (equivalent to old macro GET_PROP_TYPE(....
Definition: propertysystem.hh:233
This file provides the infrastructure to retrieve run-time parameters.
The Opm property system, traits with inheritance.
Definition: GenericOutputModule.hpp:320
std::string_view oilDensity
Definition: GenericOutputModule.hpp:321
static void registerParameters()
Registers the parameters in parameter system.