Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Activate WELPI and WPIMULT for use in Pyaction #4136

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
3 changes: 1 addition & 2 deletions msim/src/msim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,8 +141,7 @@ void msim::post_step(data::Solution& /* sol */,
for (const auto& action : actions.pending(this->action_state, std::chrono::system_clock::to_time_t(sim_time))) {
const auto result = action->eval(context);
if (result.conditionSatisfied()) {
this->schedule.applyAction(report_step, *action, result.matches(),
std::unordered_map<std::string,double>{});
this->schedule.applyAction(report_step, *action, result.matches());
}
}

Expand Down
2 changes: 1 addition & 1 deletion opm/input/eclipse/Schedule/Action/PyAction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ bool PyAction::valid_keyword(const std::string& keyword) {
"GCONINJE", "GCONPROD", "GCONSUMP","GRUPTREE",
"METRIC", "MULTX", "MULTX-", "MULTY", "MULTY-", "MULTZ", "MULTZ-",
"NEXT", "NEXTSTEP",
"WCONINJE", "WCONPROD", "WECON", "WEFAC", "WELOPEN", "WELTARG", "WGRUPCON", "WELSEGS", "WELSPECS", "WSEGVALV", "WTEST"
"WCONINJE", "WCONPROD", "WECON", "WEFAC", "WELOPEN", "WELPI", "WELTARG", "WGRUPCON", "WELSEGS", "WELSPECS", "WSEGVALV", "WPIMULT", "WTEST"
};
return pyaction_allowed_list.find(keyword) != pyaction_allowed_list.end();
}
Expand Down
6 changes: 3 additions & 3 deletions opm/input/eclipse/Schedule/HandlerContext.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ class HandlerContext
const ScheduleGrid& grid_,
const std::size_t currentStep_,
const Action::Result::MatchingEntities& matches_,
bool actionx_mode_,
bool welpi_action_mode_,
const ParseContext& parseContext_,
ErrorGuard& errors_,
SimulatorUpdate* sim_update_,
Expand All @@ -73,7 +73,7 @@ class HandlerContext
, keyword(keyword_)
, currentStep(currentStep_)
, matches(matches_)
, actionx_mode(actionx_mode_)
, welpi_action_mode(welpi_action_mode_)
, parseContext(parseContext_)
, errors(errors_)
, wpimult_global_factor(wpimult_global_factor_)
Expand Down Expand Up @@ -166,7 +166,7 @@ class HandlerContext
const DeckKeyword& keyword;
const std::size_t currentStep;
const Action::Result::MatchingEntities& matches;
const bool actionx_mode;
const bool welpi_action_mode;
const ParseContext& parseContext;
ErrorGuard& errors;
std::unordered_map<std::string, double>& wpimult_global_factor;
Expand Down
79 changes: 37 additions & 42 deletions opm/input/eclipse/Schedule/Schedule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,20 +168,20 @@ namespace Opm {

auto restart_step = this->m_static.rst_info.report_step;
this->iterateScheduleSection(0, restart_step, parseContext, errors,
grid, nullptr, "", keepKeywords);
grid, "", keepKeywords);
this->load_rst(*rst, *tracer_config, grid, fp);
if (! this->restart_output.writeRestartFile(restart_step))
this->restart_output.addRestartOutput(restart_step);
this->iterateScheduleSection(restart_step, this->m_sched_deck.size(),
parseContext, errors, grid, nullptr, "", keepKeywords);
parseContext, errors, grid, "", keepKeywords);
// Events added during restart reading well be added to previous step, but need to be active at the
// restart step to ensure well potentials and guide rates are available at the first step.
const auto prev_step = std::max(static_cast<int>(restart_step-1), 0);
this->snapshots[restart_step].update_wellgroup_events(this->snapshots[prev_step].wellgroup_events());
this->snapshots[restart_step].update_events(this->snapshots[prev_step].events());
} else {
this->iterateScheduleSection(0, this->m_sched_deck.size(),
parseContext, errors, grid, nullptr, "", keepKeywords);
parseContext, errors, grid, "", keepKeywords);
}
}
catch (const OpmInputError& opm_error) {
Expand Down Expand Up @@ -355,6 +355,7 @@ namespace Opm {
result.m_treat_critical_as_non_critical = false;
result.m_static = ScheduleStatic::serializationTestObject();
result.m_sched_deck = ScheduleDeck::serializationTestObject();
result.m_wellPIMap = {{"WELL1", 1000}, {"WELL2", 2000}};
result.action_wgnames = Action::WGNames::serializationTestObject();
result.potential_wellopen_patterns = std::unordered_set<std::string> {"W1"};
result.exit_status = EXIT_FAILURE;
Expand All @@ -363,6 +364,7 @@ namespace Opm {
result.completed_cells = CompletedCells::serializationTestObject();
result.current_report_step = 0;
result.m_lowActionParsingStrictness = false;
result.welpi_action_mode = false;
result.simUpdateFromPython = std::make_shared<SimulatorUpdate>(SimulatorUpdate::serializationTestObject());

return result;
Expand Down Expand Up @@ -393,16 +395,14 @@ namespace Opm {
ErrorGuard& errors,
const ScheduleGrid& grid,
const Action::Result::MatchingEntities& matches,
const bool actionx_mode,
SimulatorUpdate* sim_update,
const std::unordered_map<std::string, double>* target_wellpi,
std::unordered_map<std::string, double>& wpimult_global_factor,
WelSegsSet* welsegs_wells,
std::set<std::string>* compsegs_wells)
{
HandlerContext handlerContext { *this, block, keyword, grid, currentStep,
matches, actionx_mode,
parseContext, errors, sim_update, target_wellpi,
matches, this->welpi_action_mode,
parseContext, errors, sim_update, &(this->m_wellPIMap),
wpimult_global_factor, welsegs_wells, compsegs_wells};

if (!KeywordHandlers::getInstance().handleKeyword(handlerContext)) {
Expand Down Expand Up @@ -575,7 +575,6 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
const ParseContext& parseContext,
ErrorGuard& errors,
const ScheduleGrid& grid,
const std::unordered_map<std::string, double> * target_wellpi,
const std::string& prefix,
const bool keepKeywords,
const bool log_to_debug)
Expand Down Expand Up @@ -717,9 +716,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
errors,
grid,
matches,
/* actionx_mode = */ false,
/* sim_update = */ nullptr,
target_wellpi,
wpimult_global_factor,
&welsegs_wells,
&compsegs_wells);
Expand Down Expand Up @@ -908,8 +905,7 @@ Defaulted grid coordinates is not allowed for COMPDAT as part of ACTIONX)"
action_keyword.addRecord(std::move(deckRecord));
action.addKeyword(action_keyword);
SimulatorUpdate delta = this->applyAction(report_step, action,
/* matches = */ Action::Result{false}.matches(),
std::unordered_map<std::string,double>{}/*target_wellpi*/);
/* matches = */ Action::Result{false}.matches());
this->simUpdateFromPython->append(delta);
}

Expand Down Expand Up @@ -1654,7 +1650,6 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
ErrorGuard errors;
ScheduleGrid grid(this->completed_cells);
SimulatorUpdate sim_update;
std::unordered_map<std::string, double> target_wellpi;
std::unordered_map<std::string, double> wpimult_global_factor;
const auto matches = Action::Result{false}.matches();
const std::string prefix = "| "; // logger prefix string
Expand All @@ -1664,7 +1659,7 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
auto& input_block = this->m_sched_deck[reportStep];
ScheduleLogger logger(ScheduleLogger::select_stream(false, false), // will log to OpmLog::info
prefix, this->m_sched_deck.location());

for (const auto& keyword : keywords) {
const auto valid = Action::PyAction::valid_keyword(keyword->name());

Expand All @@ -1685,10 +1680,8 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
errors,
grid,
matches,
/* actionx_mode= */ false,
&sim_update,
&target_wellpi,
wpimult_global_factor);
wpimult_global_factor);
}
else {
const std::string msg_fmt =
Expand All @@ -1709,7 +1702,6 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
parseContext,
errors,
grid,
&target_wellpi,
prefix,
/* keepKeywords = */ true);
}
Expand All @@ -1718,26 +1710,10 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
}


SimulatorUpdate
Schedule::applyAction(const std::size_t reportStep,
const Action::ActionX& action,
const Action::Result::MatchingEntities& matches,
const std::unordered_map<std::string, float>& target_wellpi)
{
std::unordered_map<std::string, double> dtarget_wellpi;
for (const auto& w : target_wellpi) {
dtarget_wellpi.emplace(w.first, w.second);
}

return this->applyAction(reportStep, action, matches, dtarget_wellpi);
}


SimulatorUpdate
Schedule::applyAction(std::size_t reportStep,
const Action::ActionX& action,
const Action::Result::MatchingEntities& matches,
const std::unordered_map<std::string, double>& target_wellpi)
const Action::Result::MatchingEntities& matches)
{
const std::string prefix = "| ";
ParseContext parseContext;
Expand All @@ -1758,6 +1734,10 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
auto& input_block = this->m_sched_deck[reportStep];

std::unordered_map<std::string, double> wpimult_global_factor;

// Set welpi_action_mode to true, this is necessary for the keyword WELPI.
// This keyword is handled differently when it's called during a running simulation (see functions handleWELPI and handleWELPIRuntime).
this->welpi_action_mode = true;
for (const auto& keyword : action) {
input_block.push_back(keyword);

Expand All @@ -1772,11 +1752,11 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
errors,
grid,
matches,
/* actionx_mode = */ true,
&sim_update,
&target_wellpi,
wpimult_global_factor);
}
// The whole ACTIONX was executed, welpi_action_mode is set to false.
this->welpi_action_mode = false;

this->applyGlobalWPIMULT(wpimult_global_factor);

Expand All @@ -1797,7 +1777,7 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
const auto keepKeywords = true;
const auto log_to_debug = true;
this->iterateScheduleSection(reportStep + 1, this->m_sched_deck.size(),
parseContext, errors, grid, &target_wellpi,
parseContext, errors, grid,
prefix, keepKeywords, log_to_debug);
}

Expand Down Expand Up @@ -1881,7 +1861,6 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
const auto log_to_debug = true;
this->iterateScheduleSection(reportStep + 1, this->m_sched_deck.size(),
parseContext, errors, grid,
/* target_wellpi = */ nullptr,
prefix, keepKeywords, log_to_debug);
}

Expand Down Expand Up @@ -1910,8 +1889,7 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
}

return this->applyAction(reportStep, actions[action_name],
Action::Result{true}.wells(well_names).matches(),
std::unordered_map<std::string,double>{});
Action::Result{true}.wells(well_names).matches());
}
else {
OpmLog::error(fmt::format("Tried to apply unknown action: '{}'", action_name));
Expand Down Expand Up @@ -1982,6 +1960,9 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen


SimulatorUpdate Schedule::runPyAction(std::size_t reportStep, const Action::PyAction& pyaction, Action::State& action_state, EclipseState& ecl_state, SummaryState& summary_state) {
// Set welpi_action_mode to true, this is necessary for the keyword WELPI.
// This keyword is handled differently when it's called during a running simulation (see functions handleWELPI and handleWELPIRuntime).
this->welpi_action_mode = true;
// Reset simUpdateFromPython, pyaction.run(...) will run through the PyAction script, the calls that trigger a simulator update will append this to simUpdateFromPython.
this->simUpdateFromPython->reset();
// Set the current_report_step to the report step in which this PyAction was triggered.
Expand All @@ -1996,10 +1977,22 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
auto result = pyaction.run(ecl_state, *this, reportStep, summary_state, apply_action_callback);
action_state.add_run(pyaction, result);

// The whole pyaction script was executed, now the simUpdateFromPython is returned.
// The whole PyAction was executed, welpi_action_mode is set to false and the simUpdateFromPython is returned.
this->welpi_action_mode = false;
return *(this->simUpdateFromPython);
}

template void Schedule::setWellPIMap<double>(std::unordered_map<std::string, double>);
template void Schedule::setWellPIMap<float>(std::unordered_map<std::string, float>);

template<typename Scalar>
void Schedule::setWellPIMap(std::unordered_map<std::string, Scalar> wellPIMap) {
this->m_wellPIMap.clear();
for (const auto& [key, value] : wellPIMap) {
this->m_wellPIMap[key] = static_cast<double>(value);
}
}

void Schedule::applyWellProdIndexScaling(const std::string& well_name, const std::size_t reportStep, const double newWellPI) {
if (reportStep >= this->snapshots.size())
return;
Expand Down Expand Up @@ -2102,6 +2095,8 @@ File {} line {}.)", pattern, location.keyword, location.filename, location.linen
&& this->completed_cells == data.completed_cells
&& this->current_report_step == data.current_report_step
&& this->m_lowActionParsingStrictness == data.m_lowActionParsingStrictness
&& this->welpi_action_mode == data.welpi_action_mode
&& this->m_wellPIMap == data.m_wellPIMap
&& simUpdateFromPythonIsEqual
;
}
Expand Down
Loading