2013-11-05 05:55:03 -06:00
|
|
|
/*
|
|
|
|
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 <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
2020-10-18 18:24:11 -05:00
|
|
|
#include <memory>
|
2020-10-15 02:11:17 -05:00
|
|
|
#include <optional>
|
2020-10-18 18:24:11 -05:00
|
|
|
#include <stdexcept>
|
|
|
|
#include <utility>
|
2013-11-05 05:55:03 -06:00
|
|
|
|
|
|
|
#define BOOST_TEST_MODULE WellTest
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
2021-12-14 01:06:42 -06:00
|
|
|
#include <opm/input/eclipse/Units/Units.hpp>
|
|
|
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
|
|
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
|
|
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
|
|
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
|
|
|
|
|
|
|
#include <opm/input/eclipse/Python/Python.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
|
|
|
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
2021-12-14 01:13:41 -06:00
|
|
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
|
|
|
#include <opm/input/eclipse/Schedule/ScheduleTypes.hpp>
|
|
|
|
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
|
|
|
#include <opm/input/eclipse/Schedule/UDQ/UDQActive.hpp>
|
|
|
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
2023-01-18 03:52:39 -06:00
|
|
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
2021-12-14 01:13:41 -06:00
|
|
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
2021-12-14 01:06:42 -06:00
|
|
|
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
|
|
|
#include <opm/input/eclipse/Parser/ErrorGuard.hpp>
|
|
|
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
2021-02-28 10:04:35 -06:00
|
|
|
#include <opm/common/utility/TimeService.hpp>
|
2015-01-26 09:40:13 -06:00
|
|
|
|
2023-11-02 08:41:14 -05:00
|
|
|
#include <opm/input/eclipse/Parser/ParserKeywords/F.hpp>
|
|
|
|
|
2016-11-29 08:46:55 -06:00
|
|
|
using namespace Opm;
|
|
|
|
|
2020-10-07 16:20:26 -05:00
|
|
|
namespace {
|
2020-10-30 07:04:36 -05:00
|
|
|
double liquid_PI_unit()
|
|
|
|
{
|
|
|
|
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::liquid_productivity_index, 1.0);
|
|
|
|
}
|
|
|
|
|
2020-10-07 16:20:26 -05:00
|
|
|
double cp_rm3_per_db()
|
|
|
|
{
|
2020-10-30 07:04:36 -05:00
|
|
|
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::transmissibility, 1.0);
|
2020-10-07 16:20:26 -05:00
|
|
|
}
|
2016-10-12 09:30:06 -05:00
|
|
|
}
|
|
|
|
|
2015-08-28 09:21:14 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(WellCOMPDATtestTRACK) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input =
|
|
|
|
"START -- 0 \n"
|
|
|
|
"19 JUN 2007 / \n"
|
2021-11-03 09:47:30 -05:00
|
|
|
"GRID\n"
|
|
|
|
"PORO\n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMX \n"
|
|
|
|
"1000*1 /\n"
|
|
|
|
"PERMY \n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMZ \n"
|
|
|
|
"1000*0.01 /\n"
|
2015-08-28 09:21:14 -05:00
|
|
|
"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"
|
|
|
|
"COMPORD\n"
|
|
|
|
" OP_1 TRACK / \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 3 9 '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"
|
|
|
|
"/\n"
|
|
|
|
"DATES -- 2\n"
|
|
|
|
" 20 JAN 2010 / \n"
|
|
|
|
"/\n";
|
|
|
|
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
auto deck = parser.parseString(input);
|
2020-03-31 03:26:55 -05:00
|
|
|
auto python = std::make_shared<Python>();
|
2016-09-08 12:42:45 -05:00
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
2017-02-15 04:13:29 -06:00
|
|
|
TableManager table ( deck );
|
2020-01-16 11:20:31 -06:00
|
|
|
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
2018-10-17 06:35:25 -05:00
|
|
|
Opm::Runspec runspec (deck);
|
2020-03-26 09:31:21 -05:00
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
2019-11-12 01:29:28 -06:00
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 2);
|
2015-08-28 09:21:14 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
const auto& completions = op_1.getConnections();
|
2016-10-12 09:30:06 -05:00
|
|
|
BOOST_CHECK_EQUAL(9U, completions.size());
|
2015-08-28 09:21:14 -05:00
|
|
|
|
|
|
|
//Verify TRACK completion ordering
|
2016-10-12 09:30:06 -05:00
|
|
|
for (size_t k = 0; k < completions.size(); ++k) {
|
2020-09-29 06:54:21 -05:00
|
|
|
BOOST_CHECK_EQUAL(completions.get( k ).getK(), int(k));
|
2015-08-28 09:21:14 -05:00
|
|
|
}
|
2020-03-19 04:42:06 -05:00
|
|
|
|
|
|
|
// Output / input ordering
|
|
|
|
const auto& output_connections = completions.output(grid);
|
|
|
|
std::vector<int> expected = {0,2,3,4,5,6,7,8,1};
|
2021-07-28 04:17:12 -05:00
|
|
|
for (size_t k = 0; k < completions.size(); ++k)
|
|
|
|
BOOST_CHECK_EQUAL( expected[k], output_connections[k]->getK());
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WellCOMPDATtestDEPTH) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input = R"(
|
|
|
|
START -- 0
|
|
|
|
19 JUN 2007 /
|
2021-11-03 09:47:30 -05:00
|
|
|
GRID
|
|
|
|
PORO
|
|
|
|
1000*0.1 /
|
|
|
|
PERMX
|
|
|
|
1000*1 /
|
|
|
|
PERMY
|
|
|
|
1000*0.1 /
|
|
|
|
PERMZ
|
|
|
|
1000*0.01 /
|
2021-07-28 04:17:12 -05:00
|
|
|
SCHEDULE
|
|
|
|
DATES -- 1
|
|
|
|
10 OKT 2008 /
|
|
|
|
/
|
|
|
|
WELSPECS
|
|
|
|
'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
|
|
|
/
|
|
|
|
COMPORD
|
|
|
|
OP_1 DEPTH /
|
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
|
|
|
'OP_1' 9 9 3 9 '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 /
|
|
|
|
/
|
|
|
|
DATES -- 2
|
|
|
|
20 JAN 2010 /
|
|
|
|
/
|
|
|
|
)";
|
|
|
|
|
|
|
|
|
|
|
|
auto deck = parser.parseString(input);
|
|
|
|
auto python = std::make_shared<Python>();
|
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
|
|
|
TableManager table ( deck );
|
|
|
|
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
|
|
|
Opm::Runspec runspec (deck);
|
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 2);
|
|
|
|
|
|
|
|
const auto& completions = op_1.getConnections();
|
|
|
|
BOOST_CHECK_EQUAL(9U, completions.size());
|
|
|
|
|
|
|
|
//Verify TRACK completion ordering
|
|
|
|
for (size_t k = 0; k < completions.size() - 1; ++k) {
|
|
|
|
BOOST_CHECK(completions[k].depth() <= completions[k+1].depth());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output / input ordering
|
|
|
|
const auto& output_connections = completions.output(grid);
|
|
|
|
std::vector<int> expected = {0,2,3,4,5,6,7,8,1};
|
2020-03-19 04:42:06 -05:00
|
|
|
for (size_t k = 0; k < completions.size(); ++k)
|
|
|
|
BOOST_CHECK_EQUAL( expected[k], output_connections[k]->getK());
|
2015-08-28 09:21:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WellCOMPDATtestDefaultTRACK) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input =
|
|
|
|
"START -- 0 \n"
|
|
|
|
"19 JUN 2007 / \n"
|
2021-11-03 09:47:30 -05:00
|
|
|
"GRID\n"
|
|
|
|
"PORO\n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMX \n"
|
|
|
|
"1000*1 /\n"
|
|
|
|
"PERMY \n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMZ \n"
|
|
|
|
"1000*0.01 /\n"
|
2015-08-28 09:21:14 -05:00
|
|
|
"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 3 9 '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"
|
|
|
|
"/\n"
|
|
|
|
"DATES -- 2\n"
|
|
|
|
" 20 JAN 2010 / \n"
|
|
|
|
"/\n";
|
|
|
|
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
auto deck = parser.parseString(input);
|
2020-03-31 03:26:55 -05:00
|
|
|
auto python = std::make_shared<Python>();
|
2016-09-08 12:42:45 -05:00
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
2017-02-15 04:13:29 -06:00
|
|
|
TableManager table ( deck );
|
2020-01-16 11:20:31 -06:00
|
|
|
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
2018-10-17 06:35:25 -05:00
|
|
|
Opm::Runspec runspec (deck);
|
2020-03-26 09:31:21 -05:00
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
2019-11-12 01:29:28 -06:00
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 2);
|
2015-08-28 09:21:14 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
const auto& completions = op_1.getConnections();
|
2016-10-12 09:30:06 -05:00
|
|
|
BOOST_CHECK_EQUAL(9U, completions.size());
|
2015-08-28 09:21:14 -05:00
|
|
|
|
|
|
|
//Verify TRACK completion ordering
|
2016-10-12 09:30:06 -05:00
|
|
|
for (size_t k = 0; k < completions.size(); ++k) {
|
2020-09-29 06:54:21 -05:00
|
|
|
BOOST_CHECK_EQUAL(completions.get( k ).getK(), int(k));
|
2015-08-28 09:21:14 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WellCOMPDATtestINPUT) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input =
|
|
|
|
"START -- 0 \n"
|
|
|
|
"19 JUN 2007 / \n"
|
2021-11-03 09:47:30 -05:00
|
|
|
"GRID\n"
|
|
|
|
"PORO\n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMX \n"
|
|
|
|
"1000*1 /\n"
|
|
|
|
"PERMY \n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMZ \n"
|
|
|
|
"1000*0.01 /\n"
|
2015-08-28 09:21:14 -05:00
|
|
|
"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"
|
|
|
|
"COMPORD\n"
|
|
|
|
" OP_1 INPUT / \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 3 9 '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"
|
|
|
|
"/\n"
|
|
|
|
"DATES -- 2\n"
|
|
|
|
" 20 JAN 2010 / \n"
|
|
|
|
"/\n";
|
|
|
|
|
|
|
|
|
2019-01-03 11:05:19 -06:00
|
|
|
auto deck = parser.parseString(input);
|
2016-09-08 12:42:45 -05:00
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
2019-01-03 11:05:19 -06:00
|
|
|
Opm::ErrorGuard errors;
|
2017-02-15 04:13:29 -06:00
|
|
|
TableManager table ( deck );
|
2020-01-16 11:20:31 -06:00
|
|
|
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
2018-10-17 06:35:25 -05:00
|
|
|
Opm::Runspec runspec (deck);
|
2020-03-31 03:26:55 -05:00
|
|
|
auto python = std::make_shared<Python>();
|
2020-03-26 09:31:21 -05:00
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, Opm::ParseContext(), errors, python);
|
2019-11-12 01:29:28 -06:00
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 2);
|
2015-08-28 09:21:14 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
const auto& completions = op_1.getConnections();
|
2016-10-12 09:30:06 -05:00
|
|
|
BOOST_CHECK_EQUAL(9U, completions.size());
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 1 ).getK(), 2);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 2 ).getK(), 3);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 3 ).getK(), 4);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 4 ).getK(), 5);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 5 ).getK(), 6);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 6 ).getK(), 7);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 7 ).getK(), 8);
|
|
|
|
BOOST_CHECK_EQUAL(completions.get( 8 ).getK(), 1);
|
2015-08-28 09:21:14 -05:00
|
|
|
}
|
2013-11-08 16:20:09 -06:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(NewWellZeroCompletions) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_CHECK_EQUAL( 0U , well.getConnections( ).size() );
|
2014-01-24 06:24:22 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-11-11 07:35:14 -06:00
|
|
|
BOOST_AUTO_TEST_CASE(isProducerCorrectlySet) {
|
2014-03-17 08:13:02 -05:00
|
|
|
// HACK: This test checks correctly setting of isProducer/isInjector. This property depends on which of
|
|
|
|
// WellProductionProperties/WellInjectionProperties is set last, independent of actual values.
|
2019-06-22 17:02:23 -05:00
|
|
|
{
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-06-22 17:02:23 -05:00
|
|
|
|
|
|
|
|
|
|
|
/* 1: Well is created as producer */
|
|
|
|
BOOST_CHECK_EQUAL( false , well.isInjector());
|
|
|
|
BOOST_CHECK_EQUAL( true , well.isProducer());
|
|
|
|
|
|
|
|
/* Set a surface injection rate => Well becomes an Injector */
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injectionProps1 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injectionProps1->surfaceInjectionRate.update(100);
|
2019-06-22 17:02:23 -05:00
|
|
|
well.updateInjection(injectionProps1);
|
|
|
|
BOOST_CHECK_EQUAL( true , well.isInjector());
|
|
|
|
BOOST_CHECK_EQUAL( false , well.isProducer());
|
|
|
|
BOOST_CHECK_EQUAL( 100 , well.getInjectionProperties().surfaceInjectionRate.get<double>());
|
|
|
|
}
|
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
|
|
|
|
{
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-05-04 05:00:32 -05:00
|
|
|
|
|
|
|
/* Set a reservoir injection rate => Well becomes an Injector */
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injectionProps2 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injectionProps2->reservoirInjectionRate.update(200);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injectionProps2);
|
|
|
|
BOOST_CHECK_EQUAL( false , well.isProducer());
|
2019-06-24 02:34:11 -05:00
|
|
|
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().reservoirInjectionRate.get<double>());
|
2019-05-04 05:00:32 -05:00
|
|
|
}
|
2013-11-11 07:35:14 -06:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
{
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-05-04 05:00:32 -05:00
|
|
|
|
|
|
|
/* Set rates => Well becomes a producer; injection rate should be set to 0. */
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injectionProps3 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injectionProps3);
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto properties = std::make_shared<Opm::Well::WellProductionProperties>( well.getProductionProperties() );
|
2020-10-29 09:52:26 -05:00
|
|
|
properties->OilRate.update(100);
|
|
|
|
properties->GasRate.update(200);
|
|
|
|
properties->WaterRate.update(300);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(properties);
|
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL( false , well.isInjector());
|
|
|
|
BOOST_CHECK_EQUAL( true , well.isProducer());
|
2019-06-24 02:34:11 -05:00
|
|
|
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().surfaceInjectionRate.get<double>());
|
|
|
|
BOOST_CHECK_EQUAL( 0 , well.getInjectionProperties().reservoirInjectionRate.get<double>());
|
|
|
|
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().OilRate.get<double>());
|
|
|
|
BOOST_CHECK_EQUAL( 200 , well.getProductionProperties().GasRate.get<double>());
|
|
|
|
BOOST_CHECK_EQUAL( 300 , well.getProductionProperties().WaterRate.get<double>());
|
2019-05-04 05:00:32 -05:00
|
|
|
}
|
|
|
|
}
|
2013-11-11 07:35:14 -06:00
|
|
|
|
2013-11-25 09:06:10 -06:00
|
|
|
BOOST_AUTO_TEST_CASE(GroupnameCorretlySet) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "G1", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2013-11-25 09:06:10 -06:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_CHECK_EQUAL("G1" , well.groupName());
|
|
|
|
well.updateGroup( "GROUP2");
|
|
|
|
BOOST_CHECK_EQUAL("GROUP2" , well.groupName());
|
2013-11-25 09:06:10 -06:00
|
|
|
}
|
2014-01-20 07:52:30 -06:00
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(addWELSPECS_setData_dataSet) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 23, 42, 2334.32, Opm::WellType(Opm::Phase::WATER), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2014-01-20 07:52:30 -06:00
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL(23, well.getHeadI());
|
|
|
|
BOOST_CHECK_EQUAL(42, well.getHeadJ());
|
|
|
|
BOOST_CHECK_EQUAL(2334.32, well.getRefDepth());
|
2014-04-06 16:11:38 -05:00
|
|
|
BOOST_CHECK_EQUAL(Opm::Phase::WATER, well.getPreferredPhase());
|
2014-01-20 07:52:30 -06:00
|
|
|
}
|
2014-01-27 11:27:57 -06:00
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(XHPLimitDefault) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 23, 42, 2334.32, Opm::WellType(Opm::Phase::WATER), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-05-04 05:00:32 -05:00
|
|
|
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto productionProps = std::make_shared<Opm::Well::WellProductionProperties>(well.getProductionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
productionProps->BHPTarget.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
productionProps->addProductionControl(Opm::Well::ProducerCMode::BHP);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(productionProps);
|
2020-01-03 13:31:22 -06:00
|
|
|
BOOST_CHECK_EQUAL( 100 , well.getProductionProperties().BHPTarget.get<double>());
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL( true, well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::BHP ));
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injProps = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injProps->THPTarget.update(200);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injProps);
|
2020-01-03 13:31:22 -06:00
|
|
|
BOOST_CHECK_EQUAL( 200 , well.getInjectionProperties().THPTarget.get<double>());
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::THP ));
|
2014-01-27 11:27:57 -06:00
|
|
|
}
|
|
|
|
|
2014-01-28 07:31:51 -06:00
|
|
|
|
|
|
|
|
2020-02-27 07:29:01 -06:00
|
|
|
BOOST_AUTO_TEST_CASE(ScheduleTypesInjectorType) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 23, 42, 2334.32, Opm::WellType(Opm::Phase::WATER), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2014-12-08 09:34:28 -06:00
|
|
|
|
2018-03-07 02:42:55 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injectionProps = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-02-27 07:29:01 -06:00
|
|
|
injectionProps->injectorType = Opm::InjectorType::WATER;
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injectionProps);
|
2019-06-24 02:34:11 -05:00
|
|
|
// TODO: Should we test for something other than wate here, as long as
|
2014-03-12 05:21:57 -05:00
|
|
|
// the default value for InjectorType is WellInjector::WATER?
|
2020-02-27 07:29:01 -06:00
|
|
|
BOOST_CHECK( Opm::InjectorType::WATER == well.getInjectionProperties().injectorType);
|
2018-03-07 02:42:55 -06:00
|
|
|
|
2014-01-28 07:31:51 -06:00
|
|
|
}
|
|
|
|
|
2014-01-29 06:33:28 -06:00
|
|
|
|
|
|
|
|
2014-01-30 08:19:50 -06:00
|
|
|
/*****************************************************************/
|
|
|
|
|
|
|
|
|
2014-03-12 06:21:55 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(WellHaveProductionControlLimit) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 23, 42, 2334.32, Opm::WellType(Opm::Phase::WATER), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2014-01-30 08:19:50 -06:00
|
|
|
|
2014-03-17 08:13:02 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::ORAT ));
|
|
|
|
BOOST_CHECK( !well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::RESV ));
|
2014-03-12 06:21:55 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto properties1 = std::make_shared<Opm::Well::WellProductionProperties>(well.getProductionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
properties1->OilRate.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
properties1->addProductionControl(Opm::Well::ProducerCMode::ORAT);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(properties1);
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::ORAT ));
|
|
|
|
BOOST_CHECK( !well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::RESV ));
|
2014-01-30 09:31:35 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto properties2 = std::make_shared<Opm::Well::WellProductionProperties>(well.getProductionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
properties2->ResVRate.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
properties2->addProductionControl(Opm::Well::ProducerCMode::RESV);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(properties2);
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::RESV ));
|
2014-03-17 08:13:02 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto properties3 = std::make_shared<Opm::Well::WellProductionProperties>(well.getProductionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
properties3->OilRate.update(100);
|
|
|
|
properties3->WaterRate.update(100);
|
|
|
|
properties3->GasRate.update(100);
|
|
|
|
properties3->LiquidRate.update(100);
|
|
|
|
properties3->ResVRate.update(100);
|
|
|
|
properties3->BHPTarget.update(100);
|
|
|
|
properties3->THPTarget.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
properties3->addProductionControl(Opm::Well::ProducerCMode::ORAT);
|
|
|
|
properties3->addProductionControl(Opm::Well::ProducerCMode::LRAT);
|
|
|
|
properties3->addProductionControl(Opm::Well::ProducerCMode::BHP);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(properties3);
|
2014-02-21 05:48:36 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::ORAT ));
|
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::LRAT ));
|
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::BHP ));
|
2014-02-21 05:48:36 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto properties4 = std::make_shared<Opm::Well::WellProductionProperties>(well.getProductionProperties());
|
|
|
|
properties4->dropProductionControl( Opm::Well::ProducerCMode::LRAT );
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateProduction(properties4);
|
2014-02-21 05:48:36 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::ORAT ));
|
|
|
|
BOOST_CHECK(!well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::LRAT ));
|
|
|
|
BOOST_CHECK( well.getProductionProperties().hasProductionControl( Opm::Well::ProducerCMode::BHP ));
|
2014-02-21 05:48:36 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(WellHaveInjectionControlLimit) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1", "GROUP", 0, 1, 23, 42, 2334.32, Opm::WellType(Opm::Phase::WATER), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RATE ));
|
|
|
|
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RESV ));
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injProps1 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injProps1->surfaceInjectionRate.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
injProps1->addInjectionControl(Opm::Well::InjectorCMode::RATE);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injProps1);
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RATE ));
|
|
|
|
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RESV ));
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injProps2 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injProps2->reservoirInjectionRate.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
injProps2->addInjectionControl(Opm::Well::InjectorCMode::RESV);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injProps2);
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RESV ));
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injProps3 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
2020-10-29 09:52:26 -05:00
|
|
|
injProps3->BHPTarget.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
injProps3->addInjectionControl(Opm::Well::InjectorCMode::BHP);
|
2020-10-29 09:52:26 -05:00
|
|
|
injProps3->THPTarget.update(100);
|
2019-11-12 01:29:28 -06:00
|
|
|
injProps3->addInjectionControl(Opm::Well::InjectorCMode::THP);
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injProps3);
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RATE ));
|
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RESV ));
|
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::THP ));
|
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::BHP ));
|
2019-05-04 05:00:32 -05:00
|
|
|
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto injProps4 = std::make_shared<Opm::Well::WellInjectionProperties>(well.getInjectionProperties());
|
|
|
|
injProps4->dropInjectionControl( Opm::Well::InjectorCMode::RESV );
|
2019-05-04 05:00:32 -05:00
|
|
|
well.updateInjection(injProps4);
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RATE ));
|
|
|
|
BOOST_CHECK( !well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::RESV ));
|
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::THP ));
|
|
|
|
BOOST_CHECK( well.getInjectionProperties().hasInjectionControl( Opm::Well::InjectorCMode::BHP ));
|
2014-02-21 05:48:36 -06:00
|
|
|
}
|
2019-05-04 05:00:32 -05:00
|
|
|
/*********************************************************************/
|
2014-02-21 05:48:36 -06:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WellGuideRatePhase_GuideRatePhaseSet) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2014-02-21 05:48:36 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(Opm::Well::GuideRateTarget::UNDEFINED == well.getGuideRatePhase());
|
2014-02-21 05:48:36 -06:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(well.updateWellGuideRate(true, 100, Opm::Well::GuideRateTarget::RAT, 66.0));
|
|
|
|
BOOST_CHECK(Opm::Well::GuideRateTarget::RAT == well.getGuideRatePhase());
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_CHECK_EQUAL(100, well.getGuideRate());
|
|
|
|
BOOST_CHECK_EQUAL(66.0, well.getGuideRateScalingFactor());
|
2014-02-21 05:48:36 -06:00
|
|
|
}
|
2015-08-28 09:21:14 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(WellEfficiencyFactorSet) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2015-08-28 09:21:14 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
BOOST_CHECK_EQUAL(1.0, well.getEfficiencyFactor());
|
|
|
|
BOOST_CHECK( well.updateEfficiencyFactor(0.9));
|
|
|
|
BOOST_CHECK_EQUAL(0.9, well.getEfficiencyFactor());
|
2015-08-28 09:21:14 -05:00
|
|
|
}
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-05-04 05:00:32 -05:00
|
|
|
|
2017-05-24 07:48:27 -05:00
|
|
|
namespace {
|
|
|
|
namespace WCONHIST {
|
2018-01-05 13:04:52 -06:00
|
|
|
std::string all_specified_CMODE_THP() {
|
2017-05-24 07:48:27 -05:00
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
2018-01-05 13:04:52 -06:00
|
|
|
"'P' 'OPEN' 'THP' 1 2 3/\n/\n";
|
2017-05-24 07:48:27 -05:00
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string all_specified() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"'P' 'OPEN' 'ORAT' 1 2 3/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string orat_defaulted() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"'P' 'OPEN' 'WRAT' 1* 2 3/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string owrat_defaulted() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"'P' 'OPEN' 'GRAT' 1* 1* 3/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string all_defaulted() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"'P' 'OPEN' 'LRAT'/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string all_defaulted_with_bhp() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"-- 1 2 3 4-9 10\n"
|
|
|
|
" 'P' 'OPEN' 'RESV' 6* 500/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2018-05-30 07:12:50 -05:00
|
|
|
std::string bhp_defaulted() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"-- 1 2 3 4-9 10\n"
|
|
|
|
" 'P' 'OPEN' 'BHP' 6* 500/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string all_defaulted_with_bhp_vfp_table() {
|
|
|
|
const std::string input =
|
|
|
|
"WCONHIST\n"
|
|
|
|
"-- 1 2 3 4-6 7 8 9 10\n"
|
|
|
|
" 'P' 'OPEN' 'RESV' 3* 3 10. 1* 500/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2018-07-04 05:47:30 -05:00
|
|
|
|
2020-10-15 02:11:17 -05:00
|
|
|
Opm::Well::WellProductionProperties properties(const std::string& input, std::optional<VFPProdTable::ALQ_TYPE> alq_type = {}) {
|
2017-05-24 07:48:27 -05:00
|
|
|
Opm::Parser parser;
|
2020-03-04 13:56:16 -06:00
|
|
|
Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
2019-01-03 11:05:19 -06:00
|
|
|
auto deck = parser.parseString(input);
|
2021-11-16 07:26:04 -06:00
|
|
|
const auto& record = deck["WCONHIST"].back().getRecord(0);
|
2020-03-04 13:56:16 -06:00
|
|
|
Opm::Well::WellProductionProperties hist(unit_system, "W");
|
2023-11-02 08:41:14 -05:00
|
|
|
hist.handleWCONHIST(alq_type,
|
|
|
|
Opm::ParserKeywords::FBHPDEF::TARGET_BHP::defaultValue * unit::barsa,
|
|
|
|
unit_system, record);
|
2019-04-08 02:18:32 -05:00
|
|
|
|
2017-05-24 07:48:27 -05:00
|
|
|
|
|
|
|
return hist;
|
|
|
|
}
|
|
|
|
} // namespace WCONHIST
|
|
|
|
|
|
|
|
namespace WCONPROD {
|
|
|
|
std::string
|
|
|
|
all_specified_CMODE_BHP()
|
|
|
|
{
|
|
|
|
const std::string input =
|
2018-05-30 07:12:50 -05:00
|
|
|
"WCONHIST\n"
|
2017-05-24 07:48:27 -05:00
|
|
|
"'P' 'OPEN' 'BHP' 1 2 3/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2018-05-30 07:12:50 -05:00
|
|
|
std::string orat_CMODE_other_defaulted()
|
|
|
|
{
|
|
|
|
const std::string input =
|
|
|
|
"WCONPROD\n"
|
|
|
|
"'P' 'OPEN' 'ORAT' 1 2 3/\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string thp_CMODE()
|
|
|
|
{
|
|
|
|
const std::string input =
|
|
|
|
"WCONPROD\n"
|
|
|
|
"'P' 'OPEN' 'THP' 1 2 3 3* 10. 8 13./\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string bhp_CMODE()
|
|
|
|
{
|
|
|
|
const std::string input =
|
|
|
|
"WCONPROD\n"
|
|
|
|
"'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 8 13./\n/\n";
|
|
|
|
|
|
|
|
return input;
|
|
|
|
}
|
|
|
|
|
2020-03-04 13:56:16 -06:00
|
|
|
Opm::UnitSystem unit_system(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
2020-10-15 02:11:17 -05:00
|
|
|
Opm::Well::WellProductionProperties properties(const std::string& input, std::optional<VFPProdTable::ALQ_TYPE> alq_type = {})
|
2017-05-24 07:48:27 -05:00
|
|
|
{
|
|
|
|
Opm::Parser parser;
|
2019-01-03 11:05:19 -06:00
|
|
|
auto deck = parser.parseString(input);
|
2021-11-16 07:26:04 -06:00
|
|
|
const auto& kwd = deck["WCONPROD"].back();
|
2017-05-24 07:48:27 -05:00
|
|
|
const auto& record = kwd.getRecord(0);
|
2020-03-04 13:56:16 -06:00
|
|
|
Opm::Well::WellProductionProperties pred(unit_system, "W");
|
2023-11-02 08:41:14 -05:00
|
|
|
pred.handleWCONPROD(alq_type,
|
|
|
|
Opm::ParserKeywords::FBHPDEF::TARGET_BHP::defaultValue * unit::barsa,
|
|
|
|
unit_system, "WELL", record);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
|
|
|
return pred;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace anonymous
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_All_Specified_BHP_Defaulted)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2017-05-24 07:48:27 -05:00
|
|
|
WCONHIST::properties(WCONHIST::all_specified());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::ORAT);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
|
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_ORAT_Defaulted_BHP_Defaulted)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2017-05-24 07:48:27 -05:00
|
|
|
WCONHIST::properties(WCONHIST::orat_defaulted());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::WRAT);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_OWRAT_Defaulted_BHP_Defaulted)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2017-05-24 07:48:27 -05:00
|
|
|
WCONHIST::properties(WCONHIST::owrat_defaulted());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::GRAT);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Defaulted)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2017-05-24 07:48:27 -05:00
|
|
|
WCONHIST::properties(WCONHIST::all_defaulted());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::LRAT);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_Rates_Defaulted_BHP_Specified)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2017-05-24 07:48:27 -05:00
|
|
|
WCONHIST::properties(WCONHIST::all_defaulted_with_bhp());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::RESV);
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2018-05-30 07:12:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCH_Rates_NON_Defaulted_VFP)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2021-02-15 11:38:24 -06:00
|
|
|
WCONHIST::properties(WCONHIST::all_defaulted_with_bhp_vfp_table(), VFPProdTable::ALQ_TYPE::ALQ_UNDEF);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK(p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::RESV);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2018-07-04 05:47:30 -05:00
|
|
|
BOOST_CHECK_EQUAL(p.VFPTableNumber, 3);
|
2021-03-04 06:27:34 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.ALQValue.get<double>(), 10.);
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 101325.);
|
2018-07-04 05:47:30 -05:00
|
|
|
}
|
|
|
|
|
2018-05-30 07:12:50 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(WCH_BHP_Specified)
|
|
|
|
{
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(TimeService::now());
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2018-05-30 07:12:50 -05:00
|
|
|
WCONHIST::properties(WCONHIST::bhp_defaulted());
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::BHP);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2020-01-03 13:31:22 -06:00
|
|
|
const auto& controls = p.controls(st, 0);
|
|
|
|
BOOST_CHECK_EQUAL(controls.bhp_limit, 5e7);
|
2018-05-30 07:12:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCONPROD_ORAT_CMode)
|
|
|
|
{
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p = WCONPROD::properties(WCONPROD::orat_CMODE_other_defaulted());
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::THP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::ORAT);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL(p.VFPTableNumber, 0);
|
2021-03-04 06:27:34 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.ALQValue.get<double>(), 0.);
|
2018-05-30 07:12:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCONPROD_THP_CMode)
|
|
|
|
{
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2021-02-15 11:38:24 -06:00
|
|
|
WCONPROD::properties(WCONPROD::thp_CMODE(), VFPProdTable::ALQ_TYPE::ALQ_UNDEF);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::THP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::THP);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL(p.VFPTableNumber, 8);
|
2021-03-04 06:27:34 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.ALQValue.get<double>(), 13.);
|
2020-01-03 13:31:22 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.THPTarget.getSI(), 1000000.); // 10 barsa
|
|
|
|
BOOST_CHECK_EQUAL(p.BHPTarget.getSI(), 101325.); // 1 atm.
|
2018-05-30 07:12:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WCONPROD_BHP_CMode)
|
|
|
|
{
|
2019-11-12 01:29:28 -06:00
|
|
|
const Opm::Well::WellProductionProperties& p =
|
2021-02-15 11:38:24 -06:00
|
|
|
WCONPROD::properties(WCONPROD::bhp_CMODE(), VFPProdTable::ALQ_TYPE::ALQ_UNDEF);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::ORAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::WRAT));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::GRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::LRAT));
|
|
|
|
BOOST_CHECK( !p.hasProductionControl(Opm::Well::ProducerCMode::RESV));
|
|
|
|
BOOST_CHECK( p.hasProductionControl(Opm::Well::ProducerCMode::THP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK(p.controlMode == Opm::Well::ProducerCMode::BHP);
|
2018-05-30 07:12:50 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK_EQUAL(true, p.hasProductionControl(Opm::Well::ProducerCMode::BHP));
|
2018-05-30 07:12:50 -05:00
|
|
|
|
|
|
|
BOOST_CHECK_EQUAL(p.VFPTableNumber, 8);
|
2021-03-04 06:27:34 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.ALQValue.get<double>(), 13.);
|
2020-01-03 13:31:22 -06:00
|
|
|
BOOST_CHECK_EQUAL(p.THPTarget.get<double>(), 10.); // 10 barsa
|
|
|
|
BOOST_CHECK_EQUAL(p.BHPTarget.get<double>(), 20.); // 20 barsa
|
|
|
|
BOOST_CHECK_EQUAL(p.THPTarget.getSI(), 1000000.); // 10 barsa
|
|
|
|
BOOST_CHECK_EQUAL(p.BHPTarget.getSI(), 2000000.); // 20 barsa
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(BHP_CMODE)
|
|
|
|
{
|
2021-11-11 09:58:53 -06:00
|
|
|
BOOST_CHECK_THROW( WCONHIST::properties(WCONHIST::all_specified_CMODE_THP()) , std::exception);
|
|
|
|
BOOST_CHECK_THROW( WCONPROD::properties(WCONPROD::all_specified_CMODE_BHP()) , std::exception);
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(CMODE_DEFAULT) {
|
2020-03-04 13:56:16 -06:00
|
|
|
auto unit_system = UnitSystem::newMETRIC();
|
|
|
|
const Opm::Well::WellProductionProperties Pproperties(unit_system, "W");
|
2020-03-05 02:03:54 -06:00
|
|
|
const Opm::Well::WellInjectionProperties Iproperties(unit_system, "W");
|
2017-05-24 07:48:27 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
BOOST_CHECK( Pproperties.controlMode == Opm::Well::ProducerCMode::CMODE_UNDEFINED );
|
|
|
|
BOOST_CHECK( Iproperties.controlMode == Opm::Well::InjectorCMode::CMODE_UNDEFINED );
|
2017-05-24 07:48:27 -05:00
|
|
|
}
|
2019-05-09 10:03:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WELL_CONTROLS) {
|
2020-03-04 13:56:16 -06:00
|
|
|
auto unit_system = UnitSystem::newMETRIC();
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well well("WELL", "GROUP", 0, 0, 0, 0, 1000, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Opm::Connection::Order::DEPTH, unit_system, 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2020-03-04 13:56:16 -06:00
|
|
|
Opm::Well::WellProductionProperties prod(unit_system, "OP1");
|
2021-02-28 10:04:35 -06:00
|
|
|
Opm::SummaryState st(Opm::TimeService::now());
|
2019-06-17 02:08:47 -05:00
|
|
|
well.productionControls(st);
|
2019-06-24 02:34:11 -05:00
|
|
|
|
|
|
|
// Use a scalar FIELD variable - that should work; although it is a bit weird.
|
|
|
|
st.update("FUX", 1);
|
|
|
|
prod.OilRate = UDAValue("FUX");
|
|
|
|
BOOST_CHECK_EQUAL(1, prod.controls(st, 0).oil_rate);
|
|
|
|
|
|
|
|
|
|
|
|
// Use the wellrate WUX for well OP1; the well is now added with
|
|
|
|
// SummaryState::update_well_var() and we should automatically fetch the
|
|
|
|
// correct well value.
|
|
|
|
prod.OilRate = UDAValue("WUX");
|
|
|
|
st.update_well_var("OP1", "WUX", 10);
|
|
|
|
BOOST_CHECK_EQUAL(10, prod.controls(st, 0).oil_rate);
|
2019-05-09 10:03:29 -05:00
|
|
|
}
|
2019-06-17 00:39:23 -05:00
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(ExtraAccessors) {
|
2020-04-19 01:37:48 -05:00
|
|
|
Opm::Well inj("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
|
|
|
Opm::Well prod("WELL1" , "GROUP", 0, 1, 0, 0, 0.0, Opm::WellType(Opm::Phase::OIL), Opm::Well::ProducerCMode::CMODE_UNDEFINED, Connection::Order::DEPTH, UnitSystem::newMETRIC(), 0, 1.0, false, false, 0, Opm::Well::GasInflowEquation::STD);
|
2019-06-17 00:39:23 -05:00
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto inj_props= std::make_shared<Opm::Well::WellInjectionProperties>(inj.getInjectionProperties());
|
2019-06-17 00:39:23 -05:00
|
|
|
inj_props->VFPTableNumber = 100;
|
|
|
|
inj.updateInjection(inj_props);
|
|
|
|
|
2019-11-12 01:29:28 -06:00
|
|
|
auto prod_props = std::make_shared<Opm::Well::WellProductionProperties>( prod.getProductionProperties() );
|
2019-06-17 00:39:23 -05:00
|
|
|
prod_props->VFPTableNumber = 200;
|
|
|
|
prod.updateProduction(prod_props);
|
|
|
|
|
|
|
|
BOOST_CHECK_THROW(prod.temperature(), std::runtime_error);
|
|
|
|
BOOST_CHECK_EQUAL(inj.vfp_table_number(), 100);
|
|
|
|
BOOST_CHECK_EQUAL(prod.vfp_table_number(), 200);
|
|
|
|
}
|
2019-12-02 04:12:17 -06:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WELOPEN) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input =
|
|
|
|
"START -- 0 \n"
|
|
|
|
"19 JUN 2007 / \n"
|
2021-11-03 09:47:30 -05:00
|
|
|
"GRID\n"
|
|
|
|
"PORO\n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMX \n"
|
|
|
|
"1000*1 /\n"
|
|
|
|
"PERMY \n"
|
|
|
|
"1000*0.1 /\n"
|
|
|
|
"PERMZ \n"
|
|
|
|
"1000*0.01 /\n"
|
2019-12-02 04:12:17 -06:00
|
|
|
"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 3 9 '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"
|
|
|
|
"/\n"
|
|
|
|
"WELOPEN \n"
|
|
|
|
" 'OP_1' 'OPEN' /\n"
|
|
|
|
"/\n"
|
|
|
|
"DATES -- 2\n"
|
|
|
|
" 20 JAN 2010 / \n"
|
|
|
|
"/\n"
|
|
|
|
"WELOPEN \n"
|
|
|
|
" 'OP_1' 'SHUT' 0 0 0 2* /\n"
|
|
|
|
"/\n";
|
|
|
|
|
|
|
|
|
|
|
|
auto deck = parser.parseString(input);
|
2020-03-31 03:26:55 -05:00
|
|
|
auto python = std::make_shared<Python>();
|
2019-12-02 04:12:17 -06:00
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
|
|
|
TableManager table ( deck );
|
2020-01-16 11:20:31 -06:00
|
|
|
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
2019-12-02 04:12:17 -06:00
|
|
|
Opm::Runspec runspec (deck);
|
2020-03-26 09:31:21 -05:00
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
2019-12-02 04:12:17 -06:00
|
|
|
{
|
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 1);
|
|
|
|
BOOST_CHECK(op_1.getStatus() == Well::Status::OPEN);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& op_1 = schedule.getWell("OP_1", 2);
|
|
|
|
BOOST_CHECK(op_1.getStatus() == Well::Status::SHUT);
|
|
|
|
}
|
|
|
|
}
|
2020-02-27 07:29:01 -06:00
|
|
|
|
|
|
|
|
2020-03-03 01:47:44 -06:00
|
|
|
BOOST_AUTO_TEST_CASE(WellTypeTest) {
|
|
|
|
BOOST_CHECK_THROW(Opm::WellType(0, 3), std::invalid_argument);
|
|
|
|
BOOST_CHECK_THROW(Opm::WellType(5, 3), std::invalid_argument);
|
|
|
|
BOOST_CHECK_THROW(Opm::WellType(3, 0), std::invalid_argument);
|
|
|
|
BOOST_CHECK_THROW(Opm::WellType(3, 5), std::invalid_argument);
|
|
|
|
|
|
|
|
Opm::WellType wt1(1,1);
|
|
|
|
BOOST_CHECK(wt1.producer());
|
|
|
|
BOOST_CHECK(!wt1.injector());
|
|
|
|
BOOST_CHECK_EQUAL(wt1.ecl_wtype(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(wt1.ecl_phase(), 1);
|
|
|
|
BOOST_CHECK(wt1.preferred_phase() == Phase::OIL);
|
|
|
|
BOOST_CHECK_THROW(wt1.injector_type(), std::invalid_argument);
|
|
|
|
|
|
|
|
Opm::WellType wt4(4,3);
|
|
|
|
BOOST_CHECK(!wt4.producer());
|
|
|
|
BOOST_CHECK(wt4.injector());
|
|
|
|
BOOST_CHECK_EQUAL(wt4.ecl_wtype(), 4);
|
|
|
|
BOOST_CHECK_EQUAL(wt4.ecl_phase(), 3);
|
|
|
|
BOOST_CHECK(wt4.preferred_phase() == Phase::GAS);
|
|
|
|
BOOST_CHECK(wt4.injector_type() == InjectorType::GAS);
|
|
|
|
|
|
|
|
BOOST_CHECK(wt4.update(true));
|
|
|
|
BOOST_CHECK(!wt4.update(true));
|
|
|
|
BOOST_CHECK(wt4.producer());
|
|
|
|
BOOST_CHECK(!wt4.injector());
|
|
|
|
BOOST_CHECK_EQUAL(wt4.ecl_wtype(), 1);
|
|
|
|
BOOST_CHECK_EQUAL(wt4.ecl_phase(), 3);
|
|
|
|
BOOST_CHECK(wt4.preferred_phase() == Phase::GAS);
|
|
|
|
|
|
|
|
Opm::WellType wtp(false, Phase::WATER);
|
|
|
|
BOOST_CHECK(!wtp.producer());
|
|
|
|
BOOST_CHECK(wtp.injector());
|
|
|
|
BOOST_CHECK_EQUAL(wtp.ecl_wtype(), 3);
|
|
|
|
BOOST_CHECK_EQUAL(wtp.ecl_phase(), 2);
|
|
|
|
BOOST_CHECK(wtp.preferred_phase() == Phase::WATER);
|
|
|
|
BOOST_CHECK(wtp.injector_type() == InjectorType::WATER);
|
|
|
|
|
|
|
|
wtp.update( InjectorType::GAS );
|
|
|
|
BOOST_CHECK_EQUAL(wtp.ecl_wtype(), 4);
|
|
|
|
BOOST_CHECK_EQUAL(wtp.ecl_phase(), 2);
|
2020-10-13 09:30:03 -05:00
|
|
|
BOOST_CHECK(wtp.preferred_phase() == Phase::GAS);
|
2020-03-03 01:47:44 -06:00
|
|
|
BOOST_CHECK(wtp.injector_type() == InjectorType::GAS);
|
|
|
|
}
|
2020-03-20 11:21:58 -05:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Injector_Control_Mode) {
|
|
|
|
using IMode = ::Opm::Well::InjectorCMode;
|
|
|
|
using IType = ::Opm::InjectorType;
|
2020-10-07 10:39:31 -05:00
|
|
|
|
2021-06-18 02:09:33 -05:00
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::GRUP, IType::GAS), -1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::GRUP, IType::WATER), -1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::GRUP, IType::MULTI), -1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::GRUP, IType::OIL), -1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RATE, IType::OIL), 1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RATE, IType::WATER), 2);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RATE, IType::GAS), 3);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RATE, IType::MULTI), -10);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RESV, IType::GAS), 5);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RESV, IType::WATER), 5);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RESV, IType::MULTI), 5);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::RESV, IType::OIL), 5);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::THP, IType::GAS), 6);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::THP, IType::WATER), 6);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::THP, IType::MULTI), 6);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::THP, IType::OIL), 6);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::BHP, IType::GAS), 7);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::BHP, IType::WATER), 7);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::BHP, IType::MULTI), 7);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::BHP, IType::OIL), 7);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(IMode::CMODE_UNDEFINED, IType::WATER), -10);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(static_cast<IMode>(1729), IType::WATER), -10);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(static_cast<IMode>(1729), IType::WATER), -10); // Unknown combination
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(static_cast<IMode>(1729), IType::WATER), -10); // Unknown combination
|
2020-03-20 11:21:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Producer_Control_Mode) {
|
|
|
|
using PMode = ::Opm::Well::ProducerCMode;
|
2020-03-31 09:20:19 -05:00
|
|
|
|
2021-06-18 02:09:33 -05:00
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::GRUP), -1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::ORAT), 1);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::WRAT), 2);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::GRAT), 3);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::LRAT), 4);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::RESV), 5);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::THP ), 6);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::BHP ), 7);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::CRAT), 9);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::NONE), -10);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(PMode::CMODE_UNDEFINED), -10);
|
|
|
|
BOOST_CHECK_EQUAL(Well::eclipseControlMode(static_cast<PMode>(271828)), -10);
|
2020-10-07 10:39:31 -05:00
|
|
|
}
|
2020-03-31 09:20:19 -05:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(WPIMULT) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input = R"(
|
|
|
|
START -- 0
|
|
|
|
19 JUN 2007 /
|
2020-04-15 03:45:32 -05:00
|
|
|
|
|
|
|
REGIONS
|
|
|
|
|
|
|
|
PVTNUM
|
|
|
|
1000*77 /
|
|
|
|
|
2021-11-03 09:47:30 -05:00
|
|
|
GRID
|
|
|
|
PORO
|
|
|
|
1000*0.1 /
|
|
|
|
PERMX
|
|
|
|
1000*1 /
|
|
|
|
PERMY
|
|
|
|
1000*0.1 /
|
|
|
|
PERMZ
|
|
|
|
1000*0.01 /
|
2020-03-31 09:20:19 -05:00
|
|
|
SCHEDULE
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'OP_1' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
2020-04-15 03:45:32 -05:00
|
|
|
'OP_2' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 66 /
|
2020-03-31 09:20:19 -05:00
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'OP_1' 9 9 1 1 'OPEN' 1* 1.0 0.311 3047.839 1* 1* 'X' 22.100 /
|
|
|
|
'OP_1' 9 9 2 2 'OPEN' 1* 2.0 0.311 3047.839 1* 1* 'X' 22.100 /
|
|
|
|
'OP_1' 9 9 3 3 'OPEN' 1* 3.0 0.311 4332.346 1* 1* 'X' 22.123 /
|
|
|
|
/
|
|
|
|
DATES -- 1
|
|
|
|
20 JAN 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
-- Should not hit any connections
|
|
|
|
WPIMULT
|
|
|
|
'OP_1' 2 5 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 2
|
|
|
|
20 FEB 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
--
|
|
|
|
WPIMULT
|
|
|
|
'OP_1' 2 9 9 1 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 3
|
|
|
|
20 MAR 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
--
|
|
|
|
WPIMULT
|
|
|
|
'OP_1' 2 9 9 2 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 4
|
|
|
|
20 APR 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
--
|
|
|
|
WPIMULT
|
|
|
|
'OP_1' 2 9 9 3 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 5
|
|
|
|
20 JUN 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
--
|
|
|
|
WPIMULT
|
|
|
|
'OP_1' 0.5 /
|
|
|
|
/
|
|
|
|
|
|
|
|
)";
|
|
|
|
|
|
|
|
|
|
|
|
auto deck = parser.parseString(input);
|
|
|
|
const auto& units = deck.getActiveUnitSystem();
|
|
|
|
auto python = std::make_shared<Opm::Python>();
|
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
|
|
|
TableManager table ( deck );
|
|
|
|
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
|
|
|
Opm::Runspec runspec (deck);
|
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
|
|
|
const auto CF0 = units.to_si(Opm::UnitSystem::measure::transmissibility, 1.0);
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 0);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 1.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 3.0 * CF0, 1e-6);
|
2020-04-15 03:45:32 -05:00
|
|
|
BOOST_CHECK_EQUAL( well.pvt_table_number(), 77);
|
|
|
|
|
|
|
|
const auto& well2 = schedule.getWell("OP_2", 0);
|
|
|
|
BOOST_CHECK_EQUAL( well2.pvt_table_number(), 66);
|
2020-03-31 09:20:19 -05:00
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 1);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 1.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 3.0 * CF0, 1e-6);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 2);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 3.0 * CF0, 1e-6);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 3);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 4.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 3.0 * CF0, 1e-6);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 4);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 4.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 6.0 * CF0, 1e-6);
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& well = schedule.getWell("OP_1", 5);
|
|
|
|
const auto& connections = well.getConnections();
|
|
|
|
BOOST_CHECK_CLOSE( connections[0].CF(), 1.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[1].CF(), 2.0 * CF0, 1e-6);
|
|
|
|
BOOST_CHECK_CLOSE( connections[2].CF(), 3.0 * CF0, 1e-6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-09-09 08:07:55 -05:00
|
|
|
BOOST_AUTO_TEST_CASE(FIRST_OPEN) {
|
|
|
|
Opm::Parser parser;
|
|
|
|
std::string input = R"(
|
|
|
|
START -- 0
|
|
|
|
19 JUN 2007 /
|
|
|
|
|
|
|
|
REGIONS
|
|
|
|
|
|
|
|
PVTNUM
|
|
|
|
1000*77 /
|
|
|
|
|
2021-11-03 09:47:30 -05:00
|
|
|
GRID
|
|
|
|
PORO
|
|
|
|
1000*0.1 /
|
|
|
|
PERMX
|
|
|
|
1000*1 /
|
|
|
|
PERMY
|
|
|
|
1000*0.1 /
|
|
|
|
PERMZ
|
|
|
|
1000*0.01 /
|
|
|
|
|
2020-09-09 08:07:55 -05:00
|
|
|
SCHEDULE
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'P' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
|
|
|
'I' 'OP' 9 9 1* 'OIL' 1* 1* 1* 1* 66 /
|
|
|
|
/
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'P' 9 9 2 2 'OPEN' 1* 2.0 0.311 3047.839 1* 1* 'X' 22.100 /
|
|
|
|
'I' 9 9 3 3 'OPEN' 1* 3.0 0.311 4332.346 1* 1* 'X' 22.123 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 1
|
|
|
|
20 JAN 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
DATES -- 2
|
|
|
|
20 FEB 2010 /
|
|
|
|
/
|
|
|
|
|
|
|
|
WCONPROD
|
2020-10-15 02:11:17 -05:00
|
|
|
'P' 'OPEN' 'BHP' 1 2 3 2* 20. 10. 0 13 /
|
2020-09-09 08:07:55 -05:00
|
|
|
/
|
|
|
|
|
|
|
|
WCONINJE
|
|
|
|
'I' 'GAS' 'OPEN' 'RATE' 1000 /
|
|
|
|
/
|
|
|
|
|
|
|
|
|
|
|
|
)";
|
|
|
|
|
|
|
|
|
|
|
|
auto deck = parser.parseString(input);
|
|
|
|
auto python = std::make_shared<Opm::Python>();
|
|
|
|
Opm::EclipseGrid grid(10,10,10);
|
|
|
|
TableManager table ( deck );
|
|
|
|
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
|
|
|
Opm::Runspec runspec (deck);
|
|
|
|
Opm::Schedule schedule(deck, grid , fp, runspec, python);
|
|
|
|
{
|
|
|
|
const auto& iwell = schedule.getWell("I", 0);
|
|
|
|
const auto& pwell = schedule.getWell("P", 0);
|
|
|
|
|
|
|
|
BOOST_CHECK( iwell.getStatus() == Well::Status::SHUT );
|
|
|
|
BOOST_CHECK( pwell.getStatus() == Well::Status::SHUT );
|
|
|
|
BOOST_CHECK( !iwell.hasProduced() );
|
|
|
|
BOOST_CHECK( !pwell.hasProduced() );
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const auto& iwell = schedule.getWell("I", 2);
|
|
|
|
const auto& pwell = schedule.getWell("P", 2);
|
|
|
|
|
|
|
|
BOOST_CHECK( iwell.getStatus() == Well::Status::OPEN );
|
|
|
|
BOOST_CHECK( pwell.getStatus() == Well::Status::OPEN );
|
|
|
|
BOOST_CHECK( !iwell.hasProduced() );
|
|
|
|
BOOST_CHECK( pwell.hasProduced() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-07 16:20:26 -05:00
|
|
|
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 /
|
|
|
|
/
|
|
|
|
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState{ deck };
|
|
|
|
const auto sched = Schedule{ deck, es };
|
|
|
|
|
|
|
|
const auto expectCF = 100.0*cp_rm3_per_db();
|
|
|
|
|
|
|
|
auto wellP = sched.getWell("P", 0);
|
|
|
|
|
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), expectCF, 1.0e-10);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Simulate applying WELPI before WELPI keyword. No effect.
|
2020-10-18 18:46:38 -05:00
|
|
|
{
|
|
|
|
std::vector<bool> scalingApplicable;
|
|
|
|
wellP.applyWellProdIndexScaling(2.7182818, scalingApplicable);
|
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), expectCF, 1.0e-10);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const bool applicable : scalingApplicable) {
|
|
|
|
BOOST_CHECK_MESSAGE(! applicable, "No connection must be eligible for WELPI scaling");
|
|
|
|
}
|
2020-10-07 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Simulate applying WELPI after seeing
|
|
|
|
//
|
|
|
|
// WELPI
|
|
|
|
// P 2 /
|
|
|
|
// /
|
|
|
|
//
|
|
|
|
// (ignoring units of measure)
|
2021-02-11 04:05:09 -06:00
|
|
|
BOOST_CHECK_MESSAGE(wellP.updateWellProductivityIndex(),
|
2020-10-13 10:06:58 -05:00
|
|
|
"First call to updateWellProductivityIndex() must be a state change");
|
2021-02-11 04:05:09 -06:00
|
|
|
BOOST_CHECK_MESSAGE(!wellP.updateWellProductivityIndex(),
|
2020-10-13 10:06:58 -05:00
|
|
|
"Second call to updateWellProductivityIndex() must NOT be a state change");
|
2020-10-07 16:20:26 -05:00
|
|
|
|
|
|
|
// Want PI=2, but actual/effective PI=1 => scale CF by 2.0/1.0.
|
2020-10-18 17:57:43 -05:00
|
|
|
{
|
2021-02-11 04:05:09 -06:00
|
|
|
const auto scalingFactor = wellP.convertDeckPI(2.0) / liquid_PI_unit();
|
2020-10-18 17:57:43 -05:00
|
|
|
BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10);
|
|
|
|
|
2020-10-18 18:46:38 -05:00
|
|
|
std::vector<bool> scalingApplicable;
|
|
|
|
wellP.applyWellProdIndexScaling(scalingFactor, scalingApplicable);
|
2020-10-18 17:57:43 -05:00
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), 2.0*expectCF, 1.0e-10);
|
|
|
|
}
|
2020-10-18 18:46:38 -05:00
|
|
|
|
|
|
|
for (const bool applicable : scalingApplicable) {
|
|
|
|
BOOST_CHECK_MESSAGE(applicable, "All connections must be eligible for WELPI scaling");
|
|
|
|
}
|
2020-10-07 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// Repeated application of WELPI multiplies scaling factors.
|
2020-10-18 17:57:43 -05:00
|
|
|
{
|
2021-02-11 04:05:09 -06:00
|
|
|
const auto scalingFactor = wellP.convertDeckPI(2.0) / liquid_PI_unit();
|
2020-10-18 17:57:43 -05:00
|
|
|
BOOST_CHECK_CLOSE(scalingFactor, 2.0, 1.0e-10);
|
|
|
|
|
2020-10-18 18:46:38 -05:00
|
|
|
std::vector<bool> scalingApplicable;
|
|
|
|
wellP.applyWellProdIndexScaling(scalingFactor, scalingApplicable);
|
2020-10-18 17:57:43 -05:00
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10);
|
|
|
|
}
|
2020-10-18 18:46:38 -05:00
|
|
|
|
|
|
|
for (const bool applicable : scalingApplicable) {
|
|
|
|
BOOST_CHECK_MESSAGE(applicable, "All connections must be eligible for WELPI scaling");
|
|
|
|
}
|
2020-10-07 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
// New WELPI record does not reset the scaling factors
|
2021-02-11 04:05:09 -06:00
|
|
|
wellP.updateWellProductivityIndex();
|
2020-10-07 16:20:26 -05:00
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Effective PI=desired PI => no scaling change
|
2020-10-18 17:57:43 -05:00
|
|
|
{
|
2021-02-11 04:05:09 -06:00
|
|
|
const auto scalingFactor = wellP.convertDeckPI(3.0) / (3.0*liquid_PI_unit());
|
2020-10-18 17:57:43 -05:00
|
|
|
BOOST_CHECK_CLOSE(scalingFactor, 1.0, 1.0e-10);
|
|
|
|
|
2020-10-18 18:46:38 -05:00
|
|
|
std::vector<bool> scalingApplicable;
|
|
|
|
wellP.applyWellProdIndexScaling(scalingFactor, scalingApplicable);
|
2020-10-18 17:57:43 -05:00
|
|
|
for (const auto& conn : wellP.getConnections()) {
|
|
|
|
BOOST_CHECK_CLOSE(conn.CF(), 4.0*expectCF, 1.0e-10);
|
|
|
|
}
|
2020-10-18 18:46:38 -05:00
|
|
|
|
|
|
|
for (const bool applicable : scalingApplicable) {
|
|
|
|
BOOST_CHECK_MESSAGE(applicable, "All connections must be eligible for WELPI scaling");
|
|
|
|
}
|
2020-10-07 16:20:26 -05:00
|
|
|
}
|
|
|
|
}
|
2020-10-18 18:24:11 -05:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Has_Same_Connections_Pointers) {
|
|
|
|
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 /
|
|
|
|
/
|
|
|
|
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState{ deck };
|
|
|
|
const auto sched = Schedule{ deck, es };
|
|
|
|
|
|
|
|
const auto wellP = sched.getWell("P", 0);
|
|
|
|
auto wellQ = wellP;
|
|
|
|
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.hasSameConnectionsPointers(wellQ),
|
|
|
|
"P and Q must have the same internal connections pointers");
|
|
|
|
|
|
|
|
auto connQ = std::make_shared<WellConnections>(wellP.getConnections());
|
2021-09-01 08:44:25 -05:00
|
|
|
wellQ.updateConnections(std::move(connQ), true);
|
2020-10-18 18:24:11 -05:00
|
|
|
BOOST_CHECK_MESSAGE(! wellP.hasSameConnectionsPointers(wellQ),
|
|
|
|
"P and Q must NOT have the same internal connections pointers "
|
|
|
|
"after forcibly updating the connections structure");
|
|
|
|
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.getConnections() == wellQ.getConnections(),
|
|
|
|
"P and Q must have same WellConnections VALUE");
|
|
|
|
}
|
2020-10-22 10:04:40 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(REPERF) {
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
START
|
|
|
|
7 OCT 2020 /
|
|
|
|
|
|
|
|
DIMENS
|
|
|
|
10 10 4 /
|
|
|
|
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
4*10.0 /
|
|
|
|
|
|
|
|
DEPTHZ
|
|
|
|
121*2000.0 /
|
|
|
|
|
|
|
|
PERMX
|
|
|
|
400*100.0 /
|
|
|
|
PERMY
|
|
|
|
400*100.0 /
|
|
|
|
PERMZ
|
|
|
|
400*10.0 /
|
|
|
|
PORO
|
|
|
|
400*0.3 /
|
|
|
|
|
|
|
|
SCHEDULE
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'W1' 'G' 1 1 1* 'OIL' 2* 'STOP' 4* /
|
|
|
|
/
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'W1' 1 1 4 4 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
|
|
|
|
'W1' 1 1 3 3 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
|
|
|
|
/
|
|
|
|
-- W0
|
|
|
|
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'W1' 1 1 2 2 'OPEN' 1* 25.620 0.216 2086.842 2* 'Y' 8.486 /
|
|
|
|
/
|
|
|
|
|
|
|
|
-- W1
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
WELSPECS
|
Support Changing Selected Well Properties Through WELSPECS
This commit enables updating individual well properties for one or
more wells using the WELSPECS keyword. In particular, this revised
logic enables changing the controlling group without affecting any
other well property such as the location of the well head or the
well reference depth.
Defaulted properties do not affect change in Well::update*(). This,
in turn, begets a change to the logic of how we update the reference
depths. Previously, we always interpreted a defaulted reference
depth item as
Compute the reference depth from the location of the well's
reservoir connections
We now alter this interpretation slightly to mean
Don't recompute the reference depth if the input has already
assigned a numerical value for this property
If the input has never assigned an explicit numerical value for the
reference depth, then we continue using the original interpretation
of a defaulted reference depth item--e.g., to update the reference
depth as a result of new reservoir connections.
The simulation can request the original interpretation even after
having assigned a numeric reference depth, by entering a new
WELSPECS keyword specifying a negative value for the the reference
depth item.
To this end, introduce a new data member in the Well class,
bool Well::derive_refdepth_from_conns_
which tracks whether or not the reference depth has been assigned an
explicit numeric value.
As an example, this new WELSPECS behaviour enables using something
like
ACTIONX
A 1 /
WOPR 'P*' < 123.4 /
/
WELSPECS
'?' 'LOWPRESS' /
/
ENDACTIO
as a way to move all wells matching the pattern 'P*', and with a low
oil production rate, to the group 'LOWPRESS'. This could, in turn,
apply a different set of group-level production controls to those
wells.
2023-10-06 04:29:10 -05:00
|
|
|
'W1' 'G' 1 1 1995.0 'LIQ' /
|
2020-10-22 10:04:40 -05:00
|
|
|
/
|
|
|
|
|
|
|
|
-- W2
|
|
|
|
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'W1' 'G' 1 1 1* 'LIQ' /
|
|
|
|
/
|
|
|
|
-- W3
|
|
|
|
|
2021-01-04 11:39:45 -06:00
|
|
|
WPAVEDEP
|
|
|
|
'W1' 0 /
|
|
|
|
/
|
|
|
|
|
2020-10-22 10:04:40 -05:00
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'W1' 1 1 1 1 'OPEN' 1* 25.620 0.216 2086.842 2* 'Y' 8.486 /
|
|
|
|
/
|
|
|
|
-- W4
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
WELSPECS
|
Support Changing Selected Well Properties Through WELSPECS
This commit enables updating individual well properties for one or
more wells using the WELSPECS keyword. In particular, this revised
logic enables changing the controlling group without affecting any
other well property such as the location of the well head or the
well reference depth.
Defaulted properties do not affect change in Well::update*(). This,
in turn, begets a change to the logic of how we update the reference
depths. Previously, we always interpreted a defaulted reference
depth item as
Compute the reference depth from the location of the well's
reservoir connections
We now alter this interpretation slightly to mean
Don't recompute the reference depth if the input has already
assigned a numerical value for this property
If the input has never assigned an explicit numerical value for the
reference depth, then we continue using the original interpretation
of a defaulted reference depth item--e.g., to update the reference
depth as a result of new reservoir connections.
The simulation can request the original interpretation even after
having assigned a numeric reference depth, by entering a new
WELSPECS keyword specifying a negative value for the the reference
depth item.
To this end, introduce a new data member in the Well class,
bool Well::derive_refdepth_from_conns_
which tracks whether or not the reference depth has been assigned an
explicit numeric value.
As an example, this new WELSPECS behaviour enables using something
like
ACTIONX
A 1 /
WOPR 'P*' < 123.4 /
/
WELSPECS
'?' 'LOWPRESS' /
/
ENDACTIO
as a way to move all wells matching the pattern 'P*', and with a low
oil production rate, to the group 'LOWPRESS'. This could, in turn,
apply a different set of group-level production controls to those
wells.
2023-10-06 04:29:10 -05:00
|
|
|
'W1' 'G' 1 1 -1.0 'LIQ' /
|
2020-10-22 10:04:40 -05:00
|
|
|
/
|
|
|
|
-- W5
|
|
|
|
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState{ deck };
|
|
|
|
const auto& grid = es.getInputGrid();
|
|
|
|
const auto sched = Schedule{ deck, es };
|
|
|
|
|
|
|
|
const auto& w0 = sched.getWell("W1", 0);
|
|
|
|
const auto& w1 = sched.getWell("W1", 1);
|
|
|
|
const auto& w2 = sched.getWell("W1", 2);
|
|
|
|
const auto& w3 = sched.getWell("W1", 3);
|
|
|
|
const auto& w4 = sched.getWell("W1", 4);
|
|
|
|
const auto& w5 = sched.getWell("W1", 5);
|
|
|
|
|
Support Changing Selected Well Properties Through WELSPECS
This commit enables updating individual well properties for one or
more wells using the WELSPECS keyword. In particular, this revised
logic enables changing the controlling group without affecting any
other well property such as the location of the well head or the
well reference depth.
Defaulted properties do not affect change in Well::update*(). This,
in turn, begets a change to the logic of how we update the reference
depths. Previously, we always interpreted a defaulted reference
depth item as
Compute the reference depth from the location of the well's
reservoir connections
We now alter this interpretation slightly to mean
Don't recompute the reference depth if the input has already
assigned a numerical value for this property
If the input has never assigned an explicit numerical value for the
reference depth, then we continue using the original interpretation
of a defaulted reference depth item--e.g., to update the reference
depth as a result of new reservoir connections.
The simulation can request the original interpretation even after
having assigned a numeric reference depth, by entering a new
WELSPECS keyword specifying a negative value for the the reference
depth item.
To this end, introduce a new data member in the Well class,
bool Well::derive_refdepth_from_conns_
which tracks whether or not the reference depth has been assigned an
explicit numeric value.
As an example, this new WELSPECS behaviour enables using something
like
ACTIONX
A 1 /
WOPR 'P*' < 123.4 /
/
WELSPECS
'?' 'LOWPRESS' /
/
ENDACTIO
as a way to move all wells matching the pattern 'P*', and with a low
oil production rate, to the group 'LOWPRESS'. This could, in turn,
apply a different set of group-level production controls to those
wells.
2023-10-06 04:29:10 -05:00
|
|
|
BOOST_CHECK_CLOSE(w0.getRefDepth() , grid.getCellDepth(0, 0, 2), 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w0.getRefDepth() , w0.getWPaveRefDepth() , 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w1.getRefDepth() , w0.getRefDepth() , 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w2.getRefDepth() , 1995.0 , 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w3.getRefDepth() , 1995.0 , 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w4.getRefDepth() , w3.getRefDepth() , 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w5.getRefDepth() , grid.getCellDepth(0, 0, 0), 1.0e-8);
|
|
|
|
BOOST_CHECK_CLOSE(w5.getWPaveRefDepth(), 0.0 , 1.0e-8);
|
2020-10-22 10:04:40 -05:00
|
|
|
}
|
2021-12-17 05:45:55 -06:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Missing_RefDepth) {
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
START
|
|
|
|
17 DEC 2021 /
|
|
|
|
|
|
|
|
DIMENS
|
|
|
|
10 10 4 /
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
4*10.0 /
|
|
|
|
|
|
|
|
DEPTHZ
|
|
|
|
121*2000.0 /
|
|
|
|
|
|
|
|
PERMX
|
|
|
|
400*100.0 /
|
|
|
|
PERMY
|
|
|
|
400*100.0 /
|
|
|
|
PERMZ
|
|
|
|
400*10.0 /
|
|
|
|
PORO
|
|
|
|
400*0.3 /
|
|
|
|
|
|
|
|
-- Deactivate Cells (1,1,3) And (1,1,4)
|
|
|
|
ACTNUM
|
|
|
|
1 99*1
|
|
|
|
1 99*1
|
|
|
|
0 99*1
|
|
|
|
0 99*1
|
|
|
|
/
|
|
|
|
|
|
|
|
SCHEDULE
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'W1' 'G' 1 1 1* 'OIL' 2* 'STOP' 4* /
|
|
|
|
/
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'W1' 1 1 4 4 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
|
|
|
|
'W1' 1 1 3 3 'OPEN' 1* 34.720 0.216 3095.832 2* 'Y' 12.828 /
|
|
|
|
/
|
|
|
|
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
COMPDAT
|
|
|
|
'W1' 1 1 2 2 'OPEN' 1* 25.620 0.216 2086.842 2* 'Y' 8.486 /
|
|
|
|
/
|
|
|
|
|
|
|
|
TSTEP
|
|
|
|
1 /
|
|
|
|
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState{ deck };
|
|
|
|
const auto sched = Schedule{ deck, es };
|
|
|
|
|
|
|
|
const auto& w0 = sched[0].wells("W1");
|
|
|
|
BOOST_CHECK_MESSAGE(! w0.hasRefDepth(),
|
|
|
|
R"(Well "W1" must NOT have a BHP reference depth at report=1)");
|
|
|
|
BOOST_CHECK_THROW(w0.getRefDepth(), std::logic_error);
|
|
|
|
|
|
|
|
const auto& w1 = sched[1].wells("W1");
|
|
|
|
BOOST_CHECK_MESSAGE(w1.hasRefDepth(),
|
|
|
|
R"(Well "W1" must have a BHP reference depth at report=2)");
|
|
|
|
BOOST_CHECK_CLOSE(w1.getRefDepth(), es.getInputGrid().getCellDepth(0, 0, 1), 1.0e-8);
|
|
|
|
}
|
Support Changing Selected Well Properties Through WELSPECS
This commit enables updating individual well properties for one or
more wells using the WELSPECS keyword. In particular, this revised
logic enables changing the controlling group without affecting any
other well property such as the location of the well head or the
well reference depth.
Defaulted properties do not affect change in Well::update*(). This,
in turn, begets a change to the logic of how we update the reference
depths. Previously, we always interpreted a defaulted reference
depth item as
Compute the reference depth from the location of the well's
reservoir connections
We now alter this interpretation slightly to mean
Don't recompute the reference depth if the input has already
assigned a numerical value for this property
If the input has never assigned an explicit numerical value for the
reference depth, then we continue using the original interpretation
of a defaulted reference depth item--e.g., to update the reference
depth as a result of new reservoir connections.
The simulation can request the original interpretation even after
having assigned a numeric reference depth, by entering a new
WELSPECS keyword specifying a negative value for the the reference
depth item.
To this end, introduce a new data member in the Well class,
bool Well::derive_refdepth_from_conns_
which tracks whether or not the reference depth has been assigned an
explicit numeric value.
As an example, this new WELSPECS behaviour enables using something
like
ACTIONX
A 1 /
WOPR 'P*' < 123.4 /
/
WELSPECS
'?' 'LOWPRESS' /
/
ENDACTIO
as a way to move all wells matching the pattern 'P*', and with a low
oil production rate, to the group 'LOWPRESS'. This could, in turn,
apply a different set of group-level production controls to those
wells.
2023-10-06 04:29:10 -05:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Update_Group_Single_Well)
|
|
|
|
{
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
DIMENS
|
|
|
|
10 10 3 /
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
3*5.0 /
|
|
|
|
DEPTHZ
|
|
|
|
121*2000 /
|
|
|
|
PERMX
|
|
|
|
300*100.0 /
|
|
|
|
COPY
|
|
|
|
PERMX PERMY /
|
|
|
|
PERMX PERMZ /
|
|
|
|
/
|
|
|
|
MULTIPLY
|
|
|
|
PERMZ 0.1 /
|
|
|
|
/
|
|
|
|
PORO
|
|
|
|
300*0.3 /
|
|
|
|
SCHEDULE
|
|
|
|
WELSPECS
|
|
|
|
'P' 'G' 10 10 1* 'OIL' /
|
|
|
|
'I' 'G' 1 1 1* 'GAS' /
|
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'P' 10 10 1 3 'OPEN' /
|
|
|
|
'I' 1 1 1 1 'OPEN' /
|
|
|
|
/
|
|
|
|
WCONPROD
|
|
|
|
'P' 'OPEN' 'LRAT' 1* 1* 1* 1234.567 1* 12.34 /
|
|
|
|
/
|
|
|
|
WCONINJE
|
|
|
|
'I' 'GAS' 'OPEN' 'RATE' 20.0E3 /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
WELSPECS
|
|
|
|
'P' 'G1' /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState { deck };
|
|
|
|
const auto sched = Schedule { deck, es };
|
|
|
|
|
|
|
|
{
|
|
|
|
const auto& wellP = sched.getWell("P", 0);
|
|
|
|
BOOST_CHECK_EQUAL(wellP.groupName(), "G");
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const auto& wellP = sched.getWell("P", 1);
|
|
|
|
BOOST_CHECK_EQUAL(wellP.groupName(), "G1");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Update_Group_Multi_Well)
|
|
|
|
{
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
DIMENS
|
|
|
|
10 10 3 /
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
3*5.0 /
|
|
|
|
DEPTHZ
|
|
|
|
121*2000 /
|
|
|
|
PERMX
|
|
|
|
300*100.0 /
|
|
|
|
COPY
|
|
|
|
PERMX PERMY /
|
|
|
|
PERMX PERMZ /
|
|
|
|
/
|
|
|
|
MULTIPLY
|
|
|
|
PERMZ 0.1 /
|
|
|
|
/
|
|
|
|
PORO
|
|
|
|
300*0.3 /
|
|
|
|
SCHEDULE
|
|
|
|
WELSPECS
|
|
|
|
'P1' 'G' 1 10 1* 'OIL' /
|
|
|
|
'P2' 'G' 10 1 1* 'OIL' /
|
|
|
|
'P3' 'G' 10 10 1* 'OIL' /
|
|
|
|
'I' 'G' 1 1 1* 'GAS' /
|
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'P1' 1 10 1 3 'OPEN' /
|
|
|
|
'P2' 10 1 1 3 'OPEN' /
|
|
|
|
'P3' 10 10 1 3 'OPEN' /
|
|
|
|
'I' 1 1 1 1 'OPEN' /
|
|
|
|
/
|
|
|
|
WCONPROD
|
|
|
|
'P*' 'OPEN' 'LRAT' 1* 1* 1* 1234.567 1* 12.34 /
|
|
|
|
/
|
|
|
|
WCONINJE
|
|
|
|
'I' 'GAS' 'OPEN' 'RATE' 20.0E3 /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
WELSPECS
|
|
|
|
'P*' 'G1' /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState { deck };
|
|
|
|
const auto sched = Schedule { deck, es };
|
|
|
|
|
|
|
|
{
|
|
|
|
for (const auto* P : { "P1", "P2", "P3", }) {
|
|
|
|
const auto& wellP = sched.getWell(P, 0);
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.groupName() == "G",
|
|
|
|
"Well " << P << " must have "
|
|
|
|
"controlling group \"G\" at time zero");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
for (const auto* P : { "P1", "P2", "P3", }) {
|
|
|
|
const auto& wellP = sched.getWell(P, 1);
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.groupName() == "G1",
|
|
|
|
"Well " << P << " must have "
|
|
|
|
"controlling group \"G1\" at time one");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(Update_Group_WList)
|
|
|
|
{
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
DIMENS
|
|
|
|
10 10 3 /
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
3*5.0 /
|
|
|
|
DEPTHZ
|
|
|
|
121*2000 /
|
|
|
|
PERMX
|
|
|
|
300*100.0 /
|
|
|
|
COPY
|
|
|
|
PERMX PERMY /
|
|
|
|
PERMX PERMZ /
|
|
|
|
/
|
|
|
|
MULTIPLY
|
|
|
|
PERMZ 0.1 /
|
|
|
|
/
|
|
|
|
PORO
|
|
|
|
300*0.3 /
|
|
|
|
SCHEDULE
|
|
|
|
WELSPECS
|
|
|
|
'P1' 'G' 1 10 1* 'OIL' /
|
|
|
|
'P2' 'G' 10 1 1* 'OIL' /
|
|
|
|
'P3' 'G' 10 10 1* 'OIL' /
|
|
|
|
'I' 'G' 1 1 1* 'GAS' /
|
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'P1' 1 10 1 3 'OPEN' /
|
|
|
|
'P2' 10 1 1 3 'OPEN' /
|
|
|
|
'P3' 10 10 1 3 'OPEN' /
|
|
|
|
'I' 1 1 1 1 'OPEN' /
|
|
|
|
/
|
|
|
|
WLIST
|
|
|
|
'*QFS' NEW 'I' 'P3' /
|
|
|
|
/
|
|
|
|
WCONPROD
|
|
|
|
'P*' 'OPEN' 'LRAT' 1* 1* 1* 1234.567 1* 12.34 /
|
|
|
|
/
|
|
|
|
WCONINJE
|
|
|
|
'I' 'GAS' 'OPEN' 'RATE' 20.0E3 /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
WELSPECS
|
|
|
|
'*QFS' 'G1' /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState { deck };
|
|
|
|
const auto sched = Schedule { deck, es };
|
|
|
|
|
|
|
|
{
|
|
|
|
for (const auto* P : { "P1", "P2", "P3", "I", }) {
|
|
|
|
const auto& wellP = sched.getWell(P, 0);
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.groupName() == "G",
|
|
|
|
"Well " << P << " must have "
|
|
|
|
"controlling group \"G\" at time zero");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
for (const auto* P : { "P1", "P2", }) {
|
|
|
|
const auto& wellP = sched.getWell(P, 1);
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.groupName() == "G",
|
|
|
|
"Well " << P << " must have "
|
|
|
|
"controlling group \"G\" at time one");
|
|
|
|
}
|
|
|
|
|
|
|
|
for (const auto* P : { "P3", "I", }) {
|
|
|
|
const auto& wellP = sched.getWell(P, 1);
|
|
|
|
BOOST_CHECK_MESSAGE(wellP.groupName() == "G1",
|
|
|
|
"Well " << P << " must have "
|
|
|
|
"controlling group \"G1\" at time one");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-02 08:41:14 -05:00
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(FBHPDEF_Basic)
|
|
|
|
{
|
|
|
|
const auto deck = Parser{}.parseString(R"(RUNSPEC
|
|
|
|
DIMENS
|
|
|
|
10 10 3 /
|
|
|
|
GRID
|
|
|
|
DXV
|
|
|
|
10*100.0 /
|
|
|
|
DYV
|
|
|
|
10*100.0 /
|
|
|
|
DZV
|
|
|
|
3*5.0 /
|
|
|
|
DEPTHZ
|
|
|
|
121*2000 /
|
|
|
|
PERMX
|
|
|
|
300*100.0 /
|
|
|
|
COPY
|
|
|
|
PERMX PERMY /
|
|
|
|
PERMX PERMZ /
|
|
|
|
/
|
|
|
|
MULTIPLY
|
|
|
|
PERMZ 0.1 /
|
|
|
|
/
|
|
|
|
PORO
|
|
|
|
300*0.3 /
|
|
|
|
SCHEDULE
|
|
|
|
|
|
|
|
WELSPECS
|
|
|
|
'P' 'G' 10 10 1* 'OIL' /
|
|
|
|
'I' 'G' 1 1 1* 'GAS' /
|
|
|
|
'I2' 'W' 1 1 1* 'WATER' /
|
|
|
|
'I3' 'W' 1 1 1* 'WATER' /
|
|
|
|
/
|
|
|
|
COMPDAT
|
|
|
|
'P' 10 10 1 3 'OPEN' /
|
|
|
|
'I' 1 1 1 1 'OPEN' /
|
|
|
|
'I2' 1 1 1 1 'OPEN' /
|
|
|
|
'I3' 1 1 1 1 'OPEN' /
|
|
|
|
/
|
|
|
|
|
|
|
|
WCONINJH
|
|
|
|
I3 WATER OPEN 116281 1* 0 /
|
|
|
|
/
|
|
|
|
|
|
|
|
FBHPDEF
|
|
|
|
5.0 20.0 /
|
|
|
|
|
|
|
|
WCONPROD
|
|
|
|
'P' 'OPEN' 'LRAT' 1* 1* 1* 1234.567 1* 1* /
|
|
|
|
/
|
|
|
|
|
|
|
|
WCONINJH
|
|
|
|
I2 WATER OPEN 116281 1* 0 /
|
|
|
|
/
|
|
|
|
|
|
|
|
FBHPDEF
|
|
|
|
2.0 30.0 /
|
|
|
|
|
|
|
|
WCONINJE
|
|
|
|
'I' 'GAS' 'OPEN' 'RATE' 20.0E3 /
|
|
|
|
/
|
|
|
|
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
WELSPECS
|
|
|
|
'P' 'G1' /
|
|
|
|
/
|
|
|
|
TSTEP
|
|
|
|
30.0 /
|
|
|
|
END
|
|
|
|
)");
|
|
|
|
|
|
|
|
const auto es = EclipseState { deck };
|
|
|
|
const auto sched = Schedule { deck, es };
|
|
|
|
|
|
|
|
const auto& wellP = sched.getWell("P", 0);
|
|
|
|
BOOST_CHECK_EQUAL(wellP.getProductionProperties().BHPTarget.get<double>(), 5.0);
|
|
|
|
|
|
|
|
const auto& wellI = sched.getWell("I", 0);
|
|
|
|
BOOST_CHECK_CLOSE(wellI.getInjectionProperties().BHPTarget.get<double>(), 30.0, 1e-12);
|
|
|
|
|
|
|
|
const auto& wellI2 = sched.getWell("I2", 0);
|
|
|
|
BOOST_CHECK_EQUAL(wellI2.getInjectionProperties().bhp_hist_limit, 20.0 * unit::barsa);
|
|
|
|
|
|
|
|
const auto& wellI3 = sched.getWell("I3", 0);
|
|
|
|
BOOST_CHECK_CLOSE(wellI3.getInjectionProperties().bhp_hist_limit, 6891.2 * unit::barsa, 1e-12);
|
|
|
|
}
|