diff --git a/opm/output/eclipse/RestartValue.hpp b/opm/output/eclipse/RestartValue.hpp index 20e4b6aa1..08602ffdc 100644 --- a/opm/output/eclipse/RestartValue.hpp +++ b/opm/output/eclipse/RestartValue.hpp @@ -60,20 +60,17 @@ namespace Opm { class RestartValue { public: - using extra_vector = std::vector>>; + using ExtraVector = std::vector>>; data::Solution solution; data::Wells wells; - extra_vector extra; + ExtraVector extra; RestartValue(data::Solution sol, data::Wells wells_arg); - bool has_extra(const std::string& key) const; - void add_extra(const std::string& key, UnitSystem::measure dimension, std::vector data); - void add_extra(const std::string& key, const std::vector& data); - const std::vector& get_extra(const std::string& key) const; - - void convertFromSI(const UnitSystem& units); - void convertToSI(const UnitSystem& units); + bool hasExtra(const std::string& key) const; + void addExtra(const std::string& key, UnitSystem::measure dimension, std::vector data); + void addExtra(const std::string& key, std::vector data); + const std::vector& getExtra(const std::string& key) const; }; } diff --git a/src/opm/output/eclipse/RestartIO.cpp b/src/opm/output/eclipse/RestartIO.cpp index 73ba48ddf..b8f8708ca 100644 --- a/src/opm/output/eclipse/RestartIO.cpp +++ b/src/opm/output/eclipse/RestartIO.cpp @@ -257,13 +257,21 @@ RestartValue load( const std::string& filename, const ecl_kw_type * ecl_kw = ecl_file_view_iget_named_kw( file_view , key.c_str() , 0 ); const double * data_ptr = ecl_kw_get_double_ptr( ecl_kw ); const double * end_ptr = data_ptr + ecl_kw_get_size( ecl_kw ); - rst_value.add_extra(key, extra.dim, {data_ptr, end_ptr}); + rst_value.addExtra(key, extra.dim, {data_ptr, end_ptr}); } else if (required) throw std::runtime_error("No such key in file: " + key); } - rst_value.convertToSI(units); + // Convert solution fields and extra data from user units to SI + rst_value.solution.convertToSI(units); + for (auto & extra_value : rst_value.extra) { + const auto& restart_key = extra_value.first; + auto & data = extra_value.second; + + units.to_si(restart_key.dim, data); + } + return rst_value; } @@ -473,15 +481,15 @@ void writeHeader(ecl_rst_file_type * rst_file, ERT::ert_unique_ptr< ecl_kw_type, ecl_kw_free > kw_ptr; if (write_double) { - ecl_kw_type * ecl_kw = ecl_kw_alloc( kw.c_str() , data.size() , ECL_DOUBLE ); - ecl_kw_set_memcpy_data( ecl_kw , data.data() ); - kw_ptr.reset( ecl_kw ); + ecl_kw_type * ecl_kw = ecl_kw_alloc( kw.c_str() , data.size() , ECL_DOUBLE ); + ecl_kw_set_memcpy_data( ecl_kw , data.data() ); + kw_ptr.reset( ecl_kw ); } else { - ecl_kw_type * ecl_kw = ecl_kw_alloc( kw.c_str() , data.size() , ECL_FLOAT ); - float * float_data = ecl_kw_get_float_ptr( ecl_kw ); - for (size_t i=0; i < data.size(); i++) - float_data[i] = data[i]; - kw_ptr.reset( ecl_kw ); + ecl_kw_type * ecl_kw = ecl_kw_alloc( kw.c_str() , data.size() , ECL_FLOAT ); + float * float_data = ecl_kw_get_float_ptr( ecl_kw ); + for (size_t i=0; i < data.size(); i++) + float_data[i] = data[i]; + kw_ptr.reset( ecl_kw ); } return kw_ptr; @@ -504,7 +512,7 @@ void writeHeader(ecl_rst_file_type * rst_file, } - void writeExtraData(ecl_rst_file_type* rst_file, const RestartValue::extra_vector& extra_data) { + void writeExtraData(ecl_rst_file_type* rst_file, const RestartValue::ExtraVector& extra_data) { for (const auto& extra_value : extra_data) { const std::string& key = extra_value.first.key; const std::vector& data = extra_value.second; @@ -555,7 +563,7 @@ void checkSaveArguments(const EclipseState& es, } size_t num_regions = es.getTableManager().getEqldims().getNumEquilRegions(); - const auto& thpres = restart_value.get_extra("THPRES"); + const auto& thpres = restart_value.getExtra("THPRES"); if (thpres.size() != num_regions * num_regions) throw std::runtime_error("THPRES vector has invalid size - should have num_region * num_regions."); } @@ -586,8 +594,15 @@ void save(const std::string& filename, else rst_file.reset( ecl_rst_file_open_write( filename.c_str() ) ); + // Convert solution fields and extra values from SI to user units. + value.solution.convertFromSI(units); + for (auto & extra_value : value.extra) { + const auto& restart_key = extra_value.first; + auto & data = extra_value.second; + + units.from_si(restart_key.dim, data); + } - value.convertFromSI( units ); writeHeader( rst_file.get(), sim_step, report_step, posix_time , sim_time, ert_phase_mask, units, schedule , grid ); writeWell( rst_file.get(), sim_step, es , grid, schedule, value.wells); writeSolution( rst_file.get(), value.solution, write_double ); diff --git a/src/opm/output/eclipse/RestartValue.cpp b/src/opm/output/eclipse/RestartValue.cpp index 3fb6fc4c8..70155d40b 100644 --- a/src/opm/output/eclipse/RestartValue.cpp +++ b/src/opm/output/eclipse/RestartValue.cpp @@ -38,24 +38,34 @@ namespace Opm { { } - const std::vector& RestartValue::get_extra(const std::string& key) const { - const auto iter = std::find_if(this->extra.begin(), this->extra.end(), [&](std::pair> pair) {return (pair.first.key == key);}); + const std::vector& RestartValue::getExtra(const std::string& key) const { + const auto iter = std::find_if(this->extra.begin(), + this->extra.end(), + [&](const std::pair>& pair) + { + return (pair.first.key == key); + }); if (iter == this->extra.end()) throw std::invalid_argument("No such extra key " + key); return iter->second; } - bool RestartValue::has_extra(const std::string& key) const { - const auto iter = std::find_if(this->extra.begin(), this->extra.end(), [&](std::pair> pair) {return (pair.first.key == key);}); + bool RestartValue::hasExtra(const std::string& key) const { + const auto iter = std::find_if(this->extra.begin(), + this->extra.end(), + [&](const std::pair>& pair) + { + return (pair.first.key == key); + }); return (iter != this->extra.end()); } - void RestartValue::add_extra(const std::string& key, UnitSystem::measure dimension, std::vector data) { + void RestartValue::addExtra(const std::string& key, UnitSystem::measure dimension, std::vector data) { if (key.size() > 8) throw std::runtime_error("The keys used for Eclipse output must be maximum 8 characters long."); - if (this->has_extra(key)) + if (this->hasExtra(key)) throw std::runtime_error("The keys in the extra vector must be unique."); if (this->solution.has(key)) @@ -64,32 +74,11 @@ namespace Opm { if (reserved_keys.find(key) != reserved_keys.end()) throw std::runtime_error("Can not use reserved key:" + key); - this->extra.push_back( std::make_pair(RestartKey(key, dimension), data)); + this->extra.push_back( std::make_pair(RestartKey(key, dimension), std::move(data))); } - void RestartValue::add_extra(const std::string& key, const std::vector& data) { - this->add_extra(key, UnitSystem::measure::identity, data); - } - - - void RestartValue::convertFromSI(const UnitSystem& units) { - this->solution.convertFromSI(units); - for (auto & extra_value : this->extra) { - const auto& restart_key = extra_value.first; - auto & data = extra_value.second; - - units.from_si(restart_key.dim, data); - } - } - - void RestartValue::convertToSI(const UnitSystem& units) { - this->solution.convertToSI(units); - for (auto & extra_value : this->extra) { - const auto& restart_key = extra_value.first; - auto & data = extra_value.second; - - units.to_si(restart_key.dim, data); - } + void RestartValue::addExtra(const std::string& key, std::vector data) { + this->addExtra(key, UnitSystem::measure::identity, std::move(data)); } diff --git a/tests/test_Restart.cpp b/tests/test_Restart.cpp index 79297e21a..8b9392375 100644 --- a/tests/test_Restart.cpp +++ b/tests/test_Restart.cpp @@ -504,17 +504,17 @@ BOOST_AUTO_TEST_CASE(ExtraData_KEYS) { auto wells = mkWells(); RestartValue restart_value(cells, wells); - BOOST_CHECK_THROW( restart_value.add_extra("TOO-LONG-KEY", {0,1,2}), std::runtime_error); + BOOST_CHECK_THROW( restart_value.addExtra("TOO-LONG-KEY", {0,1,2}), std::runtime_error); // Keys must be unique - restart_value.add_extra("KEY", {0,1,1}); - BOOST_CHECK_THROW( restart_value.add_extra("KEY", {0,1,1}), std::runtime_error); + restart_value.addExtra("KEY", {0,1,1}); + BOOST_CHECK_THROW( restart_value.addExtra("KEY", {0,1,1}), std::runtime_error); /* The keys must be unique across solution and extra_data */ - BOOST_CHECK_THROW( restart_value.add_extra("PRESSURE", {0,1}), std::runtime_error); + BOOST_CHECK_THROW( restart_value.addExtra("PRESSURE", {0,1}), std::runtime_error); /* Must avoid using reserved keys like 'LOGIHEAD' */ - BOOST_CHECK_THROW( restart_value.add_extra("LOGIHEAD", {0,1}), std::runtime_error); + BOOST_CHECK_THROW( restart_value.addExtra("LOGIHEAD", {0,1}), std::runtime_error); } BOOST_AUTO_TEST_CASE(ExtraData_content) { @@ -528,7 +528,7 @@ BOOST_AUTO_TEST_CASE(ExtraData_content) { { RestartValue restart_value(cells, wells); - restart_value.add_extra("EXTRA", UnitSystem::measure::pressure, {10,1,2,3}); + restart_value.addExtra("EXTRA", UnitSystem::measure::pressure, {10,1,2,3}); RestartIO::save("FILE.UNRST", 1 , 100, restart_value, @@ -559,10 +559,10 @@ BOOST_AUTO_TEST_CASE(ExtraData_content) { {{"EXTRA", UnitSystem::measure::pressure, true}, {"EXTRA2", UnitSystem::measure::identity, false}}); - BOOST_CHECK(!rst_value.has_extra("EXTRA2")); - BOOST_CHECK( rst_value.has_extra("EXTRA")); - BOOST_CHECK_THROW(rst_value.get_extra("EXTRA2"), std::invalid_argument); - const auto& extraval = rst_value.get_extra("EXTRA"); + BOOST_CHECK(!rst_value.hasExtra("EXTRA2")); + BOOST_CHECK( rst_value.hasExtra("EXTRA")); + BOOST_CHECK_THROW(rst_value.getExtra("EXTRA2"), std::invalid_argument); + const auto& extraval = rst_value.getExtra("EXTRA"); const std::vector expected = {10,1,2,3}; BOOST_CHECK_EQUAL( rst_value.solution.has("NO") , false ); @@ -581,21 +581,24 @@ BOOST_AUTO_TEST_CASE(STORE_THPRES) { auto num_cells = setup.grid.getNumActive( ); auto cells = mkSolution( num_cells ); auto wells = mkWells(); - const auto& units = setup.es.getUnits(); { RestartValue restart_value(cells, wells); RestartValue restart_value2(cells, wells); /* Missing THPRES data in extra container. */ + /* Because it proved to difficult to update the legacy simulators + to pass THPRES values when writing restart files this BOOST_CHECK_THROW + had to be disabled. The RestartIO::save() function will just log a warning. + BOOST_CHECK_THROW( RestartIO::save("FILE.UNRST", 1 , 100, restart_value, setup.es, setup.grid, setup.schedule), std::runtime_error); + */ - - restart_value.add_extra("THPRES", UnitSystem::measure::pressure, {0,1}); + restart_value.addExtra("THPRES", UnitSystem::measure::pressure, {0,1}); /* THPRES data has wrong size in extra container. */ BOOST_CHECK_THROW( RestartIO::save("FILE.UNRST", 1 , 100, @@ -606,7 +609,7 @@ BOOST_AUTO_TEST_CASE(STORE_THPRES) { int num_regions = setup.es.getTableManager().getEqldims().getNumEquilRegions(); std::vector thpres(num_regions * num_regions, 78); - restart_value2.add_extra("THPRES", UnitSystem::measure::pressure, thpres); + restart_value2.addExtra("THPRES", UnitSystem::measure::pressure, thpres); } } }