diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 500c9b082..5a7ac58e6 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -102,7 +103,6 @@ namespace Opm class EclipseGrid; class EclipseState; class FieldPropsManager; - class Python; class Runspec; class RPTConfig; class SCHEDULESection; @@ -113,6 +113,56 @@ namespace Opm class UDQActive; + struct ScheduleStatic { + std::shared_ptr m_python_handle; + std::string m_input_path; + MessageLimits m_deck_message_limits; + UnitSystem m_unit_system; + Runspec m_runspec; + + ScheduleStatic() = default; + + explicit ScheduleStatic(std::shared_ptr python_handle) : + m_python_handle(python_handle) + {} + + ScheduleStatic(std::shared_ptr python_handle, + const Deck& deck, + const Runspec& runspec) : + m_python_handle(python_handle), + m_input_path(deck.getInputPath()), + m_deck_message_limits( deck ), + m_unit_system( deck.getActiveUnitSystem() ), + m_runspec( runspec ) + {} + + template + void serializeOp(Serializer& serializer) + { + m_deck_message_limits.serializeOp(serializer); + m_runspec.serializeOp(serializer); + m_unit_system.serializeOp(serializer); + serializer(this->m_input_path); + } + + + static ScheduleStatic serializeObject() { + auto python = std::make_shared(Python::Enable::OFF); + ScheduleStatic st(python); + st.m_deck_message_limits = MessageLimits::serializeObject(); + st.m_runspec = Runspec::serializeObject(); + st.m_unit_system = UnitSystem::newFIELD(); + st.m_input_path = "Some/funny/path"; + return st; + } + + bool operator==(const ScheduleStatic& other) const { + return this->m_input_path == other.m_input_path && + this->m_deck_message_limits == other.m_deck_message_limits && + this->m_unit_system == other.m_unit_system && + this->m_runspec == other.m_runspec; + } + }; class Schedule { @@ -123,7 +173,7 @@ namespace Opm using VFPInjMap = std::map>>; Schedule() = default; - explicit Schedule(std::shared_ptr) {} + explicit Schedule(std::shared_ptr python_handle); Schedule(const Deck& deck, const EclipseGrid& grid, const FieldPropsManager& fp, @@ -188,7 +238,7 @@ namespace Opm double seconds(std::size_t timeStep) const; double stepLength(std::size_t timeStep) const; std::optional exitStatus() const; - const UnitSystem& getUnits() const { return this->unit_system; } + const UnitSystem& getUnits() const { return this->m_static.m_unit_system; } const TimeMap& getTimeMap() const; @@ -296,14 +346,12 @@ namespace Opm { m_sched_deck.serializeOp(serializer); m_timeMap.serializeOp(serializer); - m_deck_message_limits.serializeOp(serializer); auto splitWells = splitDynMap(wells_static); serializer.vector(splitWells.first); serializer(splitWells.second); auto splitGroups = splitDynMap(groups); serializer.vector(splitGroups.first); serializer(splitGroups.second); - m_runspec.serializeOp(serializer); auto splitvfpprod = splitDynMap(vfpprod_tables); serializer.vector(splitvfpprod.first); serializer(splitvfpprod.second); @@ -323,23 +371,19 @@ namespace Opm reconstructDynMap(splitvfpprod.first, splitvfpprod.second, vfpprod_tables); reconstructDynMap(splitvfpinj.first, splitvfpinj.second, vfpinj_tables); } - unit_system.serializeOp(serializer); serializer.vector(snapshots); - serializer(this->m_input_path); + m_static.serializeOp(serializer); } private: template using Map2 = std::map; - std::shared_ptr python_handle; - std::string m_input_path; + ScheduleStatic m_static; ScheduleDeck m_sched_deck; TimeMap m_timeMap; WellMap wells_static; GroupMap groups; - Runspec m_runspec; VFPProdMap vfpprod_tables; VFPInjMap vfpinj_tables; - MessageLimits m_deck_message_limits; DynamicState> udq_config; DynamicState> udq_active; DynamicState> guide_rate_config; @@ -347,7 +391,6 @@ namespace Opm DynamicState> m_glo; RFTConfig rft_config; RestartConfig restart_config; - UnitSystem unit_system; std::optional exit_status; DynamicState> rpt_config; std::vector snapshots; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 386b2ec32..65c7e26f3 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -241,7 +241,7 @@ namespace { } void Schedule::handleDRSDT(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::size_t numPvtRegions = m_runspec.tabdims().getNumPVTTables(); + std::size_t numPvtRegions = this->m_static.m_runspec.tabdims().getNumPVTTables(); std::vector max(numPvtRegions); std::vector options(numPvtRegions); for (const auto& record : handlerContext.keyword) { @@ -253,7 +253,7 @@ namespace { } void Schedule::handleDRSDTR(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::size_t numPvtRegions = m_runspec.tabdims().getNumPVTTables(); + std::size_t numPvtRegions = this->m_static.m_runspec.tabdims().getNumPVTTables(); std::vector max(numPvtRegions); std::vector options(numPvtRegions); std::size_t pvtRegionIdx = 0; @@ -267,7 +267,7 @@ namespace { } void Schedule::handleDRVDT(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::size_t numPvtRegions = m_runspec.tabdims().getNumPVTTables(); + std::size_t numPvtRegions = this->m_static.m_runspec.tabdims().getNumPVTTables(); std::vector max(numPvtRegions); for (const auto& record : handlerContext.keyword) { std::fill(max.begin(), max.end(), record.getItem("DRVDT_MAX").getSIDouble(0)); @@ -277,7 +277,7 @@ namespace { } void Schedule::handleDRVDTR(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::size_t numPvtRegions = m_runspec.tabdims().getNumPVTTables(); + std::size_t numPvtRegions = this->m_static.m_runspec.tabdims().getNumPVTTables(); std::size_t pvtRegionIdx = 0; std::vector max(numPvtRegions); for (const auto& record : handlerContext.keyword) { @@ -417,7 +417,7 @@ namespace { { auto group_ptr = std::make_shared(this->getGroup(group_name, current_step)); - Group::GroupProductionProperties production(this->unit_system, group_name); + Group::GroupProductionProperties production(this->m_static.m_unit_system, group_name); production.gconprod_cmode = controlMode; production.active_cmode = controlMode; production.oil_target = oil_target; @@ -483,7 +483,7 @@ namespace { std::string procedure = record.getItem("MAX_PROC").getTrimmedString(0); auto udqconfig = this->getUDQConfig(handlerContext.currentStep).params().undefinedValue(); - new_gconsale.add(groupName, sales_target, max_rate, min_rate, procedure, udqconfig, this->unit_system); + new_gconsale.add(groupName, sales_target, max_rate, min_rate, procedure, udqconfig, this->m_static.m_unit_system); auto group_ptr = std::make_shared(this->getGroup(groupName, handlerContext.currentStep)); Group::GroupInjectionProperties injection; @@ -509,7 +509,7 @@ namespace { auto udqconfig = this->getUDQConfig(handlerContext.currentStep).params().undefinedValue(); - new_gconsump.add(groupName, consumption_rate, import_rate, network_node_name, udqconfig, this->unit_system); + new_gconsump.add(groupName, consumption_rate, import_rate, network_node_name, udqconfig, this->m_static.m_unit_system); } this->snapshots.back().gconsump( std::move(new_gconsump) ); } @@ -838,7 +838,7 @@ namespace { } void Schedule::handleVFPINJ(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::shared_ptr table = std::make_shared(handlerContext.keyword, this->unit_system); + std::shared_ptr table = std::make_shared(handlerContext.keyword, this->m_static.m_unit_system); int table_id = table->getTableNum(); if (vfpinj_tables.find(table_id) == vfpinj_tables.end()) { @@ -852,7 +852,7 @@ namespace { } void Schedule::handleVFPPROD(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - std::shared_ptr table = std::make_shared(handlerContext.keyword, this->unit_system); + std::shared_ptr table = std::make_shared(handlerContext.keyword, this->m_static.m_unit_system); int table_id = table->getTableNum(); if (vfpprod_tables.find(table_id) == vfpprod_tables.end()) { @@ -890,7 +890,7 @@ namespace { if (table_nr != 0) alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); - properties->handleWCONHIST(alq_type, this->unit_system, record); + properties->handleWCONHIST(alq_type, this->m_static.m_unit_system, record); if (switching_from_injector) { properties->resetDefaultBHPLimit(); @@ -960,7 +960,7 @@ namespace { if (table_nr != 0) alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); - properties->handleWCONPROD(alq_type, this->unit_system, well_name, record); + properties->handleWCONPROD(alq_type, this->m_static.m_unit_system, well_name, record); if (switching_from_injector) { properties->resetDefaultBHPLimit(); @@ -1284,7 +1284,7 @@ namespace { rates will be wrong. */ void Schedule::handleWELTARG(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { - const double SiFactorP = this->unit_system.parse("Pressure").getSIScaling(); + const double SiFactorP = this->m_static.m_unit_system.parse("Pressure").getSIScaling(); for (const auto& record : handlerContext.keyword) { const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); const auto well_names = wellNames(wellNamePattern, handlerContext.currentStep); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 983e7b06c..aef477f76 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -110,12 +110,9 @@ namespace { [[maybe_unused]] std::shared_ptr python, const RestartIO::RstState * rst) try : - python_handle(python), - m_input_path(deck.getInputPath()), + m_static( python, deck, runspec ), m_sched_deck(deck, restart_info(rst) ), m_timeMap( deck , restart_info( rst )), - m_runspec( runspec ), - m_deck_message_limits( MessageLimits(deck) ), udq_config(this->m_timeMap, std::make_shared(deck)), udq_active(this->m_timeMap, std::make_shared()), guide_rate_config(this->m_timeMap, std::make_shared()), @@ -123,7 +120,6 @@ namespace { m_glo(this->m_timeMap, std::make_shared()), rft_config(this->m_timeMap), restart_config(m_timeMap, deck, parseContext, errors), - unit_system(deck.getActiveUnitSystem()), rpt_config(this->m_timeMap, std::make_shared()) { if (rst) @@ -242,6 +238,10 @@ namespace { Schedule(deck, es, ParseContext(), ErrorGuard(), std::make_shared(), rst) {} + Schedule::Schedule(std::shared_ptr python_handle) : + m_static( python_handle ) + { + } /* In general the serializeObject() instances are used as targets for @@ -252,14 +252,12 @@ namespace { */ Schedule Schedule::serializeObject() { - auto python = std::make_shared(Python::Enable::OFF); - Schedule result(python); + Schedule result; + result.m_static = ScheduleStatic::serializeObject(); result.m_timeMap = TimeMap::serializeObject(); result.wells_static.insert({"test1", {{std::make_shared(Opm::Well::serializeObject())},1}}); result.groups.insert({"test2", {{std::make_shared(Opm::Group::serializeObject())},1}}); - result.m_deck_message_limits = MessageLimits::serializeObject(); - result.m_runspec = Runspec::serializeObject(); result.vfpprod_tables = {{1, {{std::make_shared(VFPProdTable::serializeObject())}, 1}}}; result.vfpinj_tables = {{2, {{std::make_shared(VFPInjTable::serializeObject())}, 1}}}; result.udq_config = {{std::make_shared(UDQConfig::serializeObject())}, 1}; @@ -269,9 +267,7 @@ namespace { result.m_actions = {{std::make_shared(Action::Actions::serializeObject())}, 1}; result.rft_config = RFTConfig::serializeObject(); result.restart_config = RestartConfig::serializeObject(); - result.unit_system = UnitSystem::newFIELD(); result.snapshots = { ScheduleState::serializeObject() }; - result.m_input_path = "Some/funny/path"; return result; } @@ -378,8 +374,8 @@ void Schedule::iterateScheduleSection(std::optional load_offset, const FieldPropsManager& fp) { std::vector > rftProperties; - std::string time_unit = this->unit_system.name(UnitSystem::measure::time); - auto deck_time = [this](double seconds) { return this->unit_system.from_si(UnitSystem::measure::time, seconds); }; + std::string time_unit = this->m_static.m_unit_system.name(UnitSystem::measure::time); + auto deck_time = [this](double seconds) { return this->m_static.m_unit_system.from_si(UnitSystem::measure::time, seconds); }; std::string current_file; const auto& time_map = this->m_timeMap; /* @@ -598,7 +594,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, } void Schedule::handlePYACTION(const DeckKeyword& keyword, std::size_t currentStep) { - if (!this->python_handle->enabled()) { + if (!this->m_static.m_python_handle->enabled()) { //Must have a real Python instance here - to ensure that IMPORT works const auto& loc = keyword.location(); OpmLog::warning("This version of flow is built without support for Python. Keyword PYACTION in file: " + loc.filename + " line: " + std::to_string(loc.lineno) + " is ignored."); @@ -609,12 +605,12 @@ void Schedule::iterateScheduleSection(std::optional load_offset, const auto& run_count = Action::PyAction::from_string( keyword.getRecord(0).getItem().get(0) ); const auto& module_arg = keyword.getRecord(1).getItem().get(0); std::string module; - if (this->m_input_path.empty()) + if (this->m_static.m_input_path.empty()) module = module_arg; else - module = this->m_input_path + "/" + module_arg; + module = this->m_static.m_input_path + "/" + module_arg; - Action::PyAction pyaction(this->python_handle, name, run_count, module); + Action::PyAction pyaction(this->m_static.m_python_handle, name, run_count, module); auto new_actions = std::make_shared( this->actions(currentStep) ); new_actions->add(pyaction); this->m_actions.update(currentStep, new_actions); @@ -962,7 +958,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, WellType(preferredPhase), sched_state.whistctl(), wellConnectionOrder, - this->unit_system, + this->m_static.m_unit_system, this->getUDQConfig(timeStep).params().undefinedValue(), drainageRadius, allowCrossFlow, @@ -1261,7 +1257,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, } std::vector Schedule::restart_groups(std::size_t timeStep) const { - std::size_t wdmax = this->m_runspec.wellDimensions().maxGroupsInField(); + std::size_t wdmax = this->m_static.m_runspec.wellDimensions().maxGroupsInField(); std::vector rst_groups(wdmax + 1 , nullptr ); for (const auto& group_name : this->groupNames(timeStep)) { const auto& group = this->getGroup(group_name, timeStep); @@ -1294,7 +1290,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, void Schedule::addGroup(const std::string& groupName, std::size_t timeStep) { const std::size_t insert_index = this->groups.size(); auto udq_undefined = this->getUDQConfig(timeStep).params().undefinedValue(); - auto group = Group{ groupName, insert_index, timeStep, udq_undefined, this->unit_system }; + auto group = Group{ groupName, insert_index, timeStep, udq_undefined, this->m_static.m_unit_system }; this->addGroup(group, timeStep); } @@ -1631,11 +1627,9 @@ void Schedule::iterateScheduleSection(std::optional load_offset, }; return this->m_timeMap == data.m_timeMap && - this->m_input_path == data.m_input_path && + this->m_static == data.m_static && compareMap(this->wells_static, data.wells_static) && compareMap(this->groups, data.groups) && - this->m_deck_message_limits == data.m_deck_message_limits && - this->m_runspec == data.m_runspec && compareMap(this->vfpprod_tables, data.vfpprod_tables) && compareMap(this->vfpinj_tables, data.vfpinj_tables) && compareDynState(this->m_glo, data.m_glo) && @@ -1646,7 +1640,6 @@ void Schedule::iterateScheduleSection(std::optional load_offset, compareDynState(this->rpt_config, data.rpt_config) && rft_config == data.rft_config && this->restart_config == data.restart_config && - this->unit_system == data.unit_system && this->snapshots == data.snapshots; } @@ -1657,8 +1650,8 @@ void Schedule::iterateScheduleSection(std::optional load_offset, } std::string Schedule::simulationDays(std::size_t currentStep) const { - const double sim_time { this->unit_system.from_si(UnitSystem::measure::time, simTime(currentStep)) } ; - return fmt::format("{} {}", sim_time, this->unit_system.name(UnitSystem::measure::time)); + const double sim_time { this->m_static.m_unit_system.from_si(UnitSystem::measure::time, simTime(currentStep)) } ; + return fmt::format("{} {}", sim_time, this->m_static.m_unit_system.name(UnitSystem::measure::time)); } namespace { @@ -1691,7 +1684,7 @@ namespace { } for (const auto& rst_group : rst_state.groups) { - auto group = Group{ rst_group, this->groups.size(), static_cast(report_step), udq_undefined, this->unit_system }; + auto group = Group{ rst_group, this->groups.size(), static_cast(report_step), udq_undefined, this->m_static.m_unit_system }; this->addGroup(group, report_step); if (group.isProductionGroup()) { @@ -1721,7 +1714,7 @@ namespace { } for (const auto& rst_well : rst_state.wells) { - Opm::Well well(rst_well, report_step, this->unit_system, udq_undefined); + Opm::Well well(rst_well, report_step, this->m_static.m_unit_system, udq_undefined); std::vector rst_connections; for (const auto& rst_conn : rst_well.connections) @@ -1785,7 +1778,7 @@ namespace { std::shared_ptr Schedule::python() const { - return this->python_handle; + return this->m_static.m_python_handle; } @@ -2048,9 +2041,9 @@ void Schedule::create_first(const std::chrono::system_clock::time_point& start_t this->snapshots.emplace_back(start_time); auto& sched_state = snapshots.back(); - sched_state.nupcol( this->m_runspec.nupcol() ); - sched_state.oilvap( OilVaporizationProperties( this->m_runspec.tabdims().getNumPVTTables() )); - sched_state.message_limits( this->m_deck_message_limits ); + sched_state.nupcol( this->m_static.m_runspec.nupcol() ); + sched_state.oilvap( OilVaporizationProperties( this->m_static.m_runspec.tabdims().getNumPVTTables() )); + sched_state.message_limits( this->m_static.m_deck_message_limits ); sched_state.wtest_config( WellTestConfig() ); sched_state.gconsale( GConSale() ); sched_state.gconsump( GConSump() );