diff --git a/opm/output/eclipse/EclipseWriter.hpp b/opm/output/eclipse/EclipseWriter.hpp index 21e949441..f153c3f73 100644 --- a/opm/output/eclipse/EclipseWriter.hpp +++ b/opm/output/eclipse/EclipseWriter.hpp @@ -24,7 +24,6 @@ #include #include -#include #include @@ -32,51 +31,19 @@ #include #include +#include + namespace Opm { class EclipseGrid; class Well; -namespace out { -/*! - * \brief A class to write the RFT file to disk. Keeps the file handle alive, - * i.e. you cannot read from the RFT file as long as the instance that wrote it - * is alive in the same process. - * - * You should generally not interact with this component directly, but rather - * use the higher level interface of EclipseWriter. - */ -class RFT { - public: - RFT( const char* output_dir, - const char* basename, - bool format, - const int* compressed_to_cartesian, - size_t num_cells, - size_t cartesian_size ); - - void writeTimeStep( std::vector< std::shared_ptr< const Well > >, - const EclipseGrid& grid, - int report_step, - time_t current_time, - double days, - ert_ecl_unit_enum, - const std::vector< double >& pressure, - const std::vector< double >& swat, - const std::vector< double >& sgas ); - private: - std::vector< int > global_to_active; - ERT::FortIO fortio; -}; - -} /*! * \brief A class to write the reservoir state and the well state of a * blackoil simulation to disk using the Eclipse binary format. */ -class EclipseWriter : public OutputWriter -{ +class EclipseWriter : public OutputWriter { public: /*! * \brief Sets the common attributes required to write eclipse @@ -111,21 +78,13 @@ public: data::Wells, bool isSubstep); -private: - std::shared_ptr< const EclipseState > eclipseState_; - std::string outputDir_; - std::string baseName_; - out::Summary summary_; - out::RFT rft_; - int numCells_; - std::array cartesianSize_; - const int* compressedToCartesianCellIdx_; - std::vector< int > gridToEclipseIdx_; - const double* conversion_table_; - bool enableOutput_; - int ert_phase_mask_; + EclipseWriter( const EclipseWriter& ) = delete; + ~EclipseWriter(); + +private: + class Impl; + std::unique_ptr< Impl > impl; - void init( std::shared_ptr< const EclipseState > ); }; typedef std::shared_ptr EclipseWriterPtr; diff --git a/src/opm/output/eclipse/EclipseWriter.cpp b/src/opm/output/eclipse/EclipseWriter.cpp index 2aff0da1a..811dc9180 100644 --- a/src/opm/output/eclipse/EclipseWriter.cpp +++ b/src/opm/output/eclipse/EclipseWriter.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include // to_upper_copy #include // path @@ -405,9 +406,30 @@ inline const double* get_conv_table( UnitSystem::UnitType t ) { } } -} +class RFT { + public: + RFT( const char* output_dir, + const char* basename, + bool format, + const int* compressed_to_cartesian, + size_t num_cells, + size_t cartesian_size ); -out::RFT::RFT( const char* output_dir, + void writeTimeStep( std::vector< std::shared_ptr< const Well > >, + const EclipseGrid& grid, + int report_step, + time_t current_time, + double days, + ert_ecl_unit_enum, + const std::vector< double >& pressure, + const std::vector< double >& swat, + const std::vector< double >& sgas ); + private: + std::vector< int > global_to_active; + ERT::FortIO fortio; +}; + +RFT::RFT( const char* output_dir, const char* basename, bool format, const int* compressed_to_cartesian, @@ -442,15 +464,15 @@ inline ert_ecl_unit_enum to_ert_unit( UnitSystem::UnitType t ) { throw std::invalid_argument("unhandled enum value"); } -void out::RFT::writeTimeStep( std::vector< std::shared_ptr< const Well > > wells, - const EclipseGrid& grid, - int report_step, - time_t current_time, - double days, - ert_ecl_unit_enum unitsystem, - const std::vector< double >& pressure, - const std::vector< double >& swat, - const std::vector< double >& sgas ) { +void RFT::writeTimeStep( std::vector< std::shared_ptr< const Well > > wells, + const EclipseGrid& grid, + int report_step, + time_t current_time, + double days, + ert_ecl_unit_enum unitsystem, + const std::vector< double >& pressure, + const std::vector< double >& swat, + const std::vector< double >& sgas ) { using rft = ERT::ert_unique_ptr< ecl_rft_node_type, ecl_rft_node_free >; @@ -487,62 +509,107 @@ void out::RFT::writeTimeStep( std::vector< std::shared_ptr< const Well > > wells } } +} + +class EclipseWriter::Impl { + public: + Impl( std::shared_ptr< const EclipseState > es, + int numCells, + const int* comp_to_cart ); + + std::shared_ptr< const EclipseState > es; + std::string outputDir; + std::string baseName; + out::Summary summary; + RFT rft; + int numCells; + std::array< int, 3 > cartesianSize; + const int* compressed_to_cartesian; + std::vector< int > gridToEclipseIdx; + const double* conversion_table; + bool output_enabled; + int ert_phase_mask; +}; + +EclipseWriter::Impl::Impl( std::shared_ptr< const EclipseState > eclipseState, + int numCells, + const int* compressed_to_cart ) + : es( eclipseState ) + , outputDir( eclipseState->getIOConfig()->getOutputDir() ) + , baseName( boost::to_upper_copy( eclipseState->getIOConfig()->getBaseName() ) ) + , summary( *eclipseState, eclipseState->getSummaryConfig() ) + , rft( outputDir.c_str(), baseName.c_str(), + es->getIOConfig()->getFMTOUT(), + compressed_to_cart, + numCells, es->getInputGrid()->getCartesianSize() ) + , numCells( numCells ) + , compressed_to_cartesian( compressed_to_cart ) + , gridToEclipseIdx( numCells, int(-1) ) + , conversion_table( get_conv_table( eclipseState->getDeckUnitSystem().getType() ) ) + , output_enabled( eclipseState->getIOConfig()->getOutputEnabled() ) + , ert_phase_mask( ertPhaseMask( eclipseState->getTableManager() ) ) +{} void EclipseWriter::writeInit( time_t current_posix_time, double start_time, const NNC& nnc) { - // if we don't want to write anything, this method becomes a - // no-op... - if (!enableOutput_) { + if( !this->impl->output_enabled ) return; + + const auto& es = *this->impl->es; + Init fortio( this->impl->outputDir, + this->impl->baseName, + /*stepIdx=*/0, + *es.getIOConfigConst()); + + fortio.writeHeader( this->impl->numCells, + this->impl->compressed_to_cartesian, + current_posix_time, + es, + this->impl->ert_phase_mask ); + + IOConfigConstPtr ioConfig = es.getIOConfigConst(); + const auto& props = es.get3DProperties(); + + if( !ioConfig->getWriteINITFile() ) return; + + const auto* conversion_table = this->impl->conversion_table; + const auto& gridToEclipseIdx = this->impl->gridToEclipseIdx; + + if (props.hasDeckDoubleGridProperty("PERMX")) { + auto data = props.getDoubleGridProperty("PERMX").getData(); + convertFromSiTo( data, + conversion_table, + conversions::dim::permeability ); + restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data()); + fortio.writeKeyword("PERMX", data); + } + if (props.hasDeckDoubleGridProperty("PERMY")) { + auto data = props.getDoubleGridProperty("PERMY").getData(); + convertFromSiTo( data, + conversion_table, + conversions::dim::permeability ); + restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data()); + fortio.writeKeyword("PERMY", data); + } + if (props.hasDeckDoubleGridProperty("PERMZ")) { + auto data = props.getDoubleGridProperty("PERMZ").getData(); + convertFromSiTo( data, + conversion_table, + conversions::dim::permeability ); + restrictAndReorderToActiveCells(data, gridToEclipseIdx.size(), gridToEclipseIdx.data()); + fortio.writeKeyword("PERMZ", data); } - Init fortio(outputDir_, baseName_, /*stepIdx=*/0, *eclipseState_->getIOConfigConst()); - fortio.writeHeader(numCells_, - compressedToCartesianCellIdx_, - current_posix_time, - *eclipseState_, - ert_phase_mask_, - nnc ); + if( !nnc.hasNNC() ) return; - IOConfigConstPtr ioConfig = eclipseState_->getIOConfigConst(); - const auto& props = eclipseState_->get3DProperties(); - - - if (ioConfig->getWriteINITFile()) { - if (props.hasDeckDoubleGridProperty("PERMX")) { - auto data = props.getDoubleGridProperty("PERMX").getData(); - convertFromSiTo( data, - conversion_table_, - conversions::dim::permeability ); - restrictAndReorderToActiveCells(data, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); - fortio.writeKeyword("PERMX", data); - } - if (props.hasDeckDoubleGridProperty("PERMY")) { - auto data = props.getDoubleGridProperty("PERMY").getData(); - convertFromSiTo( data, - conversion_table_, - conversions::dim::permeability ); - restrictAndReorderToActiveCells(data, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); - fortio.writeKeyword("PERMY", data); - } - if (props.hasDeckDoubleGridProperty("PERMZ")) { - auto data = props.getDoubleGridProperty("PERMZ").getData(); - convertFromSiTo( data, - conversion_table_, - conversions::dim::permeability ); - restrictAndReorderToActiveCells(data, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); - fortio.writeKeyword("PERMZ", data); - } - if (nnc.hasNNC()) { - std::vector tran; - for (NNCdata nd : nnc.nncdata()) { - tran.push_back(nd.trans); - } - - convertFromSiTo( tran, conversion_table_, conversions::dim::transmissibility ); - fortio.writeKeyword("TRANNNC", tran); - } + std::vector tran; + for( NNCdata nd : nnc.nncdata() ) { + tran.push_back( nd.trans ); } + + convertFromSiTo( tran, conversion_table, conversions::dim::transmissibility ); + fortio.writeKeyword("TRANNNC", tran); + } // implementation of the writeTimeStep method @@ -554,37 +621,39 @@ void EclipseWriter::writeTimeStep(int report_step, bool isSubstep) { - using dc = data::Solution::key; - // if we don't want to write anything, this method becomes a - // no-op... - if (!enableOutput_) { + if( !this->impl->output_enabled ) return; - } + + using dc = data::Solution::key; + + const auto* conversion_table = this->impl->conversion_table; + const auto& gridToEclipseIdx = this->impl->gridToEclipseIdx; + const auto& es = *this->impl->es; auto& pressure = cells[ dc::PRESSURE ]; convertFromSiTo( pressure, - conversion_table_, - conversions::dim::pressure ); - restrictAndReorderToActiveCells(pressure, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); + conversion_table, + conversions::dim::pressure ); + restrictAndReorderToActiveCells(pressure, gridToEclipseIdx.size(), gridToEclipseIdx.data()); if( cells.has( dc::SWAT ) ) { auto& saturation_water = cells[ dc::SWAT ]; - restrictAndReorderToActiveCells(saturation_water, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); + restrictAndReorderToActiveCells(saturation_water, gridToEclipseIdx.size(), gridToEclipseIdx.data()); } if( cells.has( dc::SGAS ) ) { auto& saturation_gas = cells[ dc::SGAS ]; - restrictAndReorderToActiveCells(saturation_gas, gridToEclipseIdx_.size(), gridToEclipseIdx_.data()); + restrictAndReorderToActiveCells(saturation_gas, gridToEclipseIdx.size(), gridToEclipseIdx.data()); } - IOConfigConstPtr ioConfig = eclipseState_->getIOConfigConst(); + IOConfigConstPtr ioConfig = this->impl->es->getIOConfigConst(); - const auto days = conversions::from_si( this->conversion_table_, + const auto days = conversions::from_si( conversion_table, conversions::dim::time, secs_elapsed ); - const auto& schedule = *this->eclipseState_->getSchedule(); + const auto& schedule = *es.getSchedule(); // Write restart file if(!isSubstep && ioConfig->getWriteRestartFile(report_step)) @@ -597,7 +666,10 @@ void EclipseWriter::writeTimeStep(int report_step, std::vector iwell_data( numWells * Restart::NIWELZ , 0 ); std::vector icon_data( numWells * ncwmax * Restart::NICONZ , 0 ); - Restart restartHandle(outputDir_, baseName_, report_step, *ioConfig); + Restart restartHandle( this->impl->outputDir, + this->impl->baseName, + report_step, + *ioConfig); for (size_t iwell = 0; iwell < wells_ptr.size(); ++iwell) { const auto& well = *wells_ptr[iwell]; @@ -616,16 +688,16 @@ void EclipseWriter::writeTimeStep(int report_step, { ecl_rsthead_type rsthead_data = {}; rsthead_data.sim_time = current_posix_time; - rsthead_data.nactive = numCells_; - rsthead_data.nx = cartesianSize_[0]; - rsthead_data.ny = cartesianSize_[1]; - rsthead_data.nz = cartesianSize_[2]; + rsthead_data.nactive = this->impl->numCells; + rsthead_data.nx = es.getInputGrid()->getNX(); + rsthead_data.ny = es.getInputGrid()->getNY(); + rsthead_data.nz = es.getInputGrid()->getNZ(); rsthead_data.nwells = numWells; rsthead_data.niwelz = Restart::NIWELZ; rsthead_data.nzwelz = Restart::NZWELZ; rsthead_data.niconz = Restart::NICONZ; rsthead_data.ncwmax = ncwmax; - rsthead_data.phase_sum = ert_phase_mask_; + rsthead_data.phase_sum = this->impl->ert_phase_mask; rsthead_data.sim_days = days; restartHandle.writeHeader( report_step, &rsthead_data); @@ -654,8 +726,8 @@ void EclipseWriter::writeTimeStep(int report_step, // write the cell temperature auto& temperature = cells[ dc::TEMP ]; convertFromSiTo( temperature, - conversion_table_, - conversions::dim::temperature ); + conversion_table, + conversions::dim::temperature ); sol.add(Keyword("TEMP", temperature)); @@ -668,7 +740,6 @@ void EclipseWriter::writeTimeStep(int report_step, sol.add( Keyword( "SGAS", cells[ dc::SGAS ] ) ); } - // Write RS - Dissolved GOR if( cells.has( dc::RS ) ) sol.add(Keyword("RS", cells[ dc::RS ] ) ); @@ -678,46 +749,31 @@ void EclipseWriter::writeTimeStep(int report_step, sol.add(Keyword("RV", cells[ dc::RV ] ) ); } - const auto unit_type = eclipseState_->getDeckUnitSystem().getType(); - this->rft_.writeTimeStep( schedule.getWells( report_step ), - *this->eclipseState_->getInputGrid(), - report_step, - current_posix_time, - days, - to_ert_unit( unit_type ), - pressure, - cells[ dc::SWAT ], - cells[ dc::SGAS ] ); + const auto unit_type = es.getDeckUnitSystem().getType(); + this->impl->rft.writeTimeStep( schedule.getWells( report_step ), + *es.getInputGrid(), + report_step, + current_posix_time, + days, + to_ert_unit( unit_type ), + pressure, + cells[ dc::SWAT ], + cells[ dc::SGAS ] ); if( isSubstep ) return; - summary_.add_timestep( report_step, secs_elapsed, *eclipseState_, wells ); - summary_.write(); + this->impl->summary.add_timestep( report_step, + secs_elapsed, + es, + wells ); + this->impl->summary.write(); } -EclipseWriter::EclipseWriter(Opm::EclipseStateConstPtr eclipseState, - int numCells, - const int* compressedToCartesianCellIdx) - : eclipseState_(eclipseState) - , outputDir_( eclipseState->getIOConfig()->getOutputDir() ) - , baseName_( boost::to_upper_copy( eclipseState->getIOConfig()->getBaseName() ) ) - , summary_( *eclipseState, eclipseState->getSummaryConfig() ) - , rft_( outputDir_.c_str(), baseName_.c_str(), - eclipseState->getIOConfig()->getFMTOUT(), - compressedToCartesianCellIdx, - numCells, eclipseState->getInputGrid()->getCartesianSize() ) - , numCells_(numCells) - , compressedToCartesianCellIdx_(compressedToCartesianCellIdx) - , gridToEclipseIdx_(numCells, int(-1) ) - , conversion_table_( get_conv_table( eclipseState->getDeckUnitSystem().getType() ) ) - , enableOutput_( eclipseState->getIOConfig()->getOutputEnabled() ) - , ert_phase_mask_( ertPhaseMask( eclipseState->getTableManager() ) ) +EclipseWriter::EclipseWriter( std::shared_ptr< const EclipseState > es, + int numCells, + const int* compressedToCartesianCellIdx ) : + impl( new Impl( es, numCells, compressedToCartesianCellIdx ) ) { - const auto eclGrid = eclipseState->getInputGrid(); - cartesianSize_[0] = eclGrid->getNX(); - cartesianSize_[1] = eclGrid->getNY(); - cartesianSize_[2] = eclGrid->getNZ(); - if( compressedToCartesianCellIdx ) { // if compressedToCartesianCellIdx available then // compute mapping to eclipse order @@ -729,29 +785,36 @@ EclipseWriter::EclipseWriter(Opm::EclipseStateConstPtr eclipseState, int idx = 0; for( auto it = indexMap.begin(), end = indexMap.end(); it != end; ++it ) { - gridToEclipseIdx_[ idx++ ] = (*it).second; + this->impl->gridToEclipseIdx[ idx++ ] = (*it).second; } } else { // if not compressedToCartesianCellIdx was given use identity for (int cellIdx = 0; cellIdx < numCells; ++cellIdx) { - gridToEclipseIdx_[ cellIdx ] = cellIdx; + this->impl->gridToEclipseIdx[ cellIdx ] = cellIdx; } } - if( enableOutput_ ) { - // make sure that the output directory exists, if not try to create it - if (!boost::filesystem::exists(outputDir_)) { - std::cout << "Trying to create directory \"" << outputDir_ << "\" for the simulation output\n"; - boost::filesystem::create_directories(outputDir_); - } + if( !this->impl->output_enabled ) return; - if (!boost::filesystem::is_directory(outputDir_)) { - OPM_THROW(std::runtime_error, - "The path specified as output directory '" << outputDir_ - << "' is not a directory"); - } + const auto& outputDir = this->impl->outputDir; + + // make sure that the output directory exists, if not try to create it + if ( !boost::filesystem::exists( outputDir ) ) { + std::cout << "Trying to create directory \"" + << outputDir + << "\" for the simulation output\n"; + boost::filesystem::create_directories( outputDir ); + } + + if (!boost::filesystem::is_directory( outputDir ) ) { + OPM_THROW(std::runtime_error, + "The path specified as output directory '" + << outputDir + << "' is not a directory"); } } +EclipseWriter::~EclipseWriter() {} + } // namespace Opm diff --git a/tests/test_RFT.cpp b/tests/test_RFT.cpp index 182cb612e..b7a1266fa 100755 --- a/tests/test_RFT.cpp +++ b/tests/test_RFT.cpp @@ -99,17 +99,6 @@ data::Solution createBlackoilState( int timeStepIdx, int numCells ) { return sol; } - - -EclipseWriter createEclipseWriter( std::shared_ptr< const EclipseState > eclipseState, - const int* compressedToCartesianCellIdx ) { - - const auto& grid = *eclipseState->getInputGrid(); - return EclipseWriter( eclipseState, - grid.getNX() * grid.getNY() * grid.getNZ(), - compressedToCartesianCellIdx ); -} - } BOOST_AUTO_TEST_CASE(test_RFT) { @@ -128,14 +117,15 @@ BOOST_AUTO_TEST_CASE(test_RFT) { * written to disk and flushed. */ - auto eclipseWriter = createEclipseWriter( eclipseState, nullptr ); + const auto numCells = eclipseState->getInputGrid()->getNX() + * eclipseState->getInputGrid()->getNY() + * eclipseState->getInputGrid()->getNZ(); + + EclipseWriter eclipseWriter( eclipseState, numCells, nullptr ); time_t btime = util_make_datetime( 0, 0, 0, 1, 12, 1979 ); time_t start_time = util_make_datetime( 0, 0, 0, 10, 10, 2008 ); eclipseWriter.writeInit( start_time, btime); - const auto numCells = eclipseState->getInputGrid()->getNX() - * eclipseState->getInputGrid()->getNY() - * eclipseState->getInputGrid()->getNZ(); time_t times[] = { btime,