From b9ed81fe2a7abe6ffd55817523eddf2f4ecebedf Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Wed, 25 May 2022 15:10:33 +0200 Subject: [PATCH 1/4] throw when report steps has start time later than end time --- src/opm/input/eclipse/Schedule/Schedule.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/opm/input/eclipse/Schedule/Schedule.cpp b/src/opm/input/eclipse/Schedule/Schedule.cpp index 3a2faf30d..c38a34238 100644 --- a/src/opm/input/eclipse/Schedule/Schedule.cpp +++ b/src/opm/input/eclipse/Schedule/Schedule.cpp @@ -1276,6 +1276,12 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen } double Schedule::stepLength(std::size_t timeStep) const { + if (this->snapshots[timeStep].end_time() < this->snapshots[timeStep].start_time()) { + const auto& start_time = Schedule::formatDate(std::chrono::system_clock::to_time_t(this->snapshots[timeStep].start_time())); + const auto& end_time = Schedule::formatDate(std::chrono::system_clock::to_time_t(this->snapshots[timeStep].end_time())); + throw std::runtime_error(fmt::format(" Report step {0} has the start time {1} later than the end time {2},\n" + "can be due to the wrong way doing restarting (forgetting SKIPREST?) or bad setup in the SCHEDULE section.", timeStep, start_time, end_time)); + } auto elapsed = this->snapshots[timeStep].end_time() - this->snapshots[timeStep].start_time(); return std::chrono::duration_cast(elapsed).count(); } From f1986689b59c177be8ee5c21342ce6f9a537912f Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Wed, 25 May 2022 22:44:46 +0200 Subject: [PATCH 2/4] fixing a schedule test and adding another for PR3035 --- tests/parser/ScheduleTests.cpp | 36 ++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index eb2449157..bfb6f2589 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -5044,8 +5044,8 @@ DATES -- 4,5 SUMTHIN 0.0 / DATES -- 6,7 - 10 SEP 2007 / - 10 OCT 2007 / + 10 NOV 2007 / + 10 DEC 2007 / / END )"); @@ -5087,6 +5087,38 @@ END R"("SUMTHIN" must NOT be configured on report step 7)"); } + +BOOST_AUTO_TEST_CASE(MISORDERD_DATES) { +const auto deck = Parser{}.parseString(R"(RUNSPEC +DIMENS + 10 10 10 / + +START -- 0 +10 MAI 2007 / + +GRID +DXV +10*100.0 / +DYV +10*100.0 / +DZV +10*10.0 / +DEPTHZ +121*2000.0 / + +SCHEDULE +DATES -- 1, 2, 3 + 10 JUN 2007 / + 10 MAY 2007 / + 10 AUG 2007 / +/ +END +)"); + +const auto es = EclipseState { deck }; +BOOST_CHECK_THROW(Schedule(deck, es), std::runtime_error); +} + BOOST_AUTO_TEST_CASE(RPTONLY_IN_SUMMARY) { const auto deck = Parser{}.parseString(R"(RUNSPEC DIMENS From 3ffc61e221c9a88a14695d462545c97efb1e1e05 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Thu, 25 Aug 2022 14:38:00 +0200 Subject: [PATCH 3/4] throw when a negative TSTEP value is input --- src/opm/input/eclipse/Schedule/ScheduleDeck.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp b/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp index 1eb2ae6a6..8e35136d9 100644 --- a/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp +++ b/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp @@ -332,6 +332,13 @@ void ScheduleDeck::add_block(ScheduleTimeType time_type, const time_point& t, Sc void ScheduleDeck::add_TSTEP(const DeckKeyword& TSTEPKeyword, ScheduleDeckContext& context) { const auto &item = TSTEPKeyword.getRecord(0).getItem(0); for (size_t itemIndex = 0; itemIndex < item.data_size(); itemIndex++) { + { + const auto tstep = item.get(itemIndex); + if (tstep < 0) { + const auto msg = fmt::format("a negatvie TSTEP value {} is input", tstep); + throw OpmInputError(msg, TSTEPKeyword.location()); + } + } auto next_time = context.last_time + std::chrono::duration_cast(std::chrono::duration(item.getSIDouble(itemIndex))); this->add_block(ScheduleTimeType::TSTEP, next_time, context, TSTEPKeyword.location()); } From 632f1457b159f6d800d44afc063817e883707b45 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Fri, 26 Aug 2022 09:23:50 +0200 Subject: [PATCH 4/4] throw for an inconsistent DATES setup --- src/opm/input/eclipse/Schedule/Schedule.cpp | 20 +++++++---- .../input/eclipse/Schedule/ScheduleDeck.cpp | 12 ++++++- tests/msim/test_msim.cpp | 4 +++ tests/parser/ScheduleTests.cpp | 35 ++++++++++++++++++- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/opm/input/eclipse/Schedule/Schedule.cpp b/src/opm/input/eclipse/Schedule/Schedule.cpp index c38a34238..fc658d410 100644 --- a/src/opm/input/eclipse/Schedule/Schedule.cpp +++ b/src/opm/input/eclipse/Schedule/Schedule.cpp @@ -89,6 +89,7 @@ #include #include #include +#include #include "Well/injection.hpp" #include "MSW/Compsegs.hpp" @@ -1276,14 +1277,19 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen } double Schedule::stepLength(std::size_t timeStep) const { - if (this->snapshots[timeStep].end_time() < this->snapshots[timeStep].start_time()) { - const auto& start_time = Schedule::formatDate(std::chrono::system_clock::to_time_t(this->snapshots[timeStep].start_time())); - const auto& end_time = Schedule::formatDate(std::chrono::system_clock::to_time_t(this->snapshots[timeStep].end_time())); - throw std::runtime_error(fmt::format(" Report step {0} has the start time {1} later than the end time {2},\n" - "can be due to the wrong way doing restarting (forgetting SKIPREST?) or bad setup in the SCHEDULE section.", timeStep, start_time, end_time)); + const auto start = this->snapshots[timeStep].start_time(); + const auto end = this->snapshots[timeStep].end_time(); + if (start > end) { + throw std::invalid_argument { + fmt::format(" Report step {} has start time after end time,\n" + " * Start time = {:%d-%b-%Y %H:%M:%S}\n" + " * End time = {:%d-%b-%Y %H:%M:%S}.\n" + " Possibly due to inconsistent RESTART/SKIPREST settings.", + timeStep + 1, + fmt::gmtime(TimeService::to_time_t(start)), + fmt::gmtime(TimeService::to_time_t(end))) }; } - auto elapsed = this->snapshots[timeStep].end_time() - this->snapshots[timeStep].start_time(); - return std::chrono::duration_cast(elapsed).count(); + return std::chrono::duration_cast(end - start).count(); } void Schedule::applyKeywords( diff --git a/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp b/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp index 8e35136d9..d0c415d51 100644 --- a/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp +++ b/src/opm/input/eclipse/Schedule/ScheduleDeck.cpp @@ -238,6 +238,16 @@ ScheduleDeck::ScheduleDeck(time_point start_time, const Deck& deck, const Schedu std::throw_with_nested(opm_error); } + const auto currenTime = std::chrono::system_clock::to_time_t(context.last_time); + if (nextTime < currenTime) { + auto msg = fmt::format( + "Keyword DATES specifies a time {:%d-%b-%Y %H:%M:%S} earlier than the end time of previous report step {:%d-%b-%Y %H:%M:%S}", + fmt::gmtime(nextTime), fmt::gmtime(currenTime)); + if (rst_info.time > 0 && !this->skiprest) { // the situation with SKIPREST is handled in function add_block + msg += "\nin a RESTARTing simulation, Please check whether SKIPREST is supposed to be used for this circumstance"; + } + throw OpmInputError(msg, keyword.location()); + } this->add_block(ScheduleTimeType::DATES, TimeService::from_time_t( nextTime ), context, keyword.location()); } continue; @@ -335,7 +345,7 @@ void ScheduleDeck::add_TSTEP(const DeckKeyword& TSTEPKeyword, ScheduleDeckContex { const auto tstep = item.get(itemIndex); if (tstep < 0) { - const auto msg = fmt::format("a negatvie TSTEP value {} is input", tstep); + const auto msg = fmt::format("a negative TSTEP value {} is input", tstep); throw OpmInputError(msg, TSTEPKeyword.location()); } } diff --git a/tests/msim/test_msim.cpp b/tests/msim/test_msim.cpp index 7117bd53b..452d5eccf 100644 --- a/tests/msim/test_msim.cpp +++ b/tests/msim/test_msim.cpp @@ -160,6 +160,10 @@ BOOST_AUTO_TEST_CASE(RUN) { } const int report_step = 50; + { + const KeywordLocation location {"SKIPREST", "SPE1CASE1.DATA", 388}; + deck.addKeyword({location, "SKIPREST"}); + } auto rst_view = std::make_shared(std::move(rst), report_step); const auto rst_state = Opm::RestartIO::RstState::load(std::move(rst_view), state.runspec(), parser); Schedule sched_rst(deck, state, python, {}, &rst_state); diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index bfb6f2589..2702fed2f 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -5116,7 +5116,40 @@ END )"); const auto es = EclipseState { deck }; -BOOST_CHECK_THROW(Schedule(deck, es), std::runtime_error); +BOOST_CHECK_THROW(Schedule(deck, es), Opm::OpmInputError); +} + +BOOST_AUTO_TEST_CASE(NEGATIVE_TSTEPS) { +const auto deck = Parser{}.parseString(R"(RUNSPEC +DIMENS + 10 10 10 / + +START -- 0 +10 MAI 2007 / + +GRID +DXV +10*100.0 / +DYV +10*100.0 / +DZV +10*10.0 / +DEPTHZ +121*2000.0 / + +SCHEDULE +DATES -- 1, 2, 3 + 10 MAY 2007 / + 10 JUN 2007 / + 10 AUG 2007 / +/ +TSTEP +-1 / +END +)"); + +const auto es = EclipseState { deck }; +BOOST_CHECK_THROW(Schedule(deck, es), Opm::OpmInputError); } BOOST_AUTO_TEST_CASE(RPTONLY_IN_SUMMARY) {