From a854bdc5b846f6a04fc8af10d8e1e0d77d9dc1b5 Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn Date: Mon, 9 Mar 2015 10:26:43 +0100 Subject: [PATCH 1/4] EclipseWriter: only write summary in sub steps that are not report steps. --- opm/core/io/eclipse/EclipseWriter.cpp | 200 +++++++++++++------------- opm/core/io/eclipse/EclipseWriter.hpp | 1 + 2 files changed, 105 insertions(+), 96 deletions(-) diff --git a/opm/core/io/eclipse/EclipseWriter.cpp b/opm/core/io/eclipse/EclipseWriter.cpp index 95af6a4d..50050133 100644 --- a/opm/core/io/eclipse/EclipseWriter.cpp +++ b/opm/core/io/eclipse/EclipseWriter.cpp @@ -2,6 +2,7 @@ Copyright (c) 2013-2014 Andreas Lauser Copyright (c) 2013 SINTEF ICT, Applied Mathematics. Copyright (c) 2013 Uni Research AS + Copyright (c) 2015 IRIS AS This file is part of the Open Porous Media project (OPM). @@ -1032,6 +1033,7 @@ void EclipseWriter::writeInit(const SimulatorTimerInterface &timer) } writeStepIdx_ = 0; + reportStepIdx_ = -1; EclipseWriterDetails::Init fortio(outputDir_, baseName_, /*stepIdx=*/0); fortio.writeHeader(numCells_, @@ -1084,123 +1086,126 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer, return; } - const size_t ncwmax = eclipseState_->getSchedule()->getMaxNumCompletionsForWells(timer.reportStepNum()); - const size_t numWells = eclipseState_->getSchedule()->numWells(timer.reportStepNum()); - std::vector wells_ptr = eclipseState_->getSchedule()->getWells(timer.reportStepNum()); - - std::vector zwell_data( numWells * Opm::EclipseWriterDetails::Restart::NZWELZ , ""); - std::vector iwell_data( numWells * Opm::EclipseWriterDetails::Restart::NIWELZ , 0 ); - std::vector icon_data( numWells * ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ , 0 ); - - EclipseWriterDetails::Restart restartHandle(outputDir_, baseName_, writeStepIdx_); - - for (size_t iwell = 0; iwell < wells_ptr.size(); ++iwell) { - WellConstPtr well = wells_ptr[iwell]; - { - size_t wellIwelOffset = Opm::EclipseWriterDetails::Restart::NIWELZ * iwell; - restartHandle.addRestartFileIwelData(iwell_data, timer.reportStepNum(), well , wellIwelOffset); - } - { - size_t wellIconOffset = ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ * iwell; - restartHandle.addRestartFileIconData(icon_data, well->getCompletions( timer.reportStepNum() ), wellIconOffset); - } - zwell_data[ iwell * Opm::EclipseWriterDetails::Restart::NZWELZ ] = well->name().c_str(); - } - + // only write solution when report step number has changed + if( reportStepIdx_ != timer.reportStepNum() ) { - ecl_rsthead_type rsthead_data = {}; - rsthead_data.sim_time = timer.currentPosixTime(); - rsthead_data.nactive = numCells_; - rsthead_data.nx = cartesianSize_[0]; - rsthead_data.ny = cartesianSize_[1]; - rsthead_data.nz = cartesianSize_[2]; - rsthead_data.nwells = numWells; - rsthead_data.niwelz = EclipseWriterDetails::Restart::NIWELZ; - rsthead_data.nzwelz = EclipseWriterDetails::Restart::NZWELZ; - rsthead_data.niconz = EclipseWriterDetails::Restart::NICONZ; - rsthead_data.ncwmax = ncwmax; - rsthead_data.phase_sum = Opm::EclipseWriterDetails::ertPhaseMask(phaseUsage_); - rsthead_data.sim_days = Opm::unit::convert::to(timer.simulationTimeElapsed(), Opm::unit::day); //data for doubhead + const size_t ncwmax = eclipseState_->getSchedule()->getMaxNumCompletionsForWells(timer.reportStepNum()); + const size_t numWells = eclipseState_->getSchedule()->numWells(timer.reportStepNum()); + std::vector wells_ptr = eclipseState_->getSchedule()->getWells(timer.reportStepNum()); - restartHandle.writeHeader(timer, - writeStepIdx_, - &rsthead_data); - } + std::vector zwell_data( numWells * Opm::EclipseWriterDetails::Restart::NZWELZ , ""); + std::vector iwell_data( numWells * Opm::EclipseWriterDetails::Restart::NIWELZ , 0 ); + std::vector icon_data( numWells * ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ , 0 ); + + EclipseWriterDetails::Restart restartHandle(outputDir_, baseName_, timer.reportStepNum()); + + for (size_t iwell = 0; iwell < wells_ptr.size(); ++iwell) { + WellConstPtr well = wells_ptr[iwell]; + { + size_t wellIwelOffset = Opm::EclipseWriterDetails::Restart::NIWELZ * iwell; + restartHandle.addRestartFileIwelData(iwell_data, timer.reportStepNum(), well , wellIwelOffset); + } + { + size_t wellIconOffset = ncwmax * Opm::EclipseWriterDetails::Restart::NICONZ * iwell; + restartHandle.addRestartFileIconData(icon_data, well->getCompletions( timer.reportStepNum() ), wellIconOffset); + } + zwell_data[ iwell * Opm::EclipseWriterDetails::Restart::NZWELZ ] = well->name().c_str(); + } + + { + ecl_rsthead_type rsthead_data = {}; + rsthead_data.sim_time = timer.currentPosixTime(); + rsthead_data.nactive = numCells_; + rsthead_data.nx = cartesianSize_[0]; + rsthead_data.ny = cartesianSize_[1]; + rsthead_data.nz = cartesianSize_[2]; + rsthead_data.nwells = numWells; + rsthead_data.niwelz = EclipseWriterDetails::Restart::NIWELZ; + rsthead_data.nzwelz = EclipseWriterDetails::Restart::NZWELZ; + rsthead_data.niconz = EclipseWriterDetails::Restart::NICONZ; + rsthead_data.ncwmax = ncwmax; + rsthead_data.phase_sum = Opm::EclipseWriterDetails::ertPhaseMask(phaseUsage_); + rsthead_data.sim_days = Opm::unit::convert::to(timer.simulationTimeElapsed(), Opm::unit::day); //data for doubhead + + restartHandle.writeHeader(timer, + timer.reportStepNum(), + &rsthead_data); + } - restartHandle.add_kw(EclipseWriterDetails::Keyword(IWEL_KW, iwell_data)); - restartHandle.add_kw(EclipseWriterDetails::Keyword(ZWEL_KW, zwell_data)); - restartHandle.add_kw(EclipseWriterDetails::Keyword(ICON_KW, icon_data)); + restartHandle.add_kw(EclipseWriterDetails::Keyword(IWEL_KW, iwell_data)); + restartHandle.add_kw(EclipseWriterDetails::Keyword(ZWEL_KW, zwell_data)); + restartHandle.add_kw(EclipseWriterDetails::Keyword(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 pressure = reservoirState.pressure(); - EclipseWriterDetails::convertFromSiTo(pressure, deckToSiPressure_); - EclipseWriterDetails::restrictAndReorderToActiveCells(pressure, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); + // 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 pressure = reservoirState.pressure(); + EclipseWriterDetails::convertFromSiTo(pressure, deckToSiPressure_); + EclipseWriterDetails::restrictAndReorderToActiveCells(pressure, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); - sol.add(EclipseWriterDetails::Keyword("PRESSURE", pressure)); + sol.add(EclipseWriterDetails::Keyword("PRESSURE", pressure)); - std::vector saturation_water; - std::vector saturation_gas; + std::vector saturation_water; + std::vector 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()); - sol.add(EclipseWriterDetails::Keyword(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Aqua], saturation_water)); - } + 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(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Aqua], saturation_water)); + } - 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(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Vapour], saturation_gas)); - } + 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(EclipseWriterDetails::saturationKeywordNames[BlackoilPhases::PhaseIndex::Vapour], saturation_gas)); + } - //Write RFT data for current timestep to RFT file - std::shared_ptr eclipseWriteRFTHandler = std::make_shared( - compressedToCartesianCellIdx_, - numCells_, - eclipseState_->getEclipseGrid()->getCartesianSize()); + //Write RFT data for current timestep to RFT file + std::shared_ptr eclipseWriteRFTHandler = std::make_shared( + compressedToCartesianCellIdx_, + numCells_, + eclipseState_->getEclipseGrid()->getCartesianSize()); - char * rft_filename = ecl_util_alloc_filename(outputDir_.c_str(), - baseName_.c_str(), - ECL_RFT_FILE, - false, - 0); + char * rft_filename = ecl_util_alloc_filename(outputDir_.c_str(), + baseName_.c_str(), + ECL_RFT_FILE, + false, + 0); - std::shared_ptr unitsystem = eclipseState_->getDeckUnitSystem(); - ert_ecl_unit_enum ecl_unit = convertUnitTypeErtEclUnitEnum(unitsystem->getType()); + std::shared_ptr unitsystem = eclipseState_->getDeckUnitSystem(); + ert_ecl_unit_enum ecl_unit = convertUnitTypeErtEclUnitEnum(unitsystem->getType()); - std::vector wells = eclipseState_->getSchedule()->getWells(timer.currentStepNum()); + std::vector wells = eclipseState_->getSchedule()->getWells(timer.currentStepNum()); - eclipseWriteRFTHandler->writeTimeStep(rft_filename, - ecl_unit, - timer, - wells, - eclipseState_->getEclipseGrid(), - pressure, - saturation_water, - saturation_gas); - + eclipseWriteRFTHandler->writeTimeStep(rft_filename, + ecl_unit, + timer, + wells, + eclipseState_->getEclipseGrid(), + pressure, + saturation_water, + saturation_gas); + } // end if( reportStepIdx_ != timer.reportStepNum() ) /* Summary variables (well reporting) */ // TODO: instead of writing the header (smspec) every time, it should @@ -1217,6 +1222,8 @@ void EclipseWriter::writeTimeStep(const SimulatorTimerInterface& timer, summary_->writeTimeStep(writeStepIdx_, timer, wellState); ++writeStepIdx_; + // store current report index + reportStepIdx_ = timer.reportStepNum(); } @@ -1292,7 +1299,8 @@ void EclipseWriter::init(const parameter::ParameterGroup& params) outputDir_ = params.getDefault("output_dir", "."); // set the index of the first time step written to 0... - writeStepIdx_ = 0; + writeStepIdx_ = 0; + reportStepIdx_ = -1; if (enableOutput_) { // make sure that the output directory exists, if not try to create it diff --git a/opm/core/io/eclipse/EclipseWriter.hpp b/opm/core/io/eclipse/EclipseWriter.hpp index 43c9c5b6..22670ee4 100644 --- a/opm/core/io/eclipse/EclipseWriter.hpp +++ b/opm/core/io/eclipse/EclipseWriter.hpp @@ -115,6 +115,7 @@ private: bool enableOutput_; int outputInterval_; int writeStepIdx_; + int reportStepIdx_; std::string outputDir_; std::string baseName_; PhaseUsage phaseUsage_; // active phases in the input deck From 75639d2824f934f80dda72d98be361e48cfe34de Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn Date: Mon, 9 Mar 2015 10:41:00 +0100 Subject: [PATCH 2/4] [cleanup] remove warnings and avoid return of uninitialized values. --- opm/core/io/eclipse/EclipseWriteRFTHandler.cpp | 4 ++-- opm/core/io/eclipse/EclipseWriter.cpp | 17 ++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/opm/core/io/eclipse/EclipseWriteRFTHandler.cpp b/opm/core/io/eclipse/EclipseWriteRFTHandler.cpp index 3dd3c71e..6b608232 100644 --- a/opm/core/io/eclipse/EclipseWriteRFTHandler.cpp +++ b/opm/core/io/eclipse/EclipseWriteRFTHandler.cpp @@ -105,7 +105,7 @@ namespace EclipseWriterDetails { ecl_rft_node_type * ecl_rft_node = ecl_rft_node_alloc_new(well_name.c_str(), type.c_str(), recording_date, days); CompletionSetConstPtr completionsSet = well->getCompletions(timestep); - for (int index = 0; index < completionsSet->size(); ++index) { + for (size_t index = 0; index < completionsSet->size(); ++index) { CompletionConstPtr completion = completionsSet->get(index); size_t i = (size_t)completion->getI(); size_t j = (size_t)completion->getJ(); @@ -131,7 +131,7 @@ namespace EclipseWriterDetails { void EclipseWriteRFTHandler::initGlobalToActiveIndex(const int * compressedToCartesianCellIdx, size_t numCells, size_t cartesianSize) { globalToActiveIndex_.resize(cartesianSize, -1); - for (int active_index = 0; active_index < numCells; ++active_index) { + for (size_t active_index = 0; active_index < numCells; ++active_index) { //If compressedToCartesianCellIdx is NULL, assume no compressed to cartesian mapping, set global equal to active index int global_index = (NULL != compressedToCartesianCellIdx) ? compressedToCartesianCellIdx[active_index] : active_index; globalToActiveIndex_[global_index] = active_index; diff --git a/opm/core/io/eclipse/EclipseWriter.cpp b/opm/core/io/eclipse/EclipseWriter.cpp index 50050133..f81040e1 100644 --- a/opm/core/io/eclipse/EclipseWriter.cpp +++ b/opm/core/io/eclipse/EclipseWriter.cpp @@ -1005,22 +1005,17 @@ int EclipseWriter::eclipseWellStatusMask(WellCommon::StatusEnum wellStatus) */ ert_ecl_unit_enum EclipseWriter::convertUnitTypeErtEclUnitEnum(UnitSystem::UnitType unit) { - ert_ecl_unit_enum ecl_type; switch (unit) { case(UnitSystem::UNIT_TYPE_METRIC): - ecl_type = ERT_ECL_METRIC_UNITS; - break; + return ERT_ECL_METRIC_UNITS; case(UnitSystem::UNIT_TYPE_FIELD) : - ecl_type = ERT_ECL_FIELD_UNITS; - break; + return ERT_ECL_FIELD_UNITS; case(UnitSystem::UNIT_TYPE_LAB): - ecl_type = ERT_ECL_LAB_UNITS; - break; + return ERT_ECL_LAB_UNITS; default: - break; - }; - - return ecl_type; + OPM_THROW(std::logic_error,"Conversion of unit from OPM to ERT failed!"); + return ERT_ECL_METRIC_UNITS; + } } From c952075556a91d62a06f007dce9661bd6b345a9d Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn Date: Tue, 10 Mar 2015 11:07:56 +0100 Subject: [PATCH 3/4] [cleanup] use std::invalid_argument instread of OPM_THROW. --- opm/core/io/eclipse/EclipseWriter.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opm/core/io/eclipse/EclipseWriter.cpp b/opm/core/io/eclipse/EclipseWriter.cpp index f81040e1..ba89d5ed 100644 --- a/opm/core/io/eclipse/EclipseWriter.cpp +++ b/opm/core/io/eclipse/EclipseWriter.cpp @@ -1013,8 +1013,7 @@ ert_ecl_unit_enum EclipseWriter::convertUnitTypeErtEclUnitEnum(UnitSystem::UnitT case(UnitSystem::UNIT_TYPE_LAB): return ERT_ECL_LAB_UNITS; default: - OPM_THROW(std::logic_error,"Conversion of unit from OPM to ERT failed!"); - return ERT_ECL_METRIC_UNITS; + throw std::invalid_argument("unhandled enum value"); } } From 50a0ca8d5d5a62ef1d19c9b19d17b72c77cdcdce Mon Sep 17 00:00:00 2001 From: Robert Kloefkorn Date: Tue, 10 Mar 2015 12:05:41 +0100 Subject: [PATCH 4/4] [revision] restructure convertUnitTypeErtEclUnitEnum to comply with core standards. --- opm/core/io/eclipse/EclipseWriter.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/opm/core/io/eclipse/EclipseWriter.cpp b/opm/core/io/eclipse/EclipseWriter.cpp index ba89d5ed..3ba6d1bc 100644 --- a/opm/core/io/eclipse/EclipseWriter.cpp +++ b/opm/core/io/eclipse/EclipseWriter.cpp @@ -1003,18 +1003,21 @@ int EclipseWriter::eclipseWellStatusMask(WellCommon::StatusEnum wellStatus) /** * Convert opm-core UnitType to eclipse format: ert_ecl_unit_enum */ -ert_ecl_unit_enum EclipseWriter::convertUnitTypeErtEclUnitEnum(UnitSystem::UnitType unit) +ert_ecl_unit_enum +EclipseWriter::convertUnitTypeErtEclUnitEnum(UnitSystem::UnitType unit) { switch (unit) { - case(UnitSystem::UNIT_TYPE_METRIC): + case UnitSystem::UNIT_TYPE_METRIC: return ERT_ECL_METRIC_UNITS; - case(UnitSystem::UNIT_TYPE_FIELD) : + + case UnitSystem::UNIT_TYPE_FIELD: return ERT_ECL_FIELD_UNITS; - case(UnitSystem::UNIT_TYPE_LAB): + + case UnitSystem::UNIT_TYPE_LAB: return ERT_ECL_LAB_UNITS; - default: - throw std::invalid_argument("unhandled enum value"); } + + throw std::invalid_argument("unhandled enum value"); }