From f2cb5fe9de5eeee9a30947980aad38f22a47972f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Petter=20=C3=98ren=20Hauge?= Date: Sun, 22 Apr 2018 10:25:17 +0200 Subject: [PATCH] Add INVALID_WELL parse context Handle invalid wellpatterns for COMPDAT. Given a deck with: ---- WELSPECS 'PROD' 'G1' 10 10 8400 'OIL' / / COMPDAT 'SOMETHINGELSE' 10 10 3 3 'OPEN' 1* 1* 0.5 / / ---- OPM will now by default abort and inform the user that no well match "SOMETHINGELSE". --- .../EclipseState/Schedule/Completion.hpp | 7 ++- .../EclipseState/Schedule/Schedule.hpp | 3 +- opm/parser/eclipse/Parser/ParseContext.hpp | 7 +++ .../EclipseState/Schedule/Completion.cpp | 9 ++- .../EclipseState/Schedule/Schedule.cpp | 12 +++- .../parser/eclipse/Parser/ParseContext.cpp | 3 + tests/parser/ParseContextTests.cpp | 57 +++++++++++++++++++ tests/parser/ScheduleTests.cpp | 1 - .../integration/CompletionsFromDeck.cpp | 2 +- 9 files changed, 91 insertions(+), 10 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/Completion.hpp b/opm/parser/eclipse/EclipseState/Schedule/Completion.hpp index caa4c36ef..7bde184de 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Completion.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Completion.hpp @@ -25,7 +25,7 @@ #include #include #include - +#include #include #include @@ -37,6 +37,7 @@ namespace Opm { class Well; class EclipseGrid; class Eclipse3DProperties; + class Schedule; class Completion { public: @@ -81,7 +82,9 @@ namespace Opm { fromCOMPDAT( const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const DeckKeyword& compdatKeyword, - const std::vector< const Well* >& ); + const std::vector< const Well* >&, + const ParseContext&, + const Schedule&); bool operator==( const Completion& ) const; bool operator!=( const Completion& ) const; diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index ce612622b..b04c87ce0 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -105,6 +105,7 @@ namespace Opm std::vector< const Group* > getGroups() const; const Tuning& getTuning() const; const MessageLimits& getMessageLimits() const; + void InvalidWellPattern (const std::string& wellNamePattern, const ParseContext& parseContext, const DeckKeyword& keyword) const; const Events& getEvents() const; const Deck& getModifierDeck(size_t timeStep) const; @@ -149,7 +150,7 @@ namespace Opm void handleWCONHIST( const DeckKeyword& keyword, size_t currentStep); void handleWCONPROD( const DeckKeyword& keyword, size_t currentStep); void handleWGRUPCON( const DeckKeyword& keyword, size_t currentStep); - void handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties); + void handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const ParseContext& parseContext); void handleCOMPLUMP( const DeckKeyword& keyword, size_t currentStep ); void handleWELSEGS( const DeckKeyword& keyword, size_t currentStep); void handleCOMPSEGS( const DeckKeyword& keyword, size_t currentStep); diff --git a/opm/parser/eclipse/Parser/ParseContext.hpp b/opm/parser/eclipse/Parser/ParseContext.hpp index a8034a6a8..c2d75803a 100644 --- a/opm/parser/eclipse/Parser/ParseContext.hpp +++ b/opm/parser/eclipse/Parser/ParseContext.hpp @@ -243,6 +243,13 @@ namespace Opm { const static std::string SUMMARY_UNKNOWN_WELL; const static std::string SUMMARY_UNKNOWN_GROUP; + /* + A well must be specified (e.g. WELSPECS) and have completions + (e.g. COMPDAT) to be able to set control mode (e.g. WCONPROD). + A well missing specification and/or completion(s) will throw. + */ + const static std::string SCHEDULE_INVALID_WELL; + private: void initDefault(); void initEnv(); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp index dec0b34b9..406dbbab9 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Completion.cpp @@ -25,11 +25,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include namespace Opm { @@ -195,7 +197,9 @@ namespace Opm { Completion::fromCOMPDAT( const EclipseGrid& grid , const Eclipse3DProperties& eclipseProperties, const DeckKeyword& compdatKeyword, - const std::vector< const Well* >& wells ) { + const std::vector< const Well* >& wells, + const ParseContext& parseContext, + const Schedule& schedule) { std::map< std::string, std::vector< Completion > > res; std::vector< int > prev_compls( wells.size(), 0 ); @@ -209,7 +213,8 @@ namespace Opm { auto well = std::find_if( wells.begin(), wells.end(), name_eq ); - if( well == wells.end() ) continue; + if( well == wells.end() ) + schedule.InvalidWellPattern(wellname, parseContext, compdatKeyword); const auto index = std::distance( wells.begin(), well ); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 08db75ae4..df363745a 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -193,7 +193,7 @@ namespace Opm { handleWGRUPCON(keyword, currentStep); else if (keyword.name() == "COMPDAT") - handleCOMPDAT(keyword, currentStep, grid, eclipseProperties); + handleCOMPDAT(keyword, currentStep, grid, eclipseProperties, parseContext); else if (keyword.name() == "WELSEGS") handleWELSEGS(keyword, currentStep); @@ -1325,9 +1325,9 @@ namespace Opm { - void Schedule::handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties) { + void Schedule::handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const ParseContext& parseContext) { const auto wells = this->getWells( currentStep ); - auto completions = Completion::fromCOMPDAT( grid, eclipseProperties, keyword, wells ); + auto completions = Completion::fromCOMPDAT( grid, eclipseProperties, keyword, wells, parseContext, *this ); for( const auto pair : completions ) { auto& well = this->m_wells.get( pair.first ); @@ -1449,6 +1449,12 @@ namespace Opm { } } + void Schedule::InvalidWellPattern( const std::string& wellNamePattern, const ParseContext& parseContext, const DeckKeyword& keyword ) const { + std::string msg = "Error when handling " + keyword.name() +". No wells match " + + wellNamePattern; + parseContext.handleError( ParseContext::SCHEDULE_INVALID_WELL, msg ); + } + const TimeMap& Schedule::getTimeMap() const { return this->m_timeMap; } diff --git a/src/opm/parser/eclipse/Parser/ParseContext.cpp b/src/opm/parser/eclipse/Parser/ParseContext.cpp index 0ab88ee45..62be4f150 100644 --- a/src/opm/parser/eclipse/Parser/ParseContext.cpp +++ b/src/opm/parser/eclipse/Parser/ParseContext.cpp @@ -85,6 +85,7 @@ namespace Opm { addKey(SUMMARY_UNKNOWN_WELL, InputError::THROW_EXCEPTION); addKey(SUMMARY_UNKNOWN_GROUP, InputError::THROW_EXCEPTION); + addKey(SCHEDULE_INVALID_WELL, InputError::THROW_EXCEPTION); } void ParseContext::initEnv() { @@ -257,6 +258,8 @@ namespace Opm { const std::string ParseContext::SUMMARY_UNKNOWN_WELL = "SUMMARY_UNKNOWN_WELL"; const std::string ParseContext::SUMMARY_UNKNOWN_GROUP = "SUMMARY_UNKNOWN_GROUP"; + + const std::string ParseContext::SCHEDULE_INVALID_WELL = "SCHEDULE_INVALID_WELL"; } diff --git a/tests/parser/ParseContextTests.cpp b/tests/parser/ParseContextTests.cpp index 260ae1da0..b0a12d3a4 100644 --- a/tests/parser/ParseContextTests.cpp +++ b/tests/parser/ParseContextTests.cpp @@ -472,3 +472,60 @@ BOOST_AUTO_TEST_CASE(test_1arg_constructor) { BOOST_CHECK_EQUAL(ctx.get(ParseContext::PARSE_RANDOM_SLASH), InputError::IGNORE); } } + +BOOST_AUTO_TEST_CASE( test_invalid_wtemplate_config ) { + const std::string defDeckString = R"( + START -- 0 + 10 'JAN' 2000 / + RUNSPEC + DIMENS + 10 10 10 / + GRID + DX + 1000*0.25 / + DY + 1000*0.25 / + DZ + 1000*0.25 / + TOPS + 100*0.25 / + SCHEDULE + DATES -- 1 + 10 OKT 2008 / + / + WELSPECS + 'PROD' 'G1' 10 10 100 'OIL' / + 'INJ' 'G1' 3 3 100 'WATER' / + / + )"; + + ParseContext parseContext; + Parser parser; + + parseContext.update(ParseContext::SCHEDULE_INVALID_WELL , InputError::THROW_EXCEPTION ); + + std::vector < std::string > testSamples; + std::string testSample; + + // Invalid well name in COMPDAT + testSample = R"( + COMPDAT + 'SOMETHINGELSE' 10 10 3 3 'OPEN' 1* 1* 0.5 / + / + )"; + testSamples.push_back(testSample); + + std::string deckinput; + + for (std::string sample : testSamples) { + + deckinput = defDeckString + sample; + auto deckUnSupported = parser.parseString( deckinput , parseContext ); + + EclipseGrid grid( deckUnSupported ); + TableManager table ( deckUnSupported ); + Eclipse3DProperties eclipseProperties ( deckUnSupported , table, grid); + + BOOST_CHECK_THROW( Schedule( deckUnSupported , grid , eclipseProperties, Phases(true, true, true) , parseContext), std::invalid_argument ); + } +} \ No newline at end of file diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 22d303c82..d77779278 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -1479,7 +1479,6 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) { 'W1' 0 0 1 1 'SHUT' 1* / -- regular completion (1) 'W1' 0 0 2 2 'SHUT' 1* / -- regular completion (2) 'W1' 0 0 3 4 'SHUT' 1* / -- two completions in one record (3, 4) - 'W3' 0 0 1 3 'SHUT' 1* / -- doesn't exist, ignored 'W2' 0 0 3 3 'SHUT' 1* / -- regular completion (1) 'W2' 0 0 1 3 'SHUT' 1* / -- two completions (one exist already) (2, 3) / diff --git a/tests/parser/integration/CompletionsFromDeck.cpp b/tests/parser/integration/CompletionsFromDeck.cpp index f1b8eb3d1..1e497759d 100644 --- a/tests/parser/integration/CompletionsFromDeck.cpp +++ b/tests/parser/integration/CompletionsFromDeck.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE( CreateCompletionsFromKeyword ) { const auto& COMPDAT1 = deck.getKeyword("COMPDAT" , 1); const auto wells = schedule.getWells( 0 ); - auto completions = Completion::fromCOMPDAT( grid, eclipseProperties, COMPDAT1, wells ); + auto completions = Completion::fromCOMPDAT( grid, eclipseProperties, COMPDAT1, wells, ParseContext(), schedule ); BOOST_CHECK_EQUAL( 3U , completions.size() ); BOOST_CHECK( completions.find("W_1") != completions.end() );