Merge pull request #677 from joakim-hove/well-names

Implement Schedule::wellNames()
This commit is contained in:
Joakim Hove
2019-03-17 08:03:25 +01:00
committed by GitHub
3 changed files with 126 additions and 0 deletions
@@ -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<std::string> wellNames(const std::string& pattern, size_t timeStep, const std::vector<std::string>& 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;
@@ -17,6 +17,7 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <fnmatch.h>
#include <string>
#include <vector>
#include <stdexcept>
@@ -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<std::string> Schedule::wellNames(const std::string& pattern, size_t timeStep, const std::vector<std::string>& matching_wells) const {
std::vector<std::string> 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<std::string> 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<std::string>& 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.
+66
View File
@@ -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<std::string>& 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"));
}