Loading...
Searching...
No Matches
OutputCompositionalModule.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_COMPOSITIONAL_MODULE_HPP
#define OPM_OUTPUT_COMPOSITIONAL_MODULE_HPP
#include <dune/grid/common/gridenums.hh>
#include <opm/simulators/utils/moduleVersion.hpp>
#include <opm/common/Exceptions.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <opm/common/TimingMacros.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/input/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
#include <opm/material/common/Valgrind.hpp>
#include <opm/models/blackoil/blackoilproperties.hh>
#include <opm/models/common/multiphasebaseproperties.hh>
#include <opm/models/utils/parametersystem.hpp>
#include <opm/models/utils/propertysystem.hh>
#include <opm/simulators/flow/CompositionalContainer.hpp>
#include <opm/simulators/flow/FlowBaseVanguard.hpp>
#include <opm/simulators/flow/GenericOutputBlackoilModule.hpp>
#include <opm/simulators/flow/OutputExtractor.hpp>
#include <algorithm>
#include <cstddef>
#include <stdexcept>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>
namespace Opm {
// forward declaration
template <class TypeTag>
class EcfvDiscretization;
template <class TypeTag>
class OutputCompositionalModule : 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 ElementContext = GetPropType<TypeTag, Properties::ElementContext>;
using IntensiveQuantities = GetPropType<TypeTag, Properties::IntensiveQuantities>;
using FluidSystem = GetPropType<TypeTag, Properties::FluidSystem>;
using BaseType = GenericOutputBlackoilModule<FluidSystem>;
using Extractor = detail::Extractor<TypeTag>;
enum { numPhases = FluidSystem::numPhases };
enum { numComponents = FluidSystem::numComponents };
enum { oilPhaseIdx = FluidSystem::oilPhaseIdx };
enum { gasPhaseIdx = FluidSystem::gasPhaseIdx };
enum { waterPhaseIdx = FluidSystem::waterPhaseIdx };
public:
template <class CollectDataToIORankType>
OutputCompositionalModule(const Simulator& simulator,
const SummaryConfig& smryCfg,
const CollectDataToIORankType& collectToIORank)
: 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)
{
for (auto& region_pair : this->regions_) {
this->createLocalRegion_(region_pair.second);
}
auto isCartIdxOnThisRank = [&collectToIORank](const int idx) {
return collectToIORank.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 (collectToIORank.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;
}
auto rstKeywords = this->schedule_.rst_keywords(reportStepNum);
this->compC_.allocate(bufferSize, rstKeywords);
this->doAllocBuffers(bufferSize, reportStepNum, substep, log, isRestart,
/* hysteresisConfig = */ nullptr,
/* numOutputNnc =*/ 0,
std::move(rstKeywords));
}
void assignToSolution(data::Solution& sol)
{
this->compC_.outputRestart(sol, this->saturation_[oilPhaseIdx]);
BaseType::assignToSolution(sol);
}
void setupExtractors(const bool /*isSubStep*/,
const std::size_t /*reportStepNum*/)
{
using Entry = typename Extractor::Entry;
using ExtractContext = typename Extractor::Context;
using ScalarEntry = typename Extractor::ScalarEntry;
using PhaseEntry = typename Extractor::PhaseEntry;
auto extractors = std::array{
Entry{PhaseEntry{&this->saturation_,
[](const unsigned phase, const ExtractContext& ectx)
{ return getValue(ectx.fs.saturation(phase)); }}
},
Entry{ScalarEntry{&this->fluidPressure_,
[](const ExtractContext& 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->temperature_,
[](const ExtractContext& ectx)
{ return getValue(ectx.fs.temperature(oilPhaseIdx)); }}
},
Entry{[&compC = this->compC_](const ExtractContext& ectx)
{
compC.assignMoleFractions(ectx.globalDofIdx,
[&fs = ectx.fs](const unsigned compIdx)
{ return getValue(fs.moleFraction(compIdx)); });
if (FluidSystem::phaseIsActive(gasPhaseIdx)) {
compC.assignGasFractions(ectx.globalDofIdx,
[&fs = ectx.fs](const unsigned compIdx)
{ return getValue(fs.moleFraction(gasPhaseIdx, compIdx)); });
}
if (FluidSystem::phaseIsActive(oilPhaseIdx)) {
compC.assignOilFractions(ectx.globalDofIdx,
[&fs = ectx.fs](const unsigned compIdx)
{ return getValue(fs.moleFraction(oilPhaseIdx, compIdx)); });
}
}, this->compC_.allocated()
},
};
this->extractors_ = Extractor::removeInactive(extractors);
}
void clearExtractors()
{ this->extractors_.clear(); }
void processElement(const ElementContext& elemCtx)
{
OPM_TIMEBLOCK_LOCAL(processElement, Subsystem::Output);
if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value) {
return;
}
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),
0, // elemCtx.primaryVars(dofIdx, /*timeIdx=*/0).pvtRegionIndex(),
elemCtx.simulator().episodeIndex(),
fs,
intQuants,
hysterParams
};
Extractor::process(ectx, extractors_);
}
}
void processElementFlows(const ElementContext& /* elemCtx */)
{
OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
if (!std::is_same_v<Discretization, EcfvDiscretization<TypeTag>>)
return;
}
void processElementBlockData(const ElementContext& /* elemCtx */)
{
OPM_TIMEBLOCK_LOCAL(processElementBlockData, Subsystem::Output);
if (!std::is_same<Discretization, EcfvDiscretization<TypeTag>>::value)
return;
}
template <class ActiveIndex, class CartesianIndex>
void processFluxes(const ElementContext& /* elemCtx */,
ActiveIndex&& /* activeIndex*/,
CartesianIndex&& /* cartesianIndex */)
{
}
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_;
}
void updateFluidInPlace(const unsigned /* globalDofIdx */,
const IntensiveQuantities& /* intQuants */,
const double /* totVolume */)
{
// this->updateFluidInPlace_(globalDofIdx, intQuants, totVolume);
}
private:
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
{
// Note: This statement is not correct for distributed wells and
// will need additional logic once those are supported for
// compositional flows.
return ! this->isDefunctParallelWell(wname);
}
bool isOnCurrentRank(const std::string& wname) const override
{
// Note: This statement is not correct for distributed wells and
// will need additional logic once those are supported for
// compositional flows.
return ! this->isDefunctParallelWell(wname);
}
void createLocalRegion_(std::vector<int>& region)
{
std::size_t elemIdx = 0;
for (const auto& elem : elements(simulator_.gridView())) {
if (elem.partitionType() != Dune::InteriorEntity) {
region[elemIdx] = 0;
}
++elemIdx;
}
}
const Simulator& simulator_;
CompositionalContainer<FluidSystem> compC_;
std::vector<typename Extractor::Entry> extractors_;
};
} // namespace Opm
#endif // OPM_OUTPUT_COMPOSITIONAL_MODULE_HPP
CompositionalContainer.hpp
Output module for the results black oil model writing in ECL binary format.
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::EcfvDiscretization
The base class for the element-centered finite-volume discretization scheme.
Definition ecfvdiscretization.hh:160
Opm::GenericOutputBlackoilModule::assignToSolution
void assignToSolution(data::Solution &sol)
Move all buffers to data::Solution.
Definition GenericOutputBlackoilModule.cpp:310
Opm::InterRegFlowMap
Inter-region flow accumulation maps for all region definition arrays.
Definition InterRegFlows.hpp:179
Opm::OutputCompositionalModule::clearExtractors
void clearExtractors()
Clear list of active element-level data extractors.
Definition OutputCompositionalModule.hpp:241
Opm::OutputCompositionalModule::initializeFluxData
void initializeFluxData()
Prepare for capturing connection fluxes, particularly to account for inter-region flows.
Definition OutputCompositionalModule.hpp:326
Opm::OutputCompositionalModule::setupExtractors
void setupExtractors(const bool, const std::size_t)
Setup list of active element-level data extractors.
Definition OutputCompositionalModule.hpp:182
Opm::OutputCompositionalModule::finalizeFluxData
void finalizeFluxData()
Finalize capturing connection fluxes.
Definition OutputCompositionalModule.hpp:336
Opm::OutputCompositionalModule::processElement
void processElement(const ElementContext &elemCtx)
Modify the internal buffers according to the intensive quanties relevant for an element.
Definition OutputCompositionalModule.hpp:248
Opm::OutputCompositionalModule::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 OutputCompositionalModule.hpp:156
Opm::OutputCompositionalModule::processFluxes
void processFluxes(const ElementContext &, ActiveIndex &&, CartesianIndex &&)
Capture connection fluxes, particularly to account for inter-region flows.
Definition OutputCompositionalModule.hpp:316
Opm::OutputCompositionalModule::getInterRegFlows
const InterRegFlowMap & getInterRegFlows() const
Get read-only access to collection of inter-region flows.
Definition OutputCompositionalModule.hpp:344
multiphasebaseproperties.hh
Defines the common properties required by the porous medium multi-phase models.
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::Extractor::Context
Context passed to extractor functions.
Definition OutputExtractor.hpp:74
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::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