/* Copyright 2013 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 . */ #include #include #include #define BOOST_TEST_MODULE ScheduleTests #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace Opm; namespace { double liquid_PI_unit() { return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0); } double cp_rm3_per_db() { return prefix::centi*unit::Poise * unit::cubic(unit::meter) / (unit::day * unit::barsa); } } static Schedule make_schedule(const std::string& deck_string) { const auto& deck = Parser{}.parseString(deck_string); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); return Schedule(deck, grid , fp, runspec, python); } static std::string createDeck() { std::string input = "START\n" "8 MAR 1998 /\n" "\n" "SCHEDULE\n" "\n"; return input; } static std::string createDeckWithWells() { std::string input = "START -- 0 \n" "10 MAI 2007 / \n" "SCHEDULE\n" "WELSPECS\n" " \'W_1\' \'OP\' 30 37 3.33 \'OIL\' 7* / \n" "/ \n" "DATES -- 1\n" " 10 \'JUN\' 2007 / \n" "/\n" "DATES -- 2,3\n" " 10 JLY 2007 / \n" " 10 AUG 2007 / \n" "/\n" "WELSPECS\n" " \'WX2\' \'OP\' 30 37 3.33 \'OIL\' 7* / \n" " \'W_3\' \'OP\' 20 51 3.92 \'OIL\' 7* / \n" "/\n"; return input; } static std::string createDeckWTEST() { std::string input = "START -- 0 \n" "10 MAI 2007 / \n" "SCHEDULE\n" "WELSPECS\n" " \'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" " \'BAN\' 1 1 1 1 \'OPEN\' 1* 1.168 0.311 107.872 1* 1* \'Z\' 21.925 / \n" "/\n" "WCONHIST\n" " 'BAN' 'OPEN' 'RESV' 0.000 0.000 0.000 5* / \n" "/\n" "WTEST\n" " 'ALLOW' 1 'PE' / \n" "/\n" "DATES -- 1\n" " 10 JUN 2007 / \n" "/\n" "WTEST\n" " 'ALLOW' 1 '' / \n" " 'BAN' 1 'DGC' / \n" "/\n" "WCONHIST\n" " 'BAN' 'OPEN' 'RESV' 1.000 0.000 0.000 5* / \n" "/\n" "DATES -- 2\n" " 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" "DATES -- 3\n" " 10 AUG 2007 / \n" "/\n" "WCONINJH\n" " 'BAN' 'WATER' 1* 0 / \n" "/\n" "DATES -- 4\n" " 10 SEP 2007 / \n" "/\n" "WELOPEN\n" " 'BAN' OPEN / \n" "/\n" "DATES -- 4\n" " 10 NOV 2007 / \n" "/\n" "WCONINJH\n" " 'BAN' 'WATER' 1* 1.0 / \n" "/\n"; return input; } static std::string createDeckForTestingCrossFlow() { std::string input = "START -- 0 \n" "10 MAI 2007 / \n" "SCHEDULE\n" "WELSPECS\n" " \'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" "/\n" "COMPDAT\n" " \'BAN\' 1 1 1 1 \'OPEN\' 1* 1.168 0.311 107.872 1* 1* \'Z\' 21.925 / \n" "/\n" "WCONHIST\n" " 'BAN' 'OPEN' 'RESV' 0.000 0.000 0.000 5* / \n" "/\n" "DATES -- 1\n" " 10 JUN 2007 / \n" "/\n" "WCONHIST\n" " 'BAN' 'OPEN' 'RESV' 1.000 0.000 0.000 5* / \n" "/\n" "DATES -- 2\n" " 10 JUL 2007 / \n" "/\n" "WCONPROD\n" " 'BAN' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / \n" "/\n" "DATES -- 3\n" " 10 AUG 2007 / \n" "/\n" "WCONINJH\n" " 'BAN' 'WATER' 1* 0 / \n" "/\n" "DATES -- 4\n" " 10 SEP 2007 / \n" "/\n" "WELOPEN\n" " 'BAN' OPEN / \n" "/\n" "DATES -- 4\n" " 10 NOV 2007 / \n" "/\n" "WCONINJH\n" " 'BAN' 'WATER' 1* 1.0 / \n" "/\n"; return input; } static std::string createDeckWithWellsOrdered() { std::string input = "START -- 0 \n" "10 MAI 2007 / \n" "WELLDIMS\n" " * * 3 /\n" "SCHEDULE\n" "WELSPECS\n" " \'CW_1\' \'CG\' 3 3 3.33 \'OIL\' 7* / \n" " \'BW_2\' \'BG\' 3 3 3.33 \'OIL\' 7* / \n" " \'AW_3\' \'AG\' 2 5 3.92 \'OIL\' 7* / \n" "/\n"; return input; } static std::string createDeckWithWellsOrderedGRUPTREE() { std::string input = "START -- 0 \n" "10 MAI 2007 / \n" "SCHEDULE\n" "GRUPTREE\n" " PG1 PLATFORM /\n" " PG2 PLATFORM /\n" " CG1 PG1 /\n" " CG2 PG2 /\n" "/\n" "WELSPECS\n" " \'DW_0\' \'CG1\' 3 3 3.33 \'OIL\' 7* / \n" " \'CW_1\' \'CG1\' 3 3 3.33 \'OIL\' 7* / \n" " \'BW_2\' \'CG2\' 3 3 3.33 \'OIL\' 7* / \n" " \'AW_3\' \'CG2\' 2 5 3.92 \'OIL\' 7* / \n" "/\n"; return input; } static std::string createDeckWithWellsAndCompletionData() { std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'OP_2' 'OP' 8 8 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'OP_3' 'OP' 7 7 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_2' 8 8 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 / \n" " 'OP_2' 8 7 3 3 'OPEN' 1* 15.071 0.311 1391.859 1* 1* 'Y' 21.920 / \n" " 'OP_2' 8 7 3 6 'OPEN' 1* 6.242 0.311 576.458 1* 1* 'Y' 21.915 / \n" " 'OP_3' 7 7 1 1 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 / \n" " 'OP_3' 7 7 2 2 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 / \n" "/\n" "DATES -- 2,3\n" " 10 JUL 2007 / \n" " 10 AUG 2007 / \n" "/\n" "COMPDAT\n" // with defaulted I and J " 'OP_1' 0 * 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n"; return input; } static std::string createDeckRFTConfig() { return R"(RUNSPEC START -- 0 1 NOV 1979 / SCHEDULE DATES -- 1 (sim step = 0) 1 DES 1979/ / WELSPECS 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / 'OP_2' 'OP' 8 8 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / 'OP_3' 'OP' 7 7 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / / COMPDAT 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / 'OP_2' 8 8 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 / 'OP_2' 8 7 3 3 'OPEN' 1* 15.071 0.311 1391.859 1* 1* 'Y' 21.920 / 'OP_2' 8 7 3 6 'OPEN' 1* 6.242 0.311 576.458 1* 1* 'Y' 21.915 / 'OP_3' 7 7 1 1 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 / 'OP_3' 7 7 2 2 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 / / WELOPEN 'OP_2' 'OPEN' / / DATES -- 2 (sim step = 1) 10 JUL 2007 / / WRFTPLT 'OP_2' 'YES' 'NO' 'NO' / / DATES -- 3 (sim step = 2) 10 AUG 2007 / / COMPDAT -- with defaulted I and J 'OP_1' 0 * 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / / END )"; } BOOST_AUTO_TEST_CASE(CreateScheduleDeckMissingReturnsDefaults) { Deck deck; Parser parser; deck.addKeyword( DeckKeyword( parser.getKeyword("SCHEDULE" ))); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule(deck, grid , fp, runspec, python); BOOST_CHECK_EQUAL( schedule.getStartTime() , TimeMap::mkdate(1983, 1 , 1)); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrdered) { const auto& schedule = make_schedule( createDeckWithWellsOrdered() ); auto well_names = schedule.wellNames(); BOOST_CHECK_EQUAL( "CW_1" , well_names[0]); BOOST_CHECK_EQUAL( "BW_2" , well_names[1]); BOOST_CHECK_EQUAL( "AW_3" , well_names[2]); auto group_names = schedule.groupNames(); BOOST_CHECK_EQUAL( "FIELD", group_names[0]); BOOST_CHECK_EQUAL( "CG", group_names[1]); BOOST_CHECK_EQUAL( "BG", group_names[2]); BOOST_CHECK_EQUAL( "AG", group_names[3]); auto restart_groups = schedule.restart_groups(0); BOOST_REQUIRE_EQUAL(restart_groups.size(), 4U); for (std::size_t group_index = 0; group_index < restart_groups.size() - 1; group_index++) { const auto& group_ptr = restart_groups[group_index]; BOOST_CHECK_EQUAL(group_ptr->insert_index(), group_index + 1); } const auto& field_ptr = restart_groups.back(); BOOST_CHECK_EQUAL(field_ptr->insert_index(), 0U); BOOST_CHECK_EQUAL(field_ptr->name(), "FIELD"); } static bool has_well( const std::vector& wells, const std::string& well_name) { for (const auto& well : wells ) if (well.name( ) == well_name) return true; return false; } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrderedGRUPTREE) { const auto& schedule = make_schedule( createDeckWithWellsOrderedGRUPTREE() ); BOOST_CHECK_THROW( schedule.getChildWells2( "NO_SUCH_GROUP" , 1 ), std::invalid_argument); { auto field_wells = schedule.getChildWells2("FIELD" , 0); BOOST_CHECK_EQUAL( field_wells.size() , 4U); BOOST_CHECK( has_well( field_wells, "DW_0" )); BOOST_CHECK( has_well( field_wells, "CW_1" )); BOOST_CHECK( has_well( field_wells, "BW_2" )); BOOST_CHECK( has_well( field_wells, "AW_3" )); } { auto platform_wells = schedule.getChildWells2("PLATFORM" , 0); BOOST_CHECK_EQUAL( platform_wells.size() , 4U); BOOST_CHECK( has_well( platform_wells, "DW_0" )); BOOST_CHECK( has_well( platform_wells, "CW_1" )); BOOST_CHECK( has_well( platform_wells, "BW_2" )); BOOST_CHECK( has_well( platform_wells, "AW_3" )); } { auto child_wells1 = schedule.getChildWells2("CG1" , 0); BOOST_CHECK_EQUAL( child_wells1.size() , 2U); BOOST_CHECK( has_well( child_wells1, "DW_0" )); BOOST_CHECK( has_well( child_wells1, "CW_1" )); } { auto parent_wells2 = schedule.getChildWells2("PG2" , 0); BOOST_CHECK_EQUAL( parent_wells2.size() , 2U); BOOST_CHECK( has_well( parent_wells2, "BW_2" )); BOOST_CHECK( has_well( parent_wells2, "AW_3" )); } auto group_names = schedule.groupNames("P*", 0); BOOST_CHECK( std::find(group_names.begin(), group_names.end(), "PG1") != group_names.end() ); BOOST_CHECK( std::find(group_names.begin(), group_names.end(), "PG2") != group_names.end() ); BOOST_CHECK( std::find(group_names.begin(), group_names.end(), "PLATFORM") != group_names.end() ); } BOOST_AUTO_TEST_CASE(GroupTree2TEST) { const auto& schedule = make_schedule( createDeckWithWellsOrderedGRUPTREE() ); BOOST_CHECK_THROW( schedule.groupTree("NO_SUCH_GROUP", 0), std::invalid_argument); auto cg1 = schedule.getGroup("CG1", 0); BOOST_CHECK( cg1.hasWell("DW_0")); BOOST_CHECK( cg1.hasWell("CW_1")); auto cg1_tree = schedule.groupTree("CG1", 0); BOOST_CHECK_EQUAL(cg1_tree.wells().size(), 2U); auto gt = schedule.groupTree(0); BOOST_CHECK_EQUAL(gt.wells().size(), 0U); BOOST_CHECK_EQUAL(gt.group().name(), "FIELD"); BOOST_CHECK_THROW(gt.parent_name(), std::invalid_argument); auto cg = gt.groups(); auto pg = cg[0]; BOOST_CHECK_EQUAL(cg.size(), 1U); BOOST_CHECK_EQUAL(pg.group().name(), "PLATFORM"); BOOST_CHECK_EQUAL(pg.parent_name(), "FIELD"); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithStart) { const auto& schedule = make_schedule( createDeck() ); BOOST_CHECK_EQUAL( schedule.getStartTime() , TimeMap::mkdate(1998, 3 , 8 )); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithSCHEDULENoThrow) { BOOST_CHECK_NO_THROW( make_schedule( "SCHEDULE" )); } BOOST_AUTO_TEST_CASE(EmptyScheduleHasNoWells) { const auto& schedule = make_schedule( createDeck() ); BOOST_CHECK_EQUAL( 0U , schedule.numWells() ); BOOST_CHECK_EQUAL( false , schedule.hasWell("WELL1") ); BOOST_CHECK_THROW( schedule.getWell("WELL2", 0) , std::invalid_argument ); } BOOST_AUTO_TEST_CASE(EmptyScheduleHasFIELDGroup) { const auto& schedule = make_schedule( createDeck() ); BOOST_CHECK_EQUAL( 1U , schedule.numGroups() ); BOOST_CHECK_EQUAL( true , schedule.hasGroup("FIELD") ); BOOST_CHECK_EQUAL( false , schedule.hasGroup("GROUP") ); BOOST_CHECK_THROW( schedule.getGroup("GROUP", 0) , std::invalid_argument ); } BOOST_AUTO_TEST_CASE(HasGroup_At_Time) { const auto input = std::string { R"( SCHEDULE WELSPECS -- Group 'P' exists from the first report step 'P1' 'P' 1 1 2502.5 'OIL' / / WCONPROD 'P1' 'OPEN' 'ORAT' 123.4 4* 50.0 / / TSTEP 10 20 30 40 / WELSPECS -- Group 'I' does not exist before now (report step 4, zero-based = 3) 'I1' 'I' 5 5 2522.5 'WATER' / / WCONINJE 'I1' 'WATER' 'OPEN' 'RATE' 200 1* 450.0 / / TSTEP 50 50 / END )" }; const auto sched = make_schedule(input); BOOST_CHECK_MESSAGE(sched.hasGroup("P"), R"(Group "P" Must Exist)"); BOOST_CHECK_MESSAGE(sched.hasGroup("I"), R"(Group "I" Must Exist)"); BOOST_CHECK_MESSAGE( sched.hasGroup("P", 3), R"(Group "P" Must Exist at Report Step 3)"); BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 3), R"(Group "I" Must NOT Exist at Report Step 3)"); BOOST_CHECK_MESSAGE( sched.hasGroup("I", 4), R"(Group "I" Must Exist at Report Step 4)"); BOOST_CHECK_MESSAGE(sched.hasGroup("P", 6), R"(Group "P" Must Exist At Last Report Step)"); BOOST_CHECK_MESSAGE(sched.hasGroup("I", 6), R"(Group "I" Must Exist At Last Report Step)"); BOOST_CHECK_MESSAGE(! sched.hasGroup("P", 7), R"(Group "P" Must NOT Exist Immediately After Last Report Step)"); BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 7), R"(Group "I" Must NOT Exist Immediately After Last Report Step)"); BOOST_CHECK_MESSAGE(! sched.hasGroup("P", 1729), R"(Group "P" Must NOT Exist Long After Last Report Step)"); BOOST_CHECK_MESSAGE(! sched.hasGroup("I", 1729), R"(Group "I" Must NOT Exist Long After Last Report Step)"); BOOST_CHECK_THROW(sched.getGroup("I", 3), std::invalid_argument); } BOOST_AUTO_TEST_CASE(WellsIterator_Empty_EmptyVectorReturned) { const auto& schedule = make_schedule( createDeck() ); const auto wells_alltimesteps = schedule.getWellsatEnd(); BOOST_CHECK_EQUAL(0U, wells_alltimesteps.size()); const auto wells_t0 = schedule.getWells(0); BOOST_CHECK_EQUAL(0U, wells_t0.size()); // The time argument is beyond the length of the vector BOOST_CHECK_THROW(schedule.getWells(1), std::invalid_argument); } BOOST_AUTO_TEST_CASE(WellsIterator_HasWells_WellsReturned) { const auto& schedule = make_schedule( createDeckWithWells() ); size_t timeStep = 0; const auto wells_alltimesteps = schedule.getWellsatEnd(); BOOST_CHECK_EQUAL(3U, wells_alltimesteps.size()); const auto wells_t0 = schedule.getWells(timeStep); BOOST_CHECK_EQUAL(1U, wells_t0.size()); const auto wells_t3 = schedule.getWells(3); BOOST_CHECK_EQUAL(3U, wells_t3.size()); } BOOST_AUTO_TEST_CASE(ReturnNumWellsTimestep) { const auto& schedule = make_schedule( createDeckWithWells() ); BOOST_CHECK_EQUAL(schedule.numWells(0), 1U); BOOST_CHECK_EQUAL(schedule.numWells(1), 1U); BOOST_CHECK_EQUAL(schedule.numWells(2), 1U); BOOST_CHECK_EQUAL(schedule.numWells(3), 3U); } BOOST_AUTO_TEST_CASE(TestCrossFlowHandling) { const auto& schedule = make_schedule( createDeckForTestingCrossFlow() ); BOOST_CHECK_EQUAL(schedule.getWell("BAN", 0).getAllowCrossFlow(), false); BOOST_CHECK_EQUAL(schedule.getWell("ALLOW", 0).getAllowCrossFlow(), true); BOOST_CHECK_EQUAL(schedule.getWell("DEFAULT", 0).getAllowCrossFlow(), true); BOOST_CHECK(Well::Status::SHUT == schedule.getWell("BAN", 0).getStatus()); BOOST_CHECK(Well::Status::OPEN == schedule.getWell("BAN", 1).getStatus()); BOOST_CHECK(Well::Status::OPEN == schedule.getWell("BAN", 2).getStatus()); BOOST_CHECK(Well::Status::SHUT == schedule.getWell("BAN", 3).getStatus()); BOOST_CHECK(Well::Status::SHUT == schedule.getWell("BAN", 4).getStatus()); // not allow to open BOOST_CHECK(Well::Status::OPEN == schedule.getWell("BAN", 5).getStatus()); } static std::string createDeckWithWellsAndConnectionDataWithWELOPEN() { std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'OP_2' 'OP' 8 8 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'OP_3' 'OP' 7 7 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_2' 8 8 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 / \n" " 'OP_2' 8 7 3 3 'OPEN' 1* 15.071 0.311 1391.859 1* 1* 'Y' 21.920 / \n" " 'OP_2' 8 7 3 6 'OPEN' 1* 6.242 0.311 576.458 1* 1* 'Y' 21.915 / \n" " 'OP_3' 7 7 1 1 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 / \n" " 'OP_3' 7 7 2 2 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 / \n" "/\n" "DATES -- 2,3\n" " 10 JUL 2007 / \n" " 10 AUG 2007 / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT / \n" " '*' OPEN 0 0 3 / \n" " 'OP_2' SHUT 0 0 0 4 6 / \n " " 'OP_3' SHUT 0 0 0 / \n" "/\n" "DATES -- 4\n" " 10 JUL 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN / \n" " 'OP_2' OPEN 0 0 0 4 6 / \n " " 'OP_3' OPEN 0 0 0 / \n" "/\n" "DATES -- 5\n" " 10 OKT 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT 0 0 0 0 0 / \n " "/\n"; return input; } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndConnectionDataWithWELOPEN) { const auto& schedule = make_schedule(createDeckWithWellsAndConnectionDataWithWELOPEN()); { constexpr auto well_shut = Well::Status::SHUT; constexpr auto well_open = Well::Status::OPEN; BOOST_CHECK(well_shut == schedule.getWell("OP_1", 3).getStatus( )); BOOST_CHECK(well_open == schedule.getWell("OP_1", 4).getStatus( )); BOOST_CHECK(well_shut == schedule.getWell("OP_1", 5).getStatus( )); } { constexpr auto comp_shut = Connection::State::SHUT; constexpr auto comp_open = Connection::State::OPEN; { const auto& well = schedule.getWell("OP_2", 3); const auto& cs = well.getConnections( ); BOOST_CHECK_EQUAL( 7U, cs.size() ); BOOST_CHECK(comp_shut == cs.getFromIJK( 7, 6, 2 ).state()); BOOST_CHECK(comp_shut == cs.getFromIJK( 7, 6, 3 ).state()); BOOST_CHECK(comp_shut == cs.getFromIJK( 7, 6, 4 ).state()); BOOST_CHECK(comp_open == cs.getFromIJK( 7, 7, 2 ).state()); } { const auto& well = schedule.getWell("OP_2", 4); const auto& cs2 = well.getConnections( ); BOOST_CHECK(comp_open == cs2.getFromIJK( 7, 6, 2 ).state()); BOOST_CHECK(comp_open == cs2.getFromIJK( 7, 6, 3 ).state()); BOOST_CHECK(comp_open == cs2.getFromIJK( 7, 6, 4 ).state()); BOOST_CHECK(comp_open == cs2.getFromIJK( 7, 7, 2 ).state()); } { const auto& well = schedule.getWell("OP_3", 3); const auto& cs3 = well.getConnections( ); BOOST_CHECK(comp_shut == cs3.get( 0 ).state()); } { const auto& well = schedule.getWell("OP_3", 4); const auto& cs4 = well.getConnections( ); BOOST_CHECK(comp_open == cs4.get( 0 ).state()); } } } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithWELOPEN_TryToOpenWellWithShutCompletionsDoNotOpenWell) { Opm::Parser parser; std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 2\n" " 10 JUL 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN / \n" "/\n" "DATES -- 3\n" " 10 OKT 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT 0 0 0 0 0 / \n " "/\n" "DATES -- 4\n" " 10 NOV 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN / \n " "/\n"; const auto& schedule = make_schedule(input); const auto& well2_3 = schedule.getWell("OP_1",3); const auto& well2_4 = schedule.getWell("OP_1",4); BOOST_CHECK(Well::Status::SHUT == well2_3.getStatus()); BOOST_CHECK(Well::Status::SHUT == well2_4.getStatus()); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithWELOPEN_CombineShutCompletionsAndAddNewCompletionsDoNotShutWell) { Opm::Parser parser; std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 2\n" " 10 JUL 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN / \n" "/\n" "DATES -- 3\n" " 10 OKT 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT 0 0 0 0 0 / \n " "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 4\n" " 10 NOV 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT 0 0 0 0 0 / \n " "/\n" "DATES -- 5\n" " 11 NOV 2008 / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 6\n" " 12 NOV 2008 / \n" "/\n"; const auto& schedule = make_schedule(input); const auto& well_3 = schedule.getWell("OP_1", 3); const auto& well_4 = schedule.getWell("OP_1", 4); const auto& well_5 = schedule.getWell("OP_1", 5); // timestep 3. Close all completions with WELOPEN and immediately open new completions with COMPDAT. BOOST_CHECK(Well::Status::OPEN == well_3.getStatus()); BOOST_CHECK( !schedule.hasWellGroupEvent( "OP_1", ScheduleEvents::WELL_STATUS_CHANGE , 3 )); // timestep 4. Close all completions with WELOPEN. The well will be shut since no completions // are open. BOOST_CHECK(Well::Status::SHUT == well_4.getStatus()); BOOST_CHECK( schedule.hasWellGroupEvent( "OP_1", ScheduleEvents::WELL_STATUS_CHANGE , 4 )); // timestep 5. Open new completions. But keep the well shut, BOOST_CHECK(Well::Status::SHUT == well_5.getStatus()); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithWRFT) { Opm::Parser parser; std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'OP_2' 'OP' 4 4 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_2' 4 4 4 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 2\n" " 10 OKT 2008 / \n" "/\n" "WRFT \n" "/ \n" "WELOPEN\n" " 'OP_1' OPEN / \n" "/\n" "DATES -- 3\n" " 10 NOV 2008 / \n" "/\n" "WELOPEN\n" " 'OP_2' OPEN / \n" "/\n" "DATES -- 4\n" " 30 NOV 2008 / \n" "/\n"; const auto& schedule = make_schedule(input); const auto& rft_config = schedule.rftConfig(); BOOST_CHECK_EQUAL(2U, rft_config.firstRFTOutput()); BOOST_CHECK_EQUAL(true, rft_config.rft("OP_1", 2)); BOOST_CHECK_EQUAL(true, rft_config.rft("OP_2", 3)); } BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithWRFTPLT) { Opm::Parser parser; std::string input = "START -- 0 \n" "1 NOV 1979 / \n" "SCHEDULE\n" "DATES -- 1\n" " 1 DES 1979/ \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT / \n" "/\n" "DATES -- 2\n" " 10 OKT 2006 / \n" "/\n" "WELOPEN\n" " 'OP_1' SHUT / \n" "/\n" "WRFTPLT \n" " 'OP_1' FOPN / \n" "/ \n" "DATES -- 3\n" " 10 OKT 2007 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN 0 0 0 0 0 / \n" "/\n" "DATES -- 4\n" " 10 OKT 2008 / \n" "/\n" "WELOPEN\n" " 'OP_1' OPEN / \n" "/\n" "DATES -- 5\n" " 10 NOV 2008 / \n" "/\n"; const auto& schedule = make_schedule(input); const auto& well = schedule.getWell("OP_1", 4); BOOST_CHECK(Well::Status::OPEN == well.getStatus()); const auto& rft_config = schedule.rftConfig(); BOOST_CHECK_EQUAL(rft_config.rft("OP_1", 3),false); BOOST_CHECK_EQUAL(rft_config.rft("OP_1", 4),true); BOOST_CHECK_EQUAL(rft_config.rft("OP_1", 5),false); } BOOST_AUTO_TEST_CASE(createDeckWithWeltArg) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONPROD\n" " 'OP_1' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / \n" "/\n" "DATES -- 2\n" " 20 JAN 2010 / \n" "/\n" "WELTARG\n" " OP_1 ORAT 1300 /\n" " OP_1 WRAT 1400 /\n" " OP_1 GRAT 1500.52 /\n" " OP_1 LRAT 1600.58 /\n" " OP_1 RESV 1801.05 /\n" " OP_1 BHP 1900 /\n" " OP_1 THP 2000 /\n" " OP_1 VFP 2100.09 /\n" " OP_1 GUID 2300.14 /\n" "/\n"; const auto& schedule = make_schedule(input); Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC ); double siFactorL = unitSystem.parse("LiquidSurfaceVolume/Time").getSIScaling(); double siFactorG = unitSystem.parse("GasSurfaceVolume/Time").getSIScaling(); double siFactorP = unitSystem.parse("Pressure").getSIScaling(); SummaryState st(std::chrono::system_clock::now()); const auto& well_1 = schedule.getWell("OP_1", 1); const auto wpp_1 = well_1.getProductionProperties(); BOOST_CHECK_EQUAL(wpp_1.WaterRate.get(), 0); BOOST_CHECK (wpp_1.hasProductionControl( Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK (!wpp_1.hasProductionControl( Opm::Well::ProducerCMode::RESV) ); const auto& well_2 = schedule.getWell("OP_1", 2); const auto wpp_2 = well_2.getProductionProperties(); const auto prod_controls = wpp_2.controls(st, 0); BOOST_CHECK_EQUAL(prod_controls.oil_rate, 1300 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.water_rate, 1400 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.gas_rate, 1500.52 * siFactorG); BOOST_CHECK_EQUAL(prod_controls.liquid_rate, 1600.58 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.resv_rate, 1801.05 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.bhp_limit, 1900 * siFactorP); BOOST_CHECK_EQUAL(prod_controls.thp_limit, 2000 * siFactorP); BOOST_CHECK_EQUAL(prod_controls.vfp_table_number, 2100); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::RESV) ); } BOOST_AUTO_TEST_CASE(createDeckWithWeltArg_UDA) { std::string input = R"( START -- 0 19 JUN 2007 / SCHEDULE DATES -- 1 10 OKT 2008 / / UDQ ASSIGN WUORAT 10 / ASSIGN WUWRAT 20 / / WELSPECS 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / / COMPDAT 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / / WCONPROD 'OP_1' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / / DATES -- 2 20 JAN 2010 / / WELTARG OP_1 ORAT WUORAT / OP_1 WRAT WUWRAT / / )"; const auto& schedule = make_schedule(input); SummaryState st(std::chrono::system_clock::now()); Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC ); double siFactorL = unitSystem.parse("LiquidSurfaceVolume/Time").getSIScaling(); st.update_well_var("OP_1", "WUORAT", 10); st.update_well_var("OP_1", "WUWRAT", 20); const auto& well_1 = schedule.getWell("OP_1", 1); const auto wpp_1 = well_1.getProductionProperties(); BOOST_CHECK_EQUAL(wpp_1.OilRate.get(), 0); BOOST_CHECK_EQUAL(wpp_1.WaterRate.get(), 0); BOOST_CHECK (wpp_1.hasProductionControl( Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK (!wpp_1.hasProductionControl( Opm::Well::ProducerCMode::RESV) ); const auto& well_2 = schedule.getWell("OP_1", 2); const auto wpp_2 = well_2.getProductionProperties(); BOOST_CHECK( wpp_2.OilRate.is() ); BOOST_CHECK_EQUAL( wpp_2.OilRate.get(), "WUORAT" ); BOOST_CHECK_EQUAL( wpp_2.WaterRate.get(), "WUWRAT" ); const auto prod_controls = wpp_2.controls(st, 0); BOOST_CHECK_EQUAL(prod_controls.oil_rate, 10 * siFactorL); BOOST_CHECK_EQUAL(prod_controls.water_rate, 20 * siFactorL); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK (wpp_2.hasProductionControl( Opm::Well::ProducerCMode::WRAT) ); } BOOST_AUTO_TEST_CASE(createDeckWithWeltArgException) { std::string input = "SCHEDULE\n" "WELTARG\n" " OP_1 GRAT 1500.52 /\n" " OP_1 LRAT /\n" " OP_1 RESV 1801.05 /\n" "/\n"; BOOST_CHECK_THROW(make_schedule(input), Opm::OpmInputError); } BOOST_AUTO_TEST_CASE(createDeckWithWeltArgException2) { std::string input = "SCHEDULE\n" "WELTARG\n" " OP_1 LRAT /\n" " OP_1 RESV 1801.05 /\n" "/\n"; BOOST_CHECK_THROW(make_schedule(input), Opm::OpmInputError); } BOOST_AUTO_TEST_CASE(createDeckWithWPIMULT) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "DATES -- 2\n" " 20 JAN 2010 / \n" "/\n" "WPIMULT\n" "OP_1 1.30 /\n" "/\n" "DATES -- 3\n" " 20 JAN 2011 / \n" "/\n" "WPIMULT\n" "OP_1 1.30 /\n" "/\n" "DATES -- 4\n" " 20 JAN 2012 / \n" "/\n" "COMPDAT\n" " 'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'OP_1' 9 9 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n"; const auto& schedule = make_schedule(input); const auto& cs1 = schedule.getWell("OP_1", 1).getConnections(); const auto& cs2 = schedule.getWell("OP_1", 2).getConnections(); const auto& cs3 = schedule.getWell("OP_1", 3).getConnections(); const auto& cs4 = schedule.getWell("OP_1", 4).getConnections(); for(size_t i = 0; i < cs2.size(); i++) BOOST_CHECK_EQUAL(cs2.get( i ).CF() / cs1.get(i).CF(), 1.3); for(size_t i = 0; i < cs3.size(); i++ ) BOOST_CHECK_EQUAL(cs3.get( i ).CF() / cs1.get(i).CF(), (1.3*1.3)); for(size_t i = 0; i < cs4.size(); i++ ) BOOST_CHECK_EQUAL(cs4.get( i ).CF(), cs1.get(i).CF()); BOOST_CHECK_THROW(schedule.simTime(10000), std::invalid_argument); auto sim_time1 = TimeStampUTC{ schedule.simTime(1) }; BOOST_CHECK_EQUAL(sim_time1.day(), 10); BOOST_CHECK_EQUAL(sim_time1.month(), 10); BOOST_CHECK_EQUAL(sim_time1.year(), 2008); sim_time1 = schedule.simTime(3); BOOST_CHECK_EQUAL(sim_time1.day(), 20); BOOST_CHECK_EQUAL(sim_time1.month(), 1); BOOST_CHECK_EQUAL(sim_time1.year(), 2011); } BOOST_AUTO_TEST_CASE(WELSPECS_WGNAME_SPACE) { Opm::Parser parser; const std::string input = 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 ' PROD1' 'G1' 1 1 10 'OIL' / 'PROD2' 'G2' 2 2 10 'OIL' / 'PROD3' 'H1' 3 3 10 'OIL' / / GCONPROD 'G1' 'ORAT' 1000 / / DATES -- 2 10 NOV 2008 / / GCONPROD 'G*' 'ORAT' 2000 / / )"; auto deck = parser.parseString(input); auto python = std::make_shared(); EclipseGrid grid( deck ); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); ParseContext parseContext; ErrorGuard errors; parseContext.update(ParseContext::PARSE_WGNAME_SPACE, InputError::THROW_EXCEPTION); BOOST_CHECK_THROW( Opm::Schedule(deck, grid, fp, runspec, parseContext, errors, python), Opm::OpmInputError); parseContext.update(ParseContext::PARSE_WGNAME_SPACE, InputError::IGNORE); BOOST_CHECK_NO_THROW( Opm::Schedule(deck, grid, fp, runspec, parseContext, errors, python)); } BOOST_AUTO_TEST_CASE(createDeckModifyMultipleGCONPROD) { const std::string input = 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 'PROD1' 'G1' 1 1 10 'OIL' / 'PROD2' 'G2' 2 2 10 'OIL' / 'PROD3' 'H1' 3 3 10 'OIL' / / GCONPROD 'G1' 'ORAT' 1000 / / DATES -- 2 10 NOV 2008 / / GCONPROD 'G*' 'ORAT' 2000 0 0 0 'NONE' 'YES' 148 'OIL'/ / )"; const auto& schedule = make_schedule(input); Opm::SummaryState st(std::chrono::system_clock::now()); Opm::UnitSystem unitSystem = UnitSystem(UnitSystem::UnitType::UNIT_TYPE_METRIC); double siFactorL = unitSystem.parse("LiquidSurfaceVolume/Time").getSIScaling(); { auto g = schedule.getGroup("G1", 1); BOOST_CHECK_EQUAL(g.productionControls(st).oil_target, 1000 * siFactorL); BOOST_CHECK(g.has_control(Group::ProductionCMode::ORAT)); BOOST_CHECK(!g.has_control(Group::ProductionCMode::WRAT)); BOOST_CHECK_EQUAL(g.productionControls(st).guide_rate, 0); } { auto g = schedule.getGroup("G1", 2); BOOST_CHECK_EQUAL(g.productionControls(st).oil_target, 2000 * siFactorL); BOOST_CHECK_EQUAL(g.productionControls(st).guide_rate, 148); BOOST_CHECK_EQUAL(true, g.productionControls(st).guide_rate_def == Group::GuideRateTarget::OIL); } auto g2 = schedule.getGroup("G2", 2); BOOST_CHECK_EQUAL(g2.productionControls(st).oil_target, 2000 * siFactorL); auto gh = schedule.getGroup("H1", 1); BOOST_CHECK( !schedule.hasWellGroupEvent( "G2", ScheduleEvents::GROUP_PRODUCTION_UPDATE , 1 )); BOOST_CHECK( schedule.hasWellGroupEvent( "G2", ScheduleEvents::GROUP_PRODUCTION_UPDATE , 2 )); } BOOST_AUTO_TEST_CASE(createDeckWithDRSDT) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "DRSDT\n" "0.0003\n" "/\n"; const auto& schedule = make_schedule(input); size_t currentStep = 1; BOOST_CHECK_EQUAL(schedule.hasOilVaporizationProperties(), true); const auto& ovap = schedule.getOilVaporizationProperties(currentStep); BOOST_CHECK_EQUAL(true, ovap.getOption(0)); BOOST_CHECK(ovap.getType() == OilVaporizationProperties::OilVaporization::DRDT); BOOST_CHECK_EQUAL(true, ovap.drsdtActive()); BOOST_CHECK_EQUAL(false, ovap.drvdtActive()); } BOOST_AUTO_TEST_CASE(createDeckWithDRSDTR) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "TABDIMS\n" " 1* 3 \n " "/\n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "DRSDTR\n" "0 /\n" "1 /\n" "2 /\n"; const auto& schedule = make_schedule(input); size_t currentStep = 1; BOOST_CHECK_EQUAL(schedule.hasOilVaporizationProperties(), true); const auto& ovap = schedule.getOilVaporizationProperties(currentStep); auto unitSystem = UnitSystem::newMETRIC(); for (int i = 0; i < 3; ++i) { double value = unitSystem.to_si( UnitSystem::measure::gas_surface_rate, i ); BOOST_CHECK_EQUAL(value, ovap.getMaxDRSDT(i)); BOOST_CHECK_EQUAL(true, ovap.getOption(i)); } BOOST_CHECK(ovap.getType() == OilVaporizationProperties::OilVaporization::DRDT); BOOST_CHECK_EQUAL(true, ovap.drsdtActive()); BOOST_CHECK_EQUAL(false, ovap.drvdtActive()); } BOOST_AUTO_TEST_CASE(createDeckWithDRSDTthenDRVDT) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "DRSDT\n" "0.0003\n" "/\n" "DATES -- 2\n" " 10 OKT 2009 / \n" "/\n" "DRVDT\n" "0.100\n" "/\n" "DATES -- 3\n" " 10 OKT 2010 / \n" "/\n" "VAPPARS\n" "2 0.100\n" "/\n"; const auto& schedule = make_schedule(input); BOOST_CHECK_EQUAL(schedule.hasOilVaporizationProperties(), true); const OilVaporizationProperties& ovap1 = schedule.getOilVaporizationProperties(1); BOOST_CHECK(ovap1.getType() == OilVaporizationProperties::OilVaporization::DRDT); BOOST_CHECK_EQUAL(true, ovap1.drsdtActive()); BOOST_CHECK_EQUAL(false, ovap1.drvdtActive()); const OilVaporizationProperties& ovap2 = schedule.getOilVaporizationProperties(2); //double value = ovap2.getMaxDRVDT(0); //BOOST_CHECK_EQUAL(1.1574074074074074e-06, value); BOOST_CHECK(ovap2.getType() == OilVaporizationProperties::OilVaporization::DRDT); BOOST_CHECK_EQUAL(true, ovap2.drvdtActive()); BOOST_CHECK_EQUAL(true, ovap2.drsdtActive()); const OilVaporizationProperties& ovap3 = schedule.getOilVaporizationProperties(3); BOOST_CHECK(ovap3.getType() == OilVaporizationProperties::OilVaporization::VAPPARS); BOOST_CHECK_EQUAL(false, ovap3.drvdtActive()); BOOST_CHECK_EQUAL(false, ovap3.drsdtActive()); } BOOST_AUTO_TEST_CASE(createDeckWithVAPPARS) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "VAPPARS\n" "2 0.100\n" "/\n"; const auto& schedule = make_schedule(input); size_t currentStep = 1; BOOST_CHECK_EQUAL(schedule.hasOilVaporizationProperties(), true); const OilVaporizationProperties& ovap = schedule.getOilVaporizationProperties(currentStep); BOOST_CHECK(ovap.getType() == OilVaporizationProperties::OilVaporization::VAPPARS); double vap1 = ovap.vap1(); BOOST_CHECK_EQUAL(2, vap1); double vap2 = ovap.vap2(); BOOST_CHECK_EQUAL(0.100, vap2); BOOST_CHECK_EQUAL(false, ovap.drsdtActive()); BOOST_CHECK_EQUAL(false, ovap.drvdtActive()); } BOOST_AUTO_TEST_CASE(createDeckWithOutOilVaporizationProperties) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n"; const auto& schedule = make_schedule(input); BOOST_CHECK_EQUAL(schedule.hasOilVaporizationProperties(), false); } BOOST_AUTO_TEST_CASE(changeBhpLimitInHistoryModeWithWeltarg) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P' 'OPEN' 'RESV' 6* 500 / \n" "/\n" "WCONINJH\n" " 'I' 'WATER' 1* 100 250 / \n" "/\n" "WELTARG\n" " 'P' 'BHP' 50 / \n" " 'I' 'BHP' 600 / \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "WCONHIST\n" " 'P' 'OPEN' 'RESV' 6* 500/\n/\n" "WCONINJH\n" " 'I' 'WATER' 1* 100 250 / \n" "/\n" "DATES -- 3\n" " 18 OKT 2008 / \n" "/\n" "WCONHIST\n" " 'I' 'OPEN' 'RESV' 6* /\n/\n" "DATES -- 4\n" " 20 OKT 2008 / \n" "/\n" "WCONINJH\n" " 'I' 'WATER' 1* 100 250 / \n" "/\n" ; const auto& sched = make_schedule(input); const auto st = ::Opm::SummaryState{ std::chrono::system_clock::now() }; UnitSystem unit_system(UnitSystem::UnitType::UNIT_TYPE_METRIC); // The BHP limit should not be effected by WCONHIST { const auto& c1 = sched.getWell("P",1).getProductionProperties().controls(st, 0); const auto& c2 = sched.getWell("P",2).getProductionProperties().controls(st, 0); BOOST_CHECK_EQUAL(c1.bhp_limit, 50 * 1e5); // 1 BOOST_CHECK_EQUAL(c2.bhp_limit, 50 * 1e5); // 2 } { const auto& c1 = sched.getWell("I",1).getInjectionProperties().controls(unit_system, st, 0); const auto& c2 = sched.getWell("I",2).getInjectionProperties().controls(unit_system, st, 0); BOOST_CHECK_EQUAL(c1.bhp_limit, 600 * 1e5); // 1 BOOST_CHECK_EQUAL(c2.bhp_limit, 600 * 1e5); // 2 } BOOST_CHECK_EQUAL(sched.getWell("I", 2).getInjectionProperties().hasInjectionControl(Opm::Well::InjectorCMode::BHP), true); // The well is producer for timestep 3 and the injection properties BHPTarget should be set to zero. BOOST_CHECK(sched.getWell("I", 3).isProducer()); BOOST_CHECK_EQUAL(sched.getWell("I", 3).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::BHP), true ); BOOST_CHECK_EQUAL(sched.getWell("I", 4).getInjectionProperties().hasInjectionControl(Opm::Well::InjectorCMode::BHP), true ); { const auto& c3 = sched.getWell("I",3).getInjectionProperties().controls(unit_system, st, 0); const auto& c4 = sched.getWell("I",4).getInjectionProperties().controls(unit_system, st, 0); BOOST_CHECK_EQUAL(c3.bhp_limit, 0); // 1 BOOST_CHECK_EQUAL(c4.bhp_limit, 6891.2 * 1e5); // 2 } } BOOST_AUTO_TEST_CASE(changeModeWithWHISTCTL) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'P2' 'OP' 5 5 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'P2' 5 5 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P2' 5 5 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "WHISTCTL\n" " RESV / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 3\n" " 18 OKT 2008 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 4\n" " 20 OKT 2008 / \n" "/\n" "WHISTCTL\n" " LRAT / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 5\n" " 25 OKT 2008 / \n" "/\n" "WHISTCTL\n" " NONE / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" ; const auto& schedule = make_schedule(input); //Start BOOST_CHECK_THROW(schedule.getWell("P1", 0), std::invalid_argument); BOOST_CHECK_THROW(schedule.getWell("P2", 0), std::invalid_argument); //10 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK(schedule.getWell("P2", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); //15 OKT 2008 { const auto& props1 = schedule.getWell("P1", 2).getProductionProperties(); const auto& props2 = schedule.getWell("P2", 2).getProductionProperties(); BOOST_CHECK(props1.controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK(props2.controlMode == Opm::Well::ProducerCMode::RESV); // under history mode, a producing well should have only one rate target/limit or have no rate target/limit. // the rate target/limit from previous report step should not be kept. BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); } //18 OKT 2008 { const auto& props1 = schedule.getWell("P1", 3).getProductionProperties(); const auto& props2 = schedule.getWell("P2", 3).getProductionProperties(); BOOST_CHECK(props1.controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK(props2.controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); } // 20 OKT 2008 { const auto& props1 = schedule.getWell("P1", 4).getProductionProperties(); const auto& props2 = schedule.getWell("P2", 4).getProductionProperties(); BOOST_CHECK(props1.controlMode == Opm::Well::ProducerCMode::LRAT); BOOST_CHECK(props2.controlMode == Opm::Well::ProducerCMode::LRAT); BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::RESV) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::RESV) ); } // 25 OKT 2008 { const auto& props1 = schedule.getWell("P1", 5).getProductionProperties(); const auto& props2 = schedule.getWell("P2", 5).getProductionProperties(); BOOST_CHECK(props1.controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK(props2.controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::LRAT) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::LRAT) ); BOOST_CHECK( !props1.hasProductionControl(Opm::Well::ProducerCMode::RESV) ); BOOST_CHECK( !props2.hasProductionControl(Opm::Well::ProducerCMode::RESV) ); } } BOOST_AUTO_TEST_CASE(fromWCONHISTtoWCONPROD) { std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'P2' 'OP' 5 5 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'P2' 5 5 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P2' 5 5 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "WCONPROD\n" " 'P1' 'OPEN' 'GRAT' 1* 200.0 300.0 / \n" " 'P2' 'OPEN' 'WRAT' 1* 100.0 300.0 / \n" "/\n" "DATES -- 3\n" " 18 OKT 2008 / \n" "/\n" ; const auto& schedule = make_schedule(input); //Start BOOST_CHECK_THROW(schedule.getWell("P1", 0), std::invalid_argument); BOOST_CHECK_THROW(schedule.getWell("P2", 0), std::invalid_argument); //10 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK(schedule.getWell("P2", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); //15 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 2).getProductionProperties().controlMode == Opm::Well::ProducerCMode::GRAT); BOOST_CHECK(schedule.getWell("P1", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::WRAT) ); BOOST_CHECK(schedule.getWell("P2", 2).getProductionProperties().controlMode == Opm::Well::ProducerCMode::WRAT); BOOST_CHECK(schedule.getWell("P2", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::GRAT) ); // the previous control limits/targets should not stay BOOST_CHECK( !schedule.getWell("P1", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !schedule.getWell("P2", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); } BOOST_AUTO_TEST_CASE(WHISTCTL_NEW_WELL) { Opm::Parser parser; std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "WHISTCTL\n" " GRAT/ \n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'P2' 'OP' 5 5 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'P2' 5 5 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P2' 5 5 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "WHISTCTL\n" " RESV / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 3\n" " 18 OKT 2008 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 4\n" " 20 OKT 2008 / \n" "/\n" "WHISTCTL\n" " LRAT / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 5\n" " 25 OKT 2008 / \n" "/\n" "WHISTCTL\n" " NONE / \n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" ; auto deck = parser.parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule(deck, grid , fp, runspec, python); //10 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::GRAT); BOOST_CHECK(schedule.getWell("P2", 1).getProductionProperties().controlMode == Opm::Well::ProducerCMode::GRAT); //15 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 2).getProductionProperties().controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK(schedule.getWell("P2", 2).getProductionProperties().controlMode == Opm::Well::ProducerCMode::RESV); // under history mode, a producing well should have only one rate target/limit or have no rate target/limit. // the rate target/limit from previous report step should not be kept. BOOST_CHECK( !schedule.getWell("P1", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !schedule.getWell("P2", 2).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); //18 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 3).getProductionProperties().controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK(schedule.getWell("P2", 3).getProductionProperties().controlMode == Opm::Well::ProducerCMode::RESV); BOOST_CHECK( !schedule.getWell("P1", 3).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !schedule.getWell("P2", 3).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); // 20 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 4).getProductionProperties().controlMode == Opm::Well::ProducerCMode::LRAT); BOOST_CHECK(schedule.getWell("P2", 4).getProductionProperties().controlMode == Opm::Well::ProducerCMode::LRAT); BOOST_CHECK( !schedule.getWell("P1", 4).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !schedule.getWell("P2", 4).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::ORAT) ); BOOST_CHECK( !schedule.getWell("P1", 4).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::RESV) ); BOOST_CHECK( !schedule.getWell("P2", 4).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::RESV) ); // 25 OKT 2008 BOOST_CHECK(schedule.getWell("P1", 5).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK(schedule.getWell("P2", 5).getProductionProperties().controlMode == Opm::Well::ProducerCMode::ORAT); BOOST_CHECK( !schedule.getWell("P1", 5).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::RESV) ); BOOST_CHECK( !schedule.getWell("P2", 5).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::RESV) ); BOOST_CHECK( !schedule.getWell("P1", 5).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::LRAT) ); BOOST_CHECK( !schedule.getWell("P2", 5).getProductionProperties().hasProductionControl(Opm::Well::ProducerCMode::LRAT) ); } BOOST_AUTO_TEST_CASE(unsupportedOptionWHISTCTL) { Opm::Parser parser; std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'P2' 'OP' 5 5 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'P2' 5 5 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P2' 5 5 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P1' 'OPEN' 'ORAT' 5*/ \n" " 'P2' 'OPEN' 'ORAT' 5*/ \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "WHISTCTL\n" " * YES / \n" ; auto deck = parser.parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); BOOST_CHECK_THROW(Schedule(deck, grid, fp, runspec, python), Opm::OpmInputError); } BOOST_AUTO_TEST_CASE(move_HEAD_I_location) { std::string input = R"( START -- 0 19 JUN 2007 / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / DATES -- 2 15 OKT 2008 / / WELSPECS 'W1' 'G1' 4 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); BOOST_CHECK_EQUAL(2, schedule.getWell("W1", 1).getHeadI()); BOOST_CHECK_EQUAL(3, schedule.getWell("W1", 2).getHeadI()); } BOOST_AUTO_TEST_CASE(change_ref_depth) { std::string input = R"( START -- 0 19 JUN 2007 / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / DATES -- 2 15 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 12.0 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); BOOST_CHECK_CLOSE(2873.94, schedule.getWell("W1", 1).getRefDepth(), 1e-5); BOOST_CHECK_EQUAL(12.0, schedule.getWell("W1", 2).getRefDepth()); } BOOST_AUTO_TEST_CASE(WTEMP_well_template) { std::string input = R"( START -- 0 19 JUN 2007 / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W3' 'G2' 6 6 1 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / WCONINJE 'W2' 'WATER' 'OPEN' 'RATE' 20000 4* / 'W3' 'WATER' 'OPEN' 'RATE' 20000 4* / / DATES -- 2 15 OKT 2008 / / WTEMP 'W*' 40.0 / / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 2).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W3", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).getInjectionProperties().temperature, 1e-5); } BOOST_AUTO_TEST_CASE(WTEMPINJ_well_template) { std::string input = R"( START -- 0 19 JUN 2007 / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W3' 'G2' 6 6 1 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / WCONINJE 'W2' 'WATER' 'OPEN' 'RATE' 20000 4* / 'W3' 'WATER' 'OPEN' 'RATE' 20000 4* / / DATES -- 2 15 OKT 2008 / / WINJTEMP 'W*' 1* 40.0 1* / / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); // Producerwell - currently setting temperature only acts on injectors. BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W1", 2).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W2", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(313.15, schedule.getWell("W2", 2).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(288.71, schedule.getWell("W3", 1).getInjectionProperties().temperature, 1e-5); BOOST_CHECK_CLOSE(313.15, schedule.getWell("W3", 2).getInjectionProperties().temperature, 1e-5); } BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT '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) / DATES -- 2 11 OKT 2008 / / COMPDAT 'W1' 0 0 1 1 'SHUT' 1* / -- respecify, essentially ignore (1) / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); const auto& cs1 = schedule.getWell( "W1", 1 ).getConnections( ); BOOST_CHECK_EQUAL( 1, cs1.get( 0 ).complnum() ); BOOST_CHECK_EQUAL( 2, cs1.get( 1 ).complnum() ); BOOST_CHECK_EQUAL( 3, cs1.get( 2 ).complnum() ); BOOST_CHECK_EQUAL( 4, cs1.get( 3 ).complnum() ); const auto& cs2 = schedule.getWell( "W1", 2 ).getConnections( ); BOOST_CHECK_EQUAL( 1, cs2.get( 0 ).complnum() ); BOOST_CHECK_EQUAL( 2, cs2.get( 1 ).complnum() ); BOOST_CHECK_EQUAL( 3, cs2.get( 2 ).complnum() ); BOOST_CHECK_EQUAL( 4, cs2.get( 3 ).complnum() ); } BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT '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) 'W2' 0 0 3 3 'SHUT' 1* / -- regular completion (1) 'W2' 0 0 1 3 'SHUT' 1* / -- two completions (one exist already) (2, 3) 'W*' 0 0 3 5 'SHUT' 1* / -- two completions, two wells (includes existing -- and adding for both wells) / )"; auto deck = Parser().parseString( input); auto python = std::make_shared(); EclipseGrid grid( 10, 10, 10 ); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); { const auto& w1cs = schedule.getWell( "W1", 1 ).getConnections(); BOOST_CHECK_EQUAL( 1, w1cs.get( 0 ).complnum() ); BOOST_CHECK_EQUAL( 2, w1cs.get( 1 ).complnum() ); BOOST_CHECK_EQUAL( 3, w1cs.get( 2 ).complnum() ); BOOST_CHECK_EQUAL( 4, w1cs.get( 3 ).complnum() ); BOOST_CHECK_EQUAL( 5, w1cs.get( 4 ).complnum() ); const auto& w2cs = schedule.getWell( "W2", 1 ).getConnections(); BOOST_CHECK_EQUAL( 1, w2cs.getFromIJK( 4, 4, 2 ).complnum() ); BOOST_CHECK_EQUAL( 2, w2cs.getFromIJK( 4, 4, 0 ).complnum() ); BOOST_CHECK_EQUAL( 3, w2cs.getFromIJK( 4, 4, 1 ).complnum() ); BOOST_CHECK_EQUAL( 4, w2cs.getFromIJK( 4, 4, 3 ).complnum() ); BOOST_CHECK_EQUAL( 5, w2cs.getFromIJK( 4, 4, 4 ).complnum() ); } { const auto& w1cs = schedule.getWell( "W1", 1 ).getConnections(); BOOST_CHECK_EQUAL( 1, w1cs.get( 0 ).complnum() ); BOOST_CHECK_EQUAL( 2, w1cs.get( 1 ).complnum() ); BOOST_CHECK_EQUAL( 3, w1cs.get( 2 ).complnum() ); BOOST_CHECK_EQUAL( 4, w1cs.get( 3 ).complnum() ); BOOST_CHECK_EQUAL( 5, w1cs.get( 4 ).complnum() ); const auto& w2cs = schedule.getWell( "W2", 1 ).getConnections(); BOOST_CHECK_EQUAL( 1, w2cs.getFromIJK( 4, 4, 2 ).complnum() ); BOOST_CHECK_EQUAL( 2, w2cs.getFromIJK( 4, 4, 0 ).complnum() ); BOOST_CHECK_EQUAL( 3, w2cs.getFromIJK( 4, 4, 1 ).complnum() ); BOOST_CHECK_EQUAL( 4, w2cs.getFromIJK( 4, 4, 3 ).complnum() ); BOOST_CHECK_EQUAL( 5, w2cs.getFromIJK( 4, 4, 4 ).complnum() ); BOOST_CHECK_THROW( w2cs.get( 5 ).complnum(), std::out_of_range ); } } BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE DATES -- 1 10 OKT 2008 / / WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT 'W1' 0 0 1 2 'SHUT' 1* / -- multiple completion (1, 2) 'W1' 0 0 2 2 'SHUT' 1* / -- updated completion (2) 'W1' 0 0 3 3 'SHUT' 1* / -- regular completion (3) / )"; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); const auto& cs = schedule.getWell( "W1", 1 ).getConnections(); BOOST_CHECK_EQUAL( 3U, cs.size() ); BOOST_CHECK_EQUAL( 1, cs.get( 0 ).complnum() ); BOOST_CHECK_EQUAL( 2, cs.get( 1 ).complnum() ); BOOST_CHECK_EQUAL( 3, cs.get( 2 ).complnum() ); } BOOST_AUTO_TEST_CASE( complump_less_than_1 ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT 'W1' 0 0 1 2 'SHUT' 1* / / COMPLUMP 'W1' 0 0 0 0 0 / / )"; auto deck = Parser().parseString( input); auto python = std::make_shared(); EclipseGrid grid( 10, 10, 10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); BOOST_CHECK_THROW( Schedule( deck , grid, fp, runspec, python), std::exception ); } BOOST_AUTO_TEST_CASE( complump ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / 'W2' 'G2' 5 5 1 'OIL' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT 'W1' 0 0 1 2 'SHUT' 1* / 'W1' 0 0 2 3 'SHUT' 1* / 'W1' 0 0 4 6 'SHUT' 1* / 'W2' 0 0 3 4 'SHUT' 1* / 'W2' 0 0 1 4 'SHUT' 1* / / COMPLUMP -- name I J K1 K2 C -- where C is the completion number of this lump 'W1' 0 0 1 3 1 / / DATES -- 1 10 OKT 2008 / / WELOPEN 'W1' 'OPEN' 0 0 0 1 1 / / )"; constexpr auto open = Connection::State::OPEN; constexpr auto shut = Connection::State::SHUT; auto deck = Parser().parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); const auto& sc0 = schedule.getWell("W1", 0).getConnections(); /* complnum should be modified by COMPLNUM */ BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 0 ).complnum() ); BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 1 ).complnum() ); BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 2 ).complnum() ); BOOST_CHECK( shut == sc0.getFromIJK( 2, 2, 0 ).state() ); BOOST_CHECK( shut == sc0.getFromIJK( 2, 2, 1 ).state() ); BOOST_CHECK( shut == sc0.getFromIJK( 2, 2, 2 ).state() ); const auto& sc1 = schedule.getWell("W1", 1).getConnections(); BOOST_CHECK( open == sc1.getFromIJK( 2, 2, 0 ).state() ); BOOST_CHECK( open == sc1.getFromIJK( 2, 2, 1 ).state() ); BOOST_CHECK( open == sc1.getFromIJK( 2, 2, 2 ).state() ); BOOST_CHECK( shut == sc1.getFromIJK( 2, 2, 3 ).state() ); const auto& completions = schedule.getWell("W1", 1).getCompletions(); BOOST_CHECK_EQUAL(completions.size(), 4U); const auto& c1 = completions.at(1); BOOST_CHECK_EQUAL(c1.size(), 3U); for (const auto& pair : completions) { if (pair.first == 1) BOOST_CHECK(pair.second.size() > 1); else BOOST_CHECK_EQUAL(pair.second.size(), 1U); } } BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) { std::string input = R"( START -- 0 19 JUN 2007 / GRID PERMX 1000*0.10/ COPY PERMX PERMY / PERMX PERMZ / / SCHEDULE WELSPECS 'W1' 'G1' 3 3 2873.94 'WATER' 0.00 'STD' 'SHUT' 'NO' 0 'SEG' / / COMPDAT -- completion number 'W1' 1 1 1 1 'SHUT' 1* / -- 1 'W1' 1 1 2 2 'SHUT' 1* / -- 2 'W1' 0 0 1 2 'SHUT' 1* / -- 3, 4 'W1' 0 0 2 3 'SHUT' 1* / -- 5 'W1' 2 2 1 1 'SHUT' 1* / -- 6 'W1' 2 2 4 6 'SHUT' 1* / -- 7, 8, 9 / DATES -- 1 10 OKT 2008 / / DATES -- 2 15 OKT 2008 / / COMPLUMP -- name I J K1 K2 C -- where C is the completion number of this lump 'W1' 0 0 2 3 2 / -- all with k = [2 <= k <= 3] -> {2, 4, 5} 'W1' 2 2 1 5 7 / -- fix'd i,j, k = [1 <= k <= 5] -> {6, 7, 8} / WELOPEN 'W1' OPEN 0 0 0 2 2 / -- open the new 2 {2, 4, 5} 'W1' OPEN 0 0 0 5 7 / -- open 5..7 {5, 6, 7, 8} / )"; constexpr auto open = Connection::State::OPEN; constexpr auto shut = Connection::State::SHUT; auto deck = Parser().parseString( input); auto python = std::make_shared(); EclipseGrid grid( 10, 10, 10 ); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); const auto& cs1 = schedule.getWell("W1", 1).getConnections(); const auto& cs2 = schedule.getWell("W1", 2).getConnections(); BOOST_CHECK_EQUAL( 9U, cs1.size() ); BOOST_CHECK( shut == cs1.getFromIJK( 0, 0, 1 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 2, 2, 0 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 2, 2, 1 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 2, 2, 2 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 1, 1, 0 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 1, 1, 3 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 1, 1, 4 ).state() ); BOOST_CHECK( shut == cs1.getFromIJK( 1, 1, 5 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 0, 0, 1 ).state() ); BOOST_CHECK( shut == cs2.getFromIJK( 2, 2, 0 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 2, 2, 1 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 2, 2, 2 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 1, 1, 0 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 1, 1, 3 ).state() ); BOOST_CHECK( open == cs2.getFromIJK( 1, 1, 4 ).state() ); BOOST_CHECK( shut == cs2.getFromIJK( 1, 1, 5 ).state() ); } BOOST_AUTO_TEST_CASE(TestCompletionStateEnum2String) { BOOST_CHECK( "AUTO" == Connection::State2String(Connection::State::AUTO)); BOOST_CHECK( "OPEN" == Connection::State2String(Connection::State::OPEN)); BOOST_CHECK( "SHUT" == Connection::State2String(Connection::State::SHUT)); } BOOST_AUTO_TEST_CASE(TestCompletionStateEnumFromString) { BOOST_CHECK_THROW( Connection::StateFromString("XXX") , std::invalid_argument ); BOOST_CHECK( Connection::State::AUTO == Connection::StateFromString("AUTO")); BOOST_CHECK( Connection::State::SHUT == Connection::StateFromString("SHUT")); BOOST_CHECK( Connection::State::SHUT == Connection::StateFromString("STOP")); BOOST_CHECK( Connection::State::OPEN == Connection::StateFromString("OPEN")); } BOOST_AUTO_TEST_CASE(TestCompletionStateEnumLoop) { BOOST_CHECK( Connection::State::AUTO == Connection::StateFromString( Connection::State2String( Connection::State::AUTO ) )); BOOST_CHECK( Connection::State::SHUT == Connection::StateFromString( Connection::State2String( Connection::State::SHUT ) )); BOOST_CHECK( Connection::State::OPEN == Connection::StateFromString( Connection::State2String( Connection::State::OPEN ) )); BOOST_CHECK( "AUTO" == Connection::State2String(Connection::StateFromString( "AUTO" ) )); BOOST_CHECK( "OPEN" == Connection::State2String(Connection::StateFromString( "OPEN" ) )); BOOST_CHECK( "SHUT" == Connection::State2String(Connection::StateFromString( "SHUT" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(TestCompletionDirectionEnum2String) { BOOST_CHECK("X" == Connection::Direction2String(Connection::Direction::X)); BOOST_CHECK("Y" == Connection::Direction2String(Connection::Direction::Y)); BOOST_CHECK("Z" == Connection::Direction2String(Connection::Direction::Z)); } BOOST_AUTO_TEST_CASE(TestCompletionDirectionEnumFromString) { BOOST_CHECK_THROW(Connection::DirectionFromString("XXX"), std::invalid_argument); BOOST_CHECK(Connection::Direction::X == Connection::DirectionFromString("X")); BOOST_CHECK(Connection::Direction::Y == Connection::DirectionFromString("Y")); BOOST_CHECK(Connection::Direction::Z == Connection::DirectionFromString("Z")); } BOOST_AUTO_TEST_CASE(TestCompletionConnectionDirectionLoop) { BOOST_CHECK(Connection::Direction::X == Connection::DirectionFromString(Connection::Direction2String(Connection::Direction::X))); BOOST_CHECK(Connection::Direction::Y == Connection::DirectionFromString(Connection::Direction2String(Connection::Direction::Y))); BOOST_CHECK(Connection::Direction::Z == Connection::DirectionFromString(Connection::Direction2String(Connection::Direction::Z))); BOOST_CHECK("X" == Connection::Direction2String(Connection::DirectionFromString("X"))); BOOST_CHECK("Y" == Connection::Direction2String(Connection::DirectionFromString("Y"))); BOOST_CHECK("Z" == Connection::Direction2String(Connection::DirectionFromString("Z"))); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(TestGroupInjectionControlEnum2String) { BOOST_CHECK_EQUAL( "NONE" , Group::InjectionCMode2String(Group::InjectionCMode::NONE)); BOOST_CHECK_EQUAL( "RATE" , Group::InjectionCMode2String(Group::InjectionCMode::RATE)); BOOST_CHECK_EQUAL( "RESV" , Group::InjectionCMode2String(Group::InjectionCMode::RESV)); BOOST_CHECK_EQUAL( "REIN" , Group::InjectionCMode2String(Group::InjectionCMode::REIN)); BOOST_CHECK_EQUAL( "VREP" , Group::InjectionCMode2String(Group::InjectionCMode::VREP)); BOOST_CHECK_EQUAL( "FLD" , Group::InjectionCMode2String(Group::InjectionCMode::FLD)); } BOOST_AUTO_TEST_CASE(TestGroupInjectionControlEnumFromString) { BOOST_CHECK_THROW( Group::InjectionCModeFromString("XXX") , std::invalid_argument ); BOOST_CHECK( Group::InjectionCMode::NONE == Group::InjectionCModeFromString("NONE")); BOOST_CHECK( Group::InjectionCMode::RATE == Group::InjectionCModeFromString("RATE")); BOOST_CHECK( Group::InjectionCMode::RESV == Group::InjectionCModeFromString("RESV")); BOOST_CHECK( Group::InjectionCMode::REIN == Group::InjectionCModeFromString("REIN")); BOOST_CHECK( Group::InjectionCMode::VREP == Group::InjectionCModeFromString("VREP")); BOOST_CHECK( Group::InjectionCMode::FLD == Group::InjectionCModeFromString("FLD")); } BOOST_AUTO_TEST_CASE(TestGroupInjectionControlEnumLoop) { BOOST_CHECK( Group::InjectionCMode::NONE == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::NONE ) )); BOOST_CHECK( Group::InjectionCMode::RATE == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::RATE ) )); BOOST_CHECK( Group::InjectionCMode::RESV == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::RESV ) )); BOOST_CHECK( Group::InjectionCMode::REIN == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::REIN ) )); BOOST_CHECK( Group::InjectionCMode::VREP == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::VREP ) )); BOOST_CHECK( Group::InjectionCMode::FLD == Group::InjectionCModeFromString( Group::InjectionCMode2String( Group::InjectionCMode::FLD ) )); BOOST_CHECK_EQUAL( "NONE" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "NONE" ) )); BOOST_CHECK_EQUAL( "RATE" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "RATE" ) )); BOOST_CHECK_EQUAL( "RESV" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "RESV" ) )); BOOST_CHECK_EQUAL( "REIN" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "REIN" ) )); BOOST_CHECK_EQUAL( "VREP" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "VREP" ) )); BOOST_CHECK_EQUAL( "FLD" , Group::InjectionCMode2String(Group::InjectionCModeFromString( "FLD" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(TestGroupProductionControlEnum2String) { BOOST_CHECK_EQUAL( "NONE" , Group::ProductionCMode2String(Group::ProductionCMode::NONE)); BOOST_CHECK_EQUAL( "ORAT" , Group::ProductionCMode2String(Group::ProductionCMode::ORAT)); BOOST_CHECK_EQUAL( "WRAT" , Group::ProductionCMode2String(Group::ProductionCMode::WRAT)); BOOST_CHECK_EQUAL( "GRAT" , Group::ProductionCMode2String(Group::ProductionCMode::GRAT)); BOOST_CHECK_EQUAL( "LRAT" , Group::ProductionCMode2String(Group::ProductionCMode::LRAT)); BOOST_CHECK_EQUAL( "CRAT" , Group::ProductionCMode2String(Group::ProductionCMode::CRAT)); BOOST_CHECK_EQUAL( "RESV" , Group::ProductionCMode2String(Group::ProductionCMode::RESV)); BOOST_CHECK_EQUAL( "PRBL" , Group::ProductionCMode2String(Group::ProductionCMode::PRBL)); } BOOST_AUTO_TEST_CASE(TestGroupProductionControlEnumFromString) { BOOST_CHECK_THROW(Group::ProductionCModeFromString("XXX") , std::invalid_argument ); BOOST_CHECK(Group::ProductionCMode::NONE == Group::ProductionCModeFromString("NONE")); BOOST_CHECK(Group::ProductionCMode::ORAT == Group::ProductionCModeFromString("ORAT")); BOOST_CHECK(Group::ProductionCMode::WRAT == Group::ProductionCModeFromString("WRAT")); BOOST_CHECK(Group::ProductionCMode::GRAT == Group::ProductionCModeFromString("GRAT")); BOOST_CHECK(Group::ProductionCMode::LRAT == Group::ProductionCModeFromString("LRAT")); BOOST_CHECK(Group::ProductionCMode::CRAT == Group::ProductionCModeFromString("CRAT")); BOOST_CHECK(Group::ProductionCMode::RESV == Group::ProductionCModeFromString("RESV")); BOOST_CHECK(Group::ProductionCMode::PRBL == Group::ProductionCModeFromString("PRBL")); } BOOST_AUTO_TEST_CASE(TestGroupProductionControlEnumLoop) { BOOST_CHECK( Group::ProductionCMode::NONE == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::NONE ) )); BOOST_CHECK( Group::ProductionCMode::ORAT == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::ORAT ) )); BOOST_CHECK( Group::ProductionCMode::WRAT == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::WRAT ) )); BOOST_CHECK( Group::ProductionCMode::GRAT == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::GRAT ) )); BOOST_CHECK( Group::ProductionCMode::LRAT == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::LRAT ) )); BOOST_CHECK( Group::ProductionCMode::CRAT == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::CRAT ) )); BOOST_CHECK( Group::ProductionCMode::RESV == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::RESV ) )); BOOST_CHECK( Group::ProductionCMode::PRBL == Group::ProductionCModeFromString( Group::ProductionCMode2String( Group::ProductionCMode::PRBL ) )); BOOST_CHECK_EQUAL( "NONE" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "NONE" ) )); BOOST_CHECK_EQUAL( "ORAT" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "ORAT" ) )); BOOST_CHECK_EQUAL( "WRAT" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "WRAT" ) )); BOOST_CHECK_EQUAL( "GRAT" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "GRAT" ) )); BOOST_CHECK_EQUAL( "LRAT" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "LRAT" ) )); BOOST_CHECK_EQUAL( "CRAT" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "CRAT" ) )); BOOST_CHECK_EQUAL( "RESV" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "RESV" ) )); BOOST_CHECK_EQUAL( "PRBL" , Group::ProductionCMode2String(Group::ProductionCModeFromString( "PRBL" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(TestGroupProductionExceedLimitControlEnum2String) { BOOST_CHECK_EQUAL( "NONE" , Group::ExceedAction2String(Group::ExceedAction::NONE)); BOOST_CHECK_EQUAL( "CON" , Group::ExceedAction2String(Group::ExceedAction::CON)); BOOST_CHECK_EQUAL( "+CON" , Group::ExceedAction2String(Group::ExceedAction::CON_PLUS)); BOOST_CHECK_EQUAL( "WELL" , Group::ExceedAction2String(Group::ExceedAction::WELL)); BOOST_CHECK_EQUAL( "PLUG" , Group::ExceedAction2String(Group::ExceedAction::PLUG)); BOOST_CHECK_EQUAL( "RATE" , Group::ExceedAction2String(Group::ExceedAction::RATE)); } BOOST_AUTO_TEST_CASE(TestGroupProductionExceedLimitActionEnumFromString) { BOOST_CHECK_THROW( Group::ExceedActionFromString("XXX") , std::invalid_argument ); BOOST_CHECK(Group::ExceedAction::NONE == Group::ExceedActionFromString("NONE")); BOOST_CHECK(Group::ExceedAction::CON == Group::ExceedActionFromString("CON" )); BOOST_CHECK(Group::ExceedAction::CON_PLUS == Group::ExceedActionFromString("+CON")); BOOST_CHECK(Group::ExceedAction::WELL == Group::ExceedActionFromString("WELL")); BOOST_CHECK(Group::ExceedAction::PLUG == Group::ExceedActionFromString("PLUG")); BOOST_CHECK(Group::ExceedAction::RATE == Group::ExceedActionFromString("RATE")); } BOOST_AUTO_TEST_CASE(TestGroupProductionExceedLimitActionEnumLoop) { BOOST_CHECK( Group::ExceedAction::NONE == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::NONE ) )); BOOST_CHECK( Group::ExceedAction::CON == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::CON ) )); BOOST_CHECK( Group::ExceedAction::CON_PLUS == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::CON_PLUS ) )); BOOST_CHECK( Group::ExceedAction::WELL == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::WELL ) )); BOOST_CHECK( Group::ExceedAction::PLUG == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::PLUG ) )); BOOST_CHECK( Group::ExceedAction::RATE == Group::ExceedActionFromString( Group::ExceedAction2String( Group::ExceedAction::RATE ) )); BOOST_CHECK_EQUAL("NONE" , Group::ExceedAction2String(Group::ExceedActionFromString( "NONE" ) )); BOOST_CHECK_EQUAL("CON" , Group::ExceedAction2String(Group::ExceedActionFromString( "CON" ) )); BOOST_CHECK_EQUAL("+CON" , Group::ExceedAction2String(Group::ExceedActionFromString( "+CON" ) )); BOOST_CHECK_EQUAL("WELL" , Group::ExceedAction2String(Group::ExceedActionFromString( "WELL" ) )); BOOST_CHECK_EQUAL("PLUG" , Group::ExceedAction2String(Group::ExceedActionFromString( "PLUG" ) )); BOOST_CHECK_EQUAL("RATE" , Group::ExceedAction2String(Group::ExceedActionFromString( "RATE" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(TestInjectorEnum2String) { BOOST_CHECK_EQUAL( "OIL" , InjectorType2String(InjectorType::OIL)); BOOST_CHECK_EQUAL( "GAS" , InjectorType2String(InjectorType::GAS)); BOOST_CHECK_EQUAL( "WATER" , InjectorType2String(InjectorType::WATER)); BOOST_CHECK_EQUAL( "MULTI" , InjectorType2String(InjectorType::MULTI)); } BOOST_AUTO_TEST_CASE(TestInjectorEnumFromString) { BOOST_CHECK_THROW( InjectorTypeFromString("XXX") , std::invalid_argument ); BOOST_CHECK( InjectorType::OIL == InjectorTypeFromString("OIL")); BOOST_CHECK( InjectorType::WATER == InjectorTypeFromString("WATER")); BOOST_CHECK( InjectorType::WATER == InjectorTypeFromString("WAT")); BOOST_CHECK( InjectorType::GAS == InjectorTypeFromString("GAS")); BOOST_CHECK( InjectorType::MULTI == InjectorTypeFromString("MULTI")); } BOOST_AUTO_TEST_CASE(TestInjectorEnumLoop) { BOOST_CHECK( InjectorType::OIL == InjectorTypeFromString( InjectorType2String( InjectorType::OIL ) )); BOOST_CHECK( InjectorType::WATER == InjectorTypeFromString( InjectorType2String( InjectorType::WATER ) )); BOOST_CHECK( InjectorType::GAS == InjectorTypeFromString( InjectorType2String( InjectorType::GAS ) )); BOOST_CHECK( InjectorType::MULTI == InjectorTypeFromString( InjectorType2String( InjectorType::MULTI ) )); BOOST_CHECK_EQUAL( "MULTI" , InjectorType2String(InjectorTypeFromString( "MULTI" ) )); BOOST_CHECK_EQUAL( "OIL" , InjectorType2String(InjectorTypeFromString( "OIL" ) )); BOOST_CHECK_EQUAL( "GAS" , InjectorType2String(InjectorTypeFromString( "GAS" ) )); BOOST_CHECK_EQUAL( "WATER" , InjectorType2String(InjectorTypeFromString( "WATER" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(InjectorCOntrolMopdeEnum2String) { BOOST_CHECK_EQUAL( "RATE" , Well::InjectorCMode2String(Well::InjectorCMode::RATE)); BOOST_CHECK_EQUAL( "RESV" , Well::InjectorCMode2String(Well::InjectorCMode::RESV)); BOOST_CHECK_EQUAL( "BHP" , Well::InjectorCMode2String(Well::InjectorCMode::BHP)); BOOST_CHECK_EQUAL( "THP" , Well::InjectorCMode2String(Well::InjectorCMode::THP)); BOOST_CHECK_EQUAL( "GRUP" , Well::InjectorCMode2String(Well::InjectorCMode::GRUP)); } BOOST_AUTO_TEST_CASE(InjectorControlModeEnumFromString) { BOOST_CHECK_THROW( Well::InjectorCModeFromString("XXX") , std::invalid_argument ); BOOST_CHECK( Well::InjectorCMode::RATE == Well::InjectorCModeFromString("RATE")); BOOST_CHECK( Well::InjectorCMode::BHP == Well::InjectorCModeFromString("BHP")); BOOST_CHECK( Well::InjectorCMode::RESV == Well::InjectorCModeFromString("RESV")); BOOST_CHECK( Well::InjectorCMode::THP == Well::InjectorCModeFromString("THP")); BOOST_CHECK( Well::InjectorCMode::GRUP == Well::InjectorCModeFromString("GRUP")); } BOOST_AUTO_TEST_CASE(InjectorControlModeEnumLoop) { BOOST_CHECK( Well::InjectorCMode::RATE == Well::InjectorCModeFromString( Well::InjectorCMode2String( Well::InjectorCMode::RATE ) )); BOOST_CHECK( Well::InjectorCMode::BHP == Well::InjectorCModeFromString( Well::InjectorCMode2String( Well::InjectorCMode::BHP ) )); BOOST_CHECK( Well::InjectorCMode::RESV == Well::InjectorCModeFromString( Well::InjectorCMode2String( Well::InjectorCMode::RESV ) )); BOOST_CHECK( Well::InjectorCMode::THP == Well::InjectorCModeFromString( Well::InjectorCMode2String( Well::InjectorCMode::THP ) )); BOOST_CHECK( Well::InjectorCMode::GRUP == Well::InjectorCModeFromString( Well::InjectorCMode2String( Well::InjectorCMode::GRUP ) )); BOOST_CHECK_EQUAL( "THP" , Well::InjectorCMode2String(Well::InjectorCModeFromString( "THP" ) )); BOOST_CHECK_EQUAL( "RATE" , Well::InjectorCMode2String(Well::InjectorCModeFromString( "RATE" ) )); BOOST_CHECK_EQUAL( "RESV" , Well::InjectorCMode2String(Well::InjectorCModeFromString( "RESV" ) )); BOOST_CHECK_EQUAL( "BHP" , Well::InjectorCMode2String(Well::InjectorCModeFromString( "BHP" ) )); BOOST_CHECK_EQUAL( "GRUP" , Well::InjectorCMode2String(Well::InjectorCModeFromString( "GRUP" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(InjectorStatusEnum2String) { BOOST_CHECK_EQUAL( "OPEN", Well::Status2String(Well::Status::OPEN)); BOOST_CHECK_EQUAL( "SHUT", Well::Status2String(Well::Status::SHUT)); BOOST_CHECK_EQUAL( "AUTO", Well::Status2String(Well::Status::AUTO)); BOOST_CHECK_EQUAL( "STOP", Well::Status2String(Well::Status::STOP)); } BOOST_AUTO_TEST_CASE(InjectorStatusEnumFromString) { BOOST_CHECK_THROW( Well::StatusFromString("XXX") , std::invalid_argument ); BOOST_CHECK( Well::Status::OPEN == Well::StatusFromString("OPEN")); BOOST_CHECK( Well::Status::AUTO == Well::StatusFromString("AUTO")); BOOST_CHECK( Well::Status::SHUT == Well::StatusFromString("SHUT")); BOOST_CHECK( Well::Status::STOP == Well::StatusFromString("STOP")); } BOOST_AUTO_TEST_CASE(InjectorStatusEnumLoop) { BOOST_CHECK( Well::Status::OPEN == Well::StatusFromString( Well::Status2String( Well::Status::OPEN ) )); BOOST_CHECK( Well::Status::AUTO == Well::StatusFromString( Well::Status2String( Well::Status::AUTO ) )); BOOST_CHECK( Well::Status::SHUT == Well::StatusFromString( Well::Status2String( Well::Status::SHUT ) )); BOOST_CHECK( Well::Status::STOP == Well::StatusFromString( Well::Status2String( Well::Status::STOP ) )); BOOST_CHECK_EQUAL( "STOP", Well::Status2String(Well::StatusFromString( "STOP" ) )); BOOST_CHECK_EQUAL( "OPEN", Well::Status2String(Well::StatusFromString( "OPEN" ) )); BOOST_CHECK_EQUAL( "SHUT", Well::Status2String(Well::StatusFromString( "SHUT" ) )); BOOST_CHECK_EQUAL( "AUTO", Well::Status2String(Well::StatusFromString( "AUTO" ) )); } /*****************************************************************/ BOOST_AUTO_TEST_CASE(ProducerCOntrolMopdeEnum2String) { BOOST_CHECK_EQUAL( "ORAT" , Well::ProducerCMode2String(Well::ProducerCMode::ORAT)); BOOST_CHECK_EQUAL( "WRAT" , Well::ProducerCMode2String(Well::ProducerCMode::WRAT)); BOOST_CHECK_EQUAL( "GRAT" , Well::ProducerCMode2String(Well::ProducerCMode::GRAT)); BOOST_CHECK_EQUAL( "LRAT" , Well::ProducerCMode2String(Well::ProducerCMode::LRAT)); BOOST_CHECK_EQUAL( "CRAT" , Well::ProducerCMode2String(Well::ProducerCMode::CRAT)); BOOST_CHECK_EQUAL( "RESV" , Well::ProducerCMode2String(Well::ProducerCMode::RESV)); BOOST_CHECK_EQUAL( "BHP" , Well::ProducerCMode2String(Well::ProducerCMode::BHP)); BOOST_CHECK_EQUAL( "THP" , Well::ProducerCMode2String(Well::ProducerCMode::THP)); BOOST_CHECK_EQUAL( "GRUP" , Well::ProducerCMode2String(Well::ProducerCMode::GRUP)); } BOOST_AUTO_TEST_CASE(ProducerControlModeEnumFromString) { BOOST_CHECK_THROW( Well::ProducerCModeFromString("XRAT") , std::invalid_argument ); BOOST_CHECK( Well::ProducerCMode::ORAT == Well::ProducerCModeFromString("ORAT")); BOOST_CHECK( Well::ProducerCMode::WRAT == Well::ProducerCModeFromString("WRAT")); BOOST_CHECK( Well::ProducerCMode::GRAT == Well::ProducerCModeFromString("GRAT")); BOOST_CHECK( Well::ProducerCMode::LRAT == Well::ProducerCModeFromString("LRAT")); BOOST_CHECK( Well::ProducerCMode::CRAT == Well::ProducerCModeFromString("CRAT")); BOOST_CHECK( Well::ProducerCMode::RESV == Well::ProducerCModeFromString("RESV")); BOOST_CHECK( Well::ProducerCMode::BHP == Well::ProducerCModeFromString("BHP" )); BOOST_CHECK( Well::ProducerCMode::THP == Well::ProducerCModeFromString("THP" )); BOOST_CHECK( Well::ProducerCMode::GRUP == Well::ProducerCModeFromString("GRUP")); } BOOST_AUTO_TEST_CASE(ProducerControlModeEnumLoop) { BOOST_CHECK( Well::ProducerCMode::ORAT == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::ORAT ) )); BOOST_CHECK( Well::ProducerCMode::WRAT == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::WRAT ) )); BOOST_CHECK( Well::ProducerCMode::GRAT == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::GRAT ) )); BOOST_CHECK( Well::ProducerCMode::LRAT == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::LRAT ) )); BOOST_CHECK( Well::ProducerCMode::CRAT == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::CRAT ) )); BOOST_CHECK( Well::ProducerCMode::RESV == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::RESV ) )); BOOST_CHECK( Well::ProducerCMode::BHP == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::BHP ) )); BOOST_CHECK( Well::ProducerCMode::THP == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::THP ) )); BOOST_CHECK( Well::ProducerCMode::GRUP == Well::ProducerCModeFromString( Well::ProducerCMode2String( Well::ProducerCMode::GRUP ) )); BOOST_CHECK_EQUAL( "ORAT" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "ORAT" ) )); BOOST_CHECK_EQUAL( "WRAT" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "WRAT" ) )); BOOST_CHECK_EQUAL( "GRAT" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "GRAT" ) )); BOOST_CHECK_EQUAL( "LRAT" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "LRAT" ) )); BOOST_CHECK_EQUAL( "CRAT" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "CRAT" ) )); BOOST_CHECK_EQUAL( "RESV" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "RESV" ) )); BOOST_CHECK_EQUAL( "BHP" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "BHP" ) )); BOOST_CHECK_EQUAL( "THP" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "THP" ) )); BOOST_CHECK_EQUAL( "GRUP" , Well::ProducerCMode2String(Well::ProducerCModeFromString( "GRUP" ) )); } /*******************************************************************/ /*****************************************************************/ BOOST_AUTO_TEST_CASE(GuideRatePhaseEnum2String) { BOOST_CHECK_EQUAL( "OIL" , Well::GuideRateTarget2String(Well::GuideRateTarget::OIL)); BOOST_CHECK_EQUAL( "WAT" , Well::GuideRateTarget2String(Well::GuideRateTarget::WAT)); BOOST_CHECK_EQUAL( "GAS" , Well::GuideRateTarget2String(Well::GuideRateTarget::GAS)); BOOST_CHECK_EQUAL( "LIQ" , Well::GuideRateTarget2String(Well::GuideRateTarget::LIQ)); BOOST_CHECK_EQUAL( "COMB" , Well::GuideRateTarget2String(Well::GuideRateTarget::COMB)); BOOST_CHECK_EQUAL( "WGA" , Well::GuideRateTarget2String(Well::GuideRateTarget::WGA)); BOOST_CHECK_EQUAL( "CVAL" , Well::GuideRateTarget2String(Well::GuideRateTarget::CVAL)); BOOST_CHECK_EQUAL( "RAT" , Well::GuideRateTarget2String(Well::GuideRateTarget::RAT)); BOOST_CHECK_EQUAL( "RES" , Well::GuideRateTarget2String(Well::GuideRateTarget::RES)); BOOST_CHECK_EQUAL( "UNDEFINED" , Well::GuideRateTarget2String(Well::GuideRateTarget::UNDEFINED)); } BOOST_AUTO_TEST_CASE(GuideRatePhaseEnumFromString) { BOOST_CHECK_THROW( Well::GuideRateTargetFromString("XRAT") , std::invalid_argument ); BOOST_CHECK( Well::GuideRateTarget::OIL == Well::GuideRateTargetFromString("OIL")); BOOST_CHECK( Well::GuideRateTarget::WAT == Well::GuideRateTargetFromString("WAT")); BOOST_CHECK( Well::GuideRateTarget::GAS == Well::GuideRateTargetFromString("GAS")); BOOST_CHECK( Well::GuideRateTarget::LIQ == Well::GuideRateTargetFromString("LIQ")); BOOST_CHECK( Well::GuideRateTarget::COMB == Well::GuideRateTargetFromString("COMB")); BOOST_CHECK( Well::GuideRateTarget::WGA == Well::GuideRateTargetFromString("WGA")); BOOST_CHECK( Well::GuideRateTarget::CVAL == Well::GuideRateTargetFromString("CVAL")); BOOST_CHECK( Well::GuideRateTarget::RAT == Well::GuideRateTargetFromString("RAT")); BOOST_CHECK( Well::GuideRateTarget::RES == Well::GuideRateTargetFromString("RES")); BOOST_CHECK( Well::GuideRateTarget::UNDEFINED == Well::GuideRateTargetFromString("UNDEFINED")); } BOOST_AUTO_TEST_CASE(GuideRatePhaseEnum2Loop) { BOOST_CHECK( Well::GuideRateTarget::OIL == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::OIL ) )); BOOST_CHECK( Well::GuideRateTarget::WAT == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::WAT ) )); BOOST_CHECK( Well::GuideRateTarget::GAS == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::GAS ) )); BOOST_CHECK( Well::GuideRateTarget::LIQ == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::LIQ ) )); BOOST_CHECK( Well::GuideRateTarget::COMB == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::COMB ) )); BOOST_CHECK( Well::GuideRateTarget::WGA == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::WGA ) )); BOOST_CHECK( Well::GuideRateTarget::CVAL == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::CVAL ) )); BOOST_CHECK( Well::GuideRateTarget::RAT == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::RAT ) )); BOOST_CHECK( Well::GuideRateTarget::RES == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::RES ) )); BOOST_CHECK( Well::GuideRateTarget::UNDEFINED == Well::GuideRateTargetFromString( Well::GuideRateTarget2String( Well::GuideRateTarget::UNDEFINED ) )); BOOST_CHECK_EQUAL( "OIL" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "OIL" ) )); BOOST_CHECK_EQUAL( "WAT" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "WAT" ) )); BOOST_CHECK_EQUAL( "GAS" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "GAS" ) )); BOOST_CHECK_EQUAL( "LIQ" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "LIQ" ) )); BOOST_CHECK_EQUAL( "COMB" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "COMB" ) )); BOOST_CHECK_EQUAL( "WGA" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "WGA" ) )); BOOST_CHECK_EQUAL( "CVAL" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "CVAL" ) )); BOOST_CHECK_EQUAL( "RAT" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "RAT" ) )); BOOST_CHECK_EQUAL( "RES" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "RES" ) )); BOOST_CHECK_EQUAL( "UNDEFINED" , Well::GuideRateTarget2String(Well::GuideRateTargetFromString( "UNDEFINED" ) )); } BOOST_AUTO_TEST_CASE(handleWEFAC) { Opm::Parser parser; std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* / \n" " 'I' 'OP' 1 1 1* 'WATER' 1* 1* 1* 1* 1* 1* 1* / \n" "/\n" "COMPDAT\n" " 'P' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" " 'P' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 / \n" " 'I' 1 1 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 / \n" "/\n" "WCONHIST\n" " 'P' 'OPEN' 'RESV' 6* 500 / \n" "/\n" "WCONINJH\n" " 'I' 'WATER' 1* 100 250 / \n" "/\n" "WEFAC\n" " 'P' 0.5 / \n" " 'I' 0.9 / \n" "/\n" "DATES -- 2\n" " 15 OKT 2008 / \n" "/\n" "DATES -- 3\n" " 18 OKT 2008 / \n" "/\n" "WEFAC\n" " 'P' 1.0 / \n" "/\n" ; auto deck = parser.parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule(deck, grid , fp, runspec, python); //1 BOOST_CHECK_EQUAL(schedule.getWell("P", 1).getEfficiencyFactor(), 0.5); BOOST_CHECK_EQUAL(schedule.getWell("I", 1).getEfficiencyFactor(), 0.9); //2 BOOST_CHECK_EQUAL(schedule.getWell("P", 2).getEfficiencyFactor(), 0.5); BOOST_CHECK_EQUAL(schedule.getWell("I", 2).getEfficiencyFactor(), 0.9); //3 BOOST_CHECK_EQUAL(schedule.getWell("P", 3).getEfficiencyFactor(), 1.0); BOOST_CHECK_EQUAL(schedule.getWell("I", 3).getEfficiencyFactor(), 0.9); } BOOST_AUTO_TEST_CASE(historic_BHP_and_THP) { Opm::Parser parser; std::string input = "START -- 0 \n" "19 JUN 2007 / \n" "SCHEDULE\n" "DATES -- 1\n" " 10 OKT 2008 / \n" "/\n" "WELSPECS\n" " 'P' 'OP' 9 9 1 'OIL' 1* / \n" " 'P1' 'OP' 9 9 1 'OIL' 1* / \n" " 'I' 'OP' 9 9 1 'WATER' 1* / \n" "/\n" "WCONHIST\n" " P SHUT ORAT 6 500 0 0 0 1.2 1.1 / \n" "/\n" "WCONPROD\n" " P1 SHUT ORAT 6 500 0 0 0 3.2 3.1 / \n" "/\n" "WCONINJH\n" " I WATER STOP 100 2.1 2.2 / \n" "/\n" ; auto deck = parser.parseString(input); auto python = std::make_shared(); EclipseGrid grid(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid, table); Runspec runspec (deck); Schedule schedule( deck, grid, fp, runspec, python); { const auto& prod = schedule.getWell("P", 1).getProductionProperties(); const auto& pro1 = schedule.getWell("P1", 1).getProductionProperties(); const auto& inje = schedule.getWell("I", 1).getInjectionProperties(); BOOST_CHECK_CLOSE( 1.1 * 1e5, prod.BHPH, 1e-5 ); BOOST_CHECK_CLOSE( 1.2 * 1e5, prod.THPH, 1e-5 ); BOOST_CHECK_CLOSE( 2.1 * 1e5, inje.BHPH, 1e-5 ); BOOST_CHECK_CLOSE( 2.2 * 1e5, inje.THPH, 1e-5 ); BOOST_CHECK_CLOSE( 0.0 * 1e5, pro1.BHPH, 1e-5 ); BOOST_CHECK_CLOSE( 0.0 * 1e5, pro1.THPH, 1e-5 ); { const auto& wtest_config = schedule.wtestConfig(0); BOOST_CHECK_EQUAL(wtest_config.size(), 0U); } { const auto& wtest_config = schedule.wtestConfig(1); BOOST_CHECK_EQUAL(wtest_config.size(), 0U); } } } BOOST_AUTO_TEST_CASE(FilterCompletions2) { const auto& deck = Parser{}.parseString(createDeckWithWellsAndCompletionData()); auto python = std::make_shared(); EclipseGrid grid1(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid1, table); Runspec runspec (deck); Schedule schedule(deck, grid1, fp, runspec, python); std::vector actnum = grid1.getACTNUM(); { const auto& c1_1 = schedule.getWell("OP_1", 1).getConnections(); const auto& c1_3 = schedule.getWell("OP_1", 3).getConnections(); BOOST_CHECK_EQUAL(2U, c1_1.size()); BOOST_CHECK_EQUAL(9U, c1_3.size()); } actnum[grid1.getGlobalIndex(8,8,1)] = 0; { std::vector globalCell(grid1.getNumActive()); for(std::size_t i = 0; i < grid1.getNumActive(); ++i) if (actnum[grid1.getGlobalIndex(i)]) globalCell[i] = grid1.getGlobalIndex(i); ActiveGridCells active(grid1.getNXYZ(), globalCell.data(), grid1.getNumActive()); schedule.filterConnections(active); const auto& c1_1 = schedule.getWell("OP_1", 1).getConnections(); const auto& c1_3 = schedule.getWell("OP_1", 3).getConnections(); BOOST_CHECK_EQUAL(1U, c1_1.size()); BOOST_CHECK_EQUAL(8U, c1_3.size()); } } BOOST_AUTO_TEST_CASE(VFPINJ_TEST) { const char *input = "\ START\n \ 8 MAR 1998 /\n \ \n \ GRID \n\ PORO\n\ 1000*0.25 /\n\ PERMX \n\ 1000*0.10/ \n\ COPY \n\ PERMX PERMY / \n\ PERMX PERMZ / \n\ / \n \ SCHEDULE \n\ VFPINJ \n \ -- Table Depth Rate TAB UNITS BODY \n\ -- ----- ----- ----- ----- ------ ----- \n\ 5 32.9 WAT THP METRIC BHP / \n\ -- Rate axis \n\ 1 3 5 / \n\ -- THP axis \n\ 7 11 / \n\ -- Table data with THP# \n\ 1 1.5 2.5 3.5 / \n\ 2 4.5 5.5 6.5 / \n\ TSTEP \n\ 10 10/\n\ VFPINJ \n \ -- Table Depth Rate TAB UNITS BODY \n\ -- ----- ----- ----- ----- ------ ----- \n\ 5 100 GAS THP METRIC BHP / \n\ -- Rate axis \n\ 1 3 5 / \n\ -- THP axis \n\ 7 11 / \n\ -- Table data with THP# \n\ 1 1.5 2.5 3.5 / \n\ 2 4.5 5.5 6.5 / \n\ --\n\ VFPINJ \n \ -- Table Depth Rate TAB UNITS BODY \n\ -- ----- ----- ----- ----- ------ ----- \n\ 10 200 WAT THP METRIC BHP / \n\ -- Rate axis \n\ 1 3 5 / \n\ -- THP axis \n\ 7 11 / \n\ -- Table data with THP# \n\ 1 1.5 2.5 3.5 / \n\ 2 4.5 5.5 6.5 / \n"; const auto& schedule = make_schedule(input); BOOST_CHECK( schedule.getEvents().hasEvent(ScheduleEvents::VFPINJ_UPDATE, 0)); BOOST_CHECK( !schedule.getEvents().hasEvent(ScheduleEvents::VFPINJ_UPDATE, 1)); BOOST_CHECK( schedule.getEvents().hasEvent(ScheduleEvents::VFPINJ_UPDATE, 2)); // No such table id BOOST_CHECK_THROW(schedule.getVFPInjTable(77,0), std::invalid_argument); // Table not defined at step 0 BOOST_CHECK_THROW(schedule.getVFPInjTable(10,0), std::invalid_argument); const Opm::VFPInjTable& vfpinjTable2 = schedule.getVFPInjTable(5, 2); BOOST_CHECK_EQUAL(vfpinjTable2.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable2.getDatumDepth(), 100); BOOST_CHECK_EQUAL(vfpinjTable2.getFloType(), Opm::VFPInjTable::FLO_GAS); const Opm::VFPInjTable& vfpinjTable3 = schedule.getVFPInjTable(10, 2); BOOST_CHECK_EQUAL(vfpinjTable3.getTableNum(), 10); BOOST_CHECK_EQUAL(vfpinjTable3.getDatumDepth(), 200); BOOST_CHECK_EQUAL(vfpinjTable3.getFloType(), Opm::VFPInjTable::FLO_WAT); const Opm::VFPInjTable& vfpinjTable = schedule.getVFPInjTable(5, 0); BOOST_CHECK_EQUAL(vfpinjTable.getTableNum(), 5); BOOST_CHECK_EQUAL(vfpinjTable.getDatumDepth(), 32.9); BOOST_CHECK_EQUAL(vfpinjTable.getFloType(), Opm::VFPInjTable::FLO_WAT); const auto vfp_tables0 = schedule.getVFPInjTables(0); BOOST_CHECK_EQUAL( vfp_tables0.size(), 1U); const auto vfp_tables2 = schedule.getVFPInjTables(2); BOOST_CHECK_EQUAL( vfp_tables2.size(), 2U); //Flo axis { const std::vector& flo = vfpinjTable.getFloAxis(); BOOST_REQUIRE_EQUAL(flo.size(), 3U); //Unit of FLO is SM3/day, convert to SM3/second double conversion_factor = 1.0 / (60*60*24); BOOST_CHECK_EQUAL(flo[0], 1*conversion_factor); BOOST_CHECK_EQUAL(flo[1], 3*conversion_factor); BOOST_CHECK_EQUAL(flo[2], 5*conversion_factor); } //THP axis { const std::vector& thp = vfpinjTable.getTHPAxis(); BOOST_REQUIRE_EQUAL(thp.size(), 2U); //Unit of THP is barsa => convert to pascal double conversion_factor = 100000.0; BOOST_CHECK_EQUAL(thp[0], 7*conversion_factor); BOOST_CHECK_EQUAL(thp[1], 11*conversion_factor); } //The data itself { typedef Opm::VFPInjTable::array_type::size_type size_type; const auto size = vfpinjTable.shape(); BOOST_CHECK_EQUAL(size[0], 2U); BOOST_CHECK_EQUAL(size[1], 3U); //Table given as BHP => barsa. Convert to pascal double conversion_factor = 100000.0; double index = 0.5; for (size_type t = 0; t < size[0]; ++t) { for (size_type f = 0; f < size[1]; ++f) { index += 1.0; BOOST_CHECK_EQUAL(vfpinjTable(t,f), index*conversion_factor); } } } } // tests for the polymer injectivity case BOOST_AUTO_TEST_CASE(POLYINJ_TEST) { const char *deckData = "START\n" " 8 MAR 2018/\n" "GRID\n" "PORO\n" " 1000*0.25 /\n" "PERMX\n" " 1000*0.25 /\n" "COPY\n" " PERMX PERMY /\n" " PERMX PERMZ /\n" "/\n" "PROPS\n \n" "SCHEDULE\n" "WELSPECS\n" "'INJE01' 'I' 1 1 1 'WATER' /\n" "/\n" "WCONINJE\n" "'INJE01' 'WATER' 'OPEN' 'RATE' 800.00 1* 1000 /\n" "/\n" "TSTEP\n" " 1/\n" "WPOLYMER\n" " 'INJE01' 1.0 0.0 /\n" "/\n" "WPMITAB\n" " 'INJE01' 2 /\n" "/\n" "WSKPTAB\n" " 'INJE01' 1 1 /\n" "/\n" "TSTEP\n" " 2*1/\n" "WPMITAB\n" " 'INJE01' 3 /\n" "/\n" "WSKPTAB\n" " 'INJE01' 2 2 /\n" "/\n" "TSTEP\n" " 1 /\n"; Opm::Parser parser; auto deck = parser.parseString(deckData); auto python = std::make_shared(); EclipseGrid grid1(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid1, table); Runspec runspec (deck); Schedule schedule(deck, grid1 , fp, runspec, python); const auto& poly0 = schedule.getWell("INJE01", 0).getPolymerProperties(); const auto& poly1 = schedule.getWell("INJE01", 1).getPolymerProperties(); const auto& poly3 = schedule.getWell("INJE01", 3).getPolymerProperties(); BOOST_CHECK_EQUAL(poly0.m_plymwinjtable, -1); BOOST_CHECK_EQUAL(poly0.m_skprwattable, -1); BOOST_CHECK_EQUAL(poly0.m_skprpolytable, -1); BOOST_CHECK_EQUAL(poly1.m_plymwinjtable, 2); BOOST_CHECK_EQUAL(poly1.m_skprwattable, 1); BOOST_CHECK_EQUAL(poly1.m_skprpolytable, 1); BOOST_CHECK_EQUAL(poly3.m_plymwinjtable, 3); BOOST_CHECK_EQUAL(poly3.m_skprwattable, 2); BOOST_CHECK_EQUAL(poly3.m_skprpolytable, 2); } // Test for WFOAM BOOST_AUTO_TEST_CASE(WFOAM_TEST) { const char *input = "START\n" " 8 MAR 2018/\n" "GRID\n" "PERMX\n" " 1000*0.25 /\n" "PORO\n" " 1000*0.25 /\n" "COPY\n" " PERMX PERMY /\n" " PERMX PERMZ /\n" "/\n" "PROPS\n \n" "SCHEDULE\n" "WELSPECS\n" "'INJE01' 'I' 1 1 1 'WATER' /\n" "/\n" "WCONINJE\n" "'INJE01' 'GAS' 'OPEN' 'RATE' 80000.00 1* 1000 /\n" "/\n" "TSTEP\n" " 1/\n" "WFOAM\n" " 'INJE01' 0.2 /\n" "/\n" "TSTEP\n" " 2*1/\n" "WFOAM\n" " 'INJE01' 0.3 /\n" "/\n" "TSTEP\n" " 1 /\n"; const auto& schedule = make_schedule(input); const auto& f0 = schedule.getWell("INJE01", 0).getFoamProperties(); const auto& f1 = schedule.getWell("INJE01", 1).getFoamProperties(); const auto& f3 = schedule.getWell("INJE01", 3).getFoamProperties(); BOOST_CHECK_EQUAL(f0.m_foamConcentration, 0.0); BOOST_CHECK_EQUAL(f1.m_foamConcentration, 0.2); BOOST_CHECK_EQUAL(f3.m_foamConcentration, 0.3); } BOOST_AUTO_TEST_CASE(WTEST_CONFIG) { const auto& schedule = make_schedule(createDeckWTEST()); const auto& wtest_config1 = schedule.wtestConfig(0); BOOST_CHECK_EQUAL(wtest_config1.size(), 2U); BOOST_CHECK(wtest_config1.has("ALLOW")); BOOST_CHECK(!wtest_config1.has("BAN")); const auto& wtest_config2 = schedule.wtestConfig(1); BOOST_CHECK_EQUAL(wtest_config2.size(), 3U); BOOST_CHECK(!wtest_config2.has("ALLOW")); BOOST_CHECK(wtest_config2.has("BAN")); BOOST_CHECK(wtest_config2.has("BAN", WellTestConfig::Reason::GROUP)); BOOST_CHECK(!wtest_config2.has("BAN", WellTestConfig::Reason::PHYSICAL)); } static 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(WELL_STATIC) { const auto& deck = Parser{}.parseString(createDeckWithWells()); auto python = std::make_shared(); EclipseGrid grid1(10,10,10); TableManager table ( deck ); FieldPropsManager fp( deck, Phases{true, true, true}, grid1, table); Runspec runspec (deck); Schedule schedule(deck, grid1, fp, runspec, python); BOOST_CHECK_THROW( schedule.getWell("NO_SUCH_WELL", 0), std::invalid_argument); BOOST_CHECK_THROW( schedule.getWell("W_3", 0), std::invalid_argument); auto ws = schedule.getWell("W_3", 3); { // Make sure the copy constructor works. Well ws_copy(ws); } BOOST_CHECK_EQUAL(ws.name(), "W_3"); BOOST_CHECK(!ws.updateHead(19, 50)); BOOST_CHECK(ws.updateHead(1,50)); BOOST_CHECK(!ws.updateHead(1,50)); BOOST_CHECK(ws.updateHead(1,1)); BOOST_CHECK(!ws.updateHead(1,1)); BOOST_CHECK(ws.updateRefDepth(1.0)); BOOST_CHECK(!ws.updateRefDepth(1.0)); ws.updateStatus(Well::Status::OPEN, false); BOOST_CHECK(!ws.updateStatus(Well::Status::OPEN, false)); BOOST_CHECK(ws.updateStatus(Well::Status::SHUT, false)); const auto& connections = ws.getConnections(); BOOST_CHECK_EQUAL(connections.size(), 0U); auto c2 = std::make_shared(Connection::Order::TRACK, 1,1); c2->addConnection(1,1,1, grid1.getGlobalIndex(1,1,1), 100, Connection::State::OPEN, 10, 10, 10, 10, 10, 100); BOOST_CHECK( ws.updateConnections(c2) ); BOOST_CHECK( !ws.updateConnections(c2) ); } BOOST_AUTO_TEST_CASE(WellNames) { const auto& schedule = make_schedule(createDeckWTEST()); auto names = schedule.wellNames("NO_SUCH_WELL", 0); BOOST_CHECK_EQUAL(names.size(), 0U); auto w1names = schedule.wellNames("W1", 0); BOOST_CHECK_EQUAL(w1names.size(), 1U); BOOST_CHECK_EQUAL(w1names[0], "W1"); auto i1names = schedule.wellNames("11", 0); BOOST_CHECK_EQUAL(i1names.size(), 0U); auto listnamese = schedule.wellNames("*NO_LIST", 0); BOOST_CHECK_EQUAL( listnamese.size(), 0U); auto listnames0 = schedule.wellNames("*ILIST", 0); BOOST_CHECK_EQUAL( listnames0.size(), 0U); auto listnames1 = schedule.wellNames("*ILIST", 2); BOOST_CHECK_EQUAL( listnames1.size(), 2U); BOOST_CHECK( has(listnames1, "I1")); BOOST_CHECK( has(listnames1, "I2")); auto pnames1 = schedule.wellNames("I*", 0); BOOST_CHECK_EQUAL(pnames1.size(), 0U); auto pnames2 = schedule.wellNames("W*", 0); BOOST_CHECK_EQUAL(pnames2.size(), 3U); 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(), 2U); BOOST_CHECK(has(anames, "W1")); BOOST_CHECK(has(anames, "W2")); auto all_names0 = schedule.wellNames("*", 0); BOOST_CHECK_EQUAL( all_names0.size(), 6U); BOOST_CHECK( has(all_names0, "W1")); BOOST_CHECK( has(all_names0, "W2")); BOOST_CHECK( has(all_names0, "W3")); BOOST_CHECK( has(all_names0, "DEFAULT")); BOOST_CHECK( has(all_names0, "ALLOW")); auto all_names = schedule.wellNames("*", 2); BOOST_CHECK_EQUAL( all_names.size(), 9U); BOOST_CHECK( has(all_names, "I1")); BOOST_CHECK( has(all_names, "I2")); BOOST_CHECK( has(all_names, "I3")); BOOST_CHECK( has(all_names, "W1")); BOOST_CHECK( has(all_names, "W2")); BOOST_CHECK( has(all_names, "W3")); BOOST_CHECK( has(all_names, "DEFAULT")); BOOST_CHECK( has(all_names, "ALLOW")); BOOST_CHECK( has(all_names, "BAN")); auto abs_all = schedule.wellNames(); BOOST_CHECK_EQUAL(abs_all.size(), 9U); } BOOST_AUTO_TEST_CASE(RFT_CONFIG) { std::vector tp = { asTimeT( TimeStampUTC(2010, 1, 1)), asTimeT( TimeStampUTC(2010, 1, 2)), asTimeT( TimeStampUTC(2010, 1, 3)), asTimeT( TimeStampUTC(2010, 1, 4)), asTimeT( TimeStampUTC(2010, 1, 5)), asTimeT( TimeStampUTC(2010, 1, 6))}; TimeMap tm(tp); RFTConfig conf(tm); BOOST_CHECK_THROW( conf.rft("W1", 100), std::invalid_argument); BOOST_CHECK_THROW( conf.plt("W1", 100), std::invalid_argument); BOOST_CHECK(!conf.rft("W1", 2)); BOOST_CHECK(!conf.plt("W1", 2)); conf.setWellOpenRFT(2); BOOST_CHECK(!conf.getWellOpenRFT("W1", 0)); conf.updateRFT("W1", 2, RFTConfig::RFT::YES); BOOST_CHECK(conf.rft("W1", 2)); BOOST_CHECK(!conf.rft("W1", 1)); BOOST_CHECK(!conf.rft("W1", 3)); conf.updateRFT("W2", 2, RFTConfig::RFT::REPT); conf.updateRFT("W2", 4, RFTConfig::RFT::NO); BOOST_CHECK(!conf.rft("W2", 1)); BOOST_CHECK( conf.rft("W2", 2)); BOOST_CHECK( conf.rft("W2", 3)); BOOST_CHECK(!conf.rft("W2", 4)); conf.setWellOpenRFT("W3"); BOOST_CHECK(conf.getWellOpenRFT("W3", 2)); conf.updateRFT("W4", 2, RFTConfig::RFT::FOPN); BOOST_CHECK(conf.getWellOpenRFT("W4", 2)); conf.addWellOpen("W10", 2); conf.addWellOpen("W100", 3); } BOOST_AUTO_TEST_CASE(RFT_CONFIG2) { const auto& schedule = make_schedule(createDeckRFTConfig()); const auto& rft_config = schedule.rftConfig(); BOOST_CHECK_EQUAL(2U, rft_config.firstRFTOutput()); } BOOST_AUTO_TEST_CASE(nupcol) { std::string input = "RUNSPEC\n" "START -- 0 \n" "19 JUN 2007 / \n" "NUPCOL\n" " 20 /\n" "SCHEDULE\n" "DATES\n -- 1\n" " 10 OKT 2008 / \n" "/\n" "NUPCOL\n" " 1* /\n" "DATES\n -- 1\n" " 10 OKT 2009 / \n" "/\n" "NUPCOL\n" " 10 /\n" "DATES\n -- 1\n" " 10 OKT 2010 / \n" "/\n" ; const auto& schedule = make_schedule(input); { // Flow uses 12 as default BOOST_CHECK_EQUAL(schedule.getNupcol(0),20); BOOST_CHECK_EQUAL(schedule.getNupcol(1),12); BOOST_CHECK_EQUAL(schedule.getNupcol(2),10); } } BOOST_AUTO_TEST_CASE(TESTGuideRateConfig) { std::string input = R"( START -- 0 10 MAI 2007 / SCHEDULE WELSPECS 'W1' 'G1' 1 2 3.33 'OIL' 7*/ 'W2' 'G2' 1 3 3.33 'OIL' 3* YES / 'W3' 'G3' 1 4 3.92 'OIL' 3* NO / / COMPDAT 'W1' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 / 'W2' 1 1 2 2 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 / 'W3' 1 1 3 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 / / WCONPROD 'W1' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / / WGRUPCON 'W1' 'YES' 0.50 'OIL' / 'W2' 'YES' 0.50 'GAS' / / GCONPROD 'G1' 'ORAT' 1000 / 'G2' 'ORAT' 1000 5* 0.25 'OIL' / / DATES -- 1 10 JUN 2007 / / WCONHIST 'W1' 'OPEN' 'ORAT' 1.000 0.000 0.000 5* / / WGRUPCON 'W1' 'YES' 0.75 'WAT' / 'W2' 'NO' / / GCONPROD 'G2' 'ORAT' 1000 / 'G1' 'ORAT' 1000 6* 'FORM' / / DATES -- 2 10 JUL 2007 / / WCONPROD 'W1' 'OPEN' 'ORAT' 0.000 0.000 0.000 5* / / DATES -- 3 10 AUG 2007 / / DATES -- 4 10 SEP 2007 / / DATES -- 5 10 NOV 2007 / / WELSPECS 'W4' 'G1' 1 2 3.33 'OIL' 7*/ / DATES -- 6 10 DEC 2007 / / COMPDAT 'W4' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 / / )"; const auto& schedule = make_schedule(input); { const auto& grc = schedule.guideRateConfig(0); const auto& w1_node = grc.well("W1"); BOOST_CHECK(w1_node.target == Well::GuideRateTarget::OIL); const auto& w2_node = grc.well("W2"); BOOST_CHECK(w2_node.target == Well::GuideRateTarget::GAS); BOOST_CHECK(!grc.has_group("G1")); BOOST_CHECK(grc.has_group("G2")); } { const auto& grc = schedule.guideRateConfig(2); const auto& w1_node = grc.well("W1"); BOOST_CHECK(w1_node.target == Well::GuideRateTarget::WAT); BOOST_CHECK_EQUAL(w1_node.guide_rate, 0.75); BOOST_CHECK(grc.has_well("W1")); BOOST_CHECK(!grc.has_well("W2")); BOOST_CHECK_THROW( grc.well("W2"), std::out_of_range); BOOST_CHECK(grc.has_group("G1")); BOOST_CHECK(!grc.has_group("G2")); } { GuideRate gr(schedule); double oil_pot = 1; double gas_pot = 1; double wat_pot = 1; gr.compute("XYZ",1, 1.0, oil_pot, gas_pot, wat_pot); } { const auto& changed_wells = schedule.changed_wells(0); BOOST_CHECK_EQUAL( changed_wells.size() , 3U); for (const auto& wname : {"W1", "W2", "W2"}) { auto find_well = std::find(changed_wells.begin(), changed_wells.end(), wname); BOOST_CHECK(find_well != changed_wells.end()); } } { const auto& changed_wells = schedule.changed_wells(2); BOOST_CHECK_EQUAL( changed_wells.size(), 0U); } { const auto& changed_wells = schedule.changed_wells(4); BOOST_CHECK_EQUAL( changed_wells.size(), 0U); } { const auto& changed_wells = schedule.changed_wells(5); BOOST_CHECK_EQUAL( changed_wells.size(), 1U); BOOST_CHECK_EQUAL( changed_wells[0], "W4"); } { const auto& changed_wells = schedule.changed_wells(6); BOOST_CHECK_EQUAL( changed_wells.size(), 1U); BOOST_CHECK_EQUAL( changed_wells[0], "W4"); } } BOOST_AUTO_TEST_CASE(Injection_Control_Mode_From_Well) { const auto input = R"(RUNSPEC SCHEDULE WELSPECS 'W1' 'G1' 1 2 3.33 'OIL' 7*/ 'W2' 'G2' 1 3 3.33 'OIL' 3* YES / 'W3' 'G3' 1 4 3.92 'OIL' 3* NO / 'W4' 'G3' 2 2 3.92 'OIL' 3* NO / 'W5' 'G3' 2 3 3.92 'OIL' 3* NO / 'W6' 'G3' 2 4 3.92 'OIL' 3* NO / 'W7' 'G3' 3 2 3.92 'OIL' 3* NO / / WCONINJE 'W1' 'WATER' 'OPEN' 'GRUP' / 'W2' 'GAS' 'OPEN' 'RATE' 200 1* 450.0 / 'W3' 'OIL' 'OPEN' 'RATE' 200 1* 450.0 / 'W4' 'WATER' 'OPEN' 'RATE' 200 1* 450.0 / 'W5' 'WATER' 'OPEN' 'RESV' 200 175 450.0 / 'W6' 'GAS' 'OPEN' 'BHP' 200 1* 450.0 / 'W7' 'GAS' 'OPEN' 'THP' 200 1* 450.0 150 / / TSTEP 30*30 / END )"; const auto sched = make_schedule(input); const auto st = ::Opm::SummaryState{ std::chrono::system_clock::now() }; BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W1", 10), st), -1); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W2", 10), st), 3); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W3", 10), st), 1); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W4", 10), st), 2); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W5", 10), st), 5); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W6", 10), st), 7); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W7", 10), st), 6); } BOOST_AUTO_TEST_CASE(Production_Control_Mode_From_Well) { const auto input = R"(RUNSPEC SCHEDULE WELSPECS 'W1' 'G1' 1 2 3.33 'OIL' 7*/ 'W2' 'G2' 1 3 3.33 'OIL' 3* YES / 'W3' 'G3' 1 4 3.92 'OIL' 3* NO / 'W4' 'G3' 2 2 3.92 'OIL' 3* NO / 'W5' 'G3' 2 3 3.92 'OIL' 3* NO / 'W6' 'G3' 2 4 3.92 'OIL' 3* NO / 'W7' 'G3' 3 2 3.92 'OIL' 3* NO / 'W8' 'G3' 3 3 3.92 'OIL' 3* NO / / WCONPROD 'W1' 'OPEN' 'GRUP' / 'W2' 'OPEN' 'ORAT' 1000.0 / 'W3' 'OPEN' 'WRAT' 1000.0 250.0 / 'W4' 'OPEN' 'GRAT' 1000.0 250.0 30.0e3 / 'W5' 'OPEN' 'LRAT' 1000.0 250.0 30.0e3 1500.0 / 'W6' 'OPEN' 'RESV' 1000.0 250.0 30.0e3 1500.0 314.15 / 'W7' 'OPEN' 'BHP' 1000.0 250.0 30.0e3 1500.0 314.15 27.1828 / 'W8' 'OPEN' 'THP' 1000.0 250.0 30.0e3 1500.0 314.15 27.1828 31.415 / / TSTEP 30*30 / END )"; const auto sched = make_schedule(input); const auto st = ::Opm::SummaryState{ std::chrono::system_clock::now() }; BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W1", 10), st), -1); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W2", 10), st), 1); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W3", 10), st), 2); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W4", 10), st), 3); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W5", 10), st), 4); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W6", 10), st), 5); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W7", 10), st), 7); BOOST_CHECK_EQUAL(eclipseControlMode(sched.getWell("W8", 10), st), 6); } BOOST_AUTO_TEST_CASE(SKIPREST_VFP) { auto python = std::make_shared(); Parser parser; auto deck = parser.parseFile("MODEL2_RESTART.DATA"); EclipseState es{ deck }; const auto& init_config = es.getInitConfig(); auto report_step = init_config.getRestartStep(); const auto& rst_filename = es.getIOConfig().getRestartFileName( init_config.getRestartRootName(), report_step, false ); Opm::EclIO::ERst rst_file(rst_filename); const auto& rst = Opm::RestartIO::RstState::load(rst_file, report_step); const auto sched = Schedule{ deck, es, python , &rst}; const auto& tables = sched.getVFPProdTables(3); BOOST_CHECK( !tables.empty() ); } BOOST_AUTO_TEST_CASE(GASLIFT_OPT) { GasLiftOpt glo; BOOST_CHECK(!glo.active()); BOOST_CHECK_THROW(glo.group("NO_SUCH_GROUP"), std::out_of_range); BOOST_CHECK_THROW(glo.well("NO_SUCH_WELL"), std::out_of_range); } BOOST_AUTO_TEST_CASE(GASLIFT_OPT_DECK) { const auto input = R"(-- Turns on gas lift optimization SCHEDULE GRUPTREE 'PROD' 'FIELD' / 'M5S' 'PLAT-A' / 'M5N' 'PLAT-A' / 'C1' 'M5N' / 'F1' 'M5N' / 'B1' 'M5S' / 'G1' 'M5S' / / LIFTOPT 12500 5E-3 0.0 YES / -- Group lift gas limits for gas lift optimization GLIFTOPT 'PLAT-A' 200000 / -- / WELSPECS --WELL GROUP IHEEL JHEEL DREF PHASE DRAD INFEQ SIINS XFLOW PRTAB DENS 'B-1H' 'B1' 11 3 1* OIL 1* 1* SHUT 1* 1* 1* / 'B-2H' 'B1' 4 7 1* OIL 1* 1* SHUT 1* 1* 1* / 'B-3H' 'B1' 11 12 1* OIL 1* 1* SHUT 1* 1* 1* / 'C-1H' 'C1' 13 20 1* OIL 1* 1* SHUT 1* 1* 1* / 'C-2H' 'C1' 12 27 1* OIL 1* 1* SHUT 1* 1* 1* / / -- well savailable for gass lift -- minimum gas lift rate, enough to keep well flowing WLIFTOPT 'B-1H' YES 150000 1.01 -1.0 / 'B-2H' YES 150000 1.01 -1.0 / 'B-3H' YES 150000 1.01 -1.0 / 'C-1H' YES 150000 1.01 -1.0 1.0 YES/ 'C-2H' NO 150000 1.01 -1.0 / / )"; Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC ); double siFactorG = unitSystem.parse("GasSurfaceVolume/Time").getSIScaling(); const auto sched = make_schedule(input); const auto& glo = sched.glo(0); const auto& plat_group = glo.group("PLAT-A"); BOOST_CHECK_EQUAL( *plat_group.max_lift_gas(), siFactorG * 200000); BOOST_CHECK(!plat_group.max_total_gas().has_value()); const auto& w1 = glo.well("B-1H"); BOOST_CHECK(w1.use_glo()); BOOST_CHECK_EQUAL(*w1.max_rate(), 150000 * siFactorG); BOOST_CHECK_EQUAL(w1.weight_factor(), 1.01); const auto& w2 = glo.well("C-2H"); BOOST_CHECK_EQUAL(w2.weight_factor(), 1.00); BOOST_CHECK_EQUAL(w2.min_rate(), 0.00); BOOST_CHECK_EQUAL(w2.inc_weight_factor(), 0.00); BOOST_CHECK(!w2.alloc_extra_gas()); const auto& w3 = glo.well("C-1H"); BOOST_CHECK_EQUAL(w3.min_rate(), -1.00 * siFactorG); BOOST_CHECK_EQUAL(w3.inc_weight_factor(), 1.00); BOOST_CHECK(w3.alloc_extra_gas()); } BOOST_AUTO_TEST_CASE(WellPI) { const auto deck = Parser{}.parseString(R"(RUNSPEC 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 / PERMX 300*100.0 / PERMY 300*100.0 / PERMZ 300*10.0 / PORO 300*0.3 / SCHEDULE WELSPECS 'P' 'G' 10 10 2005 'LIQ' / / COMPDAT 'P' 0 0 1 3 OPEN 1 100 / / TSTEP 10 / WELPI 'P' 200.0 / / TSTEP 10 / END )"); const auto es = EclipseState{ deck }; const auto sched = Schedule{ deck, es }; // Apply WELPI before seeing WELPI data { const auto expectCF = 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 0); wellP.applyWellProdIndexScaling(2.7182818); for (const auto& conn : wellP.getConnections()) { BOOST_CHECK_CLOSE(conn.CF(), expectCF, 1.0e-10); } } // Apply WELPI after seeing WELPI data. { const auto expectCF = (200.0 / 100.0) * 100.0*cp_rm3_per_db(); auto wellP = sched.getWell("P", 1); wellP.applyWellProdIndexScaling(100.0*liquid_PI_unit()); for (const auto& conn : wellP.getConnections()) { BOOST_CHECK_CLOSE(conn.CF(), expectCF, 1.0e-10); } } BOOST_CHECK_MESSAGE(sched.hasWellGroupEvent("P", ScheduleEvents::WELL_CONNECTIONS_UPDATED, 0), "Well P must have WELL_CONNECTIONS_UPDATED event at report step 0"); BOOST_CHECK_MESSAGE(!sched.hasWellGroupEvent("P", ScheduleEvents::WELL_CONNECTIONS_UPDATED, 1), "Well P must NOT have WELL_CONNECTIONS_UPDATED event at report step 0"); BOOST_CHECK_MESSAGE(sched.hasWellGroupEvent("P", ScheduleEvents::WELL_PRODUCTIVITY_INDEX, 1), "Must have WELL_PRODUCTIVITY_INDEX event at report step 1"); }