From c5935c97f6dd04a6811bb954b37c333daf3e1dce Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Thu, 14 Mar 2019 09:23:03 +0100 Subject: [PATCH] Implement Schedule::wellNames() --- .../EclipseState/Schedule/Schedule.hpp | 1 + .../EclipseState/Schedule/Schedule.cpp | 59 +++++++++++++++++ tests/parser/ScheduleTests.cpp | 66 +++++++++++++++++++ 3 files changed, 126 insertions(+) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 53f557b22..12d11d8dc 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -114,6 +114,7 @@ namespace Opm size_t numWells(size_t timestep) const; size_t getMaxNumConnectionsForWells(size_t timestep) const; bool hasWell(const std::string& wellName) const; + std::vector wellNames(const std::string& pattern, size_t timeStep, const std::vector& matching_wells = {}) const; const Well* getWell(const std::string& wellName) const; std::vector< const Well* > getOpenWells(size_t timeStep) const; std::vector< const Well* > getWells() const; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index e71f9ffc7..287cdf8b2 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -17,6 +17,7 @@ along with OPM. If not, see . */ +#include #include #include #include @@ -1897,6 +1898,64 @@ namespace Opm { return { tmp.begin(), tmp.end() }; } + + /* + There are many SCHEDULE keyword which take a wellname as argument. In + addition to giving a fully qualified name like 'W1' you can also specify + shell wildcard patterns like like 'W*', you can get all the wells in the + well-list '*WL'[1] and the wellname '?' is used to get all the wells which + already have matched a condition in a ACTIONX keyword. This function + should be one-stop function to get all well names according to a input + pattern. The timestep argument is used to check that the wells have + indeewd been defined at the point in time we are considering. + + [1]: The leading '*' in a WLIST name should not be interpreted as a shell + wildcard! + */ + + + std::vector Schedule::wellNames(const std::string& pattern, size_t timeStep, const std::vector& matching_wells) const { + std::vector names; + + // WLIST + if (pattern[0] == '*') { + const auto& wlm = this->getWListManager(timeStep); + if (wlm.hasList(pattern)) { + const auto& wlist = wlm.getList(pattern); + return { wlist.begin(), wlist.end() }; + } else + return {}; + } + + // Normal pattern matching + auto star_pos = pattern.find('*'); + if (star_pos != std::string::npos) { + int flags = 0; + std::vector names; + for (const auto& well_pair : this->m_wells) { + if (fnmatch(pattern.c_str(), well_pair.first.c_str(), flags) == 0) { + if (well_pair.second.firstTimeStep() <= timeStep) + names.push_back(well_pair.first); + } + } + return names; + } + + // ACTIONX handler + if (pattern == "?") { + return { matching_wells.begin(), matching_wells.end() }; + } + + // Normal well name without any special characters + if (this->hasWell(pattern)) { + auto well = this->getWell(pattern); + if (well->firstTimeStep() <= timeStep) + return { pattern }; + } + return {}; + } + + std::vector< Well* > Schedule::getWells(const std::string& wellNamePattern, const std::vector& matching_wells) { // If we arrive here during the handling the body of a ACTIONX keyword // we can arrive with wellname '?' and a set of matching wells. diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index cdc7d6910..07504a904 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -94,6 +94,9 @@ static Deck createDeckWTEST() { " \'DEFAULT\' \'OP\' 30 37 3.33 \'OIL\' 7*/ \n" " \'ALLOW\' \'OP\' 30 37 3.33 \'OIL\' 3* YES / \n" " \'BAN\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + " \'W1\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + " \'W2\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + " \'W3\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" "/\n" "COMPDAT\n" @@ -125,6 +128,17 @@ static Deck createDeckWTEST() { " 10 JUL 2007 / \n" "/\n" + "WELSPECS\n" + " \'I1\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + " \'I2\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + " \'I3\' \'OP\' 20 51 3.92 \'OIL\' 3* NO / \n" + "/\n" + + "WLIST\n" + " \'*ILIST\' \'NEW\' I1 /\n" + " \'*ILIST\' \'ADD\' I2 /\n" + "/\n" + "WCONPROD\n" " 'BAN' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / \n" "/\n" @@ -2816,3 +2830,55 @@ BOOST_AUTO_TEST_CASE(WTEST_CONFIG) { BOOST_CHECK(wtest_config2.has("BAN", WellTestConfig::Reason::GROUP)); BOOST_CHECK(!wtest_config2.has("BAN", WellTestConfig::Reason::PHYSICAL)); } + + +bool has(const std::vector& l, const std::string& s) { + auto f = std::find(l.begin(), l.end(), s); + return (f != l.end()); +} + + + +BOOST_AUTO_TEST_CASE(WellNames) { + auto deck = createDeckWTEST(); + EclipseGrid grid1(10,10,10); + TableManager table ( deck ); + Eclipse3DProperties eclipseProperties ( deck , table, grid1); + Runspec runspec (deck); + Schedule schedule(deck, grid1 , eclipseProperties, runspec); + + auto names = schedule.wellNames("NO_SUCH_WELL", 0); + BOOST_CHECK_EQUAL(names.size(), 0); + + auto w1names = schedule.wellNames("W1", 0); + BOOST_CHECK_EQUAL(w1names.size(), 1); + BOOST_CHECK_EQUAL(w1names[0], "W1"); + + auto i1names = schedule.wellNames("11", 0); + BOOST_CHECK_EQUAL(i1names.size(), 0); + + auto listnamese = schedule.wellNames("*NO_LIST", 0); + BOOST_CHECK_EQUAL( listnamese.size(), 0); + + auto listnames0 = schedule.wellNames("*ILIST", 0); + BOOST_CHECK_EQUAL( listnames0.size(), 0); + + auto listnames1 = schedule.wellNames("*ILIST", 2); + BOOST_CHECK_EQUAL( listnames1.size(), 2); + BOOST_CHECK( has(listnames1, "I1")); + BOOST_CHECK( has(listnames1, "I2")); + + auto pnames1 = schedule.wellNames("I*", 0); + BOOST_CHECK_EQUAL(pnames1.size(), 0); + + auto pnames2 = schedule.wellNames("W*", 0); + BOOST_CHECK_EQUAL(pnames2.size(), 3); + BOOST_CHECK( has(pnames2, "W1")); + BOOST_CHECK( has(pnames2, "W2")); + BOOST_CHECK( has(pnames2, "W3")); + + auto anames = schedule.wellNames("?", 0, {"W1", "W2"}); + BOOST_CHECK_EQUAL(anames.size(), 2); + BOOST_CHECK(has(anames, "W1")); + BOOST_CHECK(has(anames, "W2")); +}