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:
@@ -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 >},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user