From d7345edc951b42e640f66cfcc9cbcbb88fb20c96 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Wed, 13 Jan 2021 13:41:10 +0100 Subject: [PATCH] Use ScheduleState to manage VFP tables --- .../EclipseState/Schedule/Schedule.hpp | 21 +- .../EclipseState/Schedule/ScheduleState.hpp | 15 ++ src/opm/output/eclipse/AggregateWellData.cpp | 2 +- .../EclipseState/Schedule/KeywordHandlers.cpp | 30 +-- .../EclipseState/Schedule/Schedule.cpp | 185 +++--------------- .../EclipseState/Schedule/ScheduleState.cpp | 77 ++++++++ tests/parser/ScheduleTests.cpp | 20 +- 7 files changed, 131 insertions(+), 219 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index e393080d6..2eebc3dd7 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -37,8 +37,6 @@ #include #include #include -#include -#include #include #include #include @@ -169,8 +167,6 @@ namespace Opm public: using WellMap = OrderedMap>>; using GroupMap = OrderedMap>>; - using VFPProdMap = std::map>>; - using VFPInjMap = std::map>>; Schedule() = default; explicit Schedule(std::shared_ptr python_handle); @@ -300,10 +296,6 @@ namespace Opm const GuideRateConfig& guideRateConfig(std::size_t timeStep) const; const RFTConfig& rftConfig() const; - const VFPProdTable& getVFPProdTable(int table_id, std::size_t timeStep) const; - const VFPInjTable& getVFPInjTable(int table_id, std::size_t timeStep) const; - std::map > getVFPProdTables(std::size_t timeStep) const; - std::map > getVFPInjTables(std::size_t timeStep) const; /* Will remove all completions which are connected to cell which is not active. Will scan through all wells and all timesteps. @@ -350,12 +342,6 @@ namespace Opm auto splitGroups = splitDynMap(groups); serializer.vector(splitGroups.first); serializer(splitGroups.second); - auto splitvfpprod = splitDynMap(vfpprod_tables); - serializer.vector(splitvfpprod.first); - serializer(splitvfpprod.second); - auto splitvfpinj = splitDynMap(vfpinj_tables); - serializer.vector(splitvfpinj.first); - serializer(splitvfpinj.second); udq_config.serializeOp(serializer); udq_active.serializeOp(serializer); guide_rate_config.serializeOp(serializer); @@ -366,8 +352,6 @@ namespace Opm if (!serializer.isSerializing()) { reconstructDynMap(splitWells.first, splitWells.second, wells_static); reconstructDynMap(splitGroups.first, splitGroups.second, groups); - reconstructDynMap(splitvfpprod.first, splitvfpprod.second, vfpprod_tables); - reconstructDynMap(splitvfpinj.first, splitvfpinj.second, vfpinj_tables); } serializer.vector(snapshots); m_static.serializeOp(serializer); @@ -380,8 +364,6 @@ namespace Opm TimeMap m_timeMap; WellMap wells_static; GroupMap groups; - VFPProdMap vfpprod_tables; - VFPInjMap vfpinj_tables; DynamicState> udq_config; DynamicState> udq_active; DynamicState> guide_rate_config; @@ -420,7 +402,8 @@ namespace Opm void updateUDQActive( std::size_t timeStep, std::shared_ptr udq ); bool updateWellStatus( const std::string& well, std::size_t reportStep, bool runtime, Well::Status status, std::optional = {}); void addWellToGroup( const std::string& group_name, const std::string& well_name , std::size_t timeStep); - void iterateScheduleSection(std::optional load_offset, + void iterateScheduleSection(std::size_t load_start, + std::size_t load_end, const ParseContext& parseContext, ErrorGuard& errors, const EclipseGrid& grid, diff --git a/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp b/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp index a2bb52733..aa74d4397 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp @@ -37,6 +37,8 @@ #include #include #include +#include +#include namespace Opm { @@ -116,6 +118,14 @@ namespace Opm { const RPTConfig& rpt_config() const; void rpt_config(RPTConfig rpt_config); + std::vector vfpprod() const; + const VFPProdTable& vfpprod(int table_id) const; + void vfpprod(VFPProdTable vfpprod); + + std::vector vfpinj() const; + const VFPInjTable& vfpinj(int table_id) const; + void vfpinj(VFPInjTable vfpinj); + template void serializeOp(Serializer& serializer) { serializer(m_start_time); @@ -135,8 +145,11 @@ namespace Opm { serializer(m_wlist_manager); serializer(m_network); serializer(m_rptconfig); + serializer.map(m_vfpprod); + serializer.map(m_vfpinj); } + private: std::chrono::system_clock::time_point m_start_time; std::optional m_end_time; @@ -156,6 +169,8 @@ namespace Opm { std::shared_ptr m_wlist_manager; std::shared_ptr m_network; std::shared_ptr m_rptconfig; + std::map> m_vfpprod; + std::map> m_vfpinj; }; } diff --git a/src/opm/output/eclipse/AggregateWellData.cpp b/src/opm/output/eclipse/AggregateWellData.cpp index fb54e6d6f..ce002a078 100644 --- a/src/opm/output/eclipse/AggregateWellData.cpp +++ b/src/opm/output/eclipse/AggregateWellData.cpp @@ -588,7 +588,7 @@ namespace { sWell[Ix::HistBHPTarget] = sWell[Ix::BHPTarget]; if (pc.alq_value != 0.0) { - auto vfpTable = sched.getVFPProdTable(pc.vfp_table_number,sim_step); + auto vfpTable = sched[sim_step].vfpprod(pc.vfp_table_number); if (vfpTable.getALQType() == Opm::VFPProdTable::ALQ_GRAT) { sWell[Ix::Alq_value] = static_cast(units.from_si(M::gas_surface_rate, pc.alq_value)); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 5ed5c01ec..5c7370228 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -470,7 +470,6 @@ namespace { } } } - printf("GCONPROD complete\n"); } void Schedule::handleGCONSALE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { @@ -742,6 +741,7 @@ namespace { } void Schedule::handleRPTSCHED(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { + printf("snapshost.size(): %ld \n", this->snapshots.size()); this->snapshots.back().rpt_config( RPTConfig(handlerContext.keyword )); } @@ -838,31 +838,15 @@ namespace { } void Schedule::handleVFPINJ(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - 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()) { - std::pair > > pair = std::make_pair(table_id, DynamicState >(this->m_timeMap, nullptr)); - vfpinj_tables.insert( pair ); - } - - auto& table_state = vfpinj_tables.at(table_id); - table_state.update(handlerContext.currentStep, table); + auto table = VFPInjTable(handlerContext.keyword, this->m_static.m_unit_system); + this->snapshots.back().vfpinj( std::move(table) ); this->snapshots.back().events().addEvent( ScheduleEvents::VFPINJ_UPDATE ); } void Schedule::handleVFPPROD(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { - 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()) { - std::pair > > pair = std::make_pair(table_id, DynamicState >(this->m_timeMap, nullptr)); - vfpprod_tables.insert( pair ); - } - - auto& table_state = vfpprod_tables.at(table_id); - table_state.update(handlerContext.currentStep, table); + auto table = VFPProdTable(handlerContext.keyword, this->m_static.m_unit_system); this->snapshots.back().events().addEvent( ScheduleEvents::VFPPROD_UPDATE ); + this->snapshots.back().vfpprod( std::move(table) ); } void Schedule::handleWCONHIST(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { @@ -889,7 +873,7 @@ namespace { table_nr = properties->VFPTableNumber; if (table_nr != 0) - alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); + alq_type = this->snapshots.back().vfpprod(table_nr).getALQType(); properties->handleWCONHIST(alq_type, this->m_static.m_unit_system, record); if (switching_from_injector) { @@ -959,7 +943,7 @@ namespace { table_nr = properties->VFPTableNumber; if (table_nr != 0) - alq_type = this->getVFPProdTable(table_nr, handlerContext.currentStep).getALQType(); + alq_type = this->snapshots.back().vfpprod(table_nr).getALQType(); properties->handleWCONPROD(alq_type, this->m_static.m_unit_system, well_name, record); if (switching_from_injector) { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 21dc212e5..435598037 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -121,10 +121,13 @@ namespace { rft_config(this->m_timeMap), restart_config(m_timeMap, deck, parseContext, errors) { - if (rst) + if (rst) { + auto restart_step = rst->header.restart_info().second; + this->iterateScheduleSection( 0, restart_step, parseContext, errors, grid, fp); this->load_rst(*rst, grid, fp); - - this->iterateScheduleSection( {}, parseContext, errors, grid, fp); + this->iterateScheduleSection( restart_step, this->m_sched_deck.size(), parseContext, errors, grid, fp); + } else + this->iterateScheduleSection( 0, this->m_sched_deck.size(), parseContext, errors, grid, fp); /* The code in the #ifdef SCHEDULE_DEBUG is an enforced integration test @@ -135,14 +138,6 @@ namespace { if (this->size() == 0) return; - //Verify that we can safely re-iterate over the Schedule section - //if (!rst) - // this->iterateScheduleSection(0, parseContext, errors, grid, fp); - //else { - // auto restart_offset = this->m_sched_deck.restart_offset(); - // this->iterateScheduleSection(restart_offset, parseContext, errors, grid, fp); - //} - // Verify that the time schedule is correct. for (std::size_t report_step = 0; report_step < this->size() - 1; report_step++) { const auto& this_block = this->m_sched_deck[report_step]; @@ -257,8 +252,6 @@ namespace { 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.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}; result.m_glo = {{std::make_shared(GasLiftOpt::serializeObject())}, 1}; result.udq_active = {{std::make_shared(UDQActive::serializeObject())}, 1}; @@ -366,7 +359,7 @@ private: } -void Schedule::iterateScheduleSection(std::optional load_offset, +void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_end, const ParseContext& parseContext , ErrorGuard& errors, const EclipseGrid& grid, @@ -377,74 +370,6 @@ void Schedule::iterateScheduleSection(std::optional load_offset, 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; - /* - The process of transitioning to Schedule model based on ScheduleState - instances is a gradual one. For the keywords which have been converted - to the ScheduleState implementation the iterateScheduleSection() - function can be called repeatedly, whereas for the keywords which have - not yet been converted that is not safe. The old_style_keywords is a - list of keywords which should be ignored when iterateScheduleSection() - is called repeatedly. - */ - std::unordered_set old_style_keywords = { - "PYACTION", - "GCONPROD", - "GCONINJE", - "GLIFTOPT", - "WELPI", - "BRANPROP", - "COMPDAT", - "COMPLUMP", - "COMPORD", - "COMPSEGS", - "GCONINJE", - "GCONPROD", - "GCONSALE", - "GCONSUMP", - "GEFAC", - "GLIFTOPT", - "GPMAINT", - "GRUPNET", - "GRUPTREE", - "GUIDERAT", - "LIFTOPT", - "LINCOM", - "MESSAGES", - "MXUNSUPP", - "NODEPROP", - "RPTSCHED", - "UDQ", - "VFPINJ", - "VFPPROD", - "WCONHIST", - "WCONINJE", - "WCONINJH", - "WCONPROD", - "WECON", - "WEFAC", - "WELOPEN", - "WELPI", - "WELSEGS", - "WELSPECS", - "WELTARG", - "WFOAM", - "WGRUPCON", - "WINJTEMP", - "WLIFTOPT", - "WPAVEDEP", - "WPIMULT", - "WPMITAB", - "WPOLYMER", - "WSALT", - "WSEGSICD", - "WSEGAICD", - "WSEGVALV", - "WSKPTAB", - "WSOLVENT", - "WTEMP", - "WTRACER" - }; - /* The keywords in the skiprest_whitelist set are loaded from the SCHEDULE section even though the SKIPREST keyword is in action. The @@ -452,7 +377,6 @@ void Schedule::iterateScheduleSection(std::optional load_offset, all. */ std::unordered_set skiprest_whitelist = {"VFPPROD", "VFPINJ", "RPTSCHED", "RPTRST", "TUNING", "MESSAGES"}; - std::size_t currentStep = 0; /* The behavior of variable restart_skip is more lenient than the SKIPREST keyword. If this is a restarted[1] run the loop iterating @@ -469,7 +393,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, these keywords will be assigned to report step 0. */ - auto restart_skip = currentStep < this->m_timeMap.restart_offset(); + auto restart_skip = load_start < this->m_timeMap.restart_offset(); ScheduleLogger logger(restart_skip); { const auto& location = this->m_sched_deck.location(); @@ -479,44 +403,38 @@ void Schedule::iterateScheduleSection(std::optional load_offset, logger.info(fmt::format("This is a restarted run - skipping until report step {} at {}", time_map.restart_offset(), Schedule::formatDate(time_map.restart_time()))); logger(fmt::format("Initializing report step {}/{} at {} {} {} line {}", - currentStep + 1, + load_start + 1, this->size(), Schedule::formatDate(this->getStartTime()), - deck_time(time_map.getTimePassedUntil(currentStep)), + deck_time(time_map.getTimePassedUntil(load_start)), time_unit, location.lineno)); } - if (load_offset.has_value()) { - if (load_offset.value() < this->m_sched_deck.restart_offset()) - throw std::logic_error("BUG: Tried to replay schedule keywords from historical section in restarted run"); - this->snapshots.resize( load_offset.value() ); - } - - for (const auto& block : this->m_sched_deck) { + for (auto report_step = load_start; report_step < load_end; report_step++) { std::size_t keyword_index = 0; + auto& block = this->m_sched_deck[report_step]; auto time_type = block.time_type(); if (time_type == ScheduleTimeType::DATES || time_type == ScheduleTimeType::TSTEP) { const auto& start_date = Schedule::formatDate(std::chrono::system_clock::to_time_t(block.start_time())); - const auto& days = deck_time(this->stepLength(currentStep - 1)); - const auto& days_total = deck_time(time_map.getTimePassedUntil(currentStep)); + const auto& days = deck_time(this->stepLength(report_step - 1)); + const auto& days_total = deck_time(time_map.getTimePassedUntil(report_step)); logger.complete_step(fmt::format("Complete report step {0} ({1} {2}) at {3} ({4} {2})", - currentStep, + report_step, days, time_unit, start_date, days_total)); logger(fmt::format("Initializing report step {}/{} at {} ({} {}) - line {}", - currentStep + 1, + report_step + 1, this->size(), start_date, days_total, time_unit, block.location().lineno)); } - if (time_type != ScheduleTimeType::RESTART) - this->create_next(block); + this->create_next(block); while (true) { if (keyword_index == block.size()) @@ -529,13 +447,8 @@ void Schedule::iterateScheduleSection(std::optional load_offset, current_file = location.filename; } - if (load_offset.has_value() && old_style_keywords.count(keyword.name()) == 1) { - keyword_index += 1; - continue; - } - if (keyword.name() == "ACTIONX") { - Action::ActionX action(keyword, this->m_timeMap.getStartTime(currentStep)); + Action::ActionX action(keyword, this->m_timeMap.getStartTime(report_step)); while (true) { keyword_index++; if (keyword_index == block.size()) @@ -553,13 +466,13 @@ void Schedule::iterateScheduleSection(std::optional load_offset, parseContext.handleError( ParseContext::ACTIONX_ILLEGAL_KEYWORD, msg_fmt, action_keyword.location(), errors); } } - this->addACTIONX(action, currentStep); + this->addACTIONX(action, report_step); keyword_index++; continue; } logger(fmt::format("Processing keyword {} at line {}", location.keyword, location.lineno)); - this->handleKeyword(currentStep, + this->handleKeyword(report_step, block, keyword, parseContext, @@ -570,8 +483,7 @@ void Schedule::iterateScheduleSection(std::optional load_offset, keyword_index++; } - checkIfAllConnectionsIsShut(currentStep); - currentStep += 1; + checkIfAllConnectionsIsShut(report_step); } @@ -1396,49 +1308,6 @@ void Schedule::iterateScheduleSection(std::optional load_offset, } } - const VFPProdTable& Schedule::getVFPProdTable(int table_id, std::size_t timeStep) const { - const auto pair = vfpprod_tables.find(table_id); - if (pair == vfpprod_tables.end()) - throw std::invalid_argument("No such table id: " + std::to_string(table_id)); - - auto table_ptr = pair->second.get(timeStep); - if (!table_ptr) - throw std::invalid_argument("Table not yet defined at timeStep:" + std::to_string(timeStep)); - - return *table_ptr; - } - - const VFPInjTable& Schedule::getVFPInjTable(int table_id, std::size_t timeStep) const { - const auto pair = vfpinj_tables.find(table_id); - if (pair == vfpinj_tables.end()) - throw std::invalid_argument("No such table id: " + std::to_string(table_id)); - - auto table_ptr = pair->second.get(timeStep); - if (!table_ptr) - throw std::invalid_argument("Table not yet defined at timeStep:" + std::to_string(timeStep)); - - return *table_ptr; - } - - std::map > Schedule::getVFPInjTables(std::size_t timeStep) const { - std::map > tables; - for (const auto& pair : this->vfpinj_tables) { - if (pair.second.get(timeStep)) { - tables.insert(std::make_pair(pair.first, pair.second.get(timeStep)) ); - } - } - return tables; - } - - std::map > Schedule::getVFPProdTables(std::size_t timeStep) const { - std::map > tables; - for (const auto& pair : this->vfpprod_tables) { - if (pair.second.get(timeStep)) { - tables.insert(std::make_pair(pair.first, pair.second.get(timeStep)) ); - } - } - return tables; - } const UDQActive& Schedule::udqActive(std::size_t timeStep) const { return *this->udq_active[timeStep]; @@ -1624,8 +1493,6 @@ void Schedule::iterateScheduleSection(std::optional load_offset, this->m_static == data.m_static && compareMap(this->wells_static, data.wells_static) && compareMap(this->groups, data.groups) && - compareMap(this->vfpprod_tables, data.vfpprod_tables) && - compareMap(this->vfpinj_tables, data.vfpinj_tables) && compareDynState(this->m_glo, data.m_glo) && compareDynState(this->udq_config, data.udq_config) && compareDynState(this->udq_active, data.udq_active) && @@ -1666,16 +1533,8 @@ namespace { void Schedule::load_rst(const RestartIO::RstState& rst_state, const EclipseGrid& grid, const FieldPropsManager& fp) { - double udq_undefined = 0; const auto report_step = rst_state.header.report_step - 1; - auto start_time = std::chrono::system_clock::from_time_t( this->getStartTime() ); - for (int step = 0; step < report_step; step++) - this->create_next(start_time, start_time); - { - auto restart_time = std::chrono::system_clock::from_time_t( rst_state.header.restart_info().first ); - this->create_next(start_time, restart_time); - } - + double udq_undefined = 0; for (const auto& rst_group : rst_state.groups) { 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); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp index 26fc008c3..465b1a9eb 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp @@ -16,11 +16,15 @@ You should have received a copy of the GNU General Public License along with OPM. If not, see . */ +#include #include #include #include #include +#include +#include + namespace Opm { @@ -141,6 +145,30 @@ void ScheduleState::whistctl(Well::ProducerCMode whistctl) { } bool ScheduleState::operator==(const ScheduleState& other) const { + auto&& map_equal = [](const auto& map1, const auto& map2) { + if (map1.size() != map2.size()) + return false; + + auto it2 = map2.begin(); + for (const auto& it1 : map1) { + if (it1.first != it2->first) + return false; + + if (!(*it1.second == *it2->second)) + return false; + + ++it2; + } + + return true; + }; + + if (!map_equal(this->m_vfpprod, other.m_vfpprod)) + return false; + + if (!map_equal(this->m_vfpinj, other.m_vfpinj)) + return false; + return this->m_start_time == other.m_start_time && this->m_oilvap == other.m_oilvap && this->m_tuning == other.m_tuning && @@ -172,6 +200,11 @@ ScheduleState ScheduleState::serializeObject() { ts.m_gconsale = std::make_shared( GConSale::serializeObject() ); ts.m_wlist_manager = std::make_shared( WListManager::serializeObject() ); ts.m_rptconfig = std::make_shared( RPTConfig::serializeObject() ); + ts.m_vfpprod.emplace( std::make_pair(77, std::make_shared(VFPProdTable::serializeObject() ))); + ts.m_vfpprod.emplace( std::make_pair(78, std::make_shared(VFPProdTable::serializeObject() ))); + ts.m_vfpinj.emplace( std::make_pair(177, std::make_shared(VFPInjTable::serializeObject() ))); + ts.m_vfpinj.emplace( std::make_pair(178, std::make_shared(VFPInjTable::serializeObject() ))); + return ts; } @@ -260,4 +293,48 @@ const RPTConfig& ScheduleState::rpt_config() const { void ScheduleState::rpt_config(RPTConfig rpt_config) { this->m_rptconfig = std::make_shared(std::move(rpt_config)); } + +std::vector ScheduleState::vfpprod() const { + std::vector tables; + for (const auto& [_, table] : this->m_vfpprod) { + (void)_; + tables.push_back( table.get() ); + } + return tables; +} + +const VFPProdTable& ScheduleState::vfpprod(int table_id) const { + auto vfp_iter = this->m_vfpprod.find(table_id); + if (vfp_iter == this->m_vfpprod.end()) + throw std::logic_error(fmt::format("No VFPPROD table with id: {} has been registered", table_id)); + + return *vfp_iter->second; +} + +void ScheduleState::vfpprod(VFPProdTable vfpprod) { + int table_id = vfpprod.getTableNum(); + this->m_vfpprod[table_id] = std::make_shared( std::move(vfpprod) ); +} + +std::vector ScheduleState::vfpinj() const { + std::vector tables; + for (const auto& [_, table] : this->m_vfpinj) { + (void)_; + tables.push_back( table.get() ); + } + return tables; +} + +const VFPInjTable& ScheduleState::vfpinj(int table_id) const { + auto vfp_iter = this->m_vfpinj.find(table_id); + if (vfp_iter == this->m_vfpinj.end()) + throw std::logic_error(fmt::format("No VFPINJ table with id: {} has been registered", table_id)); + + return *vfp_iter->second; +} + +void ScheduleState::vfpinj(VFPInjTable vfpinj) { + int table_id = vfpinj.getTableNum(); + this->m_vfpinj[table_id] = std::make_shared( std::move(vfpinj) ); +} } diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 5f200140b..7dc61147d 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -3006,31 +3006,26 @@ VFPINJ BOOST_CHECK( schedule[2].events().hasEvent(ScheduleEvents::VFPINJ_UPDATE)); // No such table id - BOOST_CHECK_THROW(schedule.getVFPInjTable(77,0), std::invalid_argument); + BOOST_CHECK_THROW(schedule[0].vfpinj(77), std::exception); // Table not defined at step 0 - BOOST_CHECK_THROW(schedule.getVFPInjTable(10,0), std::invalid_argument); + BOOST_CHECK_THROW(schedule[0].vfpinj(10), std::exception); - const Opm::VFPInjTable& vfpinjTable2 = schedule.getVFPInjTable(5, 2); + const Opm::VFPInjTable& vfpinjTable2 = schedule[2].vfpinj(5); BOOST_CHECK_EQUAL(vfpinjTable2.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable2.getDatumDepth(), 100); BOOST_CHECK_EQUAL(vfpinjTable2.getFloType(), Opm::VFPInjTable::FLO_GAS); - const Opm::VFPInjTable& vfpinjTable3 = schedule.getVFPInjTable(10, 2); + const Opm::VFPInjTable& vfpinjTable3 = schedule[2].vfpinj(10); BOOST_CHECK_EQUAL(vfpinjTable3.getTableNum(), 10); BOOST_CHECK_EQUAL(vfpinjTable3.getDatumDepth(), 200); BOOST_CHECK_EQUAL(vfpinjTable3.getFloType(), Opm::VFPInjTable::FLO_WAT); - const Opm::VFPInjTable& vfpinjTable = schedule.getVFPInjTable(5, 0); + const Opm::VFPInjTable& vfpinjTable = schedule[0].vfpinj(5); BOOST_CHECK_EQUAL(vfpinjTable.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable.getDatumDepth(), 32.9); BOOST_CHECK_EQUAL(vfpinjTable.getFloType(), Opm::VFPInjTable::FLO_WAT); - const auto vfp_tables0 = schedule.getVFPInjTables(0); - BOOST_CHECK_EQUAL( vfp_tables0.size(), 1U); - - const auto vfp_tables2 = schedule.getVFPInjTables(2); - BOOST_CHECK_EQUAL( vfp_tables2.size(), 2U); //Flo axis { const std::vector& flo = vfpinjTable.getFloAxis(); @@ -3698,8 +3693,7 @@ BOOST_AUTO_TEST_CASE(SKIPREST_VFP) { Opm::EclIO::ERst rst_file(rst_filename); const auto& rst = Opm::RestartIO::RstState::load(rst_file, report_step); const auto sched = Schedule{ deck, es, python , &rst}; - const auto& tables = sched.getVFPProdTables(3); - BOOST_CHECK( !tables.empty() ); + BOOST_CHECK_NO_THROW( sched[3].vfpprod(5) ); } @@ -4229,7 +4223,7 @@ BOOST_AUTO_TEST_CASE(VFPPROD_SCALING) { const auto deck = Parser{}.parseFile("VFP_CASE.DATA"); const auto es = EclipseState{ deck }; const auto sched = Schedule{ deck, es }; - const auto& vfp_table = sched.getVFPProdTable(1, 0); + const auto& vfp_table = sched[0].vfpprod(1); const std::vector flo = { 0.000578704, 0.001157407, 0.002893519, 0.005787037, 0.008680556, 0.011574074, 0.017361111, 0.023148148, 0.034722222, 0.046296296}; const std::vector thp = {1300000.000000000, 2500000.000000000, 5000000.000000000, 7500000.000000000, 10000000.000000000}; const std::vector wfr = { 0.000000000, 0.100000000, 0.200000000, 0.300000000, 0.400000000, 0.500000000, 0.600000000, 0.700000000, 0.800000000, 0.990000000};