diff --git a/opm/input/eclipse/Parser/Parser.cpp b/opm/input/eclipse/Parser/Parser.cpp index 1e6eadedef3..450d0283b64 100644 --- a/opm/input/eclipse/Parser/Parser.cpp +++ b/opm/input/eclipse/Parser/Parser.cpp @@ -1602,7 +1602,7 @@ bool parseState( ParserState& parserState, const Parser& parser ) { Deck Parser::parseString(const std::string &data, const ParseContext& parseContext) const { ErrorGuard errors; - return this->parseString(data, parseContext, errors); + return this->parseString(data, parseContext, errors); } Deck Parser::parseString(const std::string &data) const { diff --git a/opm/input/eclipse/Schedule/HandlerContext.cpp b/opm/input/eclipse/Schedule/HandlerContext.cpp index 7e0addcaa1c..6cc21ab4f73 100644 --- a/opm/input/eclipse/Schedule/HandlerContext.cpp +++ b/opm/input/eclipse/Schedule/HandlerContext.cpp @@ -168,6 +168,12 @@ void HandlerContext::addGroup(const std::string& groupName) schedule_.addGroup(groupName, currentStep); } +void HandlerContext::addGroupLGR(const std::string& lgrGroup) +{ + schedule_.addGroupLGR(lgrGroup); +} + + void HandlerContext::addGroupToGroup(const std::string& parent_group, const std::string& child_group) { diff --git a/opm/input/eclipse/Schedule/HandlerContext.hpp b/opm/input/eclipse/Schedule/HandlerContext.hpp index 5605c43a77f..bc825089453 100644 --- a/opm/input/eclipse/Schedule/HandlerContext.hpp +++ b/opm/input/eclipse/Schedule/HandlerContext.hpp @@ -113,6 +113,11 @@ class HandlerContext //! \brief Adds a group to the schedule. void addGroup(const std::string& groupName); + + //! \brief Adds a group to the LGR group set. + void addGroupLGR(const std::string& lgrGroup); + + //! \brief Adds a group to a group. void addGroupToGroup(const std::string& parent_group, const std::string& child_group); @@ -166,6 +171,7 @@ class HandlerContext private: const std::unordered_map* target_wellpi{nullptr}; WelSegsSet* welsegs_wells{nullptr}; + std::set lgr_groups; std::set* compsegs_wells{nullptr}; SimulatorUpdate* sim_update{nullptr}; Schedule& schedule_; diff --git a/opm/input/eclipse/Schedule/Schedule.cpp b/opm/input/eclipse/Schedule/Schedule.cpp index f79e3b9e9b9..f0aebb22380 100644 --- a/opm/input/eclipse/Schedule/Schedule.cpp +++ b/opm/input/eclipse/Schedule/Schedule.cpp @@ -1296,6 +1296,12 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen field.updateInjection(new_group.injectionProperties(phase)); } + void Schedule::addGroupLGR(const std::string& lgr_group_key) { + if (lgr_groups.count(lgr_group_key) == 0) { + lgr_groups.insert(lgr_group_key); + } + } + void Schedule::addGroupToGroup( const std::string& parent_name, const std::string& child_name) { auto parent_group = this->snapshots.back().groups.get(parent_name); diff --git a/opm/input/eclipse/Schedule/Schedule.hpp b/opm/input/eclipse/Schedule/Schedule.hpp index be9454614f1..10b0a6d9f0d 100644 --- a/opm/input/eclipse/Schedule/Schedule.hpp +++ b/opm/input/eclipse/Schedule/Schedule.hpp @@ -477,6 +477,9 @@ namespace Opm // For parallel runs, this unordered_map is retrieved by the grid partitioner to ensure these connections // end up on the same partition. std::unordered_map>> possibleFutureConnections; + + // Set of labels for each LGR group + std::set lgr_groups; // The current_report_step is set to the current report step when a PYACTION call is executed. // This is needed since the Schedule object does not know the current report step of the simulator and @@ -526,6 +529,7 @@ namespace Opm void addGroup(const std::string& groupName , std::size_t timeStep); void addGroup(Group group); void addGroup(const RestartIO::RstGroup& rst_group, std::size_t timeStep); + void addGroupLGR(const std::string& lgrGroup); void addWell(const std::string& wellName, const DeckRecord& record, std::size_t timeStep, ConnectionOrder connection_order); void checkIfAllConnectionsIsShut(std::size_t currentStep); diff --git a/opm/input/eclipse/Schedule/Well/WellCompletionKeywordHandlers.cpp b/opm/input/eclipse/Schedule/Well/WellCompletionKeywordHandlers.cpp index e092839e6a8..31ce025fff0 100644 --- a/opm/input/eclipse/Schedule/Well/WellCompletionKeywordHandlers.cpp +++ b/opm/input/eclipse/Schedule/Well/WellCompletionKeywordHandlers.cpp @@ -104,6 +104,73 @@ Well {} is not connected to grid - will remain SHUT)", } } +void handleCOMPDATL(HandlerContext& handlerContext) +// handleWCOMPDATL copies msot of the structure handleWCOMPDAT and add +// the support for LGR. handling LGR group has not been implemented yet. +{ + std::unordered_set wells; + for (const auto& record : handlerContext.keyword) { + const auto wellNamePattern = record.getItem("WELL").getTrimmedString(0); + const auto wellnames = handlerContext.wellNames(wellNamePattern); + const auto lgr_group = record.getItem("LGR").getTrimmedString(0); + + + for (const auto& name : wellnames) { + auto well2 = handlerContext.state().wells.get(name); + + auto connections = std::make_shared(well2.getConnections()); + const auto origWellConnSetIsEmpty = connections->empty(); + + connections->loadCOMPDATL(record, handlerContext.grid, name, + well2.getWDFAC(), handlerContext.keyword.location(), lgr_group); + const auto newWellConnSetIsEmpty = connections->empty(); + + if (well2.updateConnections(std::move(connections), handlerContext.grid)) { + auto wdfac = std::make_shared(well2.getWDFAC()); + wdfac->updateWDFACType(well2.getConnections()); + + well2.updateWDFAC(std::move(wdfac)); + handlerContext.state().wells.update( well2 ); + + wells.insert(name); + } + + if (origWellConnSetIsEmpty && newWellConnSetIsEmpty) { + const auto& location = handlerContext.keyword.location(); + + const auto msg = fmt::format(R"(Problem with COMPDATL/{} +In {} line {} +Well {} is not connected to grid - will remain SHUT)", + name, location.filename, + location.lineno, name); + + OpmLog::warning(msg); + } + + handlerContext.state().wellgroup_events() + .addEvent(name, ScheduleEvents::COMPLETION_CHANGE); + } + } + + handlerContext.state().events().addEvent(ScheduleEvents::COMPLETION_CHANGE); + + // In the case the wells reference depth has been defaulted in the + // WELSPECS keyword we need to force a calculation of the wells + // reference depth exactly when the COMPDAT keyword has been completely + // processed. + for (const auto& wname : wells) { + auto well = handlerContext.state().wells.get( wname ); + well.updateRefDepth(); + + handlerContext.state().wells.update(std::move(well)); + } + + if (! wells.empty()) { + handlerContext.record_well_structure_change(); + } +} + + void handleCOMPLUMP(HandlerContext& handlerContext) { for (const auto& record : handlerContext.keyword) { @@ -219,6 +286,7 @@ getWellCompletionHandlers() { return { { "COMPDAT" , &handleCOMPDAT }, + { "COMPDATL", &handleCOMPDATL }, { "COMPLUMP", &handleCOMPLUMP }, { "COMPORD" , &handleCOMPORD }, { "COMPTRAJ", &handleCOMPTRAJ }, diff --git a/opm/input/eclipse/Schedule/Well/WellConnections.cpp b/opm/input/eclipse/Schedule/Well/WellConnections.cpp index 54209accb45..cafcb8bd3f1 100644 --- a/opm/input/eclipse/Schedule/Well/WellConnections.cpp +++ b/opm/input/eclipse/Schedule/Well/WellConnections.cpp @@ -405,7 +405,7 @@ namespace Opm { for (int k = K1; k <= K2; ++k) { const auto& cell = grid.get_cell(I, J, k); if (!cell.is_active()) { - auto msg = fmt::format(R"(Problem with COMPDAT keyword + auto msg = fmt::format(R"(Problem with COMPDATX keyword In {} line {} The cell ({},{},{}) in well {} is not active and the connection will be ignored)", location.filename, location.lineno, @@ -544,6 +544,19 @@ The cell ({},{},{}) in well {} is not active and the connection will be ignored) } } + + void WellConnections::loadCOMPDATL(const DeckRecord& record, + const ScheduleGrid& grid, + const std::string& wname, + const WDFAC& wdfac, + const KeywordLocation& location, + const std::string& lgr_group) + { + this->lgr_well = true; + loadCOMPDAT(record, grid, wname, wdfac, location); + + } + void WellConnections::loadCOMPTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, @@ -1006,6 +1019,12 @@ CF and Kh items for well {} must both be specified or both defaulted/negative)", return this->headJ; } + bool WellConnections::isLGR() const + { + return this->lgr_well; + } + + const std::vector& WellConnections::getMD() const { return this->md; diff --git a/opm/input/eclipse/Schedule/Well/WellConnections.hpp b/opm/input/eclipse/Schedule/Well/WellConnections.hpp index 73939323bdb..f6511362489 100644 --- a/opm/input/eclipse/Schedule/Well/WellConnections.hpp +++ b/opm/input/eclipse/Schedule/Well/WellConnections.hpp @@ -92,6 +92,13 @@ namespace Opm { const WDFAC& wdfac, const KeywordLocation& location); + void loadCOMPDATL(const DeckRecord& record, + const ScheduleGrid& grid, + const std::string& wname, + const WDFAC& wdfac, + const KeywordLocation& location, + const std::string& lgr_group); + void loadCOMPTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, @@ -108,6 +115,7 @@ namespace Opm { int getHeadI() const; int getHeadJ() const; + bool isLGR() const; const std::vector& getMD() const; std::size_t size() const; bool empty() const; @@ -180,6 +188,7 @@ namespace Opm { Connection::Order m_ordering { Connection::Order::TRACK }; int headI{0}; int headJ{0}; + bool lgr_well = false; std::vector m_connections{}; std::array, 3> coord{}; diff --git a/opm/input/eclipse/Schedule/Well/WellKeywordHandlers.cpp b/opm/input/eclipse/Schedule/Well/WellKeywordHandlers.cpp index d7102d0ad37..6ef7b05f6cf 100644 --- a/opm/input/eclipse/Schedule/Well/WellKeywordHandlers.cpp +++ b/opm/input/eclipse/Schedule/Well/WellKeywordHandlers.cpp @@ -594,6 +594,122 @@ Well{0} entered with 'FIELD' parent group: } } +void handleWELSPECL(HandlerContext& handlerContext) +// handleWELSPECL copies msot of the structure handleWELSPEC and add +// the support for LGR. handling LGR group has not been implemented yet. +{ + using Kw = ParserKeywords::WELSPECL; + + auto getTrimmedName = [&handlerContext](const auto& item) + { + return trim_wgname(handlerContext.keyword, + item.template get(0), + handlerContext.parseContext, + handlerContext.errors); + }; + + auto fieldWells = std::vector{}; + for (const auto& record : handlerContext.keyword) { + if (const auto fip_region_number = record.getItem().get(0); + fip_region_number != Kw::FIP_REGION::defaultValue) + { + const auto& location = handlerContext.keyword.location(); + const auto msg = fmt::format("Non-defaulted FIP region {} in WELSPECL keyword " + "in file {} line {} is not supported. " + "Reset to default value {}.", + fip_region_number, + location.filename, + location.lineno, + Kw::FIP_REGION::defaultValue); + OpmLog::warning(msg); + } + + if (const auto& density_calc_type = record.getItem().get(0); + density_calc_type != Kw::DENSITY_CALC::defaultValue) + { + const auto& location = handlerContext.keyword.location(); + const auto msg = fmt::format("Non-defaulted density calculation method '{}' " + "in WELSPECL keyword in file {} line {} is " + "not supported. Reset to default value {}.", + density_calc_type, + location.filename, + location.lineno, + Kw::DENSITY_CALC::defaultValue); + OpmLog::warning(msg); + } + + const auto wellName = getTrimmedName(record.getItem()); + const auto groupName = getTrimmedName(record.getItem()); + const auto lgrGroup = getTrimmedName(record.getItem()) ; + handlerContext.addGroupLGR(lgrGroup); + + + + // We might get here from an ACTIONX context, or we might get + // called on a well (list) template, to reassign certain well + // properties--e.g, the well's controlling group--so check if + // 'wellName' matches any existing well names through pattern + // matching before treating the wellName as a simple well name. + // + // An empty list of well names is okay since that means we're + // creating a new well in this case. + const auto allowEmptyWellList = true; + const auto existingWells = handlerContext.wellNames(wellName, allowEmptyWellList); + + if (groupName == "FIELD") { + if (existingWells.empty()) { + fieldWells.push_back(wellName); + } + else { + for (const auto& existingWell : existingWells) { + fieldWells.push_back(existingWell); + } + } + } + + if (! handlerContext.state().groups.has(groupName)) { + handlerContext.addGroup(groupName); + } + + if (existingWells.empty()) { + // 'wellName' does not match any existing wells. Create a + // new Well object for this well. + handlerContext.welspecsCreateNewWell(record, + wellName, + groupName); + } + else { + // 'wellName' matches one or more existing wells. Assign + // new properties for those wells. + handlerContext.welspecsUpdateExistingWells(record, + existingWells, + groupName); + } + } + + if (! fieldWells.empty()) { + std::sort(fieldWells.begin(), fieldWells.end()); + fieldWells.erase(std::unique(fieldWells.begin(), fieldWells.end()), + fieldWells.end()); + + const auto* plural = (fieldWells.size() == 1) ? "" : "s"; + + const auto msg_fmt = fmt::format(R"(Well{0} parented directly to 'FIELD'; this is allowed but discouraged. +Well{0} entered with 'FIELD' parent group: +* {1})", plural, fmt::join(fieldWells, "\n * ")); + + handlerContext.parseContext.handleError(ParseContext::SCHEDULE_WELL_IN_FIELD_GROUP, + msg_fmt, + handlerContext.keyword.location(), + handlerContext.errors); + } + + if (! handlerContext.keyword.empty()) { + handlerContext.record_well_structure_change(); + } +} + + /* The documentation for the WELTARG keyword says that the well must have been fully specified and initialized using one of the @@ -887,6 +1003,7 @@ getWellHandlers() { "WCONPROD", &handleWCONPROD }, { "WELOPEN" , &handleWELOPEN }, { "WELSPECS", &handleWELSPECS }, + { "WELSPECL", &handleWELSPECL}, { "WELTARG" , &handleWELTARG }, { "WELTRAJ" , &handleWELTRAJ }, { "WHISTCTL", &handleWHISTCTL }, diff --git a/opm/input/eclipse/share/keywords/000_Eclipse100/C/COMPDATL b/opm/input/eclipse/share/keywords/000_Eclipse100/C/COMPDATL new file mode 100644 index 00000000000..e4d43366cbb --- /dev/null +++ b/opm/input/eclipse/share/keywords/000_Eclipse100/C/COMPDATL @@ -0,0 +1,98 @@ +{ + "name": "COMPDATL", + "sections": [ + "SCHEDULE" + ], + "items": [ + { + "item": 1, + "name": "WELL", + "value_type": "STRING" + }, + { + "item": 2, + "name": "LOCAL_GRID", + "value_type": "STRING" + }, + { + "item": 3, + "name": "I", + "value_type": "INT", + "default": 0 + }, + { + "item": 4, + "name": "J", + "value_type": "INT", + "default": 0 + }, + { + "item": 5, + "name": "K1", + "value_type": "INT" + }, + { + "item": 6, + "name": "K2", + "value_type": "INT" + }, + { + "item": 7, + "name": "STATE", + "value_type": "STRING", + "default": "OPEN" + }, + { + "item": 8, + "name": "SAT_TABLE", + "value_type": "INT", + "default": 0 + }, + { + "item": 9, + "name": "CONNECTION_TRANSMISSIBILITY_FACTOR", + "value_type": "DOUBLE", + "dimension": "Viscosity*ReservoirVolume/Time*Pressure" + }, + { + "item": 10, + "name": "DIAMETER", + "value_type": "DOUBLE", + "dimension": "Length" + }, + { + "item": 11, + "name": "Kh", + "value_type": "DOUBLE", + "dimension": "Permeability*Length", + "default": -1 + }, + { + "item": 12, + "name": "SKIN", + "value_type": "DOUBLE", + "dimension": "1", + "default": 0 + }, + { + "item": 13, + "name": "D_FACTOR", + "value_type": "DOUBLE", + "dimension": "Time/GasSurfaceVolume", + "default": 0 + + }, + { + "item": 14, + "name": "DIR", + "value_type": "STRING", + "default": "Z" + }, + { + "item": 15, + "name": "PR", + "value_type": "DOUBLE", + "dimension": "Length" + } + ] + } \ No newline at end of file diff --git a/opm/input/eclipse/share/keywords/000_Eclipse100/W/WELSPECL b/opm/input/eclipse/share/keywords/000_Eclipse100/W/WELSPECL index 3e9458d04e9..0b962589996 100644 --- a/opm/input/eclipse/share/keywords/000_Eclipse100/W/WELSPECL +++ b/opm/input/eclipse/share/keywords/000_Eclipse100/W/WELSPECL @@ -5,84 +5,103 @@ ], "items": [ { + "item": 1, "name": "WELL", "value_type": "STRING" }, { + "item": 2, "name": "GROUP", - "value_type": "STRING" + "value_type": "STRING", + "default": "FIELD" }, { - "name": "LGR", + "item": 3, + "name": "LOCAL_GRID", "value_type": "STRING" }, { + "item": 4, "name": "HEAD_I", "value_type": "INT" }, { + "item": 5, "name": "HEAD_J", "value_type": "INT" }, { + "item": 6, "name": "REF_DEPTH", "value_type": "DOUBLE", "dimension": "Length" }, { + "item": 7, "name": "PHASE", "value_type": "STRING" }, { + "item": 8, "name": "D_RADIUS", "value_type": "DOUBLE", "default": 0, "dimension": "Length" }, { + "item": 9, "name": "INFLOW_EQ", "value_type": "STRING", "default": "STD" }, { + "item": 10, "name": "AUTO_SHUTIN", "value_type": "STRING", "default": "SHUT" }, { + "item": 11, "name": "CROSSFLOW", "value_type": "STRING", "default": "YES" }, { + "item": 12, "name": "P_TABLE", "value_type": "INT", "default": 0 }, { + "item": 13, "name": "DENSITY_CALC", "value_type": "STRING", "default": "SEG" }, { + "item": 14, "name": "FIP_REGION", "value_type": "INT", "default": 0 }, { + "item": 15, "name": "FRONTSIM1", "value_type": "STRING" }, { + "item": 16, "name": "FRONTSIM2", "value_type": "STRING" }, { + "item": 17, "name": "well_model", "value_type": "STRING", "default": "STD" }, { + "item": 18, "name": "POLYMER_TABLE", "value_type": "INT", "default": 0 diff --git a/opm/input/eclipse/share/keywords/keyword_list.cmake b/opm/input/eclipse/share/keywords/keyword_list.cmake index 464a7ab0f9d..23c55ffda43 100644 --- a/opm/input/eclipse/share/keywords/keyword_list.cmake +++ b/opm/input/eclipse/share/keywords/keyword_list.cmake @@ -88,6 +88,7 @@ set( keywords 000_Eclipse100/C/COLLAPSE 000_Eclipse100/C/COLUMNS 000_Eclipse100/C/COMPDAT + 000_Eclipse100/C/COMPDATL 000_Eclipse100/C/COMPDATX 000_Eclipse100/C/COMPFLSH 000_Eclipse100/C/COMPIMB diff --git a/tests/parser/ConnectionTests.cpp b/tests/parser/ConnectionTests.cpp index 1f423025308..f61210659c3 100644 --- a/tests/parser/ConnectionTests.cpp +++ b/tests/parser/ConnectionTests.cpp @@ -84,6 +84,40 @@ namespace { return connections; } + + Opm::WellConnections + loadCOMPDATL(const std::string& compdat_keyword) + { + Opm::WellConnections connections { + Opm::Connection::Order::TRACK, 10, 10 + }; + + const auto deck = Opm::Parser{}.parseString(compdat_keyword); + const auto wdfac = Opm::WDFAC{}; + const auto loc = Opm::KeywordLocation{}; + const std::string lgr_group = "LGR1"; + + Opm::EclipseGrid grid { 10, 10, 10 }; + const Opm::FieldPropsManager field_props { + deck, Opm::Phases{true, true, true}, grid, Opm::TableManager{} + }; + + // Must be mutable. + Opm::CompletedCells completed_cells(grid); + const auto sg = Opm::ScheduleGrid { grid, field_props, completed_cells }; + + for (const auto& rec : deck["COMPDATL"][0]) { + connections.loadCOMPDATL(rec, sg, "WELL", wdfac, loc, lgr_group); + } + + return connections; + } + + + + + + } namespace Opm { @@ -312,6 +346,78 @@ COMPDAT } + +BOOST_AUTO_TEST_CASE(loadCOMPDATLTEST) { + + const Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA. + + { + const std::string deck = R"(GRID + +PERMX + 1000*0.10 / + +COPY + 'PERMX' 'PERMZ' / + 'PERMX' 'PERMY' / +/ + +PORO + 1000*0.3 / + +SCHEDULE + +WELSPECL +-- Item #: 1 2 3 4 5 6 7 + 'PROD' 'G1' 'LGR2' 6 6 8400 'OIL' / +/ + +COMPDATL +-- Item #: 1 2 3 4 5 6 7 8 9 10 + 'PROD' 'LGR2' 6 6 9 9 'OPEN' 1* 1* 0.5 / +/)"; + + const Opm::WellConnections connections = loadCOMPDATL(deck); + const auto& conn0 = connections[0]; + BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168)); + BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 107.872)); + BOOST_CHECK_MESSAGE(conn0.ctfAssignedFromInput(), "CTF Must be Assigned From Input"); + } + +// { +// const std::string deck = R"(GRID + +// PERMX +// 1000*0.10 / + +// COPY +// 'PERMX' 'PERMZ' / +// 'PERMX' 'PERMY' / +// / + +// PORO +// 1000*0.3 / + +// SCHEDULE + +// COMPDAT +// -- CF Diam Kh Skin Df +// 'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 / +// /)"; + +// const Opm::WellConnections connections = loadCOMPDAT(deck); +// const auto& conn0 = connections[0]; +// BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168)); +// BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 0.10 * 1.0)); +// } + +} + + + + + + BOOST_AUTO_TEST_CASE(loadCOMPDATTESTSPE1) { Opm::Parser parser; diff --git a/tests/parser/WellTests.cpp b/tests/parser/WellTests.cpp index d3f1521df1d..8ba5de2dfc0 100644 --- a/tests/parser/WellTests.cpp +++ b/tests/parser/WellTests.cpp @@ -231,7 +231,7 @@ BOOST_AUTO_TEST_CASE(WellCOMPDATtestDefaultTRACK) { } BOOST_AUTO_TEST_CASE(WellCOMPDATtestINPUT) { - Opm::Parser parser; + Opm::Parser parser; std::string input = "START -- 0 \n" "19 JUN 2007 / \n" @@ -286,6 +286,69 @@ BOOST_AUTO_TEST_CASE(WellCOMPDATtestINPUT) { BOOST_CHECK_EQUAL(completions.get( 8 ).getK(), 1); } +BOOST_AUTO_TEST_CASE(WellCOMPDATLtestINPUT) { + Opm::Parser parser; + std::string input = + "START -- 0 \n" + "19 JUN 2007 / \n" + "GRID\n" + "PORO\n" + "1000*0.1 /\n" + "PERMX \n" + "1000*1 /\n" + "PERMY \n" + "1000*0.1 /\n" + "PERMZ \n" + "1000*0.01 /\n" + "SCHEDULE\n" + "DATES -- 1\n" + " 10 OKT 2008 / \n" + "/\n" + "WELSPECL\n" + " 'PROD' 'G1' 'LGR2' 6 6 8400 'OIL' / \n" + "/\n" + "COMPORD\n" + " OP_1 INPUT / \n" + "/\n" + "COMPDATL\n" + " 'PROD' 'LGR2' 6 6 9 9 'OPEN' 1* 1* 0.5 / \n" + "/\n" + "DATES -- 2\n" + " 20 JAN 2010 / \n" + "/\n"; + + + auto deck = parser.parseString(input); + Opm::EclipseGrid grid(10,10,10); + Opm::ErrorGuard errors; + TableManager table ( deck ); + FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); + Opm::Runspec runspec (deck); + auto python = std::make_shared(); + Opm::Schedule schedule(deck, grid , fp, runspec, Opm::ParseContext(), errors, python); + const auto& op_1 = schedule.getWell("OP_1", 2); + + const auto& completions = op_1.getConnections(); + BOOST_CHECK_EQUAL(9U, completions.size()); + BOOST_CHECK_EQUAL(completions.get( 1 ).getK(), 2); + BOOST_CHECK_EQUAL(completions.get( 2 ).getK(), 3); + BOOST_CHECK_EQUAL(completions.get( 3 ).getK(), 4); + BOOST_CHECK_EQUAL(completions.get( 4 ).getK(), 5); + BOOST_CHECK_EQUAL(completions.get( 5 ).getK(), 6); + BOOST_CHECK_EQUAL(completions.get( 6 ).getK(), 7); + BOOST_CHECK_EQUAL(completions.get( 7 ).getK(), 8); + BOOST_CHECK_EQUAL(completions.get( 8 ).getK(), 1); +} + + + + + + + + + + BOOST_AUTO_TEST_CASE(NewWellZeroCompletions) { Opm::Well well("WELL1", "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD); BOOST_CHECK_EQUAL( 0U , well.getConnections( ).size() );