Merge pull request #2077 from joakim-hove/actionx-gliftopt

Actionx gliftopt
This commit is contained in:
Joakim Hove 2020-11-10 09:36:21 +01:00 committed by GitHub
commit 3a1f5bd654
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 89 additions and 30 deletions

View File

@ -497,6 +497,7 @@ namespace Opm
// Keyword Handlers
void handlePYACTION (std::shared_ptr<const Python> python, const std::string& input_path, const DeckKeyword&, std::size_t currentStep);
void handleGCONPROD(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors);
void handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors);
// Normal keyword handlers -- in KeywordHandlers.cpp
void handleBRANPROP (const HandlerContext&, const ParseContext&, ErrorGuard&);

View File

@ -33,7 +33,7 @@ namespace Action {
bool ActionX::valid_keyword(const std::string& keyword) {
static std::unordered_set<std::string> actionx_allowed_list = {"EXIT", "GCONPROD", "WELSPECS","WELOPEN", "UDQ"};
static std::unordered_set<std::string> actionx_allowed_list = {"EXIT", "GCONPROD", "GLIFTOPT", "WELSPECS","WELOPEN", "UDQ"};
return (actionx_allowed_list.find(keyword) != actionx_allowed_list.end());
}

View File

@ -505,14 +505,18 @@ namespace {
}
}
void Schedule::handleGLIFTOPT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard&errors) {
auto glo = std::make_shared<GasLiftOpt>( this->glo(handlerContext.currentStep) );
void Schedule::handleGLIFTOPT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
this->handleGLIFTOPT(handlerContext.keyword, handlerContext.currentStep, parseContext, errors);
}
for (const auto& record : handlerContext.keyword) {
void Schedule::handleGLIFTOPT(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard&errors) {
auto glo = std::make_shared<GasLiftOpt>( this->glo(report_step) );
for (const auto& record : keyword) {
const std::string& groupNamePattern = record.getItem<ParserKeywords::GLIFTOPT::GROUP_NAME>().getTrimmedString(0);
const auto group_names = this->groupNames(groupNamePattern);
if (group_names.empty())
invalidNamePattern(groupNamePattern, handlerContext.currentStep, parseContext, errors, handlerContext.keyword);
invalidNamePattern(groupNamePattern, report_step, parseContext, errors, keyword);
const auto& max_gas_item = record.getItem<ParserKeywords::GLIFTOPT::MAX_LIFT_GAS_SUPPLY>();
const double max_lift_gas_value = max_gas_item.hasValue(0)
@ -533,7 +537,7 @@ namespace {
}
}
this->m_glo.update(handlerContext.currentStep, std::move(glo));
this->m_glo.update(report_step, std::move(glo));
}
void Schedule::handleGPMAINT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {

View File

@ -1499,6 +1499,9 @@ private:
if (keyword.name() == "GCONPROD")
this->handleGCONPROD(keyword, reportStep, parseContext, errors);
if (keyword.name() == "GLIFTOPT")
this->handleGLIFTOPT(keyword, reportStep, parseContext, errors);
}
}

View File

@ -3,6 +3,7 @@
"sections": [
"SCHEDULE"
],
"requires" : ["LIFTOPT"],
"items": [
{
"name": "GROUP_NAME",

View File

@ -53,6 +53,17 @@
using namespace Opm;
Schedule make_schedule(const std::string& deck_string, const ParseContext& parseContext = {}) {
ErrorGuard errors;
Opm::Parser parser;
auto deck = parser.parseString(deck_string);
EclipseGrid grid1(10,10,10);
TableManager table ( deck );
FieldPropsManager fp( deck, Phases{true, true, true}, grid1, table);
auto python = std::make_shared<Python>();
Runspec runspec (deck);
return Schedule(deck, grid1, fp, runspec, parseContext, errors, python);
}
BOOST_AUTO_TEST_CASE(Create) {
@ -128,27 +139,15 @@ ENDACTIO
TSTEP
10 /
)"};
auto python = std::make_shared<Python>();
Opm::Parser parser;
auto deck1 = parser.parseString(MISSING_END);
auto deck2 = parser.parseString(WITH_WELSPECS);
auto deck3 = parser.parseString(WITH_GRID);
EclipseGrid grid1(10,10,10);
TableManager table ( deck1 );
FieldPropsManager fp( deck1, Phases{true, true, true}, grid1, table);
Runspec runspec (deck1);
BOOST_CHECK_THROW(make_schedule(MISSING_END), OpmInputError);
// The ACTIONX keyword has no matching 'ENDACTIO' -> exception
BOOST_CHECK_THROW(Schedule(deck1, grid1, fp, runspec, python), OpmInputError);
Schedule sched(deck2, grid1, fp, runspec, python);
Schedule sched = make_schedule(WITH_WELSPECS);
BOOST_CHECK( !sched.hasWell("W1") );
BOOST_CHECK( sched.hasWell("W2"));
// The deck3 contains the 'GRID' keyword in the ACTIONX block - that is not a whitelisted keyword.
ParseContext parseContext( {{ParseContext::ACTIONX_ILLEGAL_KEYWORD, InputError::THROW_EXCEPTION}} );
ErrorGuard errors;
BOOST_CHECK_THROW(Schedule(deck3, grid1, fp, runspec, parseContext, errors, python), OpmInputError);
BOOST_CHECK_THROW( make_schedule(WITH_GRID, parseContext), OpmInputError );
}
@ -964,16 +963,8 @@ TSTEP
)"};
auto unit_system = UnitSystem::newMETRIC();
Opm::Parser parser;
auto deck = parser.parseString(deck_string);
EclipseGrid grid1(10,10,10);
TableManager table ( deck );
FieldPropsManager fp( deck, Phases{true, true, true}, grid1, table);
auto python = std::make_shared<Python>();
const auto st = SummaryState{ std::chrono::system_clock::now() };
Runspec runspec (deck);
Schedule sched(deck, grid1, fp, runspec, python);
Schedule sched = make_schedule(deck_string);
const auto& action1 = sched.actions(0).get("A");
{
const auto& group = sched.getGroup("G1", 0);
@ -990,3 +981,62 @@ TSTEP
BOOST_CHECK_CLOSE( prod.oil_target , unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 200), 1e-5 );
}
}
BOOST_AUTO_TEST_CASE(GASLIFT_OPT_DECK) {
const auto input = R"(-- Turns on gas lift optimization
RUNSPEC
LIFTOPT
/
SCHEDULE
GRUPTREE
'PROD' 'FIELD' /
'M5S' 'PLAT-A' /
'M5N' 'PLAT-A' /
'C1' 'M5N' /
'F1' 'M5N' /
'B1' 'M5S' /
'G1' 'M5S' /
/
ACTIONX
'A' /
WWCT 'OPX' > 0.75 AND /
FPR < 100 /
/
GLIFTOPT
'PLAT-A' 200000 / --
/
ENDACTIO
TSTEP
10 /
)";
Opm::UnitSystem unitSystem = UnitSystem( UnitSystem::UnitType::UNIT_TYPE_METRIC );
auto sched = make_schedule(input);
const auto& action1 = sched.actions(0).get("A");
{
const auto& glo = sched.glo(0);
BOOST_CHECK(!glo.has_group("PLAT-A"));
}
Action::Result action_result(true);
sched.applyAction(0, action1, action_result);
{
const auto& glo = sched.glo(0);
BOOST_CHECK(glo.has_group("PLAT-A"));
const auto& plat_group = glo.group("PLAT-A");
BOOST_CHECK_EQUAL( *plat_group.max_lift_gas(), unitSystem.to_si( UnitSystem::measure::gas_surface_rate, 200000));
BOOST_CHECK(!plat_group.max_total_gas().has_value());
}
}