Merge pull request #2075 from joakim-hove/actionx-gconprod

Actionx gconprod
This commit is contained in:
Joakim Hove 2020-11-09 16:40:40 +01:00 committed by GitHub
commit cddfbb5217
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 87 additions and 13 deletions

View File

@ -496,6 +496,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);
// 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", "WELSPECS","WELOPEN", "UDQ"};
static std::unordered_set<std::string> actionx_allowed_list = {"EXIT", "GCONPROD", "WELSPECS","WELOPEN", "UDQ"};
return (actionx_allowed_list.find(keyword) != actionx_allowed_list.end());
}

View File

@ -322,11 +322,17 @@ namespace {
}
void Schedule::handleGCONPROD(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
for (const auto& record : handlerContext.keyword) {
auto current_step = handlerContext.currentStep;
const auto& keyword = handlerContext.keyword;
this->handleGCONPROD(keyword, current_step, parseContext, errors);
}
void Schedule::handleGCONPROD(const DeckKeyword& keyword, std::size_t current_step, const ParseContext& parseContext, ErrorGuard& errors) {
for (const auto& record : keyword) {
const std::string& groupNamePattern = record.getItem("GROUP").getTrimmedString(0);
const auto group_names = this->groupNames(groupNamePattern);
if (group_names.empty())
invalidNamePattern(groupNamePattern, handlerContext.currentStep, parseContext, errors, handlerContext.keyword);
invalidNamePattern(groupNamePattern, current_step, parseContext, errors, keyword);
const Group::ProductionCMode controlMode = Group::ProductionCModeFromString(record.getItem("CONTROL_MODE").getTrimmedString(0));
const Group::ExceedAction exceedAction = Group::ExceedActionFromString(record.getItem("EXCEED_PROC").getTrimmedString(0));
@ -372,7 +378,7 @@ namespace {
std::string msg_fmt = "Problem with {keyword}\n"
"In {file} line {line}\n"
"The supplied guide rate will be ignored";
parseContext.handleError(ParseContext::SCHEDULE_IGNORED_GUIDE_RATE, msg_fmt, handlerContext.keyword.location(), errors);
parseContext.handleError(ParseContext::SCHEDULE_IGNORED_GUIDE_RATE, msg_fmt, keyword.location(), errors);
} else {
guide_rate = record.getItem("GUIDE_RATE").get<double>(0);
if (guide_rate == 0)
@ -382,7 +388,7 @@ namespace {
}
{
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, handlerContext.currentStep));
auto group_ptr = std::make_shared<Group>(this->getGroup(group_name, current_step));
Group::GroupProductionProperties production(this->unit_system, group_name);
production.gconprod_cmode = controlMode;
production.active_cmode = controlMode;
@ -421,17 +427,17 @@ namespace {
production.production_controls += static_cast<int>(Group::ProductionCMode::RESV);
if (group_ptr->updateProduction(production)) {
auto new_config = std::make_shared<GuideRateConfig>( this->guideRateConfig(handlerContext.currentStep) );
auto new_config = std::make_shared<GuideRateConfig>( this->guideRateConfig(current_step) );
new_config->update_group(*group_ptr);
this->guide_rate_config.update( handlerContext.currentStep, std::move(new_config) );
this->guide_rate_config.update( current_step, std::move(new_config) );
this->updateGroup(std::move(group_ptr), handlerContext.currentStep);
m_events.addEvent(ScheduleEvents::GROUP_PRODUCTION_UPDATE, handlerContext.currentStep);
this->addWellGroupEvent(group_name, ScheduleEvents::GROUP_PRODUCTION_UPDATE, handlerContext.currentStep);
this->updateGroup(std::move(group_ptr), current_step);
m_events.addEvent(ScheduleEvents::GROUP_PRODUCTION_UPDATE, current_step);
this->addWellGroupEvent(group_name, ScheduleEvents::GROUP_PRODUCTION_UPDATE, current_step);
auto udq = std::make_shared<UDQActive>(this->udqActive(handlerContext.currentStep));
if (production.updateUDQActive(this->getUDQConfig(handlerContext.currentStep), *udq))
this->updateUDQActive(handlerContext.currentStep, udq);
auto udq = std::make_shared<UDQActive>(this->udqActive(current_step));
if (production.updateUDQActive(this->getUDQConfig(current_step), *udq))
this->updateUDQActive(current_step, udq);
}
}
}

View File

@ -1496,9 +1496,14 @@ private:
if (keyword.name() == "UDQ")
this->updateUDQ(keyword, reportStep);
if (keyword.name() == "GCONPROD")
this->handleGCONPROD(keyword, reportStep, parseContext, errors);
}
}
void Schedule::applyWellProdIndexScaling(const std::string& well_name, const std::size_t reportStep, const double scalingFactor) {
auto wstat = this->wells_static.find(well_name);
if (wstat == this->wells_static.end())

View File

@ -40,6 +40,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/Action/Actions.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/State.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionX.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Action/ActionResult.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WList.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WListManager.hpp>
#include <opm/parser/eclipse/Deck/Deck.hpp>
@ -928,3 +929,64 @@ ENDACTIO
BOOST_CHECK_EQUAL( st.run_count(action1), 1U);
BOOST_CHECK_EQUAL( st.run_count(action2), 0U);
}
BOOST_AUTO_TEST_CASE(Action_GCONPROD) {
const auto deck_string = std::string{ R"(
SCHEDULE
WELSPECS
'PROD1' 'G1' 1 1 10 'OIL' /
/
GCONPROD
'G1' 'ORAT' 100 /
/
ACTIONX
'A' /
WWCT 'OPX' > 0.75 AND /
FPR < 100 /
/
GCONPROD
'G1' 'ORAT' 200 /
/
ENDACTIO
TSTEP
10 /
)"};
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);
const auto& action1 = sched.actions(0).get("A");
{
const auto& group = sched.getGroup("G1", 0);
const auto& prod = group.productionControls(st);
BOOST_CHECK_CLOSE( prod.oil_target , unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 100), 1e-5 );
}
Action::Result action_result(true);
sched.applyAction(0, action1, action_result);
{
const auto& group = sched.getGroup("G1", 1);
const auto& prod = group.productionControls(st);
BOOST_CHECK_CLOSE( prod.oil_target , unit_system.to_si(UnitSystem::measure::liquid_surface_rate, 200), 1e-5 );
}
}