Support GCONPROD in ACTIONX
This commit is contained in:
parent
bb905eb545
commit
d896b2ce15
@ -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&);
|
||||
|
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user