diff --git a/opm/output/eclipse/RestartIO.hpp b/opm/output/eclipse/RestartIO.hpp index 6359a1b17..741731d4a 100644 --- a/opm/output/eclipse/RestartIO.hpp +++ b/opm/output/eclipse/RestartIO.hpp @@ -1,4 +1,5 @@ /* + Copyright (c) 2018 Equinor ASA Copyright (c) 2016 Statoil ASA Copyright (c) 2013-2015 Andreas Lauser Copyright (c) 2013 SINTEF ICT, Applied Mathematics. @@ -23,9 +24,6 @@ #ifndef RESTART_IO_HPP #define RESTART_IO_HPP -#include -#include - #include #include #include @@ -35,24 +33,29 @@ #include #include +#include + #include #include #include #include +#include +#include +#include + namespace Opm { -class EclipseGrid; -class EclipseState; -class Phases; -class Schedule; -class SummaryState; + class EclipseGrid; + class EclipseState; + class Phases; + class Schedule; -namespace RestartIO { +} // namespace Opm /* - The two loose functions RestartIO::save() and RestartIO::load() can + The two free functions RestartIO::save() and RestartIO::load() can be used to save and load reservoir and well state from restart files. Observe that these functions 'just do it', i.e. the checking of which report step to load from, if output is enabled at all and @@ -69,39 +72,30 @@ namespace RestartIO { load("CASE.X0010" , 99 , ...) save("CASE.X0010" , 99 , ...) - will read and write to the file "CASE.X0010" - completely ignoring + will read from and write to the file "CASE.X0010" - completely ignoring the report step argument '99'. */ +namespace Opm { namespace RestartIO { -/*void save(const std::string& filename, - int report_step, - double seconds_elapsed, - data::Solution cells, - data::Wells wells, - const EclipseState& es, - const EclipseGrid& grid, - const Schedule& schedule, - std::map> extra_data = {}, - bool write_double = false); -*/ -void save(const std::string& filename, - int report_step, - double seconds_elapsed, - RestartValue value, - const EclipseState& es, - const EclipseGrid& grid, - const Schedule& schedule, - const SummaryState& sumState, - bool write_double = false); + void save(const std::string& filename, + int report_step, + double seconds_elapsed, + RestartValue value, + const EclipseState& es, + const EclipseGrid& grid, + const Schedule& schedule, + const SummaryState& sumState, + bool write_double = false); -RestartValue load( const std::string& filename, - int report_step, - const std::vector& solution_keys, - const EclipseState& es, - const EclipseGrid& grid, - const Schedule& schedule, - const std::vector& extra_keys = {}); + std::pair + load(const std::string& filename, + int report_step, + const std::vector& solution_keys, + const EclipseState& es, + const EclipseGrid& grid, + const Schedule& schedule, + const std::vector& extra_keys = {}); -} -} -#endif +}} // namespace Opm::RestartIO + +#endif // RESTART_IO_HPP diff --git a/src/opm/output/eclipse/EclipseIO.cpp b/src/opm/output/eclipse/EclipseIO.cpp index 9d5cb12bd..f89ee5f7b 100644 --- a/src/opm/output/eclipse/EclipseIO.cpp +++ b/src/opm/output/eclipse/EclipseIO.cpp @@ -500,7 +500,14 @@ RestartValue EclipseIO::loadRestart(const std::vector& solution_keys report_step, false ); - return RestartIO::load( filename , report_step , solution_keys , es, grid , schedule, extra_keys); + auto rst = RestartIO::load(filename, report_step, solution_keys, + es, grid, schedule, extra_keys); + + // Technically a violation of 'const'. Allowed because 'impl' is + // constant pointer to mutable Impl. + this->impl->summary.reset_cumulative_quantities(rst.second); + + return std::move(rst.first); } EclipseIO::EclipseIO( const EclipseState& es, diff --git a/src/opm/output/eclipse/LoadRestart.cpp b/src/opm/output/eclipse/LoadRestart.cpp index 62e72a615..2028d1de9 100644 --- a/src/opm/output/eclipse/LoadRestart.cpp +++ b/src/opm/output/eclipse/LoadRestart.cpp @@ -997,7 +997,7 @@ namespace { namespace Opm { namespace RestartIO { - RestartValue + std::pair load(const std::string& filename, int report_step, const std::vector& solution_keys, @@ -1023,6 +1023,10 @@ namespace Opm { namespace RestartIO { restoreExtra(rst_view, extra_keys, es.getUnits(), rst_value); } - return rst_value; + return { + std::move(rst_value), + restore_cumulative(rst_view, schedule) + }; } + }} // Opm::RestartIO diff --git a/tests/test_Restart.cpp b/tests/test_Restart.cpp index ec4c7df53..0fb26a47d 100644 --- a/tests/test_Restart.cpp +++ b/tests/test_Restart.cpp @@ -405,6 +405,36 @@ Opm::SummaryState sim_state() state.add("WGVIR:OP_3", 0.0); state.add("WWVIR:OP_3", 43.21); + state.add("GOPR:OP" , 110.0); + state.add("GWPR:OP" , 120.0); + state.add("GGPR:OP" , 130.0); + state.add("GVPR:OP" , 140.0); + state.add("GOPT:OP" , 1100.0); + state.add("GWPT:OP" , 1200.0); + state.add("GGPT:OP" , 1300.0); + state.add("GVPT:OP" , 1400.0); + state.add("GWIR:OP" , - 256.0); + state.add("GGIR:OP" , - 65536.0); + state.add("GWIT:OP" , 31415.9); + state.add("GGIT:OP" , 27182.8); + state.add("GWCT:OP" , 0.625); + state.add("GGOR:OP" , 1234.5); + + state.add("FOPR" , 1100.0); + state.add("FWPR" , 1200.0); + state.add("FGPR" , 1300.0); + state.add("FVPR" , 1400.0); + state.add("FOPT" , 11000.0); + state.add("FWPT" , 12000.0); + state.add("FGPT" , 13000.0); + state.add("FVPT" , 14000.0); + state.add("FWIR" , - 2560.0); + state.add("FGIR" , - 655360.0); + state.add("FWIT" , 314159.2); + state.add("FGIT" , 271828.1); + state.add("FWCT" , 0.625); + state.add("FGOR" , 1234.5); + return state; } @@ -688,7 +718,7 @@ BOOST_AUTO_TEST_CASE(ExtraData_content) { /* extra_keys = */ { {"EXTRA" , UnitSystem::measure::pressure, true} , {"EXTRA2", UnitSystem::measure::identity, false} - }); + }).first; BOOST_CHECK(!rst_value.hasExtra("EXTRA2")); BOOST_CHECK( rst_value.hasExtra("EXTRA")); @@ -777,4 +807,94 @@ BOOST_AUTO_TEST_CASE(STORE_THPRES) { +BOOST_AUTO_TEST_CASE(Restore_Cumulatives) +{ + Setup setup("FIRST_SIM.DATA"); + + // Write fully ECLIPSE compatible output. This also saves cumulatives. + setup.es.getIOConfig().setEclCompatibleRST(true); + + const auto restart_value = RestartValue { + mkSolution(setup.grid.getNumActive()), + mkWells() + }; + const auto sumState = sim_state(); + + RestartIO::save("FILE.UNRST", 1, 100, restart_value, + setup.es, setup.grid, setup.schedule, sumState); + + const auto rst_value = RestartIO::load("FILE.UNRST", 1, + /* solution_keys = */ { + RestartKey("SWAT", UnitSystem::measure::identity), + }, + setup.es, setup.grid, setup.schedule, + /* extra_keys = */ {}); + + const auto& rstSumState = rst_value.second; + + // Verify that the restored summary state has all of its requisite + // cumulative summary vectors. + + // Producer => W*IT saved/restored as zero (0.0) + BOOST_CHECK(rstSumState.has("WOPT:OP_1")); + BOOST_CHECK(rstSumState.has("WGPT:OP_1")); + BOOST_CHECK(rstSumState.has("WWPT:OP_1")); + BOOST_CHECK(rstSumState.has("WVPT:OP_1")); + BOOST_CHECK(rstSumState.has("WWIT:OP_1")); + BOOST_CHECK(rstSumState.has("WGIT:OP_1")); + + BOOST_CHECK_CLOSE(rstSumState.get("WOPT:OP_1"), 10.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WGPT:OP_1"), 30.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WWPT:OP_1"), 20.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WVPT:OP_1"), 40.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WWIT:OP_1"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WGIT:OP_1"), 0.0, 1.0e-10); + + // Gas injector => W*PT and WWIT saved/restored as zero (0.0) + BOOST_CHECK(rstSumState.has("WOPT:OP_2")); + BOOST_CHECK(rstSumState.has("WGPT:OP_2")); + BOOST_CHECK(rstSumState.has("WWPT:OP_2")); + BOOST_CHECK(rstSumState.has("WVPT:OP_2")); + BOOST_CHECK(rstSumState.has("WWIT:OP_2")); + BOOST_CHECK(rstSumState.has("WGIT:OP_2")); + + BOOST_CHECK_CLOSE(rstSumState.get("WOPT:OP_2"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WGPT:OP_2"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WWPT:OP_2"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WVPT:OP_2"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WWIT:OP_2"), 0.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("WGIT:OP_2"), 2000.0, 1.0e-10); + + // Group cumulatives saved/restored for all phases + BOOST_CHECK(rstSumState.has("GOPT:OP")); + BOOST_CHECK(rstSumState.has("GGPT:OP")); + BOOST_CHECK(rstSumState.has("GWPT:OP")); + BOOST_CHECK(rstSumState.has("GVPT:OP")); + BOOST_CHECK(rstSumState.has("GWIT:OP")); + BOOST_CHECK(rstSumState.has("GGIT:OP")); + + BOOST_CHECK_CLOSE(rstSumState.get("GOPT:OP"), 1100.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("GWPT:OP"), 1200.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("GGPT:OP"), 1300.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("GVPT:OP"), 1400.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("GWIT:OP"), 31415.9, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("GGIT:OP"), 27182.8, 1.0e-10); + + // Field cumulatives saved/restored for all phases + BOOST_CHECK(rstSumState.has("FOPT")); + BOOST_CHECK(rstSumState.has("FGPT")); + BOOST_CHECK(rstSumState.has("FWPT")); + BOOST_CHECK(rstSumState.has("FVPT")); + BOOST_CHECK(rstSumState.has("FWIT")); + BOOST_CHECK(rstSumState.has("FGIT")); + + BOOST_CHECK_CLOSE(rstSumState.get("FOPT"), 11000.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("FWPT"), 12000.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("FGPT"), 13000.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("FVPT"), 14000.0, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("FWIT"), 314159.2, 1.0e-10); + BOOST_CHECK_CLOSE(rstSumState.get("FGIT"), 271828.1, 1.0e-10); +} + + }