Merge pull request #2077 from joakim-hove/actionx-gliftopt
Actionx gliftopt
This commit is contained in:
commit
3a1f5bd654
@ -497,6 +497,7 @@ namespace Opm
|
|||||||
// Keyword Handlers
|
// Keyword Handlers
|
||||||
void handlePYACTION (std::shared_ptr<const Python> python, const std::string& input_path, const DeckKeyword&, std::size_t currentStep);
|
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 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
|
// Normal keyword handlers -- in KeywordHandlers.cpp
|
||||||
void handleBRANPROP (const HandlerContext&, const ParseContext&, ErrorGuard&);
|
void handleBRANPROP (const HandlerContext&, const ParseContext&, ErrorGuard&);
|
||||||
|
@ -33,7 +33,7 @@ namespace Action {
|
|||||||
|
|
||||||
|
|
||||||
bool ActionX::valid_keyword(const std::string& keyword) {
|
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());
|
return (actionx_allowed_list.find(keyword) != actionx_allowed_list.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,14 +505,18 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleGLIFTOPT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard&errors) {
|
void Schedule::handleGLIFTOPT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||||
auto glo = std::make_shared<GasLiftOpt>( this->glo(handlerContext.currentStep) );
|
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 std::string& groupNamePattern = record.getItem<ParserKeywords::GLIFTOPT::GROUP_NAME>().getTrimmedString(0);
|
||||||
const auto group_names = this->groupNames(groupNamePattern);
|
const auto group_names = this->groupNames(groupNamePattern);
|
||||||
if (group_names.empty())
|
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 auto& max_gas_item = record.getItem<ParserKeywords::GLIFTOPT::MAX_LIFT_GAS_SUPPLY>();
|
||||||
const double max_lift_gas_value = max_gas_item.hasValue(0)
|
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) {
|
void Schedule::handleGPMAINT(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
|
||||||
|
@ -1499,6 +1499,9 @@ private:
|
|||||||
|
|
||||||
if (keyword.name() == "GCONPROD")
|
if (keyword.name() == "GCONPROD")
|
||||||
this->handleGCONPROD(keyword, reportStep, parseContext, errors);
|
this->handleGCONPROD(keyword, reportStep, parseContext, errors);
|
||||||
|
|
||||||
|
if (keyword.name() == "GLIFTOPT")
|
||||||
|
this->handleGLIFTOPT(keyword, reportStep, parseContext, errors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
"sections": [
|
"sections": [
|
||||||
"SCHEDULE"
|
"SCHEDULE"
|
||||||
],
|
],
|
||||||
|
"requires" : ["LIFTOPT"],
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"name": "GROUP_NAME",
|
"name": "GROUP_NAME",
|
||||||
|
@ -53,6 +53,17 @@
|
|||||||
using namespace Opm;
|
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) {
|
BOOST_AUTO_TEST_CASE(Create) {
|
||||||
@ -128,27 +139,15 @@ ENDACTIO
|
|||||||
TSTEP
|
TSTEP
|
||||||
10 /
|
10 /
|
||||||
)"};
|
)"};
|
||||||
auto python = std::make_shared<Python>();
|
BOOST_CHECK_THROW(make_schedule(MISSING_END), OpmInputError);
|
||||||
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);
|
|
||||||
|
|
||||||
// The ACTIONX keyword has no matching 'ENDACTIO' -> exception
|
Schedule sched = make_schedule(WITH_WELSPECS);
|
||||||
BOOST_CHECK_THROW(Schedule(deck1, grid1, fp, runspec, python), OpmInputError);
|
|
||||||
|
|
||||||
Schedule sched(deck2, grid1, fp, runspec, python);
|
|
||||||
BOOST_CHECK( !sched.hasWell("W1") );
|
BOOST_CHECK( !sched.hasWell("W1") );
|
||||||
BOOST_CHECK( sched.hasWell("W2"));
|
BOOST_CHECK( sched.hasWell("W2"));
|
||||||
|
|
||||||
// The deck3 contains the 'GRID' keyword in the ACTIONX block - that is not a whitelisted keyword.
|
// 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}} );
|
ParseContext parseContext( {{ParseContext::ACTIONX_ILLEGAL_KEYWORD, InputError::THROW_EXCEPTION}} );
|
||||||
ErrorGuard errors;
|
BOOST_CHECK_THROW( make_schedule(WITH_GRID, parseContext), OpmInputError );
|
||||||
BOOST_CHECK_THROW(Schedule(deck3, grid1, fp, runspec, parseContext, errors, python), OpmInputError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -964,16 +963,8 @@ TSTEP
|
|||||||
)"};
|
)"};
|
||||||
|
|
||||||
auto unit_system = UnitSystem::newMETRIC();
|
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() };
|
const auto st = SummaryState{ std::chrono::system_clock::now() };
|
||||||
|
Schedule sched = make_schedule(deck_string);
|
||||||
Runspec runspec (deck);
|
|
||||||
Schedule sched(deck, grid1, fp, runspec, python);
|
|
||||||
const auto& action1 = sched.actions(0).get("A");
|
const auto& action1 = sched.actions(0).get("A");
|
||||||
{
|
{
|
||||||
const auto& group = sched.getGroup("G1", 0);
|
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_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());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user