diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index f1bd53e9684..f56df1305dc 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -244,6 +244,7 @@ list (APPEND MAIN_SOURCE_FILES opm/simulators/wells/ParallelWBPCalculation.cpp opm/simulators/wells/ParallelWellInfo.cpp opm/simulators/wells/PerfData.cpp + opm/simulators/wells/PerforationData.cpp opm/simulators/wells/RateConverter.cpp opm/simulators/wells/RatioCalculator.cpp opm/simulators/wells/SegmentState.cpp diff --git a/opm/simulators/flow/BlackoilModelParameters.cpp b/opm/simulators/flow/BlackoilModelParameters.cpp index 1e05f78a23c..6b0ecb9f293 100644 --- a/opm/simulators/flow/BlackoilModelParameters.cpp +++ b/opm/simulators/flow/BlackoilModelParameters.cpp @@ -335,6 +335,40 @@ void BlackoilModelParameters::registerParameters() #endif } +template +BlackoilModelParameters +BlackoilModelParameters::serializationTestObject() +{ + BlackoilModelParameters result; + result.tolerance_cnv_ = 1.1; + result.tolerance_cnv_relaxed_ = 1.2; + result.tolerance_mb_ = 1.3; + result.tolerance_mb_relaxed_ = 1.4; + result.newton_max_iter_ = 15; + result.newton_min_iter_ = 2; + result.tolerance_max_dp_ = 1.5; + result.tolerance_max_ds_ = 1.6; + result.tolerance_max_drs_ = 1.7; + result.tolerance_max_drv_ = 1.8; + return result; +} + +template +bool BlackoilModelParameters:: +operator==(const BlackoilModelParameters& other) const +{ + return tolerance_cnv_ == other.tolerance_cnv_ && + tolerance_cnv_relaxed_ == other.tolerance_cnv_relaxed_ && + tolerance_mb_ == other.tolerance_mb_ && + tolerance_mb_relaxed_ == other.tolerance_mb_relaxed_ && + newton_max_iter_ == other.newton_max_iter_ && + newton_min_iter_ == other.newton_min_iter_ && + tolerance_max_dp_ == other.tolerance_max_dp_ && + tolerance_max_ds_ == other.tolerance_max_ds_ && + tolerance_max_drs_ == other.tolerance_max_drs_ && + tolerance_max_drv_ == other.tolerance_max_drv_; +} + template struct BlackoilModelParameters; #if FLOW_INSTANTIATE_FLOAT diff --git a/opm/simulators/flow/BlackoilModelParameters.hpp b/opm/simulators/flow/BlackoilModelParameters.hpp index caadd0fc100..a31f6ced409 100644 --- a/opm/simulators/flow/BlackoilModelParameters.hpp +++ b/opm/simulators/flow/BlackoilModelParameters.hpp @@ -419,6 +419,27 @@ struct BlackoilModelParameters // If violated the nupcol wellstate is updated Scalar nupcol_group_rate_tolerance_; + template + void serializeOp(Serializer& serializer) + { + // Only dynamic state is serialized. Static configuration remains sourced + // from CLI/deck parameters and defaults on construction. + serializer(tolerance_cnv_); + serializer(tolerance_cnv_relaxed_); + serializer(tolerance_mb_); + serializer(tolerance_mb_relaxed_); + serializer(newton_max_iter_); + serializer(newton_min_iter_); + serializer(tolerance_max_dp_); + serializer(tolerance_max_ds_); + serializer(tolerance_max_drs_); + serializer(tolerance_max_drv_); + } + + static BlackoilModelParameters serializationTestObject(); + + bool operator==(const BlackoilModelParameters& other) const; + /// Construct from user parameters or defaults. BlackoilModelParameters(); diff --git a/opm/simulators/flow/FlowProblem.hpp b/opm/simulators/flow/FlowProblem.hpp index d9794fb29a9..4937c22ce77 100644 --- a/opm/simulators/flow/FlowProblem.hpp +++ b/opm/simulators/flow/FlowProblem.hpp @@ -1279,10 +1279,12 @@ class FlowProblem : public GetPropType void serializeOp(Serializer& serializer) { serializer(static_cast(*this)); + serializer(first_step_); serializer(drift_); serializer(wellModel_); serializer(aquiferModel_); serializer(tracerModel_); + serializer(temperatureModel_); serializer(*materialLawManager_); } diff --git a/opm/simulators/flow/SimulatorFullyImplicit_impl.hpp b/opm/simulators/flow/SimulatorFullyImplicit_impl.hpp index f250316ee54..b126b04226b 100644 --- a/opm/simulators/flow/SimulatorFullyImplicit_impl.hpp +++ b/opm/simulators/flow/SimulatorFullyImplicit_impl.hpp @@ -583,6 +583,7 @@ serializeOp(Serializer& serializer) serializer(simulator_); serializer(report_); serializer(adaptiveTimeStepping_); + serializer(modelParam_); } template diff --git a/opm/simulators/flow/TemperatureModel.hpp b/opm/simulators/flow/TemperatureModel.hpp index 513601918c3..cd0f19e7543 100644 --- a/opm/simulators/flow/TemperatureModel.hpp +++ b/opm/simulators/flow/TemperatureModel.hpp @@ -240,6 +240,19 @@ class TemperatureModel : public GenericTemperatureModeltemperature_ == other.temperature_; + } + void init() { const unsigned int numCells = simulator_.model().numTotalDof(); @@ -383,6 +396,14 @@ class TemperatureModel : public GenericTemperatureModel + void serializeOp(Serializer& serializer) + { + // Only dynamic state is serialized. Geometry-derived caches and + // solver/work arrays are rebuilt from the current simulator state. + serializer(this->temperature_); + } + protected: void updateStorageCache() { @@ -796,6 +817,12 @@ class TemperatureModel void deserialize(Restarter&) { /* not implemented */ } + template + void serializeOp(Serializer&) + { + // No dynamic state for the disabled temperature model variant. + } + void init() {} void beginTimeStep() {} const Scalar temperature(size_t /*globalIdx*/) const diff --git a/opm/simulators/wells/BlackoilWellModelGeneric.hpp b/opm/simulators/wells/BlackoilWellModelGeneric.hpp index 6de8e3aee71..1d94cea92c5 100644 --- a/opm/simulators/wells/BlackoilWellModelGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelGeneric.hpp @@ -260,11 +260,13 @@ class BlackoilWellModelGeneric serializer(initial_step_); serializer(report_step_starts_); serializer(last_run_wellpi_); + serializer(well_perf_data_); serializer(local_shut_wells_); serializer(closed_this_step_); serializer(guideRate_); serializer(genNetwork_); serializer(prev_inj_multipliers_); + serializer(filter_cake_); serializer(active_wgstate_); serializer(last_valid_wgstate_); serializer(nupcol_wgstate_); diff --git a/opm/simulators/wells/BlackoilWellModelNetwork.hpp b/opm/simulators/wells/BlackoilWellModelNetwork.hpp index 5984c769516..2f022fd3b35 100644 --- a/opm/simulators/wells/BlackoilWellModelNetwork.hpp +++ b/opm/simulators/wells/BlackoilWellModelNetwork.hpp @@ -72,7 +72,6 @@ class BlackoilWellModelNetwork : bool computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger); BlackoilWellModel& well_model_; - std::map well_group_thp_calc_; }; } // namespace Opm diff --git a/opm/simulators/wells/BlackoilWellModelNetworkGeneric.hpp b/opm/simulators/wells/BlackoilWellModelNetworkGeneric.hpp index 33e82224b47..6809602e587 100644 --- a/opm/simulators/wells/BlackoilWellModelNetworkGeneric.hpp +++ b/opm/simulators/wells/BlackoilWellModelNetworkGeneric.hpp @@ -114,6 +114,7 @@ class BlackoilWellModelNetworkGeneric serializer(last_valid_node_pressures_); serializer(branch_data_); serializer(last_valid_branch_data_); + serializer(well_group_thp_calc_); } bool operator==(const BlackoilWellModelNetworkGeneric& rhs) const; @@ -138,6 +139,8 @@ class BlackoilWellModelNetworkGeneric std::map last_valid_node_pressures_; // Valid network branch pressure drops and flow rates for output (outlet branch for production network, inlet branch for injection network) for safe restart after failed iterations std::map last_valid_branch_data_; + // Cached auto-choke THP values used when balancing network groups. + std::map well_group_thp_calc_; }; } // namespace Opm diff --git a/opm/simulators/wells/BlackoilWellModelNetwork_impl.hpp b/opm/simulators/wells/BlackoilWellModelNetwork_impl.hpp index 79cbe2c0d49..6c529a749c6 100644 --- a/opm/simulators/wells/BlackoilWellModelNetwork_impl.hpp +++ b/opm/simulators/wells/BlackoilWellModelNetwork_impl.hpp @@ -331,7 +331,7 @@ computeWellGroupThp(const double dt, DeferredLogger& local_deferredLogger) } } if (autochoke_thp.has_value()) { - well_group_thp_calc_[nodeName] = autochoke_thp.value(); + this->well_group_thp_calc_[nodeName] = autochoke_thp.value(); // Note: The node pressure of the auto-choke node is set // to well_group_thp in computeNetworkPressures() // and must be larger or equal to the pressure of the uptree node of its branch. diff --git a/opm/simulators/wells/PerforationData.cpp b/opm/simulators/wells/PerforationData.cpp new file mode 100644 index 00000000000..7f98a3b57ff --- /dev/null +++ b/opm/simulators/wells/PerforationData.cpp @@ -0,0 +1,38 @@ +#include +#include + +namespace Opm { + +template +PerforationData PerforationData::serializationTestObject() +{ + PerforationData result; + result.cell_index = 17; + result.connection_transmissibility_factor = 1.25e-8; + result.connection_d_factor = 3.5e-4; + result.satnum_id = 23; + result.ecl_index = 29; + result.grid_id = 31; + result.global_index = 37; + return result; +} + +template +bool PerforationData::operator==(const PerforationData& rhs) const +{ + return this->cell_index == rhs.cell_index + && this->connection_transmissibility_factor == rhs.connection_transmissibility_factor + && this->connection_d_factor == rhs.connection_d_factor + && this->satnum_id == rhs.satnum_id + && this->ecl_index == rhs.ecl_index + && this->grid_id == rhs.grid_id + && this->global_index == rhs.global_index; +} + +template struct PerforationData; + +#if FLOW_INSTANTIATE_FLOAT +template struct PerforationData; +#endif + +} // namespace Opm diff --git a/opm/simulators/wells/PerforationData.hpp b/opm/simulators/wells/PerforationData.hpp index fee83562ae4..48d40ce583d 100644 --- a/opm/simulators/wells/PerforationData.hpp +++ b/opm/simulators/wells/PerforationData.hpp @@ -28,6 +28,10 @@ namespace Opm { template struct PerforationData { + static PerforationData serializationTestObject(); + + bool operator==(const PerforationData&) const; + int cell_index{}; Scalar connection_transmissibility_factor{}; Scalar connection_d_factor{}; @@ -49,6 +53,18 @@ struct PerforationData /// identified via globalCellIdxMap[active_idx] alone (which returns /// the level-0 ancestor's Cartesian, shared by all siblings). std::size_t global_index{}; + + template + void serializeOp(Serializer& serializer) + { + serializer(cell_index); + serializer(connection_transmissibility_factor); + serializer(connection_d_factor); + serializer(satnum_id); + serializer(ecl_index); + serializer(grid_id); + serializer(global_index); + } }; template diff --git a/opm/simulators/wells/WellFilterCake.hpp b/opm/simulators/wells/WellFilterCake.hpp index f39201fb734..cf04396d353 100644 --- a/opm/simulators/wells/WellFilterCake.hpp +++ b/opm/simulators/wells/WellFilterCake.hpp @@ -33,6 +33,22 @@ template class WellState; template class WellFilterCake { public: + static WellFilterCake serializationTestObject() + { + WellFilterCake result; + result.inj_fc_multiplier_ = {1.1, 1.2}; + result.skin_factor_ = {2.1, 2.2}; + result.thickness_ = {3.1, 3.2}; + return result; + } + + bool operator==(const WellFilterCake& other) const + { + return inj_fc_multiplier_ == other.inj_fc_multiplier_ && + skin_factor_ == other.skin_factor_ && + thickness_ == other.thickness_; + } + //! \brief Post-step filtration model updates //! \details Calculates the filtrate deposition volumes and associated skin factors / injectivity multipliers void updatePostStep(const WellInterfaceGeneric& well, @@ -50,6 +66,16 @@ class WellFilterCake { //! \brief Returns a const-ref to multipliers. const std::vector& multipliers() const { return inj_fc_multiplier_; } + template + void serializeOp(Serializer& serializer) + { + // Only dynamic state is serialized. Model configuration remains sourced + // from schedule and runtime setup. + serializer(inj_fc_multiplier_); + serializer(skin_factor_); + serializer(thickness_); + } + private: //! \brief Update the multiplier for well transmissbility due to cake filtration. void updateSkinFactorsAndMultipliers(const WellInterfaceGeneric& well, diff --git a/tests/test_RestartSerialization.cpp b/tests/test_RestartSerialization.cpp index d9a8903faab..8152aaa31fe 100644 --- a/tests/test_RestartSerialization.cpp +++ b/tests/test_RestartSerialization.cpp @@ -33,12 +33,16 @@ #include #include +#include +#include #include +#include #include #include #include +#include #include #include #include @@ -48,8 +52,10 @@ #include #include #include +#include #include #include +#include #define BOOST_TEST_MODULE TestRestartSerialization #define BOOST_TEST_NO_MAIN @@ -64,8 +70,16 @@ namespace Opm::Properties { struct TestRestartTypeTag { using InheritsFrom = std::tuple; }; + + struct TestSequentialTemperatureTypeTag { + using InheritsFrom = std::tuple; + }; } + template + struct EnergyModuleType + { static constexpr EnergyModules value = EnergyModules::SequentialImplicitThermal; }; + template<> struct LinearSolverBackend { using type = ISTLSolver; @@ -109,6 +123,8 @@ TEST_FOR_TYPE(HardcodedTimeStepControl) TEST_FOR_TYPE(Inplace) namespace Opm { using PerfD = PerfData; } TEST_FOR_TYPE_NAMED(PerfD, PerfData) +namespace Opm { using Perf = PerforationData; } +TEST_FOR_TYPE_NAMED(Perf, PerforationData) TEST_FOR_TYPE(PIDAndIterationCountTimeStepControl) TEST_FOR_TYPE(PIDTimeStepControl) namespace Opm { using SegmState = SegmentState; } @@ -128,6 +144,28 @@ TEST_FOR_TYPE_NAMED_OBJ(ATS, AdaptiveTimeStepping3rdOrder, serializationTestObje namespace Opm { using BPV = BlackOilPrimaryVariables; } TEST_FOR_TYPE_NAMED(BPV, BlackoilPrimaryVariables) +namespace Opm { using BMP = BlackoilModelParameters; } +TEST_FOR_TYPE_NAMED(BMP, BlackoilModelParameters) +namespace Opm { using WFC = WellFilterCake; } +TEST_FOR_TYPE_NAMED(WFC, WellFilterCake) + +BOOST_AUTO_TEST_CASE(EnabledTemperatureModel) +{ + using TypeTag = Opm::Properties::TTag::TestSequentialTemperatureTypeTag; + Opm::FlowGenericVanguard::readDeck("GLIFT1.DATA"); + using Simulator = Opm::GetPropType; + Simulator simulator; + auto data_out = Opm::TemperatureModel::serializationTestObject(simulator); + Opm::Serialization::MemPacker packer; + Opm::Serializer serializer(packer); + serializer.pack(data_out); + const auto packedSize = serializer.position(); + auto data_in = Opm::TemperatureModel::serializationTestObject(simulator); + serializer.unpack(data_in); + BOOST_CHECK_EQUAL(packedSize, serializer.position()); + BOOST_CHECK(data_out == data_in); +} + namespace Opm { struct DummyMaterial { struct Params { @@ -535,7 +573,7 @@ struct AquiferFixture { Parameters::Register("The maximum number of Newton iterations per time step"); Opm::ThreadManager::registerParameters(); AdaptiveTimeStepping::registerParameters(); - BlackoilModelParameters::registerParameters(); + Opm::BlackoilModelParameters::registerParameters(); Parameters::Register("Do *NOT* use!"); setupParameters_(2, argv, /*registerParams=*/true, false, true, 0); Opm::FlowGenericVanguard::setCommunication(std::make_unique());