From 1a1edf01b53bf5310d503fc5d35469e452bc233a Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Mon, 18 Oct 2021 10:11:21 +0200 Subject: [PATCH] Internalize NEXTSTEP keyword and interact with TUNING.TSINIT --- .../EclipseState/Schedule/Schedule.hpp | 1 + .../EclipseState/Schedule/ScheduleState.hpp | 3 ++ .../eclipse/EclipseState/Schedule/Tuning.hpp | 22 +++++++++++ .../EclipseState/Schedule/KeywordHandlers.cpp | 11 ++++++ .../EclipseState/Schedule/ScheduleState.cpp | 17 +++++++++ .../eclipse/EclipseState/Schedule/Tuning.cpp | 23 ++++++++++++ tests/parser/TuningTests.cpp | 37 +++++++++++++++++-- 7 files changed, 110 insertions(+), 4 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 5d0dfe712..b4c65d5a4 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -604,6 +604,7 @@ namespace Opm void handleMULTFLT (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleMXUNSUPP (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleNETBALAN (const HandlerContext&, const ParseContext&, ErrorGuard&); + void handleNEXTSTEP (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleNODEPROP (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleNUPCOL (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleRPTONLY (const HandlerContext&, const ParseContext&, ErrorGuard&); diff --git a/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp b/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp index 444f10768..f8b4e9dc8 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.hpp @@ -300,6 +300,7 @@ namespace Opm { void update_tuning(Tuning tuning); Tuning& tuning(); const Tuning& tuning() const; + double max_next_tstep() const; void init_nupcol(Nupcol nupcol); void update_nupcol(int nupcol); @@ -468,6 +469,7 @@ namespace Opm { map_member groups; map_member wells; std::unordered_map target_wellpi; + std::optional next_tstep; using WellPIMapType = std::unordered_map; @@ -483,6 +485,7 @@ namespace Opm { serializer(m_save_step); serializer(m_sumthin); serializer(this->m_rptonly); + serializer(this->next_tstep); m_tuning.serializeOp(serializer); m_nupcol.serializeOp(serializer); m_oilvap.serializeOp(serializer); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp b/opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp index 8f6cca1b6..7e22c21b2 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Tuning.hpp @@ -21,6 +21,28 @@ #define OPM_TUNING_HPP namespace Opm { + + class NextStep { + public: + NextStep() = default; + NextStep(double value, bool every_report); + double value() const; + bool every_report() const; + bool operator==(const NextStep& other) const; + static NextStep serializeObject(); + + template + void serializeOp(Serializer& serializer) + { + serializer(this->next_tstep); + serializer(this->persist); + } + + private: + double next_tstep; + bool persist; + }; + struct Tuning { Tuning(); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index 3a0e61653..eee9b73be 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -744,6 +744,16 @@ namespace { this->snapshots.back().network_balance.update( std::move(new_balance) ); } + void Schedule::handleNEXTSTEP(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { + const auto& record = handlerContext.keyword[0]; + auto next_tstep = record.getItem().getSIDouble(0); + auto apply_to_all = DeckItem::to_bool( record.getItem().get(0) ); + + this->snapshots.back().next_tstep = NextStep{next_tstep, apply_to_all}; + this->snapshots.back().events().addEvent(ScheduleEvents::TUNING_CHANGE); + } + + void Schedule::handleNODEPROP(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { auto ext_network = this->snapshots.back().network.get(); @@ -2052,6 +2062,7 @@ namespace { { "MULTZ" , &Schedule::handleMXUNSUPP }, { "MULTZ-" , &Schedule::handleMXUNSUPP }, { "NETBALAN", &Schedule::handleNETBALAN }, + { "NEXTSTEP", &Schedule::handleNEXTSTEP }, { "NODEPROP", &Schedule::handleNODEPROP }, { "NUPCOL" , &Schedule::handleNUPCOL }, { "RPTONLY" , &Schedule::handleRPTONLY }, diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp index 178cc1a94..f45816959 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/ScheduleState.cpp @@ -114,6 +114,13 @@ ScheduleState::ScheduleState(const ScheduleState& src, const time_point& start_t new_rst.save = false; this->rst_config.update( std::move(new_rst) ); } + + if (this->next_tstep.has_value()) { + if (!this->next_tstep->every_report()) { + this->next_tstep = std::nullopt; + this->events().addEvent(ScheduleEvents::TUNING_CHANGE); + } + } } @@ -267,6 +274,7 @@ bool ScheduleState::operator==(const ScheduleState& other) const { this->vfpprod == other.vfpprod && this->vfpinj == other.vfpinj && this->m_sumthin == other.m_sumthin && + this->next_tstep == other.next_tstep && this->m_rptonly == other.m_rptonly; } @@ -325,6 +333,15 @@ Tuning& ScheduleState::tuning() { return this->m_tuning; } +double ScheduleState::max_next_tstep() const { + auto tuning_value = this->m_tuning.TSINIT; + if (!this->next_tstep.has_value()) + return tuning_value; + + auto next_value = this->next_tstep->value(); + return std::max(next_value, tuning_value); +} + void ScheduleState::update_events(Events events) { this->m_events = events; } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Tuning.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Tuning.cpp index 36b755967..eb5550fb5 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Tuning.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Tuning.cpp @@ -25,6 +25,29 @@ namespace Opm { + +NextStep::NextStep(double value, bool every_report) + : next_tstep(value) + , persist(every_report) +{} + +bool NextStep::operator==(const NextStep& other) const { + return this->next_tstep == other.next_tstep && + this->persist == other.persist; +} + +double NextStep::value() const { + return this->next_tstep; +} + +bool NextStep::every_report() const { + return this->persist; +} + + + + + Tuning::Tuning() { using TuningKw = ParserKeywords::TUNING; using WsegIterKW = ParserKeywords::WSEGITER; diff --git a/tests/parser/TuningTests.cpp b/tests/parser/TuningTests.cpp index 9374537d4..b0d4259b2 100644 --- a/tests/parser/TuningTests.cpp +++ b/tests/parser/TuningTests.cpp @@ -41,6 +41,9 @@ START 21 MAY 1981 / SCHEDULE +NEXTSTEP + 5 YES / + TSTEP 1 2 3 4 5 / @@ -49,10 +52,14 @@ TUNING 0.2 0.002 2E-7 0.0002 11 0.02 2.0E-6 0.002 0.002 0.035 66 0.02 2/ 13 2 26 2 9 9 4.0E6 4.0E6 4.0E6 1/ DATES - 1 JAN 1982 / - 1 JAN 1982 13:55:44 / - 3 JAN 1982 14:56:45.123 / + 1 JAN 1982 / -- 6 + 1 JAN 1982 13:55:44 / --7 + 3 JAN 1982 14:56:45.123 / -- 8 / + +NEXTSTEP + 10 / + TSTEP 9 10 / @@ -95,6 +102,7 @@ BOOST_AUTO_TEST_CASE(TuningTest) { const auto& tuning = schedule[4].tuning(); double TSINIT_default = tuning.TSINIT; BOOST_CHECK_CLOSE(TSINIT_default, 1 * Metric::Time, diff); + BOOST_CHECK_CLOSE(schedule[timestep].max_next_tstep(), 5*Metric::Time, diff); double TSMAXZ_default = tuning.TSMAXZ; BOOST_CHECK_CLOSE(TSMAXZ_default, 365 * Metric::Time, diff); @@ -215,6 +223,7 @@ BOOST_AUTO_TEST_CASE(TuningTest) { BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE)); double TSINIT = tuning.TSINIT; BOOST_CHECK_CLOSE(TSINIT, 2 * Metric::Time, diff); + BOOST_CHECK_CLOSE(schedule[timeStep].max_next_tstep(), 5*Metric::Time, diff); double TSMAXZ = tuning.TSMAXZ; BOOST_CHECK_CLOSE(TSMAXZ, 300 * Metric::Time, diff); @@ -322,11 +331,31 @@ BOOST_AUTO_TEST_CASE(TuningTest) { BOOST_CHECK(!event.hasEvent(ScheduleEvents::TUNING_CHANGE)); } + /*** TIMESTEP 8 ***/ + { + std::size_t timestep = 8; + const auto& event = schedule[timestep].events(); + const auto& tuning = schedule[timestep].tuning(); + BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE)); + + BOOST_CHECK_CLOSE(schedule[timestep].max_next_tstep(), 10*Metric::Time, diff); + } + + /*** TIMESTEP 9 ***/ + { + std::size_t timestep = 9; + const auto& event = schedule[timestep].events(); + const auto& tuning = schedule[timestep].tuning(); + BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE)); + + BOOST_CHECK_CLOSE(schedule[timestep].max_next_tstep(), 2*Metric::Time, diff); + } + /*** TIMESTEP 10 ***/ { /********* Record 1 ***********/ std::size_t timestep = 10; - const auto& tuning = schedule[10].tuning(); + const auto& tuning = schedule[timestep].tuning(); const auto& event = schedule[timestep].events(); BOOST_CHECK(event.hasEvent(ScheduleEvents::TUNING_CHANGE)); BOOST_CHECK_EQUAL(true, tuning.TMAXWC_has_value);