Add More Segment Level Summary Vectors
In particular, add support for
SxFT - Cumulative flow of phase 'x'
SxFV - Free flow velocity of phase 'x'
SxHF - Free flow holdup fraction of phase 'x'
SxVIS - Phase viscosity of phase 'x'
The last three of these were added to the RFT file in 802a401a8
,
but are also useful in the summary output file. In the interest of
avoiding duplicate logic, refactor the existing segment-related
quantity calculation/extraction in terms of callbacks.
This commit is contained in:
parent
4fb2a3557b
commit
5b6f064804
@ -1146,9 +1146,9 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
|
||||
}
|
||||
|
||||
const auto kw_whitelist = std::vector<const char*> {
|
||||
"SOFR" , "SOFRF", "SOFRS",
|
||||
"SGFR" , "SGFRF", "SGFRS",
|
||||
"SWFR" ,
|
||||
"SOFR" , "SOFRF", "SOFRS", "SOFT", "SOFV", "SOHF", "SOVIS",
|
||||
"SGFR" , "SGFRF", "SGFRS", "SGFT", "SGFV", "SGHF", "SGVIS",
|
||||
"SWFR" , "SWFT", "SWFV", "SWHF", "SWVIS",
|
||||
"SGOR" , "SOGR" , "SWCT" , "SWGR" ,
|
||||
"SPR" , "SPRD" , "SPRDH", "SPRDF", "SPRDA",
|
||||
};
|
||||
|
@ -7,19 +7,31 @@
|
||||
"SGFR",
|
||||
"SGFRF",
|
||||
"SGFRS",
|
||||
"SGFT",
|
||||
"SGFV",
|
||||
"SGHF",
|
||||
"SGOR",
|
||||
"SGVIS",
|
||||
"SOFR",
|
||||
"SOFRF",
|
||||
"SOFRS",
|
||||
"SOFT",
|
||||
"SOFV",
|
||||
"SOGR",
|
||||
"SOHF",
|
||||
"SOVIS",
|
||||
"SPR",
|
||||
"SWFR",
|
||||
"SWCT",
|
||||
"SWGR",
|
||||
"SPRD",
|
||||
"SPRDA",
|
||||
"SPRDF",
|
||||
"SPRDH",
|
||||
"SPRDA"
|
||||
"SWCT",
|
||||
"SWFR",
|
||||
"SWFT",
|
||||
"SWFV",
|
||||
"SWGR",
|
||||
"SWHF",
|
||||
"SWVIS"
|
||||
],
|
||||
"comment": "This list is incomplete",
|
||||
"items": [
|
||||
|
@ -1003,10 +1003,12 @@ quantity crate_resv( const fn_args& args ) {
|
||||
return { v, rate_unit<rt::reservoir_oil>() };
|
||||
}
|
||||
|
||||
template <rt phase>
|
||||
inline quantity srate(const fn_args& args)
|
||||
template <typename GetValue>
|
||||
quantity segment_quantity(const fn_args& args,
|
||||
const measure m,
|
||||
GetValue&& getValue)
|
||||
{
|
||||
const quantity zero = { 0, rate_unit<phase>() };
|
||||
const auto zero = quantity { 0.0, m };
|
||||
if (args.schedule_wells.empty()) {
|
||||
return zero;
|
||||
}
|
||||
@ -1027,16 +1029,70 @@ inline quantity srate(const fn_args& args)
|
||||
return zero;
|
||||
}
|
||||
|
||||
const auto eff_fac = efac(args.eff_factors, name);
|
||||
|
||||
// Switch sign of rate--opposite convention in Flow vs ECLIPSE.
|
||||
const auto v = -segPos->second.rates.get(phase, 0.0) * eff_fac;
|
||||
|
||||
if ((phase == rt::polymer) || (phase == rt::brine)) {
|
||||
return { v, measure::mass_rate };
|
||||
return { getValue(segPos->second), m };
|
||||
}
|
||||
|
||||
return { v, rate_unit<phase>() };
|
||||
template <Opm::data::SegmentPressures::Value ix>
|
||||
inline quantity segpress(const fn_args& args)
|
||||
{
|
||||
return segment_quantity(args, measure::pressure,
|
||||
[](const Opm::data::Segment& segment)
|
||||
{
|
||||
return segment.pressures[ix];
|
||||
});
|
||||
}
|
||||
|
||||
template <rt phase>
|
||||
inline quantity srate(const fn_args& args)
|
||||
{
|
||||
const auto m = ((phase == rt::polymer) || (phase == rt::brine))
|
||||
? measure::mass_rate
|
||||
: rate_unit<phase>();
|
||||
|
||||
return segment_quantity(args, m,
|
||||
[&args](const Opm::data::Segment& segment)
|
||||
{
|
||||
// Note: Opposite flow rate sign conventions in Flow vs. ECLIPSE.
|
||||
return - segment.rates.get(phase, 0.0)
|
||||
* efac(args.eff_factors, args.schedule_wells.front()->name());
|
||||
});
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPhaseQuantity::Item p>
|
||||
double segment_phase_quantity_value(const Opm::data::SegmentPhaseQuantity& q)
|
||||
{
|
||||
return q.has(p) ? q.get(p) : 0.0;
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPhaseQuantity::Item p>
|
||||
quantity segment_flow_velocity(const fn_args& args)
|
||||
{
|
||||
return segment_quantity(args, measure::pipeflow_velocity,
|
||||
[](const Opm::data::Segment& segment)
|
||||
{
|
||||
// Note: Opposite velocity sign conventions in Flow vs. ECLIPSE.
|
||||
return - segment_phase_quantity_value<p>(segment.velocity);
|
||||
});
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPhaseQuantity::Item p>
|
||||
quantity segment_holdup_fraction(const fn_args& args)
|
||||
{
|
||||
return segment_quantity(args, measure::identity,
|
||||
[](const Opm::data::Segment& segment)
|
||||
{
|
||||
return segment_phase_quantity_value<p>(segment.holdup);
|
||||
});
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPhaseQuantity::Item p>
|
||||
quantity segment_viscosity(const fn_args& args)
|
||||
{
|
||||
return segment_quantity(args, measure::viscosity,
|
||||
[](const Opm::data::Segment& segment)
|
||||
{
|
||||
return segment_phase_quantity_value<p>(segment.viscosity);
|
||||
});
|
||||
}
|
||||
|
||||
inline quantity trans_factors ( const fn_args& args ) {
|
||||
@ -1068,35 +1124,6 @@ inline quantity trans_factors ( const fn_args& args ) {
|
||||
return { connPos->trans_factor, measure::transmissibility };
|
||||
}
|
||||
|
||||
template <Opm::data::SegmentPressures::Value ix>
|
||||
inline quantity segpress ( const fn_args& args )
|
||||
{
|
||||
const quantity zero = { 0, measure::pressure };
|
||||
|
||||
if (args.schedule_wells.empty())
|
||||
return zero;
|
||||
|
||||
const auto* well = args.schedule_wells.front();
|
||||
auto xwPos = args.wells.find(well->name());
|
||||
if ((xwPos == args.wells.end()) ||
|
||||
(xwPos->second.dynamicStatus == Opm::Well::Status::SHUT))
|
||||
{
|
||||
return zero;
|
||||
}
|
||||
|
||||
// Like connection rate we need to look up a connection with offset 0.
|
||||
const size_t segNumber = args.num;
|
||||
|
||||
const auto& well_data = xwPos->second;
|
||||
const auto& segment = well_data.segments.find(segNumber);
|
||||
|
||||
if (segment == well_data.segments.end()) {
|
||||
return zero;
|
||||
}
|
||||
|
||||
return { segment->second.pressures[ix], measure::pressure };
|
||||
}
|
||||
|
||||
inline quantity wstat( const fn_args& args ) {
|
||||
const quantity zero = { Opm::WStat::numeric::UNKNOWN, measure::identity};
|
||||
if (args.schedule_wells.empty())
|
||||
@ -2185,12 +2212,24 @@ static const std::unordered_map< std::string, ofun > funs = {
|
||||
|
||||
// Segment summary vectors for multi-segmented wells.
|
||||
{ "SOFR" , srate<rt::oil> },
|
||||
{ "SOFT" , mul(srate<rt::oil>, duration) },
|
||||
{ "SOFRF", sub(srate<rt::oil>, srate<rt::vaporized_oil>) }, // Free oil flow
|
||||
{ "SOFRS", srate<rt::vaporized_oil> }, // Solution oil flow
|
||||
{ "SOFV" , segment_flow_velocity<Opm::data::SegmentPhaseQuantity::Item::Oil> },
|
||||
{ "SOHF" , segment_holdup_fraction<Opm::data::SegmentPhaseQuantity::Item::Oil> },
|
||||
{ "SOVIS", segment_viscosity<Opm::data::SegmentPhaseQuantity::Item::Oil> },
|
||||
{ "SGFR" , srate<rt::gas> },
|
||||
{ "SGFT" , mul(srate<rt::gas>, duration) },
|
||||
{ "SGFRF", sub(srate<rt::gas>, srate<rt::dissolved_gas>) }, // Free gas flow
|
||||
{ "SGFRS", srate<rt::dissolved_gas> }, // Solution gas flow
|
||||
{ "SGFV" , segment_flow_velocity<Opm::data::SegmentPhaseQuantity::Item::Gas> },
|
||||
{ "SGHF" , segment_holdup_fraction<Opm::data::SegmentPhaseQuantity::Item::Gas> },
|
||||
{ "SGVIS", segment_viscosity<Opm::data::SegmentPhaseQuantity::Item::Gas> },
|
||||
{ "SWFR" , srate<rt::wat> },
|
||||
{ "SWFT" , mul(srate<rt::wat>, duration) },
|
||||
{ "SWFV" , segment_flow_velocity<Opm::data::SegmentPhaseQuantity::Item::Water> },
|
||||
{ "SWHF" , segment_holdup_fraction<Opm::data::SegmentPhaseQuantity::Item::Water> },
|
||||
{ "SWVIS", segment_viscosity<Opm::data::SegmentPhaseQuantity::Item::Water> },
|
||||
{ "SGOR" , div(srate<rt::gas>, srate<rt::oil>) },
|
||||
{ "SOGR" , div(srate<rt::oil>, srate<rt::gas>) },
|
||||
{ "SWCT" , div(srate<rt::wat>, sum(srate<rt::wat>, srate<rt::oil>)) },
|
||||
|
@ -111,6 +111,30 @@ SOFR
|
||||
'PROD01' 21 /
|
||||
/
|
||||
|
||||
SOFT
|
||||
'PROD01' 1 /
|
||||
'PROD01' 10 /
|
||||
'PROD01' 21 /
|
||||
/
|
||||
|
||||
SOHF
|
||||
'PROD01' 1 /
|
||||
'PROD01' 10 /
|
||||
'PROD01' 21 /
|
||||
/
|
||||
|
||||
SOFV
|
||||
'PROD01' 1 /
|
||||
'PROD01' 10 /
|
||||
'PROD01' 21 /
|
||||
/
|
||||
|
||||
SOVIS
|
||||
'PROD01' 1 /
|
||||
'PROD01' 10 /
|
||||
'PROD01' 21 /
|
||||
/
|
||||
|
||||
SOFRF
|
||||
'PROD01' 1 /
|
||||
'PROD01' 10 /
|
||||
@ -132,6 +156,22 @@ SGFR
|
||||
'PROD01' /
|
||||
/
|
||||
|
||||
SGFT
|
||||
'PROD01' /
|
||||
/
|
||||
|
||||
SGHF
|
||||
'PROD01' /
|
||||
/
|
||||
|
||||
SGFV
|
||||
'PROD01' /
|
||||
/
|
||||
|
||||
SGVIS
|
||||
'PROD01' /
|
||||
/
|
||||
|
||||
SGFRF
|
||||
'PROD01' 2 /
|
||||
/
|
||||
@ -151,6 +191,18 @@ SPR
|
||||
SWFR
|
||||
/
|
||||
|
||||
SWFT
|
||||
/
|
||||
|
||||
SWHF
|
||||
/
|
||||
|
||||
SWFV
|
||||
/
|
||||
|
||||
SWVIS
|
||||
/
|
||||
|
||||
SWGR
|
||||
1* 3 /
|
||||
/
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user