Don't Generate History Rates for Shut/Stopped Wells

The *_history() helper functions assumed that all wells would be
flowing.  This is an incorrect assumption and would lead to, e.g.,
field-level observed rates being non-zero even if all wells were
stopped/shut.

This commit adds a check for non-flowing wells, and omits flow rate
contributions in that case.
This commit is contained in:
Bård Skaflestad
2023-06-13 17:46:17 +02:00
parent 7614a739ca
commit 53f946e776
2 changed files with 65 additions and 22 deletions

View File

@@ -1220,35 +1220,58 @@ inline quantity node_pressure(const fn_args& args)
return { nodePos->second.pressure, measure::pressure };
}
template< Opm::Phase phase >
inline quantity production_history( const fn_args& args )
template <Opm::Phase phase>
inline quantity production_history(const fn_args& args)
{
/*
* For well data, looking up historical rates (both for production and
* injection) before simulation actually starts is impossible and
* nonsensical. We therefore default to writing zero (which is what eclipse
* seems to do as well).
*/
// Looking up historical well production rates before simulation starts
// or the well is flowing is meaningless. We therefore default to
// outputting zero in this case.
double sum = 0.0;
for (const auto* sched_well : args.schedule_wells) {
const double eff_fac = efac( args.eff_factors, sched_well->name() );
sum += sched_well->production_rate( args.st, phase ) * eff_fac;
const auto& name = sched_well->name();
auto xwPos = args.wells.find(name);
if ((xwPos == args.wells.end()) ||
(xwPos->second.dynamicStatus == Opm::Well::Status::SHUT))
{
// Well's not flowing. Ignore contribution regardless of what's
// in WCONHIST.
continue;
}
const double eff_fac = efac(args.eff_factors, name);
sum += sched_well->production_rate(args.st, phase) * eff_fac;
}
return { sum, rate_unit< phase >() };
return { sum, rate_unit<phase>() };
}
template< Opm::Phase phase >
inline quantity injection_history( const fn_args& args )
template <Opm::Phase phase>
inline quantity injection_history(const fn_args& args)
{
// Looking up historical well injection rates before simulation starts
// or the well is flowing is meaningless. We therefore default to
// outputting zero in this case.
double sum = 0.0;
for (const auto* sched_well : args.schedule_wells) {
const double eff_fac = efac( args.eff_factors, sched_well->name() );
sum += sched_well->injection_rate( args.st, phase ) * eff_fac;
const auto& name = sched_well->name();
auto xwPos = args.wells.find(name);
if ((xwPos == args.wells.end()) ||
(xwPos->second.dynamicStatus == Opm::Well::Status::SHUT))
{
// Well's not flowing. Ignore contribution regardless of what's
// in WCONINJH.
continue;
}
const double eff_fac = efac(args.eff_factors, name);
sum += sched_well->injection_rate(args.st, phase) * eff_fac;
}
return { sum, rate_unit< phase >() };
return { sum, rate_unit<phase>() };
}
template< bool injection >

View File

@@ -883,14 +883,34 @@ BOOST_AUTO_TEST_CASE(well_keywords_dynamic_close) {
ecl_sum_get_well_var( resp, 2, "W_2", "WVPT" ), 1e-5 );
/* Production rates (history) */
BOOST_CHECK_CLOSE( 20.0, ecl_sum_get_well_var( resp, 1, "W_2", "WWPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.1, ecl_sum_get_well_var( resp, 1, "W_2", "WOPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.2, ecl_sum_get_well_var( resp, 1, "W_2", "WGPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.0, ecl_sum_get_well_var( resp, 0, "W_2", "WWPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.1, ecl_sum_get_well_var( resp, 0, "W_2", "WOPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.2, ecl_sum_get_well_var( resp, 0, "W_2", "WGPRH" ), 1e-5 );
// Historical rates are zero in shut/stopped wells
BOOST_CHECK_CLOSE( 0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WWPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WOPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WGPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.0, ecl_sum_get_well_var( resp, 2, "W_2", "WWPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.1, ecl_sum_get_well_var( resp, 2, "W_2", "WOPRH" ), 1e-5 );
BOOST_CHECK_CLOSE( 20.2, ecl_sum_get_well_var( resp, 2, "W_2", "WGPRH" ), 1e-5 );
/* Production totals (history) */
BOOST_CHECK_CLOSE( 2 * 20.0, ecl_sum_get_well_var( resp, 2, "W_2", "WWPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 2 * 20.1, ecl_sum_get_well_var( resp, 2, "W_2", "WOPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 2 * 20.2, ecl_sum_get_well_var( resp, 2, "W_2", "WGPTH" ), 1e-5 );
// Step 0: Elapsed time = 0
BOOST_CHECK_CLOSE( 0.0 * 20.0, ecl_sum_get_well_var( resp, 0, "W_2", "WWPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0 * 20.1, ecl_sum_get_well_var( resp, 0, "W_2", "WOPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0 * 20.2, ecl_sum_get_well_var( resp, 0, "W_2", "WGPTH" ), 1e-5 );
// Step 1: Elapsed time = 1 day, flow rates = 0.0
BOOST_CHECK_CLOSE( 0.0*20.0 + 1.0*0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WWPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0*20.1 + 1.0*0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WOPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0*20.2 + 1.0*0.0, ecl_sum_get_well_var( resp, 1, "W_2", "WGPTH" ), 1e-5 );
// Step 2: Elapsed time = 2 day, flow rates = 20.x
BOOST_CHECK_CLOSE( 0.0*20.0 + 1.0*0.0 + 1.0*20.0, ecl_sum_get_well_var( resp, 2, "W_2", "WWPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0*20.1 + 1.0*0.0 + 1.0*20.1, ecl_sum_get_well_var( resp, 2, "W_2", "WOPTH" ), 1e-5 );
BOOST_CHECK_CLOSE( 0.0*20.2 + 1.0*0.0 + 1.0*20.2, ecl_sum_get_well_var( resp, 2, "W_2", "WGPTH" ), 1e-5 );
/* WWCT - water cut */
const double wwcut = 20.0 / ( 20.0 + 20.1 );