Handle WELPI as ACTIONX keyword

This commit is contained in:
Joakim Hove
2021-02-12 12:56:28 +01:00
parent 6ad537fb20
commit 36159d8512
5 changed files with 72 additions and 14 deletions

View File

@@ -481,6 +481,7 @@ namespace Opm
const ParseContext& parseContext,
ErrorGuard& errors,
bool runtime,
const std::unordered_map<std::string, double> * target_wellpi,
const EclipseGrid* grid,
const FieldPropsManager* fp);
void addACTIONX(const Action::ActionX& action);
@@ -496,6 +497,7 @@ namespace Opm
const FieldPropsManager* fp,
const std::vector<std::string>& matching_wells,
bool runtime,
const std::unordered_map<std::string, double> * target_wellpi,
std::vector<std::pair<const DeckKeyword*, std::size_t > >& rftProperties);
static std::string formatDate(std::time_t t);
@@ -512,6 +514,7 @@ namespace Opm
const std::size_t currentStep;
const std::vector<std::string>& matching_wells;
const bool runtime;
const std::unordered_map<std::string, double> * target_wellpi;
const EclipseGrid* grid_ptr;
const FieldPropsManager* fp_ptr;
@@ -519,12 +522,14 @@ namespace Opm
const DeckKeyword& keyword_,
const std::size_t currentStep_,
const std::vector<std::string>& matching_wells_,
bool runtime_) :
bool runtime_,
const std::unordered_map<std::string, double> * target_wellpi_):
block(block_),
keyword(keyword_),
currentStep(currentStep_),
matching_wells(matching_wells_),
runtime(runtime_),
target_wellpi(target_wellpi_),
grid_ptr(nullptr),
fp_ptr(nullptr)
{}
@@ -555,6 +560,7 @@ namespace Opm
void handleGCONINJE(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);
void handleWELPI (const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors, const std::vector<std::string>& matching_wells = {});
void handleWELPIRuntime(const HandlerContext&);
// Normal keyword handlers -- in KeywordHandlers.cpp
void handleBRANPROP (const HandlerContext&, const ParseContext&, ErrorGuard&);

View File

@@ -23,6 +23,7 @@
#include <chrono>
#include <memory>
#include <optional>
#include <unordered_map>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
@@ -408,10 +409,10 @@ namespace Opm {
map_member<int, VFPInjTable> vfpinj;
map_member<std::string, Group> groups;
map_member<std::string, Well> wells;
std::map<std::string, double> target_wellpi;
std::unordered_map<std::string, double> target_wellpi;
using WellPIMapType = std::map<std::string, double>;
using WellPIMapType = std::unordered_map<std::string, double>;
template<class Serializer>
void serializeOp(Serializer& serializer) {
serializer(m_start_time);

View File

@@ -1117,7 +1117,38 @@ namespace {
}
void Schedule::handleWELPI(const HandlerContext& handlerContext, const ParseContext& parseContext, ErrorGuard& errors) {
this->handleWELPI(handlerContext.keyword, handlerContext.currentStep, parseContext, errors);
if (handlerContext.runtime)
this->handleWELPIRuntime(handlerContext);
else
this->handleWELPI(handlerContext.keyword, handlerContext.currentStep, parseContext, errors);
}
void Schedule::handleWELPIRuntime(const HandlerContext& handlerContext) {
using WELL_NAME = ParserKeywords::WELPI::WELL_NAME;
using PI = ParserKeywords::WELPI::STEADY_STATE_PRODUCTIVITY_OR_INJECTIVITY_INDEX_VALUE;
auto report_step = handlerContext.currentStep;
for (const auto& record : handlerContext.keyword) {
const auto well_names = this->wellNames(record.getItem<WELL_NAME>().getTrimmedString(0),
report_step,
handlerContext.matching_wells);
const auto targetPI = record.getItem<PI>().get<double>(0);
std::vector<bool> scalingApplicable;
const auto& current_wellpi = *handlerContext.target_wellpi;
for (const auto& well_name : well_names) {
auto wellpi_iter = current_wellpi.find(well_name);
if (wellpi_iter == current_wellpi.end())
throw std::logic_error(fmt::format("Missing current PI for well {}", well_name));
auto new_well = this->getWell(well_name, report_step);
auto scalingFactor = new_well.convertDeckPI(targetPI) / wellpi_iter->second;
new_well.updateWellProductivityIndex();
new_well.applyWellProdIndexScaling(scalingFactor, scalingApplicable);
this->snapshots.back().wells.update( std::move(new_well) );
this->snapshots.back().target_wellpi[well_name] = targetPI;
}
}
}
void Schedule::handleWELPI(const DeckKeyword& keyword, std::size_t report_step, const ParseContext& parseContext, ErrorGuard& errors, const std::vector<std::string>& matching_wells) {

View File

@@ -118,11 +118,11 @@ namespace {
{
if (rst) {
auto restart_step = rst->header.restart_info().second;
this->iterateScheduleSection( 0, restart_step, parseContext, errors, false, &grid, &fp);
this->iterateScheduleSection( 0, restart_step, parseContext, errors, false, nullptr, &grid, &fp);
this->load_rst(*rst, grid, fp);
this->iterateScheduleSection( restart_step, this->m_sched_deck.size(), parseContext, errors, false, &grid, &fp);
this->iterateScheduleSection( restart_step, this->m_sched_deck.size(), parseContext, errors, false, nullptr, &grid, &fp);
} else
this->iterateScheduleSection( 0, this->m_sched_deck.size(), parseContext, errors, false, &grid, &fp);
this->iterateScheduleSection( 0, this->m_sched_deck.size(), parseContext, errors, false, nullptr, &grid, &fp);
/*
The code in the #ifdef SCHEDULE_DEBUG is an enforced integration test
@@ -274,6 +274,7 @@ namespace {
const FieldPropsManager* fp,
const std::vector<std::string>& matching_wells,
bool runtime,
const std::unordered_map<std::string, double> * target_wellpi,
std::vector<std::pair<const DeckKeyword*, std::size_t > >& rftProperties) {
static const std::unordered_set<std::string> require_grid = {
@@ -282,7 +283,7 @@ namespace {
};
HandlerContext handlerContext { block, keyword, currentStep, matching_wells, runtime };
HandlerContext handlerContext { block, keyword, currentStep, matching_wells, runtime , target_wellpi};
/*
The grid and fieldProps members create problems for reiterating the
@@ -353,6 +354,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
const ParseContext& parseContext ,
ErrorGuard& errors,
bool runtime,
const std::unordered_map<std::string, double> * target_wellpi,
const EclipseGrid* grid,
const FieldPropsManager* fp) {
@@ -472,6 +474,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
fp,
{},
runtime,
target_wellpi,
rftProperties);
keyword_index++;
}
@@ -1192,7 +1195,7 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
}
void Schedule::applyAction(std::size_t reportStep, const std::chrono::system_clock::time_point&, const Action::ActionX& action, const Action::Result& result, const std::unordered_map<std::string, double>& ) {
void Schedule::applyAction(std::size_t reportStep, const std::chrono::system_clock::time_point&, const Action::ActionX& action, const Action::Result& result, const std::unordered_map<std::string, double>& target_wellpi) {
ParseContext parseContext;
ErrorGuard errors;
std::vector<std::pair< const DeckKeyword* , std::size_t> > ignored_rftProperties;
@@ -1211,10 +1214,11 @@ void Schedule::iterateScheduleSection(std::size_t load_start, std::size_t load_e
nullptr,
result.wells(),
true,
&target_wellpi,
ignored_rftProperties);
}
if (reportStep < this->m_sched_deck.size() - 1)
iterateScheduleSection(reportStep + 1, this->m_sched_deck.size(), parseContext, errors, true, nullptr, nullptr);
iterateScheduleSection(reportStep + 1, this->m_sched_deck.size(), parseContext, errors, true, &target_wellpi, nullptr, nullptr);
//this->m_sched_deck[reportStep].push

View File

@@ -1145,19 +1145,35 @@ TSTEP
const auto st = SummaryState{ std::chrono::system_clock::now() };
Schedule sched = make_schedule(deck_string);
const auto& action1 = sched[0].actions.get().get("A");
double CF0;
{
const auto& target_wellpi = sched[0].target_wellpi;
BOOST_CHECK_EQUAL( target_wellpi.count("PROD1"), 0);
const auto& well = sched.getWell("PROD1", 0);
CF0 = well.getConnections()[0].CF();
}
std::unordered_set<std::string> required_summary;
action1.required_summary(required_summary);
BOOST_CHECK_EQUAL( required_summary.count("WWCT"), 1);
Action::Result action_result(true);
sched.applyAction(0, std::chrono::system_clock::now(), action1, action_result, {});
BOOST_CHECK_THROW( sched.applyAction(0, std::chrono::system_clock::now(), action1, action_result, {}), std::exception);
{
const auto& well = sched.getWell("PROD1", 0);
sched.applyAction(0, std::chrono::system_clock::now(), action1, action_result, {{"PROD1", well.convertDeckPI(500)}});
}
{
const auto& target_wellpi = sched[0].target_wellpi;
BOOST_CHECK_EQUAL( target_wellpi.at("PROD1"), 1000);
const auto& well = sched.getWell("PROD1", 0);
auto CF1 = well.getConnections()[0].CF();
BOOST_CHECK_CLOSE(CF1 / CF0, 2.0, 1e-4 );
}
{
std::unordered_set<std::string> required_summary;
action1.required_summary(required_summary);
BOOST_CHECK_EQUAL( required_summary.count("WWCT"), 1);
}
}