Summary Output: Implement 'WMCTL' Keyword

This outputs a numeric code, an integer value, for all configured
wells at all times and enables more visual inspection of how the
wells' active controls change over time--either in response to
explicit target modes in the input or as a result of limits becoming
active.

Note that due to the fall-back option of selecting the input value
if no dynamic value is available, we must ensure that the test code
does not specify well types (producer/injector) that conflict with
the keywords used in the backing data set.  Update the relevant
tests accordingly.
This commit is contained in:
Bård Skaflestad
2020-03-20 22:07:32 +01:00
parent 45b501cb83
commit 2f8ad86afd
3 changed files with 55 additions and 5 deletions
+49
View File
@@ -31,6 +31,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/SummaryState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQConfig.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/UDQ/UDQContext.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/Well.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellProductionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellInjectionProperties.hpp>
#include <opm/parser/eclipse/EclipseState/SummaryConfig/SummaryConfig.hpp>
@@ -805,6 +806,52 @@ inline quantity group_control( const fn_args& args ) {
return {static_cast<double>(cntl_mode), Opm::UnitSystem::measure::identity};
}
namespace {
bool well_control_mode_defined(const ::Opm::data::Well& xw)
{
using PMode = ::Opm::Well::ProducerCMode;
using IMode = ::Opm::Well::InjectorCMode;
const auto& curr = xw.current_control;
return (curr.isProducer && (curr.prod != PMode::CMODE_UNDEFINED))
|| (!curr.isProducer && (curr.inj != IMode::CMODE_UNDEFINED));
}
}
inline quantity well_control_mode( const fn_args& args ) {
const auto unit = Opm::UnitSystem::measure::identity;
if (args.schedule_wells.empty()) {
// No wells. Possibly determining pertinent unit of measure
// during SMSPEC configuration.
return { 0.0, unit };
}
const auto& well = args.schedule_wells.front();
auto xwPos = args.wells.find(well.name());
if (xwPos == args.wells.end()) {
// No dynamic results for 'well'. Treat as shut/stopped.
return { 0.0, unit };
}
if (! well_control_mode_defined(xwPos->second)) {
// No dynamic control mode defined. Use input control.
const auto wmctl = ::Opm::eclipseControlMode(well, args.st);
return { static_cast<double>(wmctl), unit };
}
// Well has simulator-provided active control mode. Pick the
// appropriate value depending on well type (producer/injector).
const auto& curr = xwPos->second.current_control;
const auto wmctl = curr.isProducer
? ::Opm::eclipseControlMode(curr.prod, well.getStatus())
: ::Opm::eclipseControlMode(curr.inj, well.injectorType(),
well.getStatus());
return { static_cast<double>(wmctl), unit };
}
/*
* A small DSL, really poor man's function composition, to avoid massive
@@ -902,6 +949,8 @@ static const std::unordered_map< std::string, ofun > funs = {
{ "WTHP", thp },
{ "WVPRT", res_vol_production_target },
{ "WMCTL", well_control_mode },
{ "GWIR", rate< rt::wat, injector > },
{ "WGVIR", rate< rt::reservoir_gas, injector >},
{ "WWVIR", rate< rt::reservoir_water, injector >},
+4 -3
View File
@@ -245,8 +245,8 @@ static data::Wells result_wells() {
{ { segment.segNumber, segment } },
data::CurrentControl{}
};
well1.current_control.isProducer = false;
well1.current_control.inj =::Opm::Well::InjectorCMode::BHP;
well1.current_control.isProducer = true;
well1.current_control.prod = ::Opm::Well::ProducerCMode::THP;
using SegRes = decltype(well1.segments);
using Ctrl = data::CurrentControl;
@@ -255,7 +255,8 @@ static data::Wells result_wells() {
well2.current_control.prod = ::Opm::Well::ProducerCMode::ORAT;
data::Well well3 { rates3, 2.1 * ps, 2.2 * ps, 2.3 * ps, 3, { {well3_comp1} }, SegRes{}, Ctrl{} };
well2.current_control.prod = ::Opm::Well::ProducerCMode::RESV;
well3.current_control.isProducer = false;
well3.current_control.inj = ::Opm::Well::InjectorCMode::BHP;
data::Well well6 { rates6, 2.1 * ps, 2.2 * ps, 2.3 * ps, 3, { {well6_comp1} }, SegRes{}, Ctrl{} };
well6.current_control.isProducer = false;
+2 -2
View File
@@ -172,8 +172,8 @@ static data::Wells result_wells() {
{ { segment.segNumber, segment } },
data::CurrentControl{}
};
well1.current_control.isProducer = false;
well1.current_control.inj =::Opm::Well::InjectorCMode::BHP;
well1.current_control.isProducer = true;
well1.current_control.prod = ::Opm::Well::ProducerCMode::BHP;
data::Wells wellrates;