From d4513d214f666f9a4d2d5e09db2eba458a739f11 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Wed, 11 Nov 2020 11:11:44 +0100 Subject: [PATCH] Internalize WPAVE and WWPAVE keywords --- CMakeLists_files.cmake | 3 + .../EclipseState/Schedule/Schedule.hpp | 6 + .../EclipseState/Schedule/Well/PAvg.hpp | 68 +++++++++ .../EclipseState/Schedule/Well/Well.hpp | 5 + .../EclipseState/Schedule/KeywordHandlers.cpp | 23 +++ .../EclipseState/Schedule/Schedule.cpp | 18 +++ .../EclipseState/Schedule/Well/PAvg.cpp | 133 ++++++++++++++++++ .../EclipseState/Schedule/Well/Well.cpp | 17 +++ .../share/keywords/000_Eclipse100/W/WPAVE | 4 +- .../share/keywords/000_Eclipse100/W/WWPAVE | 2 +- tests/parser/PAvgTests.cpp | 96 +++++++++++++ tests/parser/ScheduleTests.cpp | 120 ++++++++++++++++ tests/parser/SummaryConfigTests.cpp | 22 +++ 13 files changed, 514 insertions(+), 3 deletions(-) create mode 100644 opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp create mode 100644 src/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.cpp create mode 100644 tests/parser/PAvgTests.cpp diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index d8a3b08b9..d80f6e3bb 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -132,6 +132,7 @@ if(ENABLE_ECL_INPUT) src/opm/parser/eclipse/EclipseState/Schedule/TimeMap.cpp src/opm/parser/eclipse/EclipseState/Schedule/Well/Connection.cpp src/opm/parser/eclipse/EclipseState/Schedule/Well/injection.cpp + src/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.cpp src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp src/opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.cpp src/opm/parser/eclipse/EclipseState/Schedule/Well/WellMatcher.cpp @@ -351,6 +352,7 @@ if(ENABLE_ECL_INPUT) tests/parser/ParseContextTests.cpp tests/parser/ParseContext_EXIT1.cpp tests/parser/ParseDATAWithDefault.cpp + tests/parser/PAvgTests.cpp tests/parser/PYACTION.cpp tests/parser/RawKeywordTests.cpp tests/parser/test_ReportConfig.cpp @@ -707,6 +709,7 @@ if(ENABLE_ECL_INPUT) opm/parser/eclipse/EclipseState/Schedule/Well/Connection.hpp opm/parser/eclipse/EclipseState/Schedule/Well/ProductionControls.hpp opm/parser/eclipse/EclipseState/Schedule/Well/InjectionControls.hpp + opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp opm/parser/eclipse/EclipseState/Schedule/Well/WList.hpp opm/parser/eclipse/EclipseState/Schedule/Well/WellMatcher.hpp diff --git a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp index 1dea43993..874c68adc 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Schedule.hpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -325,6 +326,7 @@ namespace Opm m_actions.serializeOp(serializer); m_network.serializeOp(serializer); m_glo.serializeOp(serializer); + m_pavg.serializeOp(serializer); rft_config.serializeOp(serializer); m_nupcol.template serializeOp(serializer); restart_config.serializeOp(serializer); @@ -363,6 +365,7 @@ namespace Opm DynamicState> m_actions; DynamicState> m_network; DynamicState> m_glo; + DynamicState> m_pavg; RFTConfig rft_config; DynamicState m_nupcol; RestartConfig restart_config; @@ -387,6 +390,7 @@ namespace Opm Well::GasInflowEquation gas_inflow, std::size_t timeStep, Connection::Order wellConnectionOrder); + bool updateWPAVE(const std::string& wname, std::size_t report_step, const PAvg& pavg); DynamicState> rpt_config; void updateNetwork(std::shared_ptr network, std::size_t report_step); @@ -549,6 +553,8 @@ namespace Opm void handleWINJTEMP (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleWLIFTOPT (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleWLIST (const HandlerContext&, const ParseContext&, ErrorGuard&); + void handleWPAVE (const HandlerContext&, const ParseContext&, ErrorGuard&); + void handleWWPAVE (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleWPIMULT (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleWPMITAB (const HandlerContext&, const ParseContext&, ErrorGuard&); void handleWPOLYMER (const HandlerContext&, const ParseContext&, ErrorGuard&); diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp new file mode 100644 index 000000000..b46ebe472 --- /dev/null +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.hpp @@ -0,0 +1,68 @@ +/* + Copyright 2020 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + + +#ifndef PAVE_HPP +#define PAVE_HPP + + +namespace Opm { +class DeckRecord; + +class PAvg { +public: + enum class DepthCorrection { + WELL = 1, + RES = 2, + NONE = 3 + }; + + PAvg(); + explicit PAvg(const DeckRecord& record); + PAvg(double inner_weight, double conn_weight, DepthCorrection depth_correction, bool use_open_connections); + + double inner_weight() const; + double conn_weight() const; + bool use_porv() const; + bool open_connections() const; + DepthCorrection depth_correction() const; + + + template + void serializeOp(Serializer& serializer) { + serializer(m_inner_weight); + serializer(m_conn_weight); + serializer(m_depth_correction); + serializer(m_open_connections); + } + + static PAvg serializeObject(); + + bool operator==(const PAvg& other) const; + bool operator!=(const PAvg& other) const; + +private: + double m_inner_weight; + double m_conn_weight; + DepthCorrection m_depth_correction; + bool m_open_connections; +}; + +} +#endif diff --git a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp index d684bf6a5..a367231fb 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -558,6 +559,7 @@ public: bool updateWellProductivityIndex(const double prodIndex); bool updateWSEGSICD(const std::vector >& sicd_pairs); bool updateWSEGVALV(const std::vector >& valve_pairs); + bool updateWPAVE(const PAvg& pavg); bool handleWELSEGS(const DeckKeyword& keyword); bool handleCOMPSEGS(const DeckKeyword& keyword, const EclipseGrid& grid, const ParseContext& parseContext, ErrorGuard& errors); @@ -588,6 +590,7 @@ public: double getWellPIScalingFactor(const double currentEffectivePI) const; void applyWellProdIndexScaling(const double scalingFactor, std::vector& scalingApplicable); + const PAvg& pavg() const; template void serializeOp(Serializer& serializer) @@ -624,6 +627,7 @@ public: serializer(production); serializer(injection); serializer(segments); + m_pavg.serializeOp(serializer); } private: @@ -663,6 +667,7 @@ private: std::shared_ptr production; std::shared_ptr injection; std::shared_ptr segments; + PAvg m_pavg; }; std::ostream& operator<<( std::ostream&, const Well::WellInjectionProperties& ); diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp index de3aa5ce9..299038d01 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/KeywordHandlers.cpp @@ -1755,6 +1755,27 @@ namespace { } } + void Schedule::handleWPAVE(const HandlerContext& handlerContext, const ParseContext&, ErrorGuard&) { + auto wpave = std::make_shared( handlerContext.keyword.getRecord(0) ); + for (const auto& wname : this->wellNames(handlerContext.currentStep)) + this->updateWPAVE(wname, handlerContext.currentStep, *wpave ); + + this->m_pavg.update( handlerContext.currentStep, std::move(wpave) ); + } + + void Schedule::handleWWPAVE(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { + for (const auto& record : handlerContext.keyword) { + const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0); + const auto well_names = wellNames(wellNamePattern, handlerContext.currentStep); + + if (well_names.empty()) + invalidNamePattern(wellNamePattern, handlerContext.currentStep, parseContext, errors, handlerContext.keyword); + + auto wpave = PAvg(record); + for (const auto& well_name : well_names) + this->updateWPAVE(well_name, handlerContext.currentStep, wpave); + } + } bool Schedule::handleNormalKeyword(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) { using handler_function = void (Schedule::*)(const HandlerContext&, const ParseContext&, ErrorGuard&); @@ -1821,6 +1842,8 @@ namespace { { "WINJTEMP", &Schedule::handleWINJTEMP }, { "WLIFTOPT", &Schedule::handleWLIFTOPT }, { "WLIST" , &Schedule::handleWLIST }, + { "WPAVE" , &Schedule::handleWPAVE }, + { "WWPAVE" , &Schedule::handleWWPAVE }, { "WPIMULT" , &Schedule::handleWPIMULT }, { "WPMITAB" , &Schedule::handleWPMITAB }, { "WPOLYMER", &Schedule::handleWPOLYMER }, diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index 1133ecee4..f0cee5da1 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -127,6 +127,7 @@ namespace { m_actions(this->m_timeMap, std::make_shared()), m_network(this->m_timeMap, std::make_shared()), m_glo(this->m_timeMap, std::make_shared()), + m_pavg(this->m_timeMap, std::make_shared()), rft_config(this->m_timeMap), m_nupcol(this->m_timeMap, runspec.nupcol()), restart_config(m_timeMap, deck, parseContext, errors), @@ -608,6 +609,20 @@ private: return update; } + + bool Schedule::updateWPAVE(const std::string& wname, std::size_t report_step, const PAvg& pavg) { + const auto& well = this->getWell(wname, report_step); + if (well.pavg() != pavg) { + auto& dynamic_state = this->wells_static.at(wname); + auto new_well = std::make_shared(*dynamic_state[report_step]); + new_well->updateWPAVE( pavg ); + this->updateWell(new_well, report_step); + return true; + } + return false; + } + + /* This routine is called when UDQ keywords is added in an ACTIONX block. */ @@ -891,6 +906,9 @@ private: gas_inflow); this->addWell( std::move(well), timeStep ); + + const auto& pavg_ptr = this->m_pavg.get(timeStep); + this->updateWPAVE( wellName, timeStep, *pavg_ptr ); } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.cpp new file mode 100644 index 000000000..dd6531664 --- /dev/null +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/PAvg.cpp @@ -0,0 +1,133 @@ +/* + Copyright 2020 Equinor ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ +#include + +#include +#include +#include + +namespace Opm { + +namespace { + +PAvg::DepthCorrection depthCorrectionFromString(const std::string& s) { + if (s == "WELL") + return PAvg::DepthCorrection::WELL; + + if (s == "RES") + return PAvg::DepthCorrection::RES; + + if (s == "NONE") + return PAvg::DepthCorrection::NONE; + + throw std::invalid_argument(fmt::format("{} not recognized as depth correction mode", s)); +} + +bool openConnectionsFromString(const std::string& s) { + if (s == "OPEN") + return true; + + if (s == "ALL") + return false; + + throw std::invalid_argument(fmt::format("{} not recognized as connection indicator", s)); +} + + +} + + + +PAvg::PAvg() : + m_inner_weight(ParserKeywords::WPAVE::F1::defaultValue), + m_conn_weight(ParserKeywords::WPAVE::F2::defaultValue) +{ + m_depth_correction = depthCorrectionFromString( ParserKeywords::WPAVE::DEPTH_CORRECTION::defaultValue ); + m_open_connections = openConnectionsFromString( ParserKeywords::WPAVE::CONNECTION::defaultValue ); +} + +PAvg::PAvg(double inner_weight, double conn_weight, DepthCorrection depth_correction, bool use_open_connections) : + m_inner_weight(inner_weight), + m_conn_weight(conn_weight), + m_depth_correction(depth_correction), + m_open_connections(use_open_connections) +{} + +static PAvg serializeObject() { + return PAvg(0.10, 0.30, PAvg::DepthCorrection::NONE, false); +} + +PAvg::PAvg(const DeckRecord& record) + : PAvg() +{ + /* + This code uses the WPAVE keyword to access the content of the the record, + but the record can equally well come from a WWPAVE keyword - i.e. it is a + HARD assumption that the same item names is used both for WPAVE and + WWPAVE. + */ + using WPAVE = ParserKeywords::WPAVE; + const auto& item_inner_weight = record.getItem(); + const auto& item_conn_weight = record.getItem(); + const auto& item_depth_correction = record.getItem(); + const auto& item_connections = record.getItem(); + + this->m_inner_weight = item_inner_weight.get(0); + this->m_conn_weight = item_conn_weight.get(0); + + if (!item_depth_correction.defaultApplied(0)) + this->m_depth_correction = depthCorrectionFromString( item_depth_correction.get(0) ); + + if (!item_connections.defaultApplied(0)) + this->m_open_connections = openConnectionsFromString( item_connections.get(0) ); +} + + +double PAvg::inner_weight() const { + return this->m_inner_weight; +} + +double PAvg::conn_weight() const { + return this->m_conn_weight; +} + +PAvg::DepthCorrection PAvg::depth_correction() const { + return this->m_depth_correction; +} + +bool PAvg::open_connections() const { + return this->m_open_connections; +} + +bool PAvg::use_porv() const { + return this->m_conn_weight != 1.0; +} + +bool PAvg::operator==(const PAvg& other) const { + return this->m_inner_weight == other.m_inner_weight && + this->m_conn_weight == other.m_conn_weight && + this->m_depth_correction == other.m_depth_correction && + this->m_open_connections == other.m_open_connections; +} + +bool PAvg::operator!=(const PAvg& other) const { + return !(*this == other); +} + +} diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp index 28444584f..411d3a6cf 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Well/Well.cpp @@ -387,10 +387,21 @@ Well Well::serializeObject() result.production = std::make_shared(Well::WellProductionProperties::serializeObject()); result.injection = std::make_shared(Well::WellInjectionProperties::serializeObject()); result.segments = std::make_shared(WellSegments::serializeObject()); + result.m_pavg = PAvg(); return result; } + +bool Well::updateWPAVE(const PAvg& pavg) { + if (this->m_pavg == pavg) + return false; + + this->m_pavg = pavg; + return true; +} + + bool Well::updateEfficiencyFactor(double efficiency_factor_arg) { if (this->efficiency_factor != efficiency_factor_arg) { this->efficiency_factor = efficiency_factor_arg; @@ -947,6 +958,10 @@ Well::Status Well::getStatus() const { return this->status; } +const PAvg& Well::pavg() const { + return this->m_pavg; +} + std::map> Well::getCompletions() const { std::map> completions; @@ -1614,6 +1629,7 @@ bool Well::operator==(const Well& data) const { this->productivity_index == data.productivity_index && this->getTracerProperties() == data.getTracerProperties() && this->getProductionProperties() == data.getProductionProperties() && + this->m_pavg == data.m_pavg && this->getInjectionProperties() == data.getInjectionProperties(); } @@ -1694,3 +1710,4 @@ int Opm::eclipseControlMode(const Well& well, return eclipseControlMode(ctrl.cmode, well.injectorType()); } } + diff --git a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WPAVE b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WPAVE index 31df2491b..6e8072c50 100644 --- a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WPAVE +++ b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WPAVE @@ -6,12 +6,12 @@ "size": 1, "items": [ { - "name": "WEIGTH_FACTOR1", + "name": "F1", "value_type": "DOUBLE", "default": 0.5 }, { - "name": "WEIGTH_FACTOR2", + "name": "F2", "value_type": "DOUBLE", "default": 1 }, diff --git a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WWPAVE b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WWPAVE index dd9c0febd..5cf19b45b 100644 --- a/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WWPAVE +++ b/src/opm/parser/eclipse/share/keywords/000_Eclipse100/W/WWPAVE @@ -24,7 +24,7 @@ "default": "WELL" }, { - "name": "WELL_CONNECTION", + "name": "CONNECTION", "value_type": "STRING", "default": "OPEN" } diff --git a/tests/parser/PAvgTests.cpp b/tests/parser/PAvgTests.cpp new file mode 100644 index 000000000..cc6c61fdb --- /dev/null +++ b/tests/parser/PAvgTests.cpp @@ -0,0 +1,96 @@ +/* + Copyright 2020 Statoil ASA. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . + */ + + +#define BOOST_TEST_MODULE PAvgTests + +#include +#include +#include + +#include +#include + +using namespace Opm; + +BOOST_AUTO_TEST_CASE(DEFAULT_PAVG) { + PAvg pavg; + BOOST_CHECK_EQUAL(pavg.inner_weight(), 0.50); + BOOST_CHECK_EQUAL(pavg.conn_weight(), 1.00); + BOOST_CHECK_EQUAL(pavg.use_porv(), false); + BOOST_CHECK(pavg.depth_correction() == PAvg::DepthCorrection::WELL); + BOOST_CHECK(pavg.open_connections()); +} + + +void invalid_deck(const std::string& deck_string, const std::string& kw) { + Parser parser; + auto deck = parser.parseString(deck_string); + BOOST_CHECK_THROW( PAvg(deck.getKeyword(kw).getRecord(0)), std::exception ); +} + +void valid_deck(const std::string& deck_string, const std::string& kw) { + Parser parser; + auto deck = parser.parseString(deck_string); + BOOST_CHECK_NO_THROW( PAvg(deck.getKeyword(kw).getRecord(0))); +} + + +BOOST_AUTO_TEST_CASE(PAVG_FROM_DECK) { + std::string invalid_deck1 = R"( +WPAVE + 2* Well / + +WWPAVE + W 2* Well / +/ +)"; + + std::string invalid_deck2 = R"( +WPAVE + 2* WELL all / + +WWPAVE + W 2* WELL all / +/ +)"; + + std::string valid_input = R"( +WPAVE + 0.25 0.50 WELL ALL / + +WWPAVE + W 2* WELL ALL / +/ +)"; + invalid_deck(invalid_deck1, "WPAVE"); + invalid_deck(invalid_deck1, "WWPAVE"); + + invalid_deck(invalid_deck2, "WPAVE"); + invalid_deck(invalid_deck2, "WWPAVE"); + + valid_deck(valid_input, "WPAVE"); + valid_deck(valid_input, "WWPAVE"); + + Parser parser; + PAvg pavg( parser.parseString(valid_input).getKeyword("WPAVE").getRecord(0) ); + BOOST_CHECK_EQUAL( pavg.inner_weight(), 0.25); + BOOST_CHECK_EQUAL( pavg.conn_weight(), 0.5); + BOOST_CHECK( pavg.use_porv() ); +} diff --git a/tests/parser/ScheduleTests.cpp b/tests/parser/ScheduleTests.cpp index 04053e979..df0c6154b 100644 --- a/tests/parser/ScheduleTests.cpp +++ b/tests/parser/ScheduleTests.cpp @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -4231,3 +4232,122 @@ BOOST_AUTO_TEST_CASE(VFPPROD_SCALING) { cmp_vector(gfr, vfp_table.getGFRAxis()); cmp_vector(alq, vfp_table.getALQAxis()); } + + +BOOST_AUTO_TEST_CASE(WPAVE) { + const std::string deck_string = R"( +START +7 OCT 2020 / + +DIMENS + 10 10 3 / + +GRID +DXV + 10*100.0 / +DYV + 10*100.0 / +DZV + 3*10.0 / + +DEPTHZ + 121*2000.0 / + +PORO + 300*0.3 / + +SCHEDULE +WELSPECS -- 0 + 'P1' 'G' 10 10 2005 'LIQ' / + 'P2' 'G' 1 10 2005 'LIQ' / + 'P3' 'G' 2 10 2005 'LIQ' / + 'P4' 'G' 3 10 2005 'LIQ' / +/ + + +TSTEP -- 1 + 10 +/ + + +WPAVE -- PAVG1 + 0.75 0.25 / + + +TSTEP -- 2 + 10 +/ + +WWPAVE + P1 0.30 0.60 / -- PAVG2 + P3 0.40 0.70 / -- PAVG3 +/ + + +TSTEP -- 3 + 10 +/ + +WPAVE -- PAVG4 + 0.10 0.10 / + + +TSTEP -- 4 + 10 +/ + +TSTEP -- 5 + 10 +/ + +END +)"; + + const auto deck = Parser{}.parseString(deck_string); + const auto es = EclipseState{ deck }; + auto sched = Schedule{ deck, es }; + + PAvg pavg0; + PAvg pavg1( deck.getKeyword("WPAVE", 0).getRecord(0) ); + PAvg pavg2( deck.getKeyword("WWPAVE", 0).getRecord(0) ); + PAvg pavg3( deck.getKeyword("WWPAVE", 0).getRecord(1) ); + PAvg pavg4( deck.getKeyword("WPAVE", 1).getRecord(0) ); + + { + const auto& w1 = sched.getWell("P1", 0); + const auto& w4 = sched.getWell("P4", 0); + + BOOST_CHECK(w1.pavg() == pavg0); + BOOST_CHECK(w4.pavg() == pavg0); + } + + { + const auto& w1 = sched.getWell("P1", 1); + const auto& w4 = sched.getWell("P4", 1); + + BOOST_CHECK(w1.pavg() == pavg1); + BOOST_CHECK(w4.pavg() == pavg1); + } + + { + const auto& w1 = sched.getWell("P1", 2); + const auto& w3 = sched.getWell("P3", 2); + const auto& w4 = sched.getWell("P4", 2); + + BOOST_CHECK(w1.pavg() == pavg2); + BOOST_CHECK(w3.pavg() == pavg3); + BOOST_CHECK(w4.pavg() == pavg1); + } + + { + const auto& w1 = sched.getWell("P1", 3); + const auto& w2 = sched.getWell("P2", 3); + const auto& w3 = sched.getWell("P3", 3); + const auto& w4 = sched.getWell("P4", 3); + + BOOST_CHECK(w1.pavg() == pavg4); + BOOST_CHECK(w2.pavg() == pavg4); + BOOST_CHECK(w3.pavg() == pavg4); + BOOST_CHECK(w4.pavg() == pavg4); + } +} diff --git a/tests/parser/SummaryConfigTests.cpp b/tests/parser/SummaryConfigTests.cpp index 7e99d724b..4bdf4d645 100644 --- a/tests/parser/SummaryConfigTests.cpp +++ b/tests/parser/SummaryConfigTests.cpp @@ -1319,3 +1319,25 @@ COPRL +BOOST_AUTO_TEST_CASE( WBP ) { + const std::string input = R"( +WBP +/ + +WBP4 +/ + +WBP5 +/ + +WBP9 +/ +)"; + + const auto& summary_config = createSummary(input); + + BOOST_CHECK(summary_config.hasKeyword("WBP")); + BOOST_CHECK(summary_config.hasKeyword("WBP4")); + BOOST_CHECK(summary_config.hasKeyword("WBP5")); + BOOST_CHECK(summary_config.hasKeyword("WBP9")); +}