Merge pull request #937 from chflo/OPM_251_support_restart

OPM-251: Prepare for restart
This commit is contained in:
dr-robertk 2016-01-15 14:44:06 -07:00
commit b26eb3827f
8 changed files with 231 additions and 107 deletions

View File

@ -157,7 +157,7 @@ list (APPEND MAIN_SOURCE_FILES
# find tests -name '*.cpp' -a ! -wholename '*/not-unit/*' -printf '\t%p\n' | sort
list (APPEND TEST_SOURCE_FILES
tests/test_writenumwells.cpp
tests/test_readWriteWellStateData.cpp
tests/test_writeReadRestartFile.cpp
tests/test_EclipseWriter.cpp
tests/test_EclipseWriteRFTHandler.cpp
tests/test_compressedpropertyaccess.cpp

View File

@ -20,6 +20,7 @@
#include "EclipseReader.hpp"
#include <opm/core/simulator/WellState.hpp>
#include <opm/core/simulator/SimulatorState.hpp>
#include <opm/core/simulator/BlackoilState.hpp>
#include <opm/core/utility/Units.hpp>
#include <opm/core/grid/GridHelpers.hpp>
#include <opm/core/io/eclipse/EclipseIOUtil.hpp>
@ -30,128 +31,211 @@
namespace Opm
{
void restoreOPM_XWELKeyword(const std::string& restart_filename, int reportstep, WellState& wellstate)
{
const char * keyword = "OPM_XWEL";
const char* filename = restart_filename.c_str();
ecl_file_type* file_type = ecl_file_open(filename, 0);
if (file_type != NULL) {
bool block_selected = ecl_file_select_rstblock_report_step(file_type , reportstep);
if (block_selected) {
ecl_kw_type* xwel = ecl_file_iget_named_kw(file_type , keyword, 0);
const double* xwel_data = ecl_kw_get_double_ptr(xwel);
std::copy_n(xwel_data + wellstate.getRestartTemperatureOffset(), wellstate.temperature().size(), wellstate.temperature().begin());
std::copy_n(xwel_data + wellstate.getRestartBhpOffset(), wellstate.bhp().size(), wellstate.bhp().begin());
std::copy_n(xwel_data + wellstate.getRestartPerfPressOffset(), wellstate.perfPress().size(), wellstate.perfPress().begin());
std::copy_n(xwel_data + wellstate.getRestartPerfRatesOffset(), wellstate.perfRates().size(), wellstate.perfRates().begin());
std::copy_n(xwel_data + wellstate.getRestartWellRatesOffset(), wellstate.wellRates().size(), wellstate.wellRates().begin());
}
ecl_file_close(file_type);
}
}
namespace {
void restoreTemperatureData(const ecl_file_type* file,
const EclipseState& eclipse_state,
const UnstructuredGrid& grid,
SimulatorState& simulator_state) {
const char* temperature_keyword = "TEMP";
EclipseStateConstPtr eclipse_state,
int numcells,
SimulatorState& simulator_state) {
const char* temperature = "TEMP";
if (ecl_file_has_kw(file , temperature_keyword)) {
ecl_kw_type* temperature_kw = ecl_file_iget_named_kw(file, temperature_keyword, 0);
if (ecl_file_has_kw(file , temperature)) {
ecl_kw_type* temperature_kw = ecl_file_iget_named_kw(file, temperature, 0);
if (ecl_kw_get_size(temperature_kw) != Opm::UgGridHelpers::numCells(grid)) {
if (ecl_kw_get_size(temperature_kw) != numcells) {
throw std::runtime_error("Read of restart file: Could not restore temperature data, length of data from file not equal number of cells");
}
float* temperature_data = ecl_kw_get_float_ptr(temperature_kw);
// factor and offset from the temperature values given in the deck to Kelvin
double scaling = eclipse_state.getDeckUnitSystem()->parse("Temperature")->getSIScaling();
double offset = eclipse_state.getDeckUnitSystem()->parse("Temperature")->getSIOffset();
double scaling = eclipse_state->getDeckUnitSystem()->parse("Temperature")->getSIScaling();
double offset = eclipse_state->getDeckUnitSystem()->parse("Temperature")->getSIOffset();
for (size_t index = 0; index < simulator_state.temperature().size(); ++index) {
simulator_state.temperature()[index] = unit::convert::from((double)temperature_data[index] - offset, scaling);
}
}
} else {
throw std::runtime_error("Read of restart file: File does not contain TEMP data\n");
}
}
void restorePressureData(const ecl_file_type* file,
const EclipseState& eclipse_state,
const UnstructuredGrid& grid,
EclipseStateConstPtr eclipse_state,
int numcells,
SimulatorState& simulator_state) {
const char* pressure_keyword = "PRESSURE";
const char* pressure = "PRESSURE";
if (ecl_file_has_kw(file , pressure_keyword)) {
if (ecl_file_has_kw(file , pressure)) {
ecl_kw_type* pressure_kw = ecl_file_iget_named_kw(file, pressure_keyword, 0);
ecl_kw_type* pressure_kw = ecl_file_iget_named_kw(file, pressure, 0);
if (ecl_kw_get_size(pressure_kw) != Opm::UgGridHelpers::numCells(grid)) {
if (ecl_kw_get_size(pressure_kw) != numcells) {
throw std::runtime_error("Read of restart file: Could not restore pressure data, length of data from file not equal number of cells");
}
float* pressure_data = ecl_kw_get_float_ptr(pressure_kw);
const double deck_pressure_unit = (eclipse_state.getDeckUnitSystem()->getType() == UnitSystem::UNIT_TYPE_METRIC) ? Opm::unit::barsa : Opm::unit::psia;
const double deck_pressure_unit = (eclipse_state->getDeckUnitSystem()->getType() == UnitSystem::UNIT_TYPE_METRIC) ? Opm::unit::barsa : Opm::unit::psia;
for (size_t index = 0; index < simulator_state.pressure().size(); ++index) {
simulator_state.pressure()[index] = unit::convert::from((double)pressure_data[index], deck_pressure_unit);
}
} else {
throw std::runtime_error("Read of restart file: File does not contain PRESSURE data\n");
}
}
}
void restoreSOLUTIONData(const std::string& restart_filename,
int reportstep,
const EclipseState& eclipseState,
const UnstructuredGrid& grid,
const PhaseUsage& phaseUsage,
SimulatorState& simulator_state)
void restoreSaturation(const ecl_file_type* file_type,
const PhaseUsage& phaseUsage,
int numcells,
SimulatorState& simulator_state) {
float* sgas_data = NULL;
float* swat_data = NULL;
if (phaseUsage.phase_used[BlackoilPhases::Aqua]) {
const char* swat = "SWAT";
if (ecl_file_has_kw(file_type, swat)) {
ecl_kw_type* swat_kw = ecl_file_iget_named_kw(file_type , swat, 0);
swat_data = ecl_kw_get_float_ptr(swat_kw);
std::vector<double> swat_datavec(&swat_data[0], &swat_data[numcells]);
EclipseIOUtil::addToStripedData(swat_datavec, simulator_state.saturation(), phaseUsage.phase_pos[BlackoilPhases::Aqua], phaseUsage.num_phases);
} else {
std::string error_str = "Restart file is missing SWAT data!\n";
throw std::runtime_error(error_str);
}
}
if (phaseUsage.phase_used[BlackoilPhases::Vapour]) {
const char* sgas = "SGAS";
if (ecl_file_has_kw(file_type, sgas)) {
ecl_kw_type* sgas_kw = ecl_file_iget_named_kw(file_type , sgas, 0);
sgas_data = ecl_kw_get_float_ptr(sgas_kw);
std::vector<double> sgas_datavec(&sgas_data[0], &sgas_data[numcells]);
EclipseIOUtil::addToStripedData(sgas_datavec, simulator_state.saturation(), phaseUsage.phase_pos[BlackoilPhases::Vapour], phaseUsage.num_phases);
} else {
std::string error_str = "Restart file is missing SGAS data!\n";
throw std::runtime_error(error_str);
}
}
}
void restoreRSandRV(const ecl_file_type* file_type,
SimulationConfigConstPtr sim_config,
int numcells,
BlackoilState* blackoil_state) {
if (sim_config->hasDISGAS()) {
const char* RS = "RS";
if (ecl_file_has_kw(file_type, RS)) {
ecl_kw_type* rs_kw = ecl_file_iget_named_kw(file_type, RS, 0);
float* rs_data = ecl_kw_get_float_ptr(rs_kw);
std::vector<double> rs_datavec(&rs_data[0], &rs_data[numcells]);
blackoil_state->gasoilratio().clear();
blackoil_state->gasoilratio().insert(blackoil_state->gasoilratio().begin(), rs_datavec.begin(), rs_datavec.end());
} else {
throw std::runtime_error("Restart file is missing RS data!\n");
}
}
if (sim_config->hasVAPOIL()) {
const char* RV = "RV";
if (ecl_file_has_kw(file_type, RV)) {
ecl_kw_type* rv_kw = ecl_file_iget_named_kw(file_type, RV, 0);
float* rv_data = ecl_kw_get_float_ptr(rv_kw);
std::vector<double> rv_datavec(&rv_data[0], &rv_data[numcells]);
blackoil_state->rv().clear();
blackoil_state->rv().insert(blackoil_state->rv().begin(), rv_datavec.begin(), rv_datavec.end());
} else {
throw std::runtime_error("Restart file is missing RV data!\n");
}
}
}
void restoreSOLUTION(const std::string& restart_filename,
int reportstep,
bool unified,
EclipseStateConstPtr eclipseState,
int numcells,
const PhaseUsage& phaseUsage,
SimulatorState& simulator_state)
{
const char* filename = restart_filename.c_str();
ecl_file_type* file_type = ecl_file_open(filename, 0);
if (file_type != NULL) {
bool block_selected = ecl_file_select_rstblock_report_step(file_type , reportstep);
if (file_type) {
bool block_selected = unified ? ecl_file_select_rstblock_report_step(file_type , reportstep) : true;
if (block_selected) {
restorePressureData(file_type, eclipseState, grid, simulator_state);
restoreTemperatureData(file_type, eclipseState, grid, simulator_state);
int numcells = Opm::UgGridHelpers::numCells(grid);
float* sgas_data = NULL;
float* swat_data = NULL;
if (phaseUsage.phase_used[BlackoilPhases::Aqua]) {
ecl_kw_type* swat_kw = ecl_file_iget_named_kw(file_type , "SWAT", 0);
swat_data = ecl_kw_get_float_ptr(swat_kw);
std::vector<double> swat_datavec(&swat_data[0], &swat_data[numcells]);
EclipseIOUtil::addToStripedData(swat_datavec, simulator_state.saturation(), phaseUsage.phase_pos[BlackoilPhases::Aqua], phaseUsage.num_phases);
}
if (phaseUsage.phase_used[BlackoilPhases::Vapour]) {
ecl_kw_type* sgas_kw = ecl_file_iget_named_kw(file_type , "SGAS", 0);
sgas_data = ecl_kw_get_float_ptr(sgas_kw);
std::vector<double> sgas_datavec(&sgas_data[0], &sgas_data[numcells]);
EclipseIOUtil::addToStripedData(sgas_datavec, simulator_state.saturation(), phaseUsage.phase_pos[BlackoilPhases::Vapour], phaseUsage.num_phases);
restorePressureData(file_type, eclipseState, numcells, simulator_state);
restoreTemperatureData(file_type, eclipseState, numcells, simulator_state);
restoreSaturation(file_type, phaseUsage, numcells, simulator_state);
BlackoilState* blackoilState = dynamic_cast<BlackoilState*>(&simulator_state);
if (blackoilState) {
SimulationConfigConstPtr sim_config = eclipseState->getSimulationConfig();
restoreRSandRV(file_type, sim_config, numcells, blackoilState);
}
} else {
std::cerr << "Warning: Could not load solution data for report step " << reportstep << ", data for reportstep not found on file " << filename << std::endl;
std::string error_str = "Restart file " + restart_filename + " does not contain data for report step " + std::to_string(reportstep) + "!\n";
throw std::runtime_error(error_str);
}
ecl_file_close(file_type);
} else {
std::string error_str = "Restart file " + restart_filename + " not found!\n";
throw std::runtime_error(error_str);
}
}
void restoreOPM_XWELKeyword(const std::string& restart_filename, int reportstep, bool unified, WellState& wellstate)
{
const char * keyword = "OPM_XWEL";
const char* filename = restart_filename.c_str();
ecl_file_type* file_type = ecl_file_open(filename, 0);
if (file_type != NULL) {
bool block_selected = unified ? ecl_file_select_rstblock_report_step(file_type , reportstep) : true;
if (block_selected) {
ecl_kw_type* xwel = ecl_file_iget_named_kw(file_type , keyword, 0);
const double* xwel_data = ecl_kw_get_double_ptr(xwel);
std::copy_n(xwel_data + wellstate.getRestartTemperatureOffset(), wellstate.temperature().size(), wellstate.temperature().begin());
std::copy_n(xwel_data + wellstate.getRestartBhpOffset(), wellstate.bhp().size(), wellstate.bhp().begin());
std::copy_n(xwel_data + wellstate.getRestartPerfPressOffset(), wellstate.perfPress().size(), wellstate.perfPress().begin());
std::copy_n(xwel_data + wellstate.getRestartPerfRatesOffset(), wellstate.perfRates().size(), wellstate.perfRates().begin());
std::copy_n(xwel_data + wellstate.getRestartWellRatesOffset(), wellstate.wellRates().size(), wellstate.wellRates().begin());
} else {
std::string error_str = "Restart file " + restart_filename + " does not contain data for report step " + std::to_string(reportstep) + "!\n";
throw std::runtime_error(error_str);
}
ecl_file_close(file_type);
} else {
std::string error_str = "Restart file " + restart_filename + " not found!\n";
throw std::runtime_error(error_str);
}
}
void init_from_restart_file(EclipseStateConstPtr eclipse_state,
int numcells,
const PhaseUsage& phase_usage,
SimulatorState& simulator_state,
WellState& wellstate) {
InitConfigConstPtr initConfig = eclipse_state->getInitConfig();
IOConfigConstPtr ioConfig = eclipse_state->getIOConfig();
int restart_step = initConfig->getRestartStep();
const std::string& restart_file_root = initConfig->getRestartRootName();
bool output = false;
const std::string& restart_file_name = ioConfig->getRestartFileName(restart_file_root, restart_step, output);
Opm::restoreSOLUTION(restart_file_name, restart_step, ioConfig->getUNIFIN(), eclipse_state, numcells, phase_usage, simulator_state);
Opm::restoreOPM_XWELKeyword(restart_file_name, restart_step, ioConfig->getUNIFIN(), wellstate);
}
} // namespace Opm

View File

@ -10,23 +10,24 @@
namespace Opm
{
///
/// \brief restoreOPM_XWELKeyword
/// Reading from the restart file, information stored under the OPM_XWEL keyword is in this method filled into
/// an instance of a wellstate object.
/// \param restart_filename
/// The filename of the restart file.
/// \param reportstep
/// The report step to restart from.
/// \brief init_from_restart_file
/// Reading from the restart file, information stored under the OPM_XWEL keyword and SOLUTION data is in this method filled into
/// an instance of a wellstate object and a SimulatorState object.
/// \param grid
/// UnstructuredGrid reference
/// \param pu
/// PhaseUsage reference
/// \param simulator_state
/// An instance of a SimulatorState object
/// \param wellstate
/// An instance of a WellState object, with correct size for each of the 5 contained std::vector<double> objects.
/// An instance of a WellState object, with correct size for each of the 5 contained std::vector<double> objects
///
void restoreOPM_XWELKeyword(const std::string& restart_filename, int report_step, WellState& wellState);
void restoreSOLUTIONData(const std::string& restart_filename,
int report_step,
const EclipseState &eclipseState,
const UnstructuredGrid& grid,
const PhaseUsage& phaseUsage,
SimulatorState& simulator_state);
void init_from_restart_file(EclipseStateConstPtr eclipse_state,
int numcells,
const PhaseUsage& pu,
SimulatorState& simulator_state,
WellState& wellstate);
}

View File

@ -370,6 +370,8 @@ public:
ecl_rsthead_type * rsthead_data)
{
ecl_util_set_date_values( rsthead_data->sim_time , &rsthead_data->day , &rsthead_data->month , &rsthead_data->year );
ecl_rst_file_fwrite_header(restartFileHandle_,
writeStepIdx,
rsthead_data);
@ -1338,6 +1340,17 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer,
sol.add(EclipseWriterDetails::Keyword<float>(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Vapour], saturation_gas));
}
const BlackoilState* blackoilState = dynamic_cast<const BlackoilState*>(&reservoirState);
if (blackoilState) {
// Write RS - Dissolved GOR
const std::vector<double>& rs = blackoilState->gasoilratio();
sol.add(EclipseWriterDetails::Keyword<float>("RS", rs));
// Write RV - Volatilized oil/gas ratio
const std::vector<double>& rv = blackoilState->rv();
sol.add(EclipseWriterDetails::Keyword<float>("RV", rv));
}
}

View File

@ -98,7 +98,8 @@ public:
*/
virtual void writeTimeStep(const SimulatorTimerInterface& timer,
const SimulatorState& reservoirState,
const WellState& wellState, bool isSubstep );
const WellState& wellState,
bool isSubstep);
static int eclipseWellTypeMask(WellType wellType, WellInjector::TypeEnum injectorType);

View File

@ -49,14 +49,16 @@ namespace Opm
}
/// Use the SimulatorTimer as a shim around opm-parser's Opm::TimeMap
void SimulatorTimer::init(Opm::TimeMapConstPtr timeMap)
void SimulatorTimer::init(Opm::TimeMapConstPtr timeMap, bool restart, size_t report_step)
{
current_step_ = 0;
total_time_ = timeMap->getTotalTime();
timesteps_.resize(timeMap->numTimesteps());
for ( size_t i = 0; i < timeMap->numTimesteps(); ++i ) {
timesteps_[i] = timeMap->getTimeStepLength(i);
}
setCurrentStepNum(report_step);
boost::posix_time::ptime start_time = timeMap->getStartTime(0);
start_date_ = start_time.date();
}

View File

@ -47,7 +47,7 @@ namespace Opm
void init(const parameter::ParameterGroup& param);
/// Use the SimulatorTimer as a shim around opm-parser's Opm::TimeMap
void init(TimeMapConstPtr timeMap);
void init(TimeMapConstPtr timeMap, bool restart = false, size_t report_step = 0);
/// Total number of steps.
int numSteps() const;

View File

@ -58,13 +58,16 @@
#include <string.h>
//
std::string input =
"RUNSPEC\n"
"OIL\n"
"GAS\n"
"WATER\n"
"DISGAS\n"
"VAPOIL\n"
"UNIFOUT\n"
"UNIFIN\n"
"DIMENS\n"
" 10 10 10 /\n"
@ -79,10 +82,16 @@ std::string input =
"100*0.25 /\n"
"\n"
"SOLUTION\n"
"RESTART\n"
"TESTWELLSTATE 1/\n"
"\n"
"START -- 0 \n"
"1 NOV 1979 / \n"
"SCHEDULE\n"
"SKIPREST\n"
"RPTRST\n"
"BASIC=1\n"
"/\n"
@ -240,7 +249,6 @@ void setValuesInWellState(std::shared_ptr<Opm::WellState> wellState){
BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData)
{
std::string eclipse_data_filename = "TestWellState.DATA";
std::string eclipse_restart_filename = "TESTWELLSTATE.UNRST";
test_work_area_type * test_area = test_work_area_alloc("EclipseReadWriteWellStateData");
Opm::Parser parser;
@ -281,18 +289,32 @@ BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData)
std::vector<double> sgasdata(1000, 9);
Opm::EclipseIOUtil::addToStripedData(sgasdata, blackoilState->saturation(), phaseUsage.phase_pos[Opm::BlackoilPhases::Vapour], phaseUsage.num_phases);
// Set test data for rs
double rs = 300.0;
std::vector<double>& rs_vec = blackoilState->gasoilratio();
for (std::vector<double>::iterator rs_iter = rs_vec.begin(); rs_iter != rs_vec.end(); ++ rs_iter) {
*rs_iter = rs;
rs = rs + 1.0;
}
// Set testdata for rv
double rv = 400.0;
std::vector<double>& rv_vec = blackoilState->rv();
for (std::vector<double>::iterator rv_iter = rv_vec.begin(); rv_iter != rv_vec.end(); ++rv_iter) {
*rv_iter = rv;
rv = rv + 1.0;
}
setValuesInWellState(wellState);
simTimer->setCurrentStepNum(1);
eclipseWriter->writeTimeStep(*simTimer, *blackoilState, *wellState , false);
const char * test_area_path = test_work_area_get_cwd(test_area);
std::string slash = "/";
const std::string restart_filename = test_area_path + slash + eclipse_restart_filename;
std::shared_ptr<Opm::WellState> wellStateRestored(new Opm::WellState());
wellStateRestored->init(wells, *blackoilState);
//Read and verify OPM XWEL data
Opm::restoreOPM_XWELKeyword(restart_filename, 1, *wellStateRestored);
//Read and verify OPM XWEL data, and solution data: pressure, temperature, saturation data, rs and rv
std::shared_ptr<Opm::BlackoilState> blackoilStateRestored = createBlackOilState(eclipseState->getEclipseGrid());
Opm::init_from_restart_file(eclipseState, Opm::UgGridHelpers::numCells(*gridManager.c_grid()), phaseUsage, *blackoilStateRestored, *wellStateRestored);
BOOST_CHECK_EQUAL_COLLECTIONS(wellState->bhp().begin(), wellState->bhp().end(), wellStateRestored->bhp().begin(), wellStateRestored->bhp().end());
BOOST_CHECK_EQUAL_COLLECTIONS(wellState->temperature().begin(), wellState->temperature().end(), wellStateRestored->temperature().begin(), wellStateRestored->temperature().end());
@ -300,11 +322,6 @@ BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData)
BOOST_CHECK_EQUAL_COLLECTIONS(wellState->perfRates().begin(), wellState->perfRates().end(), wellStateRestored->perfRates().begin(), wellStateRestored->perfRates().end());
BOOST_CHECK_EQUAL_COLLECTIONS(wellState->perfPress().begin(), wellState->perfPress().end(), wellStateRestored->perfPress().begin(), wellStateRestored->perfPress().end());
//Read and verify pressure, temperature and saturation data
std::shared_ptr<Opm::BlackoilState> blackoilStateRestored = createBlackOilState(eclipseState->getEclipseGrid());
Opm::restoreSOLUTIONData(restart_filename, 1, *eclipseState, *gridManager.c_grid(), phaseUsage, *blackoilStateRestored);
std::vector<double> swat_restored;
std::vector<double> swat;
std::vector<double> sgas_restored;
@ -321,5 +338,11 @@ BOOST_AUTO_TEST_CASE(EclipseReadWriteWellStateData)
BOOST_CHECK_CLOSE(sgas[cellindex], sgas_restored[cellindex], 0.00001);
}
for (size_t cellindex = 0; cellindex < 1000; ++cellindex) {
BOOST_CHECK_CLOSE(blackoilState->gasoilratio()[cellindex], blackoilStateRestored->gasoilratio()[cellindex], 0.0000001);
BOOST_CHECK_CLOSE(blackoilState->rv()[cellindex], blackoilStateRestored->rv()[cellindex], 0.0000001);
}
test_work_area_free(test_area);
}