Merge pull request #1047 from dr-robertk/PR/cleanup-output-writers

[WIP] Unify output writers to avoid code duplication.
This commit is contained in:
Atgeirr Flø Rasmussen 2017-02-14 15:27:22 +01:00 committed by GitHub
commit 0ebff11099
13 changed files with 427 additions and 1206 deletions

View File

@ -35,7 +35,6 @@ list (APPEND MAIN_SOURCE_FILES
opm/autodiff/ImpesTPFAAD.cpp
opm/autodiff/moduleVersion.cpp
opm/autodiff/SimulatorFullyImplicitBlackoilOutput.cpp
opm/autodiff/SimulatorFullyImplicitBlackoilOutputEbos.cpp
opm/autodiff/SimulatorIncompTwophaseAd.cpp
opm/autodiff/TransportSolverTwophaseAd.cpp
opm/autodiff/BlackoilPropsAdFromDeck.cpp
@ -209,7 +208,6 @@ list (APPEND PUBLIC_HEADER_FILES
opm/autodiff/SimulatorFullyImplicitBlackoilSolvent_impl.hpp
opm/autodiff/SimulatorFullyImplicitBlackoilMultiSegment.hpp
opm/autodiff/SimulatorFullyImplicitBlackoilMultiSegment_impl.hpp
opm/autodiff/SimulatorFullyImplicitBlackoilOutputEbos.hpp
opm/autodiff/SimulatorIncompTwophaseAd.hpp
opm/autodiff/SimulatorSequentialBlackoil.hpp
opm/autodiff/TransportSolverTwophaseAd.hpp

View File

@ -39,6 +39,8 @@
#include <opm/simulators/timestepping/SimulatorTimerInterface.hpp>
#include <opm/core/simulator/SimulatorReport.hpp>
#include <opm/common/data/SimulationDataContainer.hpp>
#include <array>
struct Wells;
@ -50,7 +52,6 @@ namespace Opm {
class RockCompressibility;
class NewtonIterationBlackoilInterface;
class VFPProperties;
class SimulationDataContainer;
/// Traits to encapsulate the types used by classes using or
/// extending this model. Forward declared here, must be
@ -92,24 +93,21 @@ namespace Opm {
ADB mob; // Phase mobility (per cell)
};
struct SimulatorData {
struct SimulatorData : public Opm::FIPDataEnums {
SimulatorData(int num_phases);
enum FipId {
FIP_AQUA = Opm::Water,
FIP_LIQUID = Opm::Oil,
FIP_VAPOUR = Opm::Gas,
FIP_DISSOLVED_GAS = 3,
FIP_VAPORIZED_OIL = 4,
FIP_PV = 5, //< Pore volume
FIP_WEIGHTED_PRESSURE = 6
};
using Opm::FIPDataEnums :: FipId ;
using Opm::FIPDataEnums :: fipValues ;
std::vector<ReservoirResidualQuant> rq;
ADB rsSat; // Saturated gas-oil ratio
ADB rvSat; // Saturated oil-gas ratio
std::array<V, 7> fip;
std::array<V, fipValues> fip;
};
typedef Opm::FIPData FIPDataType;
typedef typename ModelTraits<Implementation>::ReservoirState ReservoirState;
typedef typename ModelTraits<Implementation>::WellState WellState;
typedef typename ModelTraits<Implementation>::ModelParameters ModelParameters;
@ -264,6 +262,11 @@ namespace Opm {
return sd_;
}
/// Return fluid-in-place data (for output functionality)
FIPDataType getFIPData() const {
return FIPDataType( sd_.fip );
}
/// Compute fluid in place.
/// \param[in] ReservoirState
/// \param[in] FIPNUM for active cells not global cells.

View File

@ -51,7 +51,6 @@
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/Tables/TableManager.hpp>
#include <opm/common/data/SimulationDataContainer.hpp>
#include <dune/common/timer.hh>
@ -389,7 +388,6 @@ typedef Eigen::Array<double,
template <class Grid, class WellModel, class Implementation>
int
BlackoilModelBase<Grid, WellModel, Implementation>::
@ -445,7 +443,6 @@ typedef Eigen::Array<double,
template <class Grid, class WellModel, class Implementation>
BlackoilModelBase<Grid, WellModel, Implementation>::
ReservoirResidualQuant::ReservoirResidualQuant()

View File

@ -143,19 +143,7 @@ namespace Opm {
using RateConverterType = RateConverter::
SurfaceToReservoirVoidage<BlackoilPropsAdFromDeck::FluidSystem, std::vector<int> >;
struct FIPData {
enum FipId {
FIP_AQUA = Opm::Water,
FIP_LIQUID = Opm::Oil,
FIP_VAPOUR = Opm::Gas,
FIP_DISSOLVED_GAS = 3,
FIP_VAPORIZED_OIL = 4,
FIP_PV = 5, //< Pore volume
FIP_WEIGHTED_PRESSURE = 6
};
static const int fipValues = FIP_WEIGHTED_PRESSURE + 1 ;
std::array<std::vector<double>, fipValues> fip;
};
typedef Opm::FIPData FIPDataType;
// --------- Public methods ---------
@ -1022,7 +1010,7 @@ namespace Opm {
const auto& pv = geo_.poreVolume();
const int maxnp = Opm::BlackoilPhases::MaxNumPhases;
for (int i = 0; i<FIPData::fipValues; i++) {
for (int i = 0; i<FIPDataType::fipValues; i++) {
fip_.fip[i].resize(nc,0.0);
}
@ -1051,14 +1039,14 @@ namespace Opm {
if (active_[ Oil ] && active_[ Gas ]) {
// Account for gas dissolved in oil and vaporized oil
fip_.fip[FIPData::FIP_DISSOLVED_GAS][cellIdx] = fs.Rs().value() * fip_.fip[FIPData::FIP_LIQUID][cellIdx];
fip_.fip[FIPData::FIP_VAPORIZED_OIL][cellIdx] = fs.Rv().value() * fip_.fip[FIPData::FIP_VAPOUR][cellIdx];
fip_.fip[FIPDataType::FIP_DISSOLVED_GAS][cellIdx] = fs.Rs().value() * fip_.fip[FIPDataType::FIP_LIQUID][cellIdx];
fip_.fip[FIPDataType::FIP_VAPORIZED_OIL][cellIdx] = fs.Rv().value() * fip_.fip[FIPDataType::FIP_VAPOUR][cellIdx];
}
}
// For a parallel run this is just a local maximum and needs to be updated later
int dims = *std::max_element(fipnum.begin(), fipnum.end());
std::vector<std::vector<double>> values(dims, std::vector<double>(FIPData::fipValues,0.0));
std::vector<std::vector<double>> values(dims, std::vector<double>(FIPDataType::fipValues,0.0));
std::vector<double> hcpv(dims, 0.0);
std::vector<double> pres(dims, 0.0);
@ -1082,8 +1070,8 @@ namespace Opm {
for (int c = 0; c < nc; ++c) {
const int region = fipnum[c] - 1;
if (region != -1) {
values[region][FIPData::FIP_DISSOLVED_GAS] += fip_.fip[FIPData::FIP_DISSOLVED_GAS][c];
values[region][FIPData::FIP_VAPORIZED_OIL] += fip_.fip[FIPData::FIP_VAPORIZED_OIL][c];
values[region][FIPDataType::FIP_DISSOLVED_GAS] += fip_.fip[FIPDataType::FIP_DISSOLVED_GAS][c];
values[region][FIPDataType::FIP_VAPORIZED_OIL] += fip_.fip[FIPDataType::FIP_VAPORIZED_OIL][c];
}
}
}
@ -1102,7 +1090,7 @@ namespace Opm {
const int region = fipnum[c] - 1;
if (region != -1) {
fip_.fip[FIPData::FIP_PV][c] = pv[c];
fip_.fip[FIPDataType::FIP_PV][c] = pv[c];
const auto& intQuants = *ebosSimulator_.model().cachedIntensiveQuantities(c, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const double hydrocarbon = fs.saturation(FluidSystem::oilPhaseIdx).value() + fs.saturation(FluidSystem::gasPhaseIdx).value();
@ -1110,13 +1098,13 @@ namespace Opm {
//Compute hydrocarbon pore volume weighted average pressure.
//If we have no hydrocarbon in region, use pore volume weighted average pressure instead
if (hcpv[region] != 0) {
fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c] = pv[c] * fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbon / hcpv[region];
fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c] = pv[c] * fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbon / hcpv[region];
} else {
fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c] = pres[region] / pv[c];
fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c] = pres[region] / pv[c];
}
values[region][FIPData::FIP_PV] += fip_.fip[FIPData::FIP_PV][c];
values[region][FIPData::FIP_WEIGHTED_PRESSURE] += fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c];
values[region][FIPDataType::FIP_PV] += fip_.fip[FIPDataType::FIP_PV][c];
values[region][FIPDataType::FIP_WEIGHTED_PRESSURE] += fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c];
}
}
}
@ -1131,7 +1119,7 @@ namespace Opm {
auto comm = pinfo.communicator();
// Compute the global dims value and resize values accordingly.
dims = comm.max(dims);
values.resize(dims, std::vector<double>(FIPData::fipValues,0.0));
values.resize(dims, std::vector<double>(FIPDataType::fipValues,0.0));
//Accumulate phases for each region
for (int phase = 0; phase < maxnp; ++phase) {
@ -1148,8 +1136,8 @@ namespace Opm {
for (int c = 0; c < nc; ++c) {
const int region = fipnum[c] - 1;
if (region != -1 && mask[c]) {
values[region][FIPData::FIP_DISSOLVED_GAS] += fip_.fip[FIPData::FIP_DISSOLVED_GAS][c];
values[region][FIPData::FIP_VAPORIZED_OIL] += fip_.fip[FIPData::FIP_VAPORIZED_OIL][c];
values[region][FIPDataType::FIP_DISSOLVED_GAS] += fip_.fip[FIPDataType::FIP_DISSOLVED_GAS][c];
values[region][FIPDataType::FIP_VAPORIZED_OIL] += fip_.fip[FIPDataType::FIP_VAPORIZED_OIL][c];
}
}
}
@ -1174,19 +1162,19 @@ namespace Opm {
for (int c = 0; c < nc; ++c) {
const int region = fipnum[c] - 1;
if (region != -1 && mask[c]) {
fip_.fip[FIPData::FIP_PV][c] = pv[c];
fip_.fip[FIPDataType::FIP_PV][c] = pv[c];
const auto& intQuants = *ebosSimulator_.model().cachedIntensiveQuantities(c, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const double hydrocarbon = fs.saturation(FluidSystem::oilPhaseIdx).value() + fs.saturation(FluidSystem::gasPhaseIdx).value();
if (hcpv[region] != 0) {
fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c] = pv[c] * fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbon / hcpv[region];
fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c] = pv[c] * fs.pressure(FluidSystem::oilPhaseIdx).value() * hydrocarbon / hcpv[region];
} else {
fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c] = pres[region] / pv[c];
fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c] = pres[region] / pv[c];
}
values[region][FIPData::FIP_PV] += fip_.fip[FIPData::FIP_PV][c];
values[region][FIPData::FIP_WEIGHTED_PRESSURE] += fip_.fip[FIPData::FIP_WEIGHTED_PRESSURE][c];
values[region][FIPDataType::FIP_PV] += fip_.fip[FIPDataType::FIP_PV][c];
values[region][FIPDataType::FIP_WEIGHTED_PRESSURE] += fip_.fip[FIPDataType::FIP_WEIGHTED_PRESSURE][c];
}
}
@ -1206,7 +1194,131 @@ namespace Opm {
return values;
}
const FIPData& getFIPData() const {
SimulationDataContainer getSimulatorData () const
{
typedef std::vector<double> VectorType;
const auto& ebosModel = ebosSimulator().model();
const auto& phaseUsage = fluid_.phaseUsage();
// extract everything which can possibly be written to disk
const int numCells = ebosModel.numGridDof();
const int num_phases = numPhases();
SimulationDataContainer simData( numCells, 0, num_phases );
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
const int aqua_pos = phaseUsage.phase_pos[ Opm::PhaseUsage::Aqua ];
const int liquid_pos = phaseUsage.phase_pos[ Opm::PhaseUsage::Liquid ];
const int vapour_pos = phaseUsage.phase_pos[ Opm::PhaseUsage::Vapour ];
VectorType zero;
VectorType& pressureOil = simData.pressure();
VectorType& temperature = simData.temperature();
VectorType& saturation = simData.saturation();
// WATER
if( aqua_active ) {
simData.registerCellData("1OVERBW", 1 );
simData.registerCellData("WAT_DEN", 1 );
simData.registerCellData("WAT_VISC", 1 );
simData.registerCellData("WATKR", 1 );
}
VectorType& bWater = aqua_active ? simData.getCellData( "1OVERBW" ) : zero;
VectorType& rhoWater = aqua_active ? simData.getCellData( "WAT_DEN" ) : zero;
VectorType& muWater = aqua_active ? simData.getCellData( "WAT_VISC" ) : zero;
VectorType& krWater = aqua_active ? simData.getCellData( "WATKR" ) : zero;
// OIL
if( liquid_active ) {
simData.registerCellData("1OVERBO", 1 );
simData.registerCellData("OIL_DEN", 1 );
simData.registerCellData("OIL_VISC", 1 );
simData.registerCellData("OILKR", 1 );
}
VectorType& bOil = liquid_active ? simData.getCellData( "1OVERBO" ) : zero;
VectorType& rhoOil = liquid_active ? simData.getCellData( "OIL_DEN" ) : zero;
VectorType& muOil = liquid_active ? simData.getCellData( "OIL_VISC" ) : zero;
VectorType& krOil = liquid_active ? simData.getCellData( "OILKR" ) : zero;
// GAS
if( vapour_active ) {
simData.registerCellData("1OVERBG", 1 );
simData.registerCellData("GAS_DEN", 1 );
simData.registerCellData("GAS_VISC", 1 );
simData.registerCellData("GASKR", 1 );
}
VectorType& bGas = vapour_active ? simData.getCellData( "1OVERBG" ) : zero;
VectorType& rhoGas = vapour_active ? simData.getCellData( "GAS_DEN" ) : zero;
VectorType& muGas = vapour_active ? simData.getCellData( "GAS_VISC" ) : zero;
VectorType& krGas = vapour_active ? simData.getCellData( "GASKR" ) : zero;
simData.registerCellData( BlackoilState::GASOILRATIO, 1 );
simData.registerCellData( BlackoilState::RV, 1 );
simData.registerCellData("RSSAT", 1 );
simData.registerCellData("RVSAT", 1 );
VectorType& Rs = simData.getCellData( BlackoilState::GASOILRATIO );
VectorType& Rv = simData.getCellData( BlackoilState::RV );
VectorType& RsSat = simData.getCellData( "RSSAT" );
VectorType& RvSat = simData.getCellData( "RVSAT" );
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
const auto& intQuants = *ebosModel.cachedIntensiveQuantities(cellIdx, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
const int satIdx = cellIdx * num_phases;
pressureOil[cellIdx] = fs.pressure(FluidSystem::oilPhaseIdx).value();
temperature[cellIdx] = fs.temperature(FluidSystem::oilPhaseIdx).value();
if (aqua_active) {
saturation[ satIdx + aqua_pos ] = fs.saturation(FluidSystem::waterPhaseIdx).value();
bWater[cellIdx] = fs.invB(FluidSystem::waterPhaseIdx).value();
rhoWater[cellIdx] = fs.density(FluidSystem::waterPhaseIdx).value();
muWater[cellIdx] = fs.viscosity(FluidSystem::waterPhaseIdx).value();
krWater[cellIdx] = intQuants.relativePermeability(FluidSystem::waterPhaseIdx).value();
}
if (vapour_active) {
saturation[ satIdx + vapour_pos ] = fs.saturation(FluidSystem::gasPhaseIdx).value();
bGas[cellIdx] = fs.invB(FluidSystem::gasPhaseIdx).value();
rhoGas[cellIdx] = fs.density(FluidSystem::gasPhaseIdx).value();
muGas[cellIdx] = fs.viscosity(FluidSystem::gasPhaseIdx).value();
krGas[cellIdx] = intQuants.relativePermeability(FluidSystem::gasPhaseIdx).value();
Rs[cellIdx] = fs.Rs().value();
Rv[cellIdx] = fs.Rv().value();
RsSat[cellIdx] = FluidSystem::saturatedDissolutionFactor(fs,
FluidSystem::oilPhaseIdx,
intQuants.pvtRegionIndex(),
/*maxOilSaturation=*/1.0).value();
RvSat[cellIdx] = FluidSystem::saturatedDissolutionFactor(fs,
FluidSystem::gasPhaseIdx,
intQuants.pvtRegionIndex(),
/*maxOilSaturation=*/1.0).value();
}
if( liquid_active )
{
saturation[ satIdx + liquid_pos ] = fs.saturation(FluidSystem::oilPhaseIdx).value();
bOil[cellIdx] = fs.invB(FluidSystem::oilPhaseIdx).value();
rhoOil[cellIdx] = fs.density(FluidSystem::oilPhaseIdx).value();
muOil[cellIdx] = fs.viscosity(FluidSystem::oilPhaseIdx).value();
krOil[cellIdx] = intQuants.relativePermeability(FluidSystem::oilPhaseIdx).value();
}
}
return simData;
}
const FIPDataType& getFIPData() const {
return fip_;
}
@ -1254,7 +1366,7 @@ namespace Opm {
std::vector<std::vector<double>> residual_norms_history_;
double current_relaxation_;
BVector dx_old_;
mutable FIPData fip_;
mutable FIPDataType fip_;

View File

@ -22,6 +22,9 @@
#include <opm/core/props/BlackoilPhases.hpp>
#include <array>
#include <vector>
namespace Opm
{
@ -45,6 +48,44 @@ namespace Opm
Next // For extension.
};
struct FIPDataEnums {
enum FipId {
FIP_AQUA = Opm::Water,
FIP_LIQUID = Opm::Oil,
FIP_VAPOUR = Opm::Gas,
FIP_DISSOLVED_GAS = 3,
FIP_VAPORIZED_OIL = 4,
FIP_PV = 5, //< Pore volume
FIP_WEIGHTED_PRESSURE = 6
};
static const int fipValues = FIP_WEIGHTED_PRESSURE + 1 ;
};
class FIPData : public FIPDataEnums
{
public:
typedef std::vector<double> VectorType;
using FIPDataEnums :: FipId;
using FIPDataEnums :: fipValues ;
std::array< VectorType, fipValues> fip;
// default constructor
FIPData() {}
// initialize from array of Eigen vectors (or std::vectors)
template <class V>
explicit FIPData( const std::array< V, fipValues>& otherFip )
{
// copy fip vector from V to std::vector
for( int i=0; i<fipValues; ++i ) {
fip[ i ] = VectorType(otherFip[ i ].data(), otherFip[ i ].data() + otherFip[ i ].size() );
}
}
};
} // namespace Opm
#endif // OPM_BLACKOILMODELENUMS_HEADER_INCLUDED

View File

@ -56,6 +56,7 @@ namespace Opm {
typedef BlackoilPressureModel<Grid, WellModel> PressureModel;
typedef BlackoilTransportModel<Grid, WellModel> TransportModel;
typedef typename TransportModel::SimulatorData SimulatorData;
typedef typename TransportModel::FIPDataType FIPDataType;
/// Construct the model. It will retain references to the
/// arguments of this functions, and they are expected to
@ -276,6 +277,11 @@ namespace Opm {
return transport_solver_.model().getSimulatorData();
}
/// Return fluid-in-place data (for output functionality)
FIPDataType getFIPData() const {
return transport_solver_.model().getFIPData();
}
protected:
typedef NonlinearSolver<PressureModel> PressureSolver;

View File

@ -556,12 +556,11 @@ namespace Opm
// output_writer_
void setupOutputWriter()
{
const PhaseUsage pu = Opm::phaseUsageFromDeck(deck());
output_writer_.reset(new OutputWriter(grid(),
param_,
eclState(),
*eclIO_,
pu));
std::move( eclIO_ ),
Opm::phaseUsageFromDeck(deck())) );
}
// Run the simulator.

View File

@ -22,7 +22,8 @@
#define OPM_SIMULATORFULLYIMPLICITBLACKOILEBOS_HEADER_INCLUDED
//#include <opm/autodiff/SimulatorBase.hpp>
#include <opm/autodiff/SimulatorFullyImplicitBlackoilOutputEbos.hpp>
//#include <opm/autodiff/SimulatorFullyImplicitBlackoilOutputEbos.hpp>
#include <opm/autodiff/SimulatorFullyImplicitBlackoilOutput.hpp>
#include <opm/autodiff/IterationReport.hpp>
#include <opm/autodiff/NonlinearSolver.hpp>
#include <opm/autodiff/BlackoilModelEbos.hpp>
@ -59,7 +60,7 @@ public:
typedef WellStateFullyImplicitBlackoilDense WellState;
typedef BlackoilState ReservoirState;
typedef BlackoilOutputWriterEbos OutputWriter;
typedef BlackoilOutputWriter OutputWriter;
typedef BlackoilModelEbos Model;
typedef BlackoilModelParameters ModelParameters;
typedef NonlinearSolver<Model> Solver;
@ -98,7 +99,7 @@ public:
const bool has_disgas,
const bool has_vapoil,
const EclipseState& /* eclState */,
BlackoilOutputWriterEbos& output_writer,
OutputWriter& output_writer,
const std::unordered_set<std::string>& defunct_well_names)
: ebosSimulator_(ebosSimulator),
param_(param),

View File

@ -280,11 +280,11 @@ namespace Opm
const int desiredReportStep);
template <class Grid>
void initFromRestartFile(const PhaseUsage& phaseusage,
template <class Grid, class WellStateFullyImplicitBlackOel>
void initFromRestartFile(const PhaseUsage& phaseUsage,
const Grid& grid,
SimulationDataContainer& simulatorstate,
WellStateFullyImplicitBlackoil& wellstate);
WellStateFullyImplicitBlackOel& wellstate);
bool isRestart() const;
@ -349,7 +349,7 @@ namespace Opm
Opm::OpmLog::warning("Parallel Output Config",
"Velocity output for matlab is broken in parallel.");
}
if( parallelOutput_->isIORank() ) {
if ( output_matlab )
@ -395,13 +395,13 @@ namespace Opm
}
template <class Grid>
template <class Grid, class WellStateFullyImplicitBlackOel>
inline void
BlackoilOutputWriter::
initFromRestartFile( const PhaseUsage& phaseusage,
initFromRestartFile( const PhaseUsage& phaseUsage,
const Grid& grid,
SimulationDataContainer& simulatorstate,
WellStateFullyImplicitBlackoil& wellstate)
WellStateFullyImplicitBlackOel& wellstate)
{
std::map<std::string, UnitSystem::measure> solution_keys {{"PRESSURE" , UnitSystem::measure::pressure},
{"SWAT" , UnitSystem::measure::identity},
@ -430,11 +430,11 @@ namespace Opm
std::unordered_set<std::string>());
const Wells* wells = wellsmanager.c_wells();
wellstate.resize(wells, simulatorstate); //Resize for restart step
wellstate.resize(wells, simulatorstate, phaseUsage ); //Resize for restart step
auto state = eclIO_->loadRestart(solution_keys);
solutionToSim( state.first, phaseusage, simulatorstate );
wellsToState( state.second, phaseusage, wellstate );
solutionToSim( state.first, phaseUsage, simulatorstate );
wellsToState( state.second, phaseUsage, wellstate );
}
@ -443,50 +443,130 @@ namespace Opm
namespace detail {
/**
* Converts an ADB::V into a standard vector by copy
*/
inline std::vector<double> adbVToDoubleVector(const Opm::AutoDiffBlock<double>::V& adb_v) {
std::vector<double> vec(adb_v.data(), adb_v.data() + adb_v.size());
return vec;
template <class V>
void addToSimData( SimulationDataContainer& simData,
const std::string& name,
const V& vec )
{
typedef std::vector< double > OutputVectorType;
// get data map
auto& dataMap = simData.cellData();
// insert name,vector into data map
dataMap.insert( std::make_pair( name, OutputVectorType( vec.data(), vec.data() + vec.size() ) ) );
}
template <class Scalar>
void addToSimData( SimulationDataContainer& simData,
const std::string& name,
const AutoDiffBlock<Scalar>& adb )
{
// forward value of ADB to output
addToSimData( simData, name, adb.value() );
}
/**
* Converts an ADB into a standard vector by copy
*/
inline std::vector<double> adbToDoubleVector(const Opm::AutoDiffBlock<double>& adb) {
return adbVToDoubleVector(adb.value());
// this method basically converts all Eigen vectors to std::vectors
// stored in a SimulationDataContainer
template <class SimulatorData>
SimulationDataContainer
convertToSimulationDataContainer( const SimulatorData& sd,
const SimulationDataContainer& localState,
const Opm::PhaseUsage& phaseUsage )
{
// copy local state and then add missing data
SimulationDataContainer simData( localState );
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
const int aqua_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Aqua];
const int liquid_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Liquid];
const int vapour_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Vapour];
// WATER
if( aqua_active ) {
addToSimData( simData, "1OVERBW", sd.rq[aqua_idx].b );
addToSimData( simData, "WAT_DEN", sd.rq[aqua_idx].rho );
addToSimData( simData, "WAT_VISC", sd.rq[aqua_idx].mu );
addToSimData( simData, "WATKR", sd.rq[aqua_idx].kr );
}
// OIL
if( liquid_active ) {
addToSimData( simData, "1OVERBO", sd.rq[liquid_idx].b );
addToSimData( simData, "OIL_DEN", sd.rq[liquid_idx].rho );
addToSimData( simData, "OIL_VISC", sd.rq[liquid_idx].mu );
addToSimData( simData, "OILKR", sd.rq[liquid_idx].kr );
}
// GAS
if( vapour_active ) {
addToSimData( simData, "1OVERBG", sd.rq[vapour_idx].b );
addToSimData( simData, "GAS_DEN", sd.rq[vapour_idx].rho );
addToSimData( simData, "GAS_VISC", sd.rq[vapour_idx].mu );
addToSimData( simData, "GASKR", sd.rq[vapour_idx].kr );
}
// RS and RV
addToSimData( simData, "RSSAT", sd.rsSat );
addToSimData( simData, "RVSAT", sd.rvSat );
return simData;
}
// in case the data is already in a SimulationDataContainer no
// conversion is needed
inline
SimulationDataContainer&&
convertToSimulationDataContainer( SimulationDataContainer&& sd,
const SimulationDataContainer& ,
const Opm::PhaseUsage& )
{
return std::move( sd );
}
/**
* Returns the data requested in the restartConfig
*/
template<class Model>
void getRestartData(data::Solution& output,
const Opm::PhaseUsage& phaseUsage,
const Model& physicalModel,
SimulationDataContainer&& sd,
const Opm::PhaseUsage& /* phaseUsage */,
const Model& /* physicalModel */,
const RestartConfig& restartConfig,
const int reportStepNum,
const bool log) {
const typename Model::SimulatorData& sd = physicalModel.getSimulatorData();
const bool log)
{
//Get the value of each of the keys for the restart keywords
std::map<std::string, int> rstKeywords = restartConfig.getRestartKeywords(reportStepNum);
for (auto& keyValue : rstKeywords) {
keyValue.second = restartConfig.getKeyword(keyValue.first, reportStepNum);
}
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
const int aqua_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Aqua];
const int liquid_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Liquid];
const int vapour_idx = phaseUsage.phase_pos[Opm::PhaseUsage::Vapour];
const bool aqua_active = sd.hasCellData("1OVERBW");
const bool liquid_active = sd.hasCellData("1OVERBO");
const bool vapour_active = sd.hasCellData("1OVERBG");
assert( aqua_active == (sd.hasCellData("WAT_DEN") &&
sd.hasCellData("WAT_VISC") &&
sd.hasCellData("WATKR")
)
);
assert( liquid_active == (sd.hasCellData("OIL_DEN") &&
sd.hasCellData("OIL_VISC") &&
sd.hasCellData("OILKR")
)
);
assert( vapour_active == (sd.hasCellData("GAS_DEN") &&
sd.hasCellData("GAS_VISC") &&
sd.hasCellData("GASKR")
)
);
/**
* Formation volume factors for water, oil, gas
@ -495,21 +575,21 @@ namespace Opm
rstKeywords["BW"] = 0;
output.insert("1OVERBW",
Opm::UnitSystem::measure::water_inverse_formation_volume_factor,
adbToDoubleVector(sd.rq[aqua_idx].b),
std::move( sd.getCellData("1OVERBW") ),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active && rstKeywords["BO"] > 0) {
rstKeywords["BO"] = 0;
output.insert("1OVERBO",
Opm::UnitSystem::measure::oil_inverse_formation_volume_factor,
adbToDoubleVector(sd.rq[liquid_idx].b),
std::move( sd.getCellData("1OVERBO") ),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active && rstKeywords["BG"] > 0) {
rstKeywords["BG"] = 0;
output.insert("1OVERBG",
Opm::UnitSystem::measure::gas_inverse_formation_volume_factor,
adbToDoubleVector(sd.rq[vapour_idx].b),
std::move( sd.getCellData("1OVERBG") ),
data::TargetType::RESTART_AUXILLARY);
}
@ -521,19 +601,19 @@ namespace Opm
if (aqua_active) {
output.insert("WAT_DEN",
Opm::UnitSystem::measure::density,
adbToDoubleVector(sd.rq[aqua_idx].rho),
std::move( sd.getCellData("WAT_DEN") ),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active) {
output.insert("OIL_DEN",
Opm::UnitSystem::measure::density,
adbToDoubleVector(sd.rq[liquid_idx].rho),
std::move( sd.getCellData("OIL_DEN") ),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active) {
output.insert("GAS_DEN",
Opm::UnitSystem::measure::density,
adbToDoubleVector(sd.rq[vapour_idx].rho),
std::move( sd.getCellData("GAS_DEN") ),
data::TargetType::RESTART_AUXILLARY);
}
}
@ -546,19 +626,19 @@ namespace Opm
if (aqua_active) {
output.insert("WAT_VISC",
Opm::UnitSystem::measure::viscosity,
adbToDoubleVector(sd.rq[aqua_idx].mu),
std::move( sd.getCellData("WAT_VISC") ),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active) {
output.insert("OIL_VISC",
Opm::UnitSystem::measure::viscosity,
adbToDoubleVector(sd.rq[liquid_idx].mu),
std::move( sd.getCellData("OIL_VISC") ),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active) {
output.insert("GAS_VISC",
Opm::UnitSystem::measure::viscosity,
adbToDoubleVector(sd.rq[vapour_idx].mu),
std::move( sd.getCellData("GAS_VISC") ),
data::TargetType::RESTART_AUXILLARY);
}
}
@ -567,11 +647,12 @@ namespace Opm
* Relative permeabilities for water, oil, gas
*/
if (aqua_active && rstKeywords["KRW"] > 0) {
if (sd.rq[aqua_idx].kr.size() > 0) {
auto& krWater = sd.getCellData("WATKR");
if (krWater.size() > 0) {
rstKeywords["KRW"] = 0;
output.insert("WATKR",
output.insert("WATKR", // WAT_KR ???
Opm::UnitSystem::measure::identity,
adbToDoubleVector(sd.rq[aqua_idx].kr),
std::move( krWater ),
data::TargetType::RESTART_AUXILLARY);
}
else {
@ -583,11 +664,12 @@ namespace Opm
}
}
if (liquid_active && rstKeywords["KRO"] > 0) {
if (sd.rq[liquid_idx].kr.size() > 0) {
auto& krOil = sd.getCellData("OILKR");
if (krOil.size() > 0) {
rstKeywords["KRO"] = 0;
output.insert("OILKR",
Opm::UnitSystem::measure::identity,
adbToDoubleVector(sd.rq[liquid_idx].kr),
std::move( krOil ),
data::TargetType::RESTART_AUXILLARY);
}
else {
@ -599,11 +681,12 @@ namespace Opm
}
}
if (vapour_active && rstKeywords["KRG"] > 0) {
if (sd.rq[vapour_idx].kr.size() > 0) {
auto& krGas = sd.getCellData("GASKR");
if (krGas.size() > 0) {
rstKeywords["KRG"] = 0;
output.insert("GASKR",
Opm::UnitSystem::measure::identity,
adbToDoubleVector(sd.rq[vapour_idx].kr),
std::move( krGas ),
data::TargetType::RESTART_AUXILLARY);
}
else {
@ -622,14 +705,14 @@ namespace Opm
rstKeywords["RSSAT"] = 0;
output.insert("RSSAT",
Opm::UnitSystem::measure::gas_oil_ratio,
adbToDoubleVector(sd.rsSat),
std::move( sd.getCellData("RSSAT") ),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active && liquid_active && rstKeywords["RVSAT"] > 0) {
rstKeywords["RVSAT"] = 0;
output.insert("RVSAT",
Opm::UnitSystem::measure::oil_gas_ratio,
adbToDoubleVector(sd.rvSat),
std::move( sd.getCellData("RVSAT") ),
data::TargetType::RESTART_AUXILLARY);
}
@ -637,7 +720,7 @@ namespace Opm
/**
* Bubble point and dew point pressures
*/
if (log && vapour_active &&
if (log && vapour_active &&
liquid_active && rstKeywords["PBPD"] > 0) {
rstKeywords["PBPD"] = 0;
Opm::OpmLog::warning("Bubble/dew point pressure output unsupported",
@ -683,9 +766,10 @@ namespace Opm
const Model& physicalModel,
const SummaryConfig& summaryConfig) {
typedef Opm::AutoDiffBlock<double> ADB;
typedef typename Model::FIPDataType FIPDataType;
typedef typename FIPDataType::VectorType VectorType;
const typename Model::SimulatorData& sd = physicalModel.getSimulatorData();
FIPDataType fd = physicalModel.getFIPData();
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
@ -699,60 +783,79 @@ namespace Opm
if (aqua_active && hasFRBKeyword(summaryConfig, "WIP")) {
output.insert("WIP",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(sd.fip[Model::SimulatorData::FIP_AQUA]),
std::move( fd.fip[ FIPDataType::FIP_AQUA ] ),
data::TargetType::SUMMARY );
}
if (liquid_active) {
const ADB::V& oipl = sd.fip[Model::SimulatorData::FIP_LIQUID];
const ADB::V& oipg = vapour_active ? sd.fip[Model::SimulatorData::FIP_VAPORIZED_OIL] : ADB::V();
const ADB::V& oip = vapour_active ? oipl + oipg : oipl;
const VectorType& oipl = fd.fip[FIPDataType::FIP_LIQUID];
VectorType oip ( oipl );
const size_t size = oip.size();
const VectorType& oipg = vapour_active ? fd.fip[FIPDataType::FIP_VAPORIZED_OIL] : VectorType(size, 0.0);
if( vapour_active )
{
// oip = oipl + oipg
for( size_t i=0; i<size; ++ i ) {
oip[ i ] += oipg[ i ];
}
}
//Oil in place (liquid phase only)
if (hasFRBKeyword(summaryConfig, "OIPL")) {
output.insert("OIPL",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(oipl),
std::move( oipl ),
data::TargetType::SUMMARY );
}
//Oil in place (gas phase only)
if (hasFRBKeyword(summaryConfig, "OIPG")) {
output.insert("OIPG",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(oipg),
std::move( oipg ),
data::TargetType::SUMMARY );
}
// Oil in place (in liquid and gas phases)
if (hasFRBKeyword(summaryConfig, "OIP")) {
output.insert("OIP",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(oip),
std::move( oip ),
data::TargetType::SUMMARY );
}
}
if (vapour_active) {
const ADB::V& gipg = sd.fip[Model::SimulatorData::FIP_VAPOUR];
const ADB::V& gipl = liquid_active ? sd.fip[Model::SimulatorData::FIP_DISSOLVED_GAS] : ADB::V();
const ADB::V& gip = liquid_active ? gipg + gipl : gipg;
const VectorType& gipg = fd.fip[ FIPDataType::FIP_VAPOUR];
VectorType gip( gipg );
const size_t size = gip.size();
const VectorType& gipl = liquid_active ? fd.fip[ FIPDataType::FIP_DISSOLVED_GAS ] : VectorType(size,0.0);
if( liquid_active )
{
// gip = gipg + gipl
for( size_t i=0; i<size; ++ i ) {
gip[ i ] += gipl[ i ];
}
}
// Gas in place (gas phase only)
if (hasFRBKeyword(summaryConfig, "GIPG")) {
output.insert("GIPG",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(gipg),
std::move( gipg ),
data::TargetType::SUMMARY );
}
// Gas in place (liquid phase only)
if (hasFRBKeyword(summaryConfig, "GIPL")) {
output.insert("GIPL",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(gipl),
std::move( gipl ),
data::TargetType::SUMMARY );
}
// Gas in place (in both liquid and gas phases)
if (hasFRBKeyword(summaryConfig, "GIP")) {
output.insert("GIP",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(gip),
std::move( gip ),
data::TargetType::SUMMARY );
}
}
@ -760,14 +863,14 @@ namespace Opm
if (hasFRBKeyword(summaryConfig, "RPV")) {
output.insert("RPV",
Opm::UnitSystem::measure::volume,
adbVToDoubleVector(sd.fip[Model::SimulatorData::FIP_PV]),
std::move( fd.fip[FIPDataType::FIP_PV]),
data::TargetType::SUMMARY );
}
// Pressure averaged value (hydrocarbon pore volume weighted)
if (summaryConfig.hasKeyword("FPRH") || summaryConfig.hasKeyword("RPRH")) {
output.insert("PRH",
Opm::UnitSystem::measure::pressure,
adbVToDoubleVector(sd.fip[Model::SimulatorData::FIP_WEIGHTED_PRESSURE]),
std::move(fd.fip[FIPDataType::FIP_WEIGHTED_PRESSURE]),
data::TargetType::SUMMARY );
}
}
@ -791,15 +894,26 @@ namespace Opm
const SummaryConfig& summaryConfig = eclipseState_.getSummaryConfig();
const int reportStepNum = timer.reportStepNum();
bool logMessages = output_ && parallelOutput_->isIORank();
if( output_ )
{
localCellData = simToSolution(localState, phaseUsage_); // Get "normal" data (SWAT, PRESSURE, ...);
detail::getRestartData( localCellData, phaseUsage_, physicalModel,
restartConfig, reportStepNum, logMessages );
{
// get all data that need to be included in output from the model
// for flow_legacy and polymer this is a struct holding the data
// while for flow_ebos a SimulationDataContainer is returned
// this is addressed in the above specialized methods
SimulationDataContainer sd =
detail::convertToSimulationDataContainer( physicalModel.getSimulatorData(), localState, phaseUsage_ );
localCellData = simToSolution( sd, phaseUsage_); // Get "normal" data (SWAT, PRESSURE, ...);
detail::getRestartData( localCellData, std::move(sd), phaseUsage_, physicalModel,
restartConfig, reportStepNum, logMessages );
// sd will be invalid after getRestartData has been called
}
detail::getSummaryData( localCellData, phaseUsage_, physicalModel, summaryConfig );
}
writeTimeStepWithCellProperties(timer, localState, localCellData, localWellState, substep);
}
}

View File

@ -1,307 +0,0 @@
/*
Copyright (c) 2014 SINTEF ICT, Applied Mathematics.
Copyright (c) 2015-2016 IRIS AS
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 3 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/>.
*/
#include "config.h"
#include "SimulatorFullyImplicitBlackoilOutputEbos.hpp"
#include <opm/common/data/SimulationDataContainer.hpp>
#include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
#include <opm/core/simulator/BlackoilState.hpp>
#include <opm/core/utility/DataMap.hpp>
#include <opm/autodiff/Compat.hpp>
#include <opm/simulators/vtk/writeVtkData.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <opm/core/utility/miscUtilities.hpp>
#include <opm/parser/eclipse/Units/Units.hpp>
#include <opm/autodiff/GridHelpers.hpp>
#include <opm/autodiff/BackupRestore.hpp>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <boost/filesystem.hpp>
//For OutputWriterHelper
#include <map>
#include <opm/parser/eclipse/Units/UnitSystem.hpp>
#ifdef HAVE_OPM_GRID
#include <opm/common/utility/platform_dependent/disable_warnings.h>
#include <dune/common/version.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#include <opm/common/utility/platform_dependent/reenable_warnings.h>
#endif
namespace Opm
{
namespace detail {
struct WriterCallEbos : public ThreadHandle :: ObjectInterface
{
BlackoilOutputWriterEbos& writer_;
std::unique_ptr< SimulatorTimerInterface > timer_;
const SimulationDataContainer state_;
const WellStateFullyImplicitBlackoil wellState_;
data::Solution simProps_;
const bool substep_;
explicit WriterCallEbos( BlackoilOutputWriterEbos& writer,
const SimulatorTimerInterface& timer,
const SimulationDataContainer& state,
const WellStateFullyImplicitBlackoil& wellState,
const data::Solution& simProps,
bool substep )
: writer_( writer ),
timer_( timer.clone() ),
state_( state ),
wellState_( wellState ),
simProps_( simProps ),
substep_( substep )
{
}
// callback to writer's serial writeTimeStep method
void run ()
{
// write data
writer_.writeTimeStepSerial( *timer_, state_, wellState_, simProps_, substep_ );
}
};
}
void
BlackoilOutputWriterEbos::
writeTimeStepWithoutCellProperties(
const SimulatorTimerInterface& timer,
const SimulationDataContainer& localState,
const WellStateFullyImplicitBlackoil& localWellState,
bool substep)
{
data::Solution noCellProperties;
writeTimeStepWithCellProperties(timer, localState, localWellState, noCellProperties, substep);
}
void
BlackoilOutputWriterEbos::
writeTimeStepWithCellProperties(
const SimulatorTimerInterface& timer,
const SimulationDataContainer& localState,
const WellStateFullyImplicitBlackoil& localWellState,
const data::Solution& sol,
bool substep)
{
bool isIORank = output_ ;
if( parallelOutput_ && parallelOutput_->isParallel() )
{
// If this is not the initial write and no substep, then the well
// state used in the computation is actually the one of the last
// step. We need that well state for the gathering. Otherwise
// It an exception with a message like "global state does not
// contain well ..." might be thrown.
int wellStateStepNumber = ( ! substep && timer.reportStepNum() > 0) ?
(timer.reportStepNum() - 1) : timer.reportStepNum();
// collect all solutions to I/O rank
isIORank = parallelOutput_->collectToIORank( localState, localWellState, sol, wellStateStepNumber );
}
const SimulationDataContainer& state = (parallelOutput_ && parallelOutput_->isParallel() ) ? parallelOutput_->globalReservoirState() : localState;
const WellStateFullyImplicitBlackoil& wellState = (parallelOutput_ && parallelOutput_->isParallel() ) ? parallelOutput_->globalWellState() : localWellState;
// serial output is only done on I/O rank
int err = 0;
std::string emsg;
if( isIORank )
{
if( asyncOutput_ ) {
// dispatch the write call to the extra thread
asyncOutput_->dispatch( detail::WriterCallEbos( *this, timer, state, wellState, sol, substep ) );
}
else {
// just write the data to disk
try {
writeTimeStepSerial( timer, state, wellState, sol, substep );
} catch (std::runtime_error& msg) {
err = 1;
emsg = msg.what();
}
}
}
if (!asyncOutput_) {
#if HAVE_MPI
MPI_Bcast(&err, 1, MPI_INT, 0, MPI_COMM_WORLD);
#endif
if (err) {
if (isIORank) {
throw std::runtime_error(emsg);
} else {
throw std::runtime_error("I/O process encountered problems.");
}
}
}
}
void
BlackoilOutputWriterEbos::
writeTimeStepSerial(const SimulatorTimerInterface& timer,
const SimulationDataContainer& state,
const WellStateFullyImplicitBlackoil& wellState,
const data::Solution& sol,
bool substep)
{
// ECL output
if (output())
{
const auto& initConfig = eclipseState_.getInitConfig();
if (initConfig.restartRequested() && ((initConfig.getRestartStep()) == (timer.currentStepNum()))) {
std::cout << "Skipping restart write in start of step " << timer.currentStepNum() << std::endl;
} else {
data::Solution combined_sol = simToSolution(state, phaseUsage_); // Get "normal" data (SWAT, PRESSURE, ...)
combined_sol.insert(sol.begin(), sol.end()); // ... insert "extra" data (KR, VISC, ...)
eclIO_.writeTimeStep(timer.reportStepNum(),
substep,
timer.simulationTimeElapsed(),
combined_sol,
wellState.report(phaseUsage_));
}
}
// write backup file
if( backupfile_.is_open() )
{
int reportStep = timer.reportStepNum();
int currentTimeStep = timer.currentStepNum();
if( (reportStep == currentTimeStep || // true for SimulatorTimer
currentTimeStep == 0 || // true for AdaptiveSimulatorTimer at reportStep
timer.done() ) // true for AdaptiveSimulatorTimer at reportStep
&& lastBackupReportStep_ != reportStep ) // only backup report step once
{
// store report step
lastBackupReportStep_ = reportStep;
// write resport step number
backupfile_.write( (const char *) &reportStep, sizeof(int) );
try {
backupfile_ << state;
const WellStateFullyImplicitBlackoil& boWellState = static_cast< const WellStateFullyImplicitBlackoil& > (wellState);
backupfile_ << boWellState;
}
catch ( const std::bad_cast& e )
{
}
backupfile_ << std::flush;
}
} // end backup
}
void
BlackoilOutputWriterEbos::
restore(SimulatorTimerInterface& timer,
BlackoilState& state,
WellStateFullyImplicitBlackoilDense& wellState,
const std::string& filename,
const int desiredResportStep )
{
std::ifstream restorefile( filename.c_str() );
if( restorefile )
{
std::cout << "============================================================================"<<std::endl;
std::cout << "Restoring from ";
if( desiredResportStep < 0 ) {
std::cout << "last";
}
else {
std::cout << desiredResportStep;
}
std::cout << " report step! filename = " << filename << std::endl << std::endl;
int reportStep;
restorefile.read( (char *) &reportStep, sizeof(int) );
const int readReportStep = (desiredResportStep < 0) ?
std::numeric_limits<int>::max() : desiredResportStep;
while( reportStep <= readReportStep && ! timer.done() && restorefile )
{
restorefile >> state;
restorefile >> wellState;
// No per cell data is written for restore steps, but will be
// for subsequent steps, when we have started simulating
writeTimeStepWithoutCellProperties( timer, state, wellState );
// some output
std::cout << "Restored step " << timer.reportStepNum() << " at day "
<< unit::convert::to(timer.simulationTimeElapsed(),unit::day) << std::endl;
if( readReportStep == reportStep ) {
break;
}
// if the stream is not valid anymore we just use the last state read
if( ! restorefile ) {
std::cerr << "Reached EOF, using last state read!" << std::endl;
break;
}
// try to read next report step
restorefile.read( (char *) &reportStep, sizeof(int) );
// if read failed, exit loop
if( ! restorefile ) {
break;
}
// next step
timer.advance();
if( timer.reportStepNum() != reportStep ) {
break;
}
}
}
else
{
std::cerr << "Warning: Couldn't open restore file '" << filename << "'" << std::endl;
}
}
bool BlackoilOutputWriterEbos::isRestart() const {
const auto& initconfig = eclipseState_.getInitConfig();
return initconfig.restartRequested();
}
bool BlackoilOutputWriterEbos::requireFIPNUM() const {
return eclipseState_.getSummaryConfig().requireFIPNUM();
}
}

View File

@ -1,749 +0,0 @@
/*
Copyright (c) 2014 SINTEF ICT, Applied Mathematics.
Copyright (c) 2015 IRIS AS
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 3 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/>.
*/
#ifndef OPM_SIMULATORFULLYIMPLICITBLACKOILOUTPUTEBOS_HEADER_INCLUDED
#define OPM_SIMULATORFULLYIMPLICITBLACKOILOUTPUTEBOS_HEADER_INCLUDED
#include <opm/core/grid.h>
#include <opm/simulators/timestepping/SimulatorTimerInterface.hpp>
#include <opm/core/simulator/WellState.hpp>
#include <opm/core/utility/DataMap.hpp>
#include <opm/common/ErrorMacros.hpp>
#include <opm/common/OpmLog/OpmLog.hpp>
#include <opm/core/utility/miscUtilities.hpp>
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/wells/DynamicListEconLimited.hpp>
#include <opm/output/eclipse/EclipseIO.hpp>
#include <opm/autodiff/Compat.hpp>
#include <opm/autodiff/GridHelpers.hpp>
#include <opm/autodiff/ParallelDebugOutput.hpp>
#include <opm/autodiff/WellStateFullyImplicitBlackoilDense.hpp>
#include <opm/autodiff/ThreadHandle.hpp>
#include <opm/autodiff/AutoDiffBlock.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <opm/parser/eclipse/EclipseState/InitConfig/InitConfig.hpp>
#include <string>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <thread>
#include <memory>
#include <boost/filesystem.hpp>
#ifdef HAVE_OPM_GRID
#include <dune/grid/CpGrid.hpp>
#endif
namespace Opm
{
class BlackoilState;
/** \brief Wrapper class for VTK, Matlab, and ECL output. */
class BlackoilOutputWriterEbos
{
public:
// constructor creating different sub writers
template <class Grid>
BlackoilOutputWriterEbos(const Grid& grid,
const parameter::ParameterGroup& param,
const EclipseState& eclipseState,
EclipseIO& eclIO,
const Opm::PhaseUsage &phaseUsage);
/*!
* \brief Write a blackoil reservoir state to disk for later inspection with
* visualization tools like ResInsight. This function will extract the
* requested output cell properties specified by the RPTRST keyword
* and write these to file.
*/
template<class Model>
void writeTimeStep(const SimulatorTimerInterface& timer,
const SimulationDataContainer& reservoirState,
const Opm::WellStateFullyImplicitBlackoil& wellState,
const Model& physicalModel,
bool substep = false);
/*!
* \brief Write a blackoil reservoir state to disk for later inspection with
* visualization tools like ResInsight. This function will write all
* CellData in simProps to the file as well.
*/
void writeTimeStepWithCellProperties(
const SimulatorTimerInterface& timer,
const SimulationDataContainer& reservoirState,
const Opm::WellStateFullyImplicitBlackoil& wellState,
const data::Solution& sol,
bool substep = false);
/*!
* \brief Write a blackoil reservoir state to disk for later inspection with
* visualization tools like ResInsight. This function will not write
* any cell properties (e.g., those requested by RPTRST keyword)
*/
void writeTimeStepWithoutCellProperties(
const SimulatorTimerInterface& timer,
const SimulationDataContainer& reservoirState,
const Opm::WellStateFullyImplicitBlackoil& wellState,
bool substep = false);
/*!
* \brief Write a blackoil reservoir state to disk for later inspection withS
* visualization tools like ResInsight. This is the function which does
* the actual write to file.
*/
void writeTimeStepSerial(const SimulatorTimerInterface& timer,
const SimulationDataContainer& reservoirState,
const Opm::WellStateFullyImplicitBlackoil& wellState,
const data::Solution& simProps,
bool substep);
/** \brief return output directory */
const std::string& outputDirectory() const { return outputDir_; }
/** \brief return true if output is enabled */
bool output () const { return output_; }
/** \brief Whether this process does write to disk */
bool isIORank () const
{
return parallelOutput_->isIORank();
}
void restore(SimulatorTimerInterface& timer,
BlackoilState& state,
WellStateFullyImplicitBlackoilDense& wellState,
const std::string& filename,
const int desiredReportStep);
template <class Grid>
void initFromRestartFile(const PhaseUsage& phaseusage,
const Grid& grid,
SimulationDataContainer& simulatorstate,
WellStateFullyImplicitBlackoilDense& wellstate);
bool isRestart() const;
bool requireFIPNUM() const;
protected:
const bool output_;
std::unique_ptr< ParallelDebugOutputInterface > parallelOutput_;
// Parameters for output.
const std::string outputDir_;
const int output_interval_;
int lastBackupReportStep_;
std::ofstream backupfile_;
Opm::PhaseUsage phaseUsage_;
EclipseIO& eclIO_;
const EclipseState& eclipseState_;
std::unique_ptr< ThreadHandle > asyncOutput_;
};
//////////////////////////////////////////////////////////////
//
// Implementation
//
//////////////////////////////////////////////////////////////
template <class Grid>
inline
BlackoilOutputWriterEbos::
BlackoilOutputWriterEbos(const Grid& grid,
const parameter::ParameterGroup& param,
const Opm::EclipseState& eclipseState,
EclipseIO& eclIO,
const Opm::PhaseUsage &phaseUsage)
: output_( param.getDefault("output", true) ),
parallelOutput_( output_ ? new ParallelDebugOutput< Grid >( grid, eclipseState, phaseUsage.num_phases, phaseUsage ) : 0 ),
outputDir_( output_ ? param.getDefault("output_dir", std::string("output")) : "." ),
output_interval_( output_ ? param.getDefault("output_interval", 1): 0 ),
lastBackupReportStep_( -1 ),
phaseUsage_( phaseUsage ),
eclIO_(eclIO),
eclipseState_(eclipseState),
asyncOutput_()
{
// For output.
if (output_ && parallelOutput_->isIORank() ) {
// Ensure that output dir exists
boost::filesystem::path fpath(outputDir_);
try {
create_directories(fpath);
}
catch (...) {
OPM_THROW(std::runtime_error, "Creating directories failed: " << fpath);
}
// create output thread if enabled and rank is I/O rank
// async output is enabled by default if pthread are enabled
#if HAVE_PTHREAD
const bool asyncOutputDefault = false;
#else
const bool asyncOutputDefault = false;
#endif
if( param.getDefault("async_output", asyncOutputDefault ) )
{
#if HAVE_PTHREAD
asyncOutput_.reset( new ThreadHandle() );
#else
OPM_THROW(std::runtime_error,"Pthreads were not found, cannot enable async_output");
#endif
}
std::string backupfilename = param.getDefault("backupfile", std::string("") );
if( ! backupfilename.empty() )
{
backupfile_.open( backupfilename.c_str() );
}
}
}
template <class Grid>
inline void
BlackoilOutputWriterEbos::
initFromRestartFile( const PhaseUsage& phaseusage,
const Grid& grid,
SimulationDataContainer& simulatorstate,
WellStateFullyImplicitBlackoilDense& wellstate)
{
std::map<std::string, UnitSystem::measure> solution_keys {{"PRESSURE" , UnitSystem::measure::pressure},
{"SWAT" , UnitSystem::measure::identity},
{"SGAS" , UnitSystem::measure::identity},
{"TEMP" , UnitSystem::measure::temperature},
{"RS" , UnitSystem::measure::gas_oil_ratio},
{"RV" , UnitSystem::measure::oil_gas_ratio}};
// gives a dummy dynamic_list_econ_limited
DynamicListEconLimited dummy_list_econ_limited;
WellsManager wellsmanager(eclipseState_,
eclipseState_.getInitConfig().getRestartStep(),
Opm::UgGridHelpers::numCells(grid),
Opm::UgGridHelpers::globalCell(grid),
Opm::UgGridHelpers::cartDims(grid),
Opm::UgGridHelpers::dimensions(grid),
Opm::UgGridHelpers::cell2Faces(grid),
Opm::UgGridHelpers::beginFaceCentroids(grid),
dummy_list_econ_limited
// We need to pass the optionaly arguments
// as we get the following error otherwise
// with c++ (Debian 4.9.2-10) 4.9.2 and -std=c++11
// converting to const std::unordered_set<std::basic_string<char> > from initializer list would use explicit constructo
, false,
std::vector<double>(),
std::unordered_set<std::string>());
const Wells* wells = wellsmanager.c_wells();
wellstate.resize(wells, simulatorstate, phaseusage ); //Resize for restart step
auto state = eclIO_.loadRestart(solution_keys);
solutionToSim( state.first, phaseusage, simulatorstate );
wellsToState( state.second, phaseusage, wellstate );
}
namespace detail {
template<class Model>
void getOutputDataEbos(data::Solution& output,
const Opm::PhaseUsage& phaseUsage,
const Model& model,
const RestartConfig& restartConfig,
const int reportStepNum,
const bool log)
{
typedef typename Model::FluidSystem FluidSystem;
//Get the value of each of the keys
std::map<std::string, int> outKeywords = restartConfig.getRestartKeywords(reportStepNum);
for (auto& keyValue : outKeywords) {
keyValue.second = restartConfig.getKeyword(keyValue.first, reportStepNum);
}
const auto& ebosModel = model.ebosSimulator().model();
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
// extract everything which can possibly be written to disk
int numCells = ebosModel.numGridDof();
std::vector<double> pressureOil(numCells);
std::vector<double> temperature(numCells);
std::vector<double> satWater(numCells);
std::vector<double> satGas(numCells);
std::vector<double> bWater(numCells);
std::vector<double> bOil(numCells);
std::vector<double> bGas(numCells);
std::vector<double> rhoWater(numCells);
std::vector<double> rhoOil(numCells);
std::vector<double> rhoGas(numCells);
std::vector<double> muWater(numCells);
std::vector<double> muOil(numCells);
std::vector<double> muGas(numCells);
std::vector<double> krWater(numCells);
std::vector<double> krOil(numCells);
std::vector<double> krGas(numCells);
std::vector<double> Rs(numCells);
std::vector<double> Rv(numCells);
std::vector<double> RsSat(numCells);
std::vector<double> RvSat(numCells);
for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) {
const auto& intQuants = *ebosModel.cachedIntensiveQuantities(cellIdx, /*timeIdx=*/0);
const auto& fs = intQuants.fluidState();
pressureOil[cellIdx] = fs.pressure(FluidSystem::oilPhaseIdx).value();
temperature[cellIdx] = fs.temperature(FluidSystem::oilPhaseIdx).value();
if (aqua_active) {
satWater[cellIdx] = fs.saturation(FluidSystem::waterPhaseIdx).value();
bWater[cellIdx] = fs.invB(FluidSystem::waterPhaseIdx).value();
rhoWater[cellIdx] = fs.density(FluidSystem::waterPhaseIdx).value();
muWater[cellIdx] = fs.viscosity(FluidSystem::waterPhaseIdx).value();
krWater[cellIdx] = intQuants.relativePermeability(FluidSystem::waterPhaseIdx).value();
}
if (vapour_active) {
satGas[cellIdx] = fs.saturation(FluidSystem::gasPhaseIdx).value();
bGas[cellIdx] = fs.invB(FluidSystem::gasPhaseIdx).value();
rhoGas[cellIdx] = fs.density(FluidSystem::gasPhaseIdx).value();
muGas[cellIdx] = fs.viscosity(FluidSystem::gasPhaseIdx).value();
krGas[cellIdx] = intQuants.relativePermeability(FluidSystem::gasPhaseIdx).value();
Rs[cellIdx] = fs.Rs().value();
Rv[cellIdx] = fs.Rv().value();
RsSat[cellIdx] = FluidSystem::saturatedDissolutionFactor(fs,
FluidSystem::oilPhaseIdx,
intQuants.pvtRegionIndex(),
/*maxOilSaturation=*/1.0).value();
RvSat[cellIdx] = FluidSystem::saturatedDissolutionFactor(fs,
FluidSystem::gasPhaseIdx,
intQuants.pvtRegionIndex(),
/*maxOilSaturation=*/1.0).value();
}
// oil is always active
bOil[cellIdx] = fs.invB(FluidSystem::oilPhaseIdx).value();
rhoOil[cellIdx] = fs.density(FluidSystem::oilPhaseIdx).value();
muOil[cellIdx] = fs.viscosity(FluidSystem::oilPhaseIdx).value();
krOil[cellIdx] = intQuants.relativePermeability(FluidSystem::oilPhaseIdx).value();
}
/**
* Oil Pressures
*/
outKeywords["PRESSURE"] = 0;
output.insert("PRESSURE",
UnitSystem::measure::pressure,
std::move(pressureOil),
data::TargetType::RESTART_SOLUTION);
/**
* Temperatures
*/
outKeywords["TEMP"] = 0;
output.insert("TEMP",
UnitSystem::measure::temperature,
std::move(temperature),
data::TargetType::RESTART_SOLUTION);
/**
* Water and gas saturation.
*/
outKeywords["SWAT"] = 0;
outKeywords["SGAS"] = 0;
output.insert("SWAT",
UnitSystem::measure::identity,
std::move(satWater),
data::TargetType::RESTART_SOLUTION);
output.insert("SGAS",
UnitSystem::measure::identity,
std::move(satGas),
data::TargetType::RESTART_SOLUTION);
/**
* the dissolution factors
*/
outKeywords["RS"] = 0;
outKeywords["RV"] = 0;
output.insert("RS",
UnitSystem::measure::gas_oil_ratio,
std::move(Rs),
data::TargetType::RESTART_SOLUTION);
output.insert("RV",
UnitSystem::measure::oil_gas_ratio,
std::move(Rv),
data::TargetType::RESTART_SOLUTION);
/**
* Formation volume factors for water, oil, gas
*/
if (aqua_active && outKeywords["BW"] > 0) {
outKeywords["BW"] = 0;
output.insert("BW",
Opm::UnitSystem::measure::water_inverse_formation_volume_factor,
std::move(bWater),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active && outKeywords["BO"] > 0) {
outKeywords["BO"] = 0;
output.insert("BO",
Opm::UnitSystem::measure::oil_inverse_formation_volume_factor,
std::move(bOil),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active && outKeywords["BG"] > 0) {
outKeywords["BG"] = 0;
output.insert("BG",
Opm::UnitSystem::measure::gas_inverse_formation_volume_factor,
std::move(bGas),
data::TargetType::RESTART_AUXILLARY);
}
/**
* Densities for water, oil gas
*/
if (outKeywords["DEN"] > 0) {
outKeywords["DEN"] = 0;
if (aqua_active) {
output.insert("WAT_DEN",
Opm::UnitSystem::measure::density,
std::move(rhoWater),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active) {
output.insert("OIL_DEN",
Opm::UnitSystem::measure::density,
std::move(rhoOil),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active) {
output.insert("GAS_DEN",
Opm::UnitSystem::measure::density,
std::move(rhoGas),
data::TargetType::RESTART_AUXILLARY);
}
}
/**
* Viscosities for water, oil gas
*/
if (outKeywords["VISC"] > 0) {
outKeywords["VISC"] = 0;
if (aqua_active) {
output.insert("WAT_VISC",
Opm::UnitSystem::measure::viscosity,
std::move(muWater),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active) {
output.insert("OIL_VISC",
Opm::UnitSystem::measure::viscosity,
std::move(muOil),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active) {
output.insert("GAS_VISC",
Opm::UnitSystem::measure::viscosity,
std::move(muGas),
data::TargetType::RESTART_AUXILLARY);
}
}
/**
* Relative permeabilities for water, oil, gas
*/
if (aqua_active && outKeywords["KRW"] > 0) {
outKeywords["KRW"] = 0;
output.insert("WATKR",
Opm::UnitSystem::measure::identity,
std::move(krWater),
data::TargetType::RESTART_AUXILLARY);
}
if (liquid_active && outKeywords["KRO"] > 0) {
outKeywords["KRO"] = 0;
output.insert("OILKR",
Opm::UnitSystem::measure::identity,
std::move(krOil),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active && outKeywords["KRG"] > 0) {
outKeywords["KRG"] = 0;
output.insert("GASKR",
Opm::UnitSystem::measure::identity,
std::move(krGas),
data::TargetType::RESTART_AUXILLARY);
}
/**
* Vaporized and dissolved gas/oil ratio
*/
if (vapour_active && liquid_active && outKeywords["RSSAT"] > 0) {
outKeywords["RSSAT"] = 0;
output.insert("RSSAT",
Opm::UnitSystem::measure::gas_oil_ratio,
std::move(RsSat),
data::TargetType::RESTART_AUXILLARY);
}
if (vapour_active && liquid_active && outKeywords["RVSAT"] > 0) {
outKeywords["RVSAT"] = 0;
output.insert("RVSAT",
Opm::UnitSystem::measure::oil_gas_ratio,
std::move(RvSat),
data::TargetType::RESTART_AUXILLARY);
}
/**
* Bubble point and dew point pressures
*/
if (log && vapour_active &&
liquid_active && outKeywords["PBPD"] > 0) {
Opm::OpmLog::warning("Bubble/dew point pressure output unsupported",
"Writing bubble points and dew points (PBPD) to file is unsupported, "
"as the simulator does not use these internally.");
}
//Warn for any unhandled keyword
if (log) {
for (auto& keyValue : outKeywords) {
if (keyValue.second > 0) {
std::string logstring = "Keyword '";
logstring.append(keyValue.first);
logstring.append("' is unhandled for output to file.");
Opm::OpmLog::warning("Unhandled output keyword", logstring);
}
}
}
}
/**
* Checks if the summaryConfig has a keyword with the standardized field, region, or block prefixes.
*/
inline bool hasFRBKeyword(const SummaryConfig& summaryConfig, const std::string keyword) {
std::string field_kw = "F" + keyword;
std::string region_kw = "R" + keyword;
std::string block_kw = "B" + keyword;
return summaryConfig.hasKeyword(field_kw)
|| summaryConfig.hasKeyword(region_kw)
|| summaryConfig.hasKeyword(block_kw);
}
/**
* Returns the data as asked for in the summaryConfig
*/
template<class Model>
void getSummaryData(data::Solution& output,
const Opm::PhaseUsage& phaseUsage,
const Model& physicalModel,
const SummaryConfig& summaryConfig) {
const typename Model::FIPData& fip = physicalModel.getFIPData();
//Get shorthands for water, oil, gas
const int aqua_active = phaseUsage.phase_used[Opm::PhaseUsage::Aqua];
const int liquid_active = phaseUsage.phase_used[Opm::PhaseUsage::Liquid];
const int vapour_active = phaseUsage.phase_used[Opm::PhaseUsage::Vapour];
/**
* Now process all of the summary config files
*/
// Water in place
if (aqua_active && hasFRBKeyword(summaryConfig, "WIP")) {
output.insert("WIP",
Opm::UnitSystem::measure::volume,
fip.fip[Model::FIPData::FIP_AQUA],
data::TargetType::SUMMARY );
}
if (liquid_active) {
const std::vector<double>& oipl = fip.fip[Model::FIPData::FIP_LIQUID];
const int size = oipl.size();
const std::vector<double>& oipg = vapour_active ? fip.fip[Model::FIPData::FIP_VAPORIZED_OIL] : std::vector<double>(size,0.0);
std::vector<double> oip = oipl;
if (vapour_active) {
std::transform(oip.begin(), oip.end(), oipg.begin(), oip.begin(), std::plus<double>());
}
//Oil in place (liquid phase only)
if (hasFRBKeyword(summaryConfig, "OIPL")) {
output.insert("OIPL",
Opm::UnitSystem::measure::volume,
oipl,
data::TargetType::SUMMARY );
}
//Oil in place (gas phase only)
if (hasFRBKeyword(summaryConfig, "OIPG")) {
output.insert("OIPG",
Opm::UnitSystem::measure::volume,
oipg,
data::TargetType::SUMMARY );
}
// Oil in place (in liquid and gas phases)
if (hasFRBKeyword(summaryConfig, "OIP")) {
output.insert("OIP",
Opm::UnitSystem::measure::volume,
oip,
data::TargetType::SUMMARY );
}
}
if (vapour_active) {
const std::vector<double>& gipg = fip.fip[Model::FIPData::FIP_VAPOUR];
const int size = gipg.size();
const std::vector<double>& gipl= liquid_active ? fip.fip[Model::FIPData::FIP_DISSOLVED_GAS] : std::vector<double>(size,0.0);
std::vector<double> gip = gipg;
if (liquid_active) {
std::transform(gip.begin(), gip.end(), gipl.begin(), gip.begin(), std::plus<double>());
}
// Gas in place (gas phase only)
if (hasFRBKeyword(summaryConfig, "GIPG")) {
output.insert("GIPG",
Opm::UnitSystem::measure::volume,
gipg,
data::TargetType::SUMMARY );
}
// Gas in place (liquid phase only)
if (hasFRBKeyword(summaryConfig, "GIPL")) {
output.insert("GIPL",
Opm::UnitSystem::measure::volume,
gipl,
data::TargetType::SUMMARY );
}
// Gas in place (in both liquid and gas phases)
if (hasFRBKeyword(summaryConfig, "GIP")) {
output.insert("GIP",
Opm::UnitSystem::measure::volume,
gip,
data::TargetType::SUMMARY );
}
}
// Cell pore volume in reservoir conditions
if (hasFRBKeyword(summaryConfig, "RPV")) {
output.insert("RPV",
Opm::UnitSystem::measure::volume,
fip.fip[Model::FIPData::FIP_PV],
data::TargetType::SUMMARY );
}
// Pressure averaged value (hydrocarbon pore volume weighted)
if (summaryConfig.hasKeyword("FPRH") || summaryConfig.hasKeyword("RPRH")) {
output.insert("PRH",
Opm::UnitSystem::measure::pressure,
fip.fip[Model::FIPData::FIP_WEIGHTED_PRESSURE],
data::TargetType::SUMMARY );
}
}
}
template<class Model>
inline void
BlackoilOutputWriterEbos::
writeTimeStep(const SimulatorTimerInterface& timer,
const SimulationDataContainer& localState,
const WellStateFullyImplicitBlackoil& localWellState,
const Model& physicalModel,
bool substep)
{
data::Solution cellData{};
const RestartConfig& restartConfig = eclipseState_.getRestartConfig();
const SummaryConfig& summaryConfig = eclipseState_.getSummaryConfig();
const int reportStepNum = timer.reportStepNum();
bool logMessages = output_ && parallelOutput_->isIORank();
if( output_ && !parallelOutput_->isParallel() )
{
detail::getOutputDataEbos( cellData, phaseUsage_, physicalModel,
restartConfig, reportStepNum, logMessages );
detail::getSummaryData( cellData, phaseUsage_, physicalModel, summaryConfig );
}
else
{
if ( logMessages )
{
std::map<std::string, int> rstKeywords = restartConfig.getRestartKeywords(reportStepNum);
std::vector<const char*> keywords =
{ "WIP", "OIPL", "OIPG", "OIP", "GIPG", "GIPL", "GIP",
"RPV", "FRPH", "RPRH"};
std::ostringstream str;
str << "Output of restart/summary config not supported in parallel. Requested keywords were ";
std::size_t no_kw = 0;
auto func = [&] (const char* kw)
{
if ( detail::hasFRBKeyword(summaryConfig, kw) )
{
str << kw << " ";
++ no_kw;
}
};
std::for_each(keywords.begin(), keywords.end(), func);
for (auto& keyValue : rstKeywords)
{
str << keyValue.first << " ";
++ no_kw;
}
if ( no_kw )
{
Opm::OpmLog::warning("Unhandled ouput request", str.str());
}
}
}
writeTimeStepWithCellProperties(timer, localState, localWellState, cellData, substep);
}
}
#endif

View File

@ -20,7 +20,7 @@
#ifndef OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
#define OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED
#include <opm/autodiff/BlackoilModelEnums.hpp>
#include <opm/core/wells.h>
#include <opm/core/well_controls.h>
#include <opm/core/simulator/WellState.hpp>
@ -176,11 +176,15 @@ namespace Opm
}
template <class State>
void resize(const Wells* wells, const State& state) {
void resize(const Wells* wells, const State& state ) {
const WellStateFullyImplicitBlackoil dummy_state{}; // Init with an empty previous state only resizes
init(wells, state, dummy_state) ;
}
template <class State>
void resize(const Wells* wells, const State& state, const PhaseUsage& ) {
resize( wells, state );
}
/// One rate per phase and well connection.
std::vector<double>& perfPhaseRates() { return perfphaserates_; }

View File

@ -76,7 +76,7 @@ namespace Opm {
std::vector<ADB> ads; // Adsorption term.
};
struct SimulatorData {
struct SimulatorData : public Opm::FIPDataEnums {
SimulatorData(int num_phases)
: rq(num_phases)
, rsSat(ADB::null())
@ -85,21 +85,18 @@ namespace Opm {
{
}
enum FipId {
FIP_AQUA = Opm::Water,
FIP_LIQUID = Opm::Oil,
FIP_VAPOUR = Opm::Gas,
FIP_DISSOLVED_GAS = 3,
FIP_VAPORIZED_OIL = 4,
FIP_PV = 5, //< Pore volume
FIP_WEIGHTED_PRESSURE = 6
};
using Opm::FIPDataEnums::FipId;
using Opm::FIPDataEnums::fipValues;
std::vector<ReservoirResidualQuant> rq;
ADB rsSat;
ADB rvSat;
std::array<V, 7> fip;
std::array<V, fipValues> fip;
};
typedef Opm::FIPData FIPDataType;
/// Construct a solver. It will retain references to the
/// arguments of this functions, and they are expected to
/// remain in scope for the lifetime of the solver.
@ -153,12 +150,17 @@ namespace Opm {
return sd_;
}
/// Return reservoir simulation data (for output functionality)
FIPDataType getFIPData() const {
return FIPDataType( sd_.fip );
}
/// Compute fluid in place.
/// \param[in] ReservoirState
/// \param[in] WellState
/// \param[in] FIPNUM for active cells not global cells.
/// \return fluid in place, number of fip regions, each region contains 5 values which are liquid, vapour, water, free gas and dissolved gas.
std::vector<std::vector<double> >
/// \return fluid in place, number of fip regions, each region contains 5 values which are liquid, vapour, water, free gas and dissolved gas.
std::vector<std::vector<double> >
computeFluidInPlace(const PolymerBlackoilState& x,
const std::vector<int>& fipnum);
@ -224,7 +226,7 @@ namespace Opm {
void
assemble(const double dt,
const PolymerBlackoilState& x,
const WellStateFullyImplicitBlackoil& xw,
const WellStateFullyImplicitBlackoil& xw,
const std::vector<double>& polymer_inflow);
V solveJacobianSystem() const;
@ -298,10 +300,10 @@ namespace Opm {
ADB
transMult(const ADB& p) const;
const std::vector<PhasePresence>
phaseCondition() const { return phaseCondition_; }
void
classifyCondition(const PolymerBlackoilState& state);
};