Merge pull request #812 from chflo/OPM-206

Opm 206 Use IOConfig from EclipseState to decide which Eclipse output files to write (and when)
This commit is contained in:
Joakim Hove 2015-06-15 17:30:03 +02:00
commit b29ea2ae1c
4 changed files with 130 additions and 106 deletions

View File

@ -237,12 +237,13 @@ public:
FileName(const std::string& outputDir, FileName(const std::string& outputDir,
const std::string& baseName, const std::string& baseName,
ecl_file_enum type, ecl_file_enum type,
int writeStepIdx) int writeStepIdx,
bool formatted)
{ {
ertHandle_ = ecl_util_alloc_filename(outputDir.c_str(), ertHandle_ = ecl_util_alloc_filename(outputDir.c_str(),
baseName.c_str(), baseName.c_str(),
type, type,
false, // formatted? formatted,
writeStepIdx); writeStepIdx);
} }
@ -284,19 +285,23 @@ public:
Restart(const std::string& outputDir, Restart(const std::string& outputDir,
const std::string& baseName, const std::string& baseName,
int writeStepIdx) int writeStepIdx,
IOConfigConstPtr ioConfig)
{ {
ecl_file_enum type_of_restart_file = ioConfig->getUNIFOUT() ? ECL_UNIFIED_RESTART_FILE : ECL_RESTART_FILE;
restartFileName_ = ecl_util_alloc_filename(outputDir.c_str(), restartFileName_ = ecl_util_alloc_filename(outputDir.c_str(),
baseName.c_str(), baseName.c_str(),
/*type=*/ECL_UNIFIED_RESTART_FILE, type_of_restart_file,
false, // use formatted instead of binary output? ioConfig->getFMTOUT(), // use formatted instead of binary output?
writeStepIdx); writeStepIdx);
if (writeStepIdx == 0) { if ((writeStepIdx > 0) && (ECL_UNIFIED_RESTART_FILE == type_of_restart_file)) {
restartFileHandle_ = ecl_rst_file_open_write(restartFileName_); restartFileHandle_ = ecl_rst_file_open_append(restartFileName_);
} }
else { else {
restartFileHandle_ = ecl_rst_file_open_append(restartFileName_); restartFileHandle_ = ecl_rst_file_open_write(restartFileName_);
} }
} }
@ -499,25 +504,23 @@ class Init : private boost::noncopyable
public: public:
Init(const std::string& outputDir, Init(const std::string& outputDir,
const std::string& baseName, const std::string& baseName,
int writeStepIdx) int writeStepIdx,
: egridFileName_(outputDir, IOConfigConstPtr ioConfig) : egridFileName_(outputDir,
baseName, baseName,
ECL_EGRID_FILE, ECL_EGRID_FILE,
writeStepIdx) writeStepIdx,
ioConfig->getFMTOUT())
{ {
bool formatted = ioConfig->getFMTOUT();
FileName initFileName(outputDir, FileName initFileName(outputDir,
baseName, baseName,
ECL_INIT_FILE, ECL_INIT_FILE,
writeStepIdx); writeStepIdx,
formatted);
bool isFormatted;
if (!ecl_util_fmt_file(initFileName.ertHandle(), &isFormatted)) {
OPM_THROW(std::runtime_error,
"Could not determine formatted/unformatted status of file:" << initFileName.ertHandle() << " non-standard name?" << std::endl);
}
ertHandle_ = fortio_open_writer(initFileName.ertHandle(), ertHandle_ = fortio_open_writer(initFileName.ertHandle(),
isFormatted, formatted,
ECL_ENDIAN_FLIP); ECL_ENDIAN_FLIP);
} }
@ -549,18 +552,24 @@ public:
// finally, write the grid to disk // finally, write the grid to disk
if (eclipseState->getDeckUnitSystem()->getType() == UnitSystem::UNIT_TYPE_METRIC){ IOConfigConstPtr ioConfig = eclipseState->getIOConfigConst();
eclGrid->fwriteEGRID(egridFileName_.ertHandle(), true); if (ioConfig->getWriteEGRIDFile()) {
}else{ if (eclipseState->getDeckUnitSystem()->getType() == UnitSystem::UNIT_TYPE_METRIC){
eclGrid->fwriteEGRID(egridFileName_.ertHandle(), false); eclGrid->fwriteEGRID(egridFileName_.ertHandle(), true);
}else{
eclGrid->fwriteEGRID(egridFileName_.ertHandle(), false);
}
} }
Keyword<float> poro_kw("PORO", dataField);
ecl_init_file_fwrite_header(ertHandle(), if (ioConfig->getWriteINITFile()) {
eclGrid->c_ptr(), Keyword<float> poro_kw("PORO", dataField);
poro_kw.ertHandle(), ecl_init_file_fwrite_header(ertHandle(),
ertPhaseMask(uses), eclGrid->c_ptr(),
timer.currentPosixTime()); poro_kw.ertHandle(),
ertPhaseMask(uses),
timer.currentPosixTime());
}
} }
void writeKeyword(const std::string& keywordName, const std::vector<double> &data) void writeKeyword(const std::string& keywordName, const std::vector<double> &data)
@ -577,6 +586,9 @@ private:
FileName egridFileName_; FileName egridFileName_;
}; };
/** /**
* Summary variable that reports a characteristics of a well. * Summary variable that reports a characteristics of a well.
*/ */
@ -1149,27 +1161,31 @@ void EclipseWriter::writeInit(const SimulatorTimerInterface &timer)
writeStepIdx_ = 0; writeStepIdx_ = 0;
reportStepIdx_ = -1; reportStepIdx_ = -1;
EclipseWriterDetails::Init fortio(outputDir_, baseName_, /*stepIdx=*/0); EclipseWriterDetails::Init fortio(outputDir_, baseName_, /*stepIdx=*/0, eclipseState_->getIOConfigConst());
fortio.writeHeader(numCells_, fortio.writeHeader(numCells_,
compressedToCartesianCellIdx_, compressedToCartesianCellIdx_,
timer, timer,
eclipseState_, eclipseState_,
phaseUsage_); phaseUsage_);
if (eclipseState_->hasDoubleGridProperty("PERMX")) { IOConfigConstPtr ioConfig = eclipseState_->getIOConfigConst();
auto data = eclipseState_->getDoubleGridProperty("PERMX")->getData();
EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy); if (ioConfig->getWriteINITFile()) {
fortio.writeKeyword("PERMX", data); if (eclipseState_->hasDoubleGridProperty("PERMX")) {
} auto data = eclipseState_->getDoubleGridProperty("PERMX")->getData();
if (eclipseState_->hasDoubleGridProperty("PERMY")) { EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy);
auto data = eclipseState_->getDoubleGridProperty("PERMY")->getData(); fortio.writeKeyword("PERMX", data);
EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy); }
fortio.writeKeyword("PERMY", data); if (eclipseState_->hasDoubleGridProperty("PERMY")) {
} auto data = eclipseState_->getDoubleGridProperty("PERMY")->getData();
if (eclipseState_->hasDoubleGridProperty("PERMZ")) { EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy);
auto data = eclipseState_->getDoubleGridProperty("PERMZ")->getData(); fortio.writeKeyword("PERMY", data);
EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy); }
fortio.writeKeyword("PERMZ", data); if (eclipseState_->hasDoubleGridProperty("PERMZ")) {
auto data = eclipseState_->getDoubleGridProperty("PERMZ")->getData();
EclipseWriterDetails::convertFromSiTo(data, Opm::prefix::milli * Opm::unit::darcy);
fortio.writeKeyword("PERMZ", data);
}
} }
/* Create summary object (could not do it at construction time, /* Create summary object (could not do it at construction time,
@ -1205,13 +1221,38 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer,
return; return;
} }
// respected the output_interval parameter
if (writeStepIdx_ % outputInterval_ != 0) { std::vector<double> pressure = reservoirState.pressure();
return; EclipseWriterDetails::convertFromSiTo(pressure, deckToSiPressure_);
EclipseWriterDetails::restrictAndReorderToActiveCells(pressure, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
std::vector<double> saturation_water;
std::vector<double> saturation_gas;
if (phaseUsage_.phase_used[BlackoilPhases::Aqua]) {
saturation_water = reservoirState.saturation();
EclipseWriterDetails::extractFromStripedData(saturation_water,
/*offset=*/phaseUsage_.phase_pos[BlackoilPhases::Aqua],
/*stride=*/phaseUsage_.num_phases);
EclipseWriterDetails::restrictAndReorderToActiveCells(saturation_water, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
} }
// only write solution when report step number has changed
if( reportStepIdx_ != timer.reportStepNum() ) if (phaseUsage_.phase_used[BlackoilPhases::Vapour]) {
saturation_gas = reservoirState.saturation();
EclipseWriterDetails::extractFromStripedData(saturation_gas,
/*offset=*/phaseUsage_.phase_pos[BlackoilPhases::Vapour],
/*stride=*/phaseUsage_.num_phases);
EclipseWriterDetails::restrictAndReorderToActiveCells(saturation_gas, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
}
IOConfigConstPtr ioConfig = eclipseState_->getIOConfigConst();
// Write restart file
if(ioConfig->getWriteRestartFile(timer.reportStepNum()))
{ {
const size_t ncwmax = eclipseState_->getSchedule()->getMaxNumCompletionsForWells(timer.reportStepNum()); const size_t ncwmax = eclipseState_->getSchedule()->getMaxNumCompletionsForWells(timer.reportStepNum());
const size_t numWells = eclipseState_->getSchedule()->numWells(timer.reportStepNum()); const size_t numWells = eclipseState_->getSchedule()->numWells(timer.reportStepNum());
@ -1221,7 +1262,8 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer,
std::vector<int> iwell_data( numWells * Opm::EclipseWriterDetails::Restart::NIWELZ , 0 ); std::vector<int> iwell_data( numWells * Opm::EclipseWriterDetails::Restart::NIWELZ , 0 );
std::vector<int> icon_data( numWells * ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ , 0 ); std::vector<int> icon_data( numWells * ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ , 0 );
EclipseWriterDetails::Restart restartHandle(outputDir_, baseName_, timer.reportStepNum());
EclipseWriterDetails::Restart restartHandle(outputDir_, baseName_, timer.reportStepNum(), ioConfig);
for (size_t iwell = 0; iwell < wells_ptr.size(); ++iwell) { for (size_t iwell = 0; iwell < wells_ptr.size(); ++iwell) {
WellConstPtr well = wells_ptr[iwell]; WellConstPtr well = wells_ptr[iwell];
@ -1236,6 +1278,7 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer,
zwell_data[ iwell * Opm::EclipseWriterDetails::Restart::NZWELZ ] = well->name().c_str(); zwell_data[ iwell * Opm::EclipseWriterDetails::Restart::NZWELZ ] = well->name().c_str();
} }
{ {
ecl_rsthead_type rsthead_data = {}; ecl_rsthead_type rsthead_data = {};
rsthead_data.sim_time = timer.currentPosixTime(); rsthead_data.sim_time = timer.currentPosixTime();
@ -1261,82 +1304,62 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer,
restartHandle.add_kw(EclipseWriterDetails::Keyword<const char *>(ZWEL_KW, zwell_data)); restartHandle.add_kw(EclipseWriterDetails::Keyword<const char *>(ZWEL_KW, zwell_data));
restartHandle.add_kw(EclipseWriterDetails::Keyword<int>(ICON_KW, icon_data)); restartHandle.add_kw(EclipseWriterDetails::Keyword<int>(ICON_KW, icon_data));
EclipseWriterDetails::Solution sol(restartHandle); EclipseWriterDetails::Solution sol(restartHandle);
// write out the pressure of the reference phase (whatever phase that is...). this is
// not the most performant solution thinkable, but this is also not in the most
// performance critical code path!
//
// Also, we want to use the same units as the deck for pressure output, i.e. we have
// to mutliate our nice SI pressures by the inverse of the conversion factor of deck
// to SI pressure units...
std::vector<double> pressure = reservoirState.pressure();
EclipseWriterDetails::convertFromSiTo(pressure, deckToSiPressure_);
EclipseWriterDetails::restrictAndReorderToActiveCells(pressure, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
sol.add(EclipseWriterDetails::Keyword<float>("PRESSURE", pressure)); sol.add(EclipseWriterDetails::Keyword<float>("PRESSURE", pressure));
// write the cell temperature // write the cell temperature
std::vector<double> temperature = reservoirState.temperature(); std::vector<double> temperature = reservoirState.temperature();
EclipseWriterDetails::convertFromSiTo(temperature, deckToSiTemperatureFactor_, deckToSiTemperatureOffset_); EclipseWriterDetails::convertFromSiTo(temperature, deckToSiTemperatureFactor_, deckToSiTemperatureOffset_);
EclipseWriterDetails::restrictAndReorderToActiveCells(temperature, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); EclipseWriterDetails::restrictAndReorderToActiveCells(temperature, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
sol.add(EclipseWriterDetails::Keyword<float>("TEMP", temperature)); sol.add(EclipseWriterDetails::Keyword<float>("TEMP", temperature));
std::vector<double> saturation_water;
std::vector<double> saturation_gas;
if (phaseUsage_.phase_used[BlackoilPhases::Aqua]) { if (phaseUsage_.phase_used[BlackoilPhases::Aqua]) {
saturation_water = reservoirState.saturation();
EclipseWriterDetails::extractFromStripedData(saturation_water,
/*offset=*/phaseUsage_.phase_pos[BlackoilPhases::Aqua],
/*stride=*/phaseUsage_.num_phases);
EclipseWriterDetails::restrictAndReorderToActiveCells(saturation_water, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
sol.add(EclipseWriterDetails::Keyword<float>(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Aqua], saturation_water)); sol.add(EclipseWriterDetails::Keyword<float>(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Aqua], saturation_water));
} }
if (phaseUsage_.phase_used[BlackoilPhases::Vapour]) { if (phaseUsage_.phase_used[BlackoilPhases::Vapour]) {
saturation_gas = reservoirState.saturation();
EclipseWriterDetails::extractFromStripedData(saturation_gas,
/*offset=*/phaseUsage_.phase_pos[BlackoilPhases::Vapour],
/*stride=*/phaseUsage_.num_phases);
EclipseWriterDetails::restrictAndReorderToActiveCells(saturation_gas, gridToEclipseIdx_.size(), gridToEclipseIdx_.data());
sol.add(EclipseWriterDetails::Keyword<float>(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Vapour], saturation_gas)); sol.add(EclipseWriterDetails::Keyword<float>(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Vapour], saturation_gas));
} }
}
//Write RFT data for current timestep to RFT file //Write RFT data for current timestep to RFT file
std::shared_ptr<EclipseWriterDetails::EclipseWriteRFTHandler> eclipseWriteRFTHandler = std::make_shared<EclipseWriterDetails::EclipseWriteRFTHandler>( std::shared_ptr<EclipseWriterDetails::EclipseWriteRFTHandler> eclipseWriteRFTHandler = std::make_shared<EclipseWriterDetails::EclipseWriteRFTHandler>(
compressedToCartesianCellIdx_, compressedToCartesianCellIdx_,
numCells_, numCells_,
eclipseState_->getEclipseGrid()->getCartesianSize()); eclipseState_->getEclipseGrid()->getCartesianSize());
char * rft_filename = ecl_util_alloc_filename(outputDir_.c_str(), char * rft_filename = ecl_util_alloc_filename(outputDir_.c_str(),
baseName_.c_str(), baseName_.c_str(),
ECL_RFT_FILE, ECL_RFT_FILE,
false, ioConfig->getFMTOUT(),
0); 0);
std::shared_ptr<const UnitSystem> unitsystem = eclipseState_->getDeckUnitSystem(); std::shared_ptr<const UnitSystem> unitsystem = eclipseState_->getDeckUnitSystem();
ert_ecl_unit_enum ecl_unit = convertUnitTypeErtEclUnitEnum(unitsystem->getType()); ert_ecl_unit_enum ecl_unit = convertUnitTypeErtEclUnitEnum(unitsystem->getType());
std::vector<WellConstPtr> wells = eclipseState_->getSchedule()->getWells(timer.currentStepNum()); std::vector<WellConstPtr> wells = eclipseState_->getSchedule()->getWells(timer.currentStepNum());
eclipseWriteRFTHandler->writeTimeStep(rft_filename, eclipseWriteRFTHandler->writeTimeStep(rft_filename,
ecl_unit, ecl_unit,
timer, timer,
wells, wells,
eclipseState_->getEclipseGrid(), eclipseState_->getEclipseGrid(),
pressure, pressure,
saturation_water, saturation_water,
saturation_gas); saturation_gas);
free( rft_filename );
free( rft_filename );
} // end if( reportStepIdx_ != timer.reportStepNum() )
/* Summary variables (well reporting) */ /* Summary variables (well reporting) */
// TODO: instead of writing the header (smspec) every time, it should // TODO: instead of writing the header (smspec) every time, it should
@ -1428,10 +1451,6 @@ void EclipseWriter::init(const parameter::ParameterGroup& params)
// retrieve the value of the "output" parameter // retrieve the value of the "output" parameter
enableOutput_ = params.getDefault<bool>("output", /*defaultValue=*/true); enableOutput_ = params.getDefault<bool>("output", /*defaultValue=*/true);
// retrieve the interval at which something should get written to
// disk (once every N timesteps)
outputInterval_ = params.getDefault<int>("output_interval", /*defaultValue=*/1);
// store in current directory if not explicitly set // store in current directory if not explicitly set
outputDir_ = params.getDefault<std::string>("output_dir", "."); outputDir_ = params.getDefault<std::string>("output_dir", ".");

View File

@ -115,7 +115,6 @@ private:
double deckToSiTemperatureFactor_; double deckToSiTemperatureFactor_;
double deckToSiTemperatureOffset_; double deckToSiTemperatureOffset_;
bool enableOutput_; bool enableOutput_;
int outputInterval_;
int writeStepIdx_; int writeStepIdx_;
int reportStepIdx_; int reportStepIdx_;
std::string outputDir_; std::string outputDir_;

View File

@ -365,6 +365,8 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
{ {
const char *deckString = const char *deckString =
"RUNSPEC\n" "RUNSPEC\n"
"INIT\n"
"UNIFOUT\n"
"OIL\n" "OIL\n"
"GAS\n" "GAS\n"
"WATER\n" "WATER\n"
@ -386,6 +388,9 @@ BOOST_AUTO_TEST_CASE(EclipseWriterIntegration)
"PERMX\n" "PERMX\n"
"27*1 /\n" "27*1 /\n"
"SCHEDULE\n" "SCHEDULE\n"
"RPTRST\n"
"BASIC=1\n"
"/\n"
"TSTEP\n" "TSTEP\n"
"1.0 2.0 3.0 4.0 /\n" "1.0 2.0 3.0 4.0 /\n"
"WELSPECS\n" "WELSPECS\n"

View File

@ -162,7 +162,8 @@ Opm::EclipseWriterPtr createEclipseWriter(Opm::DeckConstPtr deck,
BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo) BOOST_AUTO_TEST_CASE(EclipseWriteRestartWellInfo)
{ {
std::string eclipse_data_filename = "testBlackoilState3.DATA"; std::string eclipse_data_filename = "testBlackoilState3.DATA";
std::string eclipse_restart_filename = "TESTBLACKOILSTATE3.UNRST"; std::string eclipse_restart_filename = "TESTBLACKOILSTATE3.X0004";
test_work_area_type * test_area = test_work_area_alloc("TEST_EclipseWriteNumWells"); test_work_area_type * test_area = test_work_area_alloc("TEST_EclipseWriteNumWells");
test_work_area_copy_file(test_area, eclipse_data_filename.c_str()); test_work_area_copy_file(test_area, eclipse_data_filename.c_str());