diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp index f1e988136..a2217e6ec 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp @@ -42,11 +42,15 @@ public: double test_interval; int num_test; double startup_time; + // the related WTEST keywords is entered and will begin + // taking effects since this report step + int begin_report_step; }; WellTestConfig(); - void add_well(const std::string& well, Reason reason, double test_interval, int num_test, double startup_time); - void add_well(const std::string& well, const std::string& reasons, double test_interval, int num_test, double startup_time); + void add_well(const std::string& well, Reason reason, double test_interval, int num_test, double startup_time, int current_step); + void add_well(const std::string& well, const std::string& reasons, double test_interval, + int num_test, double startup_time, int current_step); void drop_well(const std::string& well); bool has(const std::string& well) const; bool has(const std::string& well, Reason reason) const; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp index 67a2f3614..b96d4a790 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp @@ -48,6 +48,11 @@ public: // or the time that the well is closed if not test has not been performed after double last_test; int num_attempt; + // if there is a WTEST setup for well testing, + // it will be the report step that WTEST is specified. + // if no, it is -1, which indicates we do not know the associated WTEST yet, + // or there is not associated WTEST request + int wtest_report_step; }; @@ -113,6 +118,8 @@ private: WTestWell* getWell(const std::string& well_name, WellTestConfig::Reason reason); + + void updateForNewWTEST(const WellTestConfig& config); }; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 115213575..ef530ce50 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -1116,15 +1116,15 @@ namespace Opm { invalidNamePattern(wellNamePattern, parseContext, errors, keyword); double test_interval = record.getItem("INTERVAL").getSIDouble(0); - const std::string& reason = record.getItem("REASON").get(0); + const std::string& reasons = record.getItem("REASON").get(0); int num_test = record.getItem("TEST_NUM").get(0); double startup_time = record.getItem("START_TIME").getSIDouble(0); for(const auto& well_name : well_names) { - if (reason.size() == 0) + if (reasons.empty()) new_config->drop_well(well_name); else - new_config->add_well(well_name, reason, test_interval, num_test, startup_time); + new_config->add_well(well_name, reasons, test_interval, num_test, startup_time, currentStep); } } this->wtest_config.update(currentStep, new_config); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp index 2ea08d50a..35fe058a4 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp @@ -28,31 +28,33 @@ WellTestConfig::WellTestConfig() { } -void WellTestConfig::add_well(const std::string& well, Reason shut_reason, double test_interval, int num_retries, double startup_time) { - wells.push_back({well, shut_reason, test_interval, num_retries, startup_time}); +void WellTestConfig::add_well(const std::string& well, Reason shut_reason, double test_interval, + int num_retries, double startup_time, const int current_step) { + wells.push_back({well, shut_reason, test_interval, num_retries, startup_time, current_step}); } -void WellTestConfig::add_well(const std::string& well, const std::string& reasons, double test_interval, int num_retries, double startup_time) { - if (reasons.size() == 0) +void WellTestConfig::add_well(const std::string& well, const std::string& reasons, double test_interval, + int num_retries, double startup_time, const int current_step) { + if (reasons.empty()) throw std::invalid_argument("Can not pass empty string to stop testing to add_well() method."); for (auto c : reasons) { switch(c) { case 'P' : - add_well(well, Reason::PHYSICAL, test_interval, num_retries, startup_time); + add_well(well, Reason::PHYSICAL, test_interval, num_retries, startup_time, current_step); break; case 'E' : - add_well(well, Reason::ECONOMIC, test_interval, num_retries, startup_time); + add_well(well, Reason::ECONOMIC, test_interval, num_retries, startup_time, current_step); break; case 'G': - add_well(well, Reason::GROUP, test_interval, num_retries, startup_time); + add_well(well, Reason::GROUP, test_interval, num_retries, startup_time, current_step); break; case 'D': - add_well(well, Reason::THP_DESIGN, test_interval, num_retries, startup_time); + add_well(well, Reason::THP_DESIGN, test_interval, num_retries, startup_time, current_step); break; case 'C': - add_well(well, Reason::COMPLETION, test_interval, num_retries, startup_time); + add_well(well, Reason::COMPLETION, test_interval, num_retries, startup_time, current_step); break; default: throw std::invalid_argument("Invalid character in WTEST configuration"); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp index 81f48775c..4ccd9a593 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp @@ -31,11 +31,19 @@ namespace Opm { WTestWell* well_ptr = getWell(well_name, reason); if (well_ptr) { + if (well_ptr->closed) { + throw std::runtime_error( " Well " + well_name + " is closed with reason " + + WellTestConfig::reasonToString(reason) + + ", we ware trying to close it again with same reason!"); + } // the well exists already, we just update it with action of closing well_ptr->closed = true; well_ptr->last_test = sim_time; - } else - this->wells.push_back({well_name, reason, true, sim_time, 0}); + } else { + // by default, we use -1 if there is no WTEST request for this well + // it will be updated when checking for WellTestConfig + this->wells.push_back({well_name, reason, true, sim_time, 0, -1}); + } } @@ -79,6 +87,9 @@ namespace Opm { std::vector> WellTestState::updateWell(const WellTestConfig& config, double sim_time) { std::vector> output; + + updateForNewWTEST(config); + for (auto& well : this->wells) { if (well.closed && config.has(well.name, well.reason)) { const auto& well_config = config.get(well.name, well.reason); @@ -161,6 +172,32 @@ namespace Opm { return well_iter->last_test; } + void WellTestState::updateForNewWTEST(const Opm::WellTestConfig& config) + { + // check whether to reset based on the new WTEST request + for (auto& well: this->wells) { + if (config.has(well.name, well.reason)) { + const auto& well_config = config.get(well.name, well.reason); + if (well_config.begin_report_step > well.wtest_report_step) { + // there is a new WTEST input, we should reset the counting + well.num_attempt = 0; + well.wtest_report_step = well_config.begin_report_step; + } + assert(well_config.begin_report_step == well.wtest_report_step); + } else { + // If there is WTEST step, due to new WTEST input, which does not specify any testing closure cause, + // there is no WTEST request anymore. + // If there is no WTEST step, then everything stay the same. + if (well.wtest_report_step >= 0) { + well.wtest_report_step = -1; + well.num_attempt = 0; + } + assert(well.wtest_report_step == -1); + assert(well.num_attempt == 0); + } + } + } + } diff --git a/tests/parser/WTEST.cpp b/tests/parser/WTEST.cpp index d28739857..e2ba9f99e 100644 --- a/tests/parser/WTEST.cpp +++ b/tests/parser/WTEST.cpp @@ -45,14 +45,14 @@ BOOST_AUTO_TEST_CASE(CreateWellTestConfig) { BOOST_CHECK_EQUAL(wc.size() , 0); - wc.add_well("NAME", WellTestConfig::Reason::PHYSICAL, 10, 10, 10); + wc.add_well("NAME", WellTestConfig::Reason::PHYSICAL, 10, 10, 10, 1); BOOST_CHECK_EQUAL(wc.size(), 1); - BOOST_CHECK_THROW(wc.add_well("NAME2", "", 10.0,10,10.0), std::invalid_argument); - BOOST_CHECK_THROW(wc.add_well("NAME3", "X", 1,2,3), std::invalid_argument); + BOOST_CHECK_THROW(wc.add_well("NAME2", "", 10.0,10,10.0, 1), std::invalid_argument); + BOOST_CHECK_THROW(wc.add_well("NAME3", "X", 1,2,3, 1), std::invalid_argument); - wc.add_well("NAME", "PEGDC", 10, 10, 10); + wc.add_well("NAME", "PEGDC", 10, 10, 10, 1); BOOST_CHECK_EQUAL(wc.size(), 6); - wc.add_well("NAMEX", "PGDC", 10, 10, 10); + wc.add_well("NAMEX", "PGDC", 10, 10, 10, 1); BOOST_CHECK_EQUAL(wc.size(), 10); wc.drop_well("NAME"); BOOST_CHECK_EQUAL(wc.size(), 4); @@ -71,7 +71,7 @@ BOOST_AUTO_TEST_CASE(CreateWellTestConfig) { BOOST_AUTO_TEST_CASE(WTEST_STATE2) { WellTestConfig wc; WellTestState st; - wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 0, 0, 0); + wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 0, 0, 0, 0); st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100); BOOST_CHECK_EQUAL(st.sizeWells(), 1); @@ -101,7 +101,7 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE) { auto shut_wells = st.updateWell(wc, 5000); BOOST_CHECK_EQUAL( shut_wells.size(), 0); - wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 2, 0); + wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 2, 0, 1); // Not sufficient time has passed. BOOST_CHECK_EQUAL( st.updateWell(wc, 200. * day).size(), 0); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE_COMPLETIONS) { auto closed_completions = st.updateWell(wc, 5000); BOOST_CHECK_EQUAL( closed_completions.size(), 0); - wc.add_well("WELL_NAME", WellTestConfig::Reason::COMPLETION, 1000, 2, 0); + wc.add_well("WELL_NAME", WellTestConfig::Reason::COMPLETION, 1000, 2, 0, 0); // Not sufficient time has passed. BOOST_CHECK_EQUAL( st.updateCompletion(wc, 200).size(), 0);