From c0c9d70dcfb9ea04bb4a12f436b5206da47ba2f8 Mon Sep 17 00:00:00 2001 From: Kai Bao Date: Mon, 24 Jun 2019 11:09:49 +0200 Subject: [PATCH] not removing the well from WellTestState when testing is successful --- .../Schedule/Well/WellTestConfig.hpp | 2 + .../Schedule/Well/WellTestState.hpp | 18 +++-- .../Schedule/Well/WellTestConfig.cpp | 17 ++++ .../Schedule/Well/WellTestState.cpp | 77 ++++++++++++------- tests/parser/WTEST.cpp | 38 +++++---- 5 files changed, 106 insertions(+), 46 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp index 727e13fe7..f1e988136 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.hpp @@ -53,6 +53,8 @@ public: const WTESTWell& get(const std::string& well, Reason reason) const; size_t size() const; + static std::string reasonToString(const Reason reason); + private: std::vector wells; }; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp index 3c6ce753d..30096007f 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.hpp @@ -39,9 +39,13 @@ public: - struct ClosedWell { + struct WTestWell { std::string name; WellTestConfig::Reason reason; + // the well can be re-opened if the well testing is successful. We only test when it is closed. + bool closed; + // it can be the time of last test, + // or the time that the well is closed if not test has not been performed after double last_test; int num_attempt; }; @@ -58,7 +62,7 @@ public: The simulator has decided to close a particular well; we then add it here as a closed well with a particualar reason. */ - void addClosedWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time); + void closeWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time); /* The simulator has decided to close a particular completion in a well; we then add it here @@ -97,8 +101,9 @@ public: */ void dropCompletion(const std::string& well_name, int complnum); - bool hasWell(const std::string& well_name, WellTestConfig::Reason reason) const; - void openWell(const std::string& well_name); + bool hasWellClosed(const std::string& well_name, WellTestConfig::Reason reason) const; + + void openWell(const std::string& well_name, WellTestConfig::Reason reason); bool hasCompletion(const std::string& well_name, const int complnum) const; @@ -111,8 +116,11 @@ public: double lastTestTime(const std::string& well_name) const; private: - std::vector wells; + std::vector wells; std::vector completions; + + + WTestWell* getWell(const std::string& well_name, WellTestConfig::Reason reason); }; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp index 246d9da4f..2ea08d50a 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestConfig.cpp @@ -102,6 +102,23 @@ const WellTestConfig::WTESTWell& WellTestConfig::get(const std::string& well, Re +std::string WellTestConfig::reasonToString(const Reason reason) { + switch(reason) { + case PHYSICAL: + return std::string("PHYSICAL"); + case ECONOMIC: + return std::string("ECONOMIC"); + case GROUP: + return std::string("GROUP"); + case THP_DESIGN: + return std::string("THP_DESIGN"); + case COMPLETION: + return std::string("COMPLETION"); + default: + throw std::runtime_error("unknown closure reason"); + } +} + size_t WellTestConfig::size() const { diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp index 09c1897b2..7a8dfa3a4 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/WellTestState.cpp @@ -19,72 +19,95 @@ #include #include +#include #include #include +#include namespace Opm { - void WellTestState::addClosedWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time) { - if (this->hasWell(well_name, reason)) - return; + void WellTestState::closeWell(const std::string& well_name, WellTestConfig::Reason reason, double sim_time) { - this->wells.push_back({well_name, reason, sim_time, 0}); + WTestWell* well_ptr = getWell(well_name, reason); + + if (well_ptr) { + // 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}); } - void WellTestState::openWell(const std::string& well_name) { - wells.erase(std::remove_if(wells.begin(), - wells.end(), - [&well_name](const ClosedWell& well) { return (well.name == well_name); }), - wells.end()); + void WellTestState::openWell(const std::string& well_name, WellTestConfig::Reason reason) { + + WTestWell* well_ptr = getWell(well_name, reason); + + if (well_ptr) + well_ptr->closed = false; + else + throw std::runtime_error("No well named " + well_name + " with close reason " + + WellTestConfig::reasonToString(reason) + + " found in WellTestState."); } void WellTestState::dropWell(const std::string& well_name, WellTestConfig::Reason reason) { wells.erase(std::remove_if(wells.begin(), wells.end(), - [&well_name, reason](const ClosedWell& well) { return (well.name == well_name && well.reason == reason); }), + [&well_name, reason](const WTestWell& well) { return (well.name == well_name && well.reason == reason); }), wells.end()); } - bool WellTestState::hasWell(const std::string& well_name, WellTestConfig::Reason reason) const { + bool WellTestState::hasWellClosed(const std::string& well_name, WellTestConfig::Reason reason) const { const auto well_iter = std::find_if(wells.begin(), wells.end(), - [&well_name, &reason](const ClosedWell& well) - { - return (reason == well.reason && well.name == well_name); + [&well_name, &reason](const WTestWell& well) + { + return (reason == well.reason && well.name == well_name && well.closed); }); return (well_iter != wells.end()); } + + WellTestState::WTestWell* WellTestState::getWell(const std::string& well_name, WellTestConfig::Reason reason) + { + const auto well_iter = std::find_if(wells.begin(), wells.end(), [&well_name, &reason](const WTestWell& well) { + return (reason == well.reason && well.name == well_name); + }); + + return (well_iter == wells.end() ? nullptr : &(*well_iter) ); + } + + size_t WellTestState::sizeWells() const { return this->wells.size(); } std::vector> WellTestState::updateWell(const WellTestConfig& config, double sim_time) { std::vector> output; - for (auto& closed_well : this->wells) { - if (config.has(closed_well.name, closed_well.reason)) { - const auto& well_config = config.get(closed_well.name, closed_well.reason); - double elapsed = sim_time - closed_well.last_test; + for (auto& well : this->wells) { + if (well.closed && config.has(well.name, well.reason)) { + const auto& well_config = config.get(well.name, well.reason); + double elapsed = sim_time - well.last_test; if (elapsed >= well_config.test_interval) - if (well_config.num_test == 0 || (closed_well.num_attempt < well_config.num_test)) { - closed_well.last_test = sim_time; - closed_well.num_attempt += 1; - output.push_back(std::make_pair(closed_well.name, closed_well.reason)); + if (well_config.num_test == 0 || (well.num_attempt < well_config.num_test)) { + well.last_test = sim_time; + well.num_attempt ++; + output.emplace_back(std::make_pair(well.name, well.reason)); + if ( (well_config.num_test != 0) && (well.num_attempt >= well_config.num_test) ) { + OpmLog::info(well.name + " will be tested for " + WellTestConfig::reasonToString(well.reason) + + " reason for the last time! " ); + } } - } } return output; } - - - void WellTestState::addClosedCompletion(const std::string& well_name, int complnum, double sim_time) { if (this->hasCompletion(well_name, complnum)) return; @@ -136,7 +159,7 @@ namespace Opm { double WellTestState::lastTestTime(const std::string& well_name) const { const auto well_iter = std::find_if(wells.begin(), wells.end(), - [&well_name](const ClosedWell& well) + [&well_name](const WTestWell& well) { return (well.name == well_name); }); diff --git a/tests/parser/WTEST.cpp b/tests/parser/WTEST.cpp index 46f1293c9..b7a8f3579 100644 --- a/tests/parser/WTEST.cpp +++ b/tests/parser/WTEST.cpp @@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE2) { WellTestConfig wc; WellTestState st; wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 0, 0, 0); - st.addClosedWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100); + st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100); BOOST_CHECK_EQUAL(st.sizeWells(), 1); auto shut_wells = st.updateWell(wc, 5000); @@ -80,43 +80,53 @@ BOOST_AUTO_TEST_CASE(WTEST_STATE2) { } BOOST_AUTO_TEST_CASE(WTEST_STATE) { + const double day = 86400.; WellTestConfig wc; WellTestState st; - st.addClosedWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100); + st.closeWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100. * day); BOOST_CHECK_EQUAL(st.sizeWells(), 1); - st.addClosedWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100); + st.openWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC); BOOST_CHECK_EQUAL(st.sizeWells(), 1); - st.addClosedWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100); + st.closeWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC, 100. * day); + BOOST_CHECK_EQUAL(st.sizeWells(), 1); + + st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 100. * day); BOOST_CHECK_EQUAL(st.sizeWells(), 2); - st.addClosedWell("WELLX", WellTestConfig::Reason::PHYSICAL, 100); + st.closeWell("WELLX", WellTestConfig::Reason::PHYSICAL, 100. * day); BOOST_CHECK_EQUAL(st.sizeWells(), 3); auto shut_wells = st.updateWell(wc, 5000); BOOST_CHECK_EQUAL( shut_wells.size(), 0); - wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000, 2, 0); + wc.add_well("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1000. * day, 2, 0); // Not sufficient time has passed. - BOOST_CHECK_EQUAL( st.updateWell(wc, 200).size(), 0); + BOOST_CHECK_EQUAL( st.updateWell(wc, 200. * day).size(), 0); // We should test it: - BOOST_CHECK_EQUAL( st.updateWell(wc, 1200).size(), 1); + BOOST_CHECK_EQUAL( st.updateWell(wc, 1200. * day).size(), 1); // Not sufficient time has passed. - BOOST_CHECK_EQUAL( st.updateWell(wc, 1700).size(), 0); + BOOST_CHECK_EQUAL( st.updateWell(wc, 1700. * day).size(), 0); - // We should test it: - BOOST_CHECK_EQUAL( st.updateWell(wc, 2400).size(), 1); + st.openWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL); + + st.closeWell("WELL_NAME", WellTestConfig::Reason::PHYSICAL, 1900. * day); + + // We should not test it: + BOOST_CHECK_EQUAL( st.updateWell(wc, 2400. * day).size(), 0); + + // We should test it now: + BOOST_CHECK_EQUAL( st.updateWell(wc, 3000. * day).size(), 1); // Too many attempts: - BOOST_CHECK_EQUAL( st.updateWell(wc, 24000).size(), 0); + BOOST_CHECK_EQUAL( st.updateWell(wc, 24000. * day).size(), 0); st.dropWell("WELL_NAME", WellTestConfig::Reason::ECONOMIC); - st.openWell("WELL_NAME"); - BOOST_CHECK_EQUAL(st.sizeWells(), 1); + BOOST_CHECK_EQUAL(st.sizeWells(), 2); }