Removal of SimulatorFullyImplicitBlackoilOutputEbos.{h,c}pp.

All simulators now use SimulationDataContainer to store intermediate data that
is passed to the output Solution container. This is in cases not the most
efficient way, but it's unified to avoid errors from code duplication.
This commit is contained in:
Robert Kloefkorn 2017-02-09 13:54:42 +01:00
parent 9f34dc492e
commit 82658c92d0
13 changed files with 425 additions and 1204 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
@ -203,7 +202,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/core/simulator/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,130 @@ 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 numPhazes = numPhases();
SimulationDataContainer simData( numCells, 0, numPhazes );
//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 * numPhazes;
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();
}
// oil is always 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 std::move(simData);
}
const FIPDataType& getFIPData() const {
return fip_;
}
@ -1254,7 +1365,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 std::move( 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,
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/core/simulator/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

@ -32,6 +32,7 @@
#include <opm/polymer/fullyimplicit/PolymerPropsAd.hpp>
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/core/simulator/SimulatorTimerInterface.hpp>
#include <opm/common/data/SimulationDataContainer.hpp>
struct UnstructuredGrid;
struct Wells;
@ -76,7 +77,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 +86,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 +151,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 +227,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 +301,10 @@ namespace Opm {
ADB
transMult(const ADB& p) const;
const std::vector<PhasePresence>
phaseCondition() const { return phaseCondition_; }
void
classifyCondition(const PolymerBlackoilState& state);
};