From 72133deadcf9f4a5055a4cda7b09f8756d9c51e4 Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Thu, 9 Feb 2023 12:50:46 +0100 Subject: [PATCH] added: support for loading serialized state from .OPMRST file --- .../SimulatorFullyImplicitBlackoilEbos.hpp | 59 +++++++++++++++++++ opm/simulators/wells/BlackoilWellModel.hpp | 7 +++ .../wells/BlackoilWellModelGeneric.cpp | 23 ++++++++ .../wells/BlackoilWellModelGeneric.hpp | 4 ++ opm/simulators/wells/WellState.hpp | 5 ++ 5 files changed, 98 insertions(+) diff --git a/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp b/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp index 6d5beab61..d49598206 100644 --- a/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp +++ b/opm/simulators/flow/SimulatorFullyImplicitBlackoilEbos.hpp @@ -75,6 +75,12 @@ struct SaveStep using type = UndefinedProperty; }; +template +struct LoadStep +{ + using type = UndefinedProperty; +}; + template struct EnableTerminalOutput { static constexpr bool value = true; @@ -100,6 +106,12 @@ struct SaveStep static constexpr auto* value = ""; }; +template +struct LoadStep +{ + static constexpr int value = -1; +}; + } // namespace Opm::Properties namespace Opm { @@ -180,6 +192,8 @@ public: } else if (!saveSpec.empty()) { saveStep_ = std::atoi(saveSpec.c_str()); } + + loadStep_ = EWOMS_GET_PARAM(TypeTag, int, LoadStep); } ~SimulatorFullyImplicitBlackoilEbos() @@ -213,6 +227,10 @@ public: "Save serialized state to .OPMRST file. " "Either a specific report step, \"all\" to save " "all report steps or \":x\" to save every x'th step."); + EWOMS_REGISTER_PARAM(TypeTag, int, LoadStep, + "Load serialized state from .OPMRST file. " + "Either a specific report step, or 0 to load last " + "stored report step."); } /// Run the simulation. @@ -277,6 +295,10 @@ public: return false; } + if (loadStep_ > -1) { + loadTimerInfo(timer); + } + // Report timestep. if (terminalOutput_) { std::ostringstream ss; @@ -312,7 +334,14 @@ public: + schedule().seconds(timer.currentStepNum()), timer.currentStepLength()); ebosSimulator_.setEpisodeIndex(timer.currentStepNum()); + if (loadStep_> -1) { + wellModel_().prepareDeserialize(loadStep_ - 1); + loadSimulatorState(); + loadStep_ = -1; + ebosSimulator_.model().invalidateAndUpdateIntensiveQuantities(/*timeIdx=*/0); + } solver->model().beginReportStep(); + bool enableTUNING = EWOMS_GET_PARAM(TypeTag, bool, EnableTuning); // If sub stepping is enabled allow the solver to sub cycle @@ -549,6 +578,35 @@ protected: } } + //! \brief Load timer info from serialized state. + void loadTimerInfo([[maybe_unused]] SimulatorTimer& timer) + { +#if !HAVE_HDF5 + OpmLog::error("Loading of serialized state requested, but no HDF5 support available."); + loadStep_ = -1; +#else + const std::string fileName = ebosSimulator_.vanguard().caseName() + ".OPMRST"; + HDF5Serializer reader(saveFile_, HDF5File::OpenMode::READ); + if (loadStep_ == 0) + loadStep_ = reader.lastReportStep(); + + OpmLog::info("Loading serialized state for report step " + std::to_string(loadStep_)); + const std::string groupName = "/report_step/" + std::to_string(loadStep_); + reader.read(timer, groupName, "simulator_timer"); +#endif + } + + //! \brief Load simulator state from serialized state. + void loadSimulatorState() + { +#if HAVE_HDF5 + const std::string fileName = ebosSimulator_.vanguard().caseName() + ".OPMRST"; + HDF5Serializer reader(fileName, HDF5File::OpenMode::READ); + const std::string groupName = "/report_step/" + std::to_string(loadStep_); + reader.read(*this, groupName, "simulator_data"); +#endif + } + // Data. Simulator& ebosSimulator_; std::unique_ptr> wellAuxMod_; @@ -572,6 +630,7 @@ protected: int saveStride_ = -1; //!< Stride to save serialized state at int saveStep_ = -1; //!< Specific step to save serialized state at + int loadStep_ = -1; //!< Step to load serialized state from }; } // namespace Opm diff --git a/opm/simulators/wells/BlackoilWellModel.hpp b/opm/simulators/wells/BlackoilWellModel.hpp index 3ea1f7a01..4e13bdc8f 100644 --- a/opm/simulators/wells/BlackoilWellModel.hpp +++ b/opm/simulators/wells/BlackoilWellModel.hpp @@ -228,6 +228,13 @@ namespace Opm { param_.use_multisegment_well_); } + using BlackoilWellModelGeneric::prepareDeserialize; + void prepareDeserialize(const int report_step) + { + prepareDeserialize(report_step, grid().size(0), + param_.use_multisegment_well_); + } + data::Wells wellData() const { auto wsrpt = this->wellState() diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.cpp b/opm/simulators/wells/BlackoilWellModelGeneric.cpp index 71f85d79d..16f1eeced 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.cpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.cpp @@ -218,6 +218,29 @@ initFromRestartFile(const RestartValue& restartValues, initial_step_ = false; } +void +BlackoilWellModelGeneric:: +prepareDeserialize(int report_step, const size_t numCells, bool handle_ms_well) +{ + // wells_ecl_ should only contain wells on this processor. + wells_ecl_ = getLocalWells(report_step); + this->local_parallel_well_info_ = createLocalParallelWellInfo(wells_ecl_); + + this->initializeWellProdIndCalculators(); + initializeWellPerfData(); + + if (! this->wells_ecl_.empty()) { + handle_ms_well &= anyMSWellOpenLocal(); + this->wellState().resize(this->wells_ecl_, this->local_parallel_well_info_, + this->schedule(), handle_ms_well, numCells, + this->well_perf_data_, this->summaryState_); + + } + this->wellState().clearWellRates(); + this->commitWGState(); + this->updateNupcolWGState(); +} + std::vector BlackoilWellModelGeneric:: getLocalWells(const int timeStepIdx) const diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index b3aba78dc..87f906314 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -138,6 +138,10 @@ public: const size_t numCells, bool handle_ms_well); + void prepareDeserialize(int report_step, + const size_t numCells, + bool handle_ms_well); + /* Will assign the internal member last_valid_well_state_ to the current value of the this->active_well_state_. The state stored diff --git a/opm/simulators/wells/WellState.hpp b/opm/simulators/wells/WellState.hpp index 23c11ac0b..0943e3b65 100644 --- a/opm/simulators/wells/WellState.hpp +++ b/opm/simulators/wells/WellState.hpp @@ -124,6 +124,11 @@ public: return this->well_rates.find(wellName) != this->well_rates.end(); } + void clearWellRates() + { + this->well_rates.clear(); + } + template void gatherVectorsOnRoot(const std::vector< data::Connection >& from_connections, std::vector< data::Connection >& to_connections,