Recognize Additional Per-Segment Summary Vector Keywords

In particular, add parser and summary output support for the free
vs. solution flow rates of gas and oil as well as the dissolved
gas/oil ratio, the vaporised oil/gas ratio, and the water/gas ratio.
This commit is contained in:
Bård Skaflestad 2022-11-04 18:22:41 +01:00
parent 9d983cb2f3
commit dbd2acee71
5 changed files with 629 additions and 69 deletions

View File

@ -225,8 +225,8 @@ struct SummaryConfigContext {
static const keyword_set ratekw {
"OPR", "GPR", "WPR", "GLIR", "LPR", "NPR", "CPR", "VPR", "TPR", "TPC",
"OFR", "OFR+", "OFR-",
"GFR", "GFR+", "GFR-",
"OFR", "OFRF", "OFRS", "OFR+", "OFR-",
"GFR", "GFRF", "GFRS", "GFR+", "GFR-",
"WFR", "WFR+", "WFR-",
"OPGR", "GPGR", "WPGR", "VPGR",
@ -252,8 +252,8 @@ struct SummaryConfigContext {
bool is_ratio(const std::string& keyword) {
static const keyword_set ratiokw {
"GLR", "GOR", "WCT",
"GLRH", "GORH", "WCTH",
"GLR" , "GOR" , "OGR", "WCT" , "WGR",
"GLRH", "GORH", "WCTH",
};
return is_in_set(ratiokw, keyword.substr(1));
@ -1099,63 +1099,67 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
{
const auto& kw = keyword.name();
if (kw.size() > 5) {
if (kw.size() > std::string::size_type{5}) {
// Easy check first--handles SUMMARY and SUMTHIN &c.
return false;
}
const auto kw_whitelist = std::vector<const char*> {
"SOFR", "SGFR", "SWFR", "SWCT",
"SPR", "SPRD", "SPRDH", "SPRDF", "SPRDA",
"SOFR" , "SOFRF", "SOFRS",
"SGFR" , "SGFRF", "SGFRS",
"SWFR" ,
"SGOR" , "SOGR" , "SWCT" , "SWGR" ,
"SPR" , "SPRD" , "SPRDH", "SPRDF", "SPRDA",
};
return std::any_of(kw_whitelist.begin(), kw_whitelist.end(),
[&kw](const char* known) -> bool
{
return kw == known;
});
[&kw](const char* known)
{
return kw == known;
});
}
int maxNumWellSegments(const std::size_t /* last_timestep */,
const Well& well)
int maxNumWellSegments(const Well& well)
{
return well.isMultiSegment()
? well.getSegments().size() : 0;
}
void makeSegmentNodes(const std::size_t last_timestep,
const int segID,
void makeSegmentNodes(const int segID,
const DeckKeyword& keyword,
const Well& well,
SummaryConfig::keyword_list& list)
{
if (!well.isMultiSegment())
if (!well.isMultiSegment()) {
// Not an MSW. Don't create summary vectors for segments.
return;
}
auto param = SummaryConfigNode {
keyword.name(), SummaryConfigNode::Category::Segment, keyword.location()
}
.namedEntity( well.name() )
.isUserDefined( is_udq(keyword.name()) );
.namedEntity(well.name())
.parameterType(parseKeywordType(keyword.name()))
.isUserDefined(is_udq(keyword.name()));
if (segID < 1) {
// Segment number defaulted. Allocate a summary
// vector for each segment.
const auto nSeg = maxNumWellSegments(last_timestep, well);
// Segment number defaulted. Allocate a summary vector for each
// segment.
const auto nSeg = maxNumWellSegments(well);
for (auto segNumber = 0*nSeg; segNumber < nSeg; ++segNumber)
list.push_back( param.number(segNumber + 1) );
for (auto segNumber = 0*nSeg; segNumber < nSeg; ++segNumber) {
list.push_back(param.number(segNumber + 1));
}
}
else {
// Segment number specified. Allocate single summary vector for
// that segment number.
list.push_back(param.number(segID));
}
else
// Segment number specified. Allocate single
// summary vector for that segment number.
list.push_back( param.number(segID) );
}
void keywordSNoRecords(const std::size_t last_timestep,
const DeckKeyword& keyword,
void keywordSNoRecords(const DeckKeyword& keyword,
const Schedule& schedule,
SummaryConfig::keyword_list& list)
{
@ -1169,13 +1173,12 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
const auto segID = -1;
for (const auto& well : schedule.getWellsatEnd())
makeSegmentNodes(last_timestep, segID, keyword,
well, list);
for (const auto& well : schedule.getWellsatEnd()) {
makeSegmentNodes(segID, keyword, well, list);
}
}
void keywordSWithRecords(const std::size_t last_timestep,
const ParseContext& parseContext,
void keywordSWithRecords(const ParseContext& parseContext,
ErrorGuard& errors,
const DeckKeyword& keyword,
const Schedule& schedule,
@ -1203,17 +1206,19 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
? schedule.wellNames()
: schedule.wellNames(wellitem.getTrimmedString(0));
if (well_names.empty())
if (well_names.empty()) {
handleMissingWell(parseContext, errors, keyword.location(),
wellitem.getTrimmedString(0));
}
// Negative 1 (< 0) if segment ID defaulted. Defaulted
// segment number in record implies all segments.
const auto segID = record.getItem(1).defaultApplied(0)
? -1 : record.getItem(1).get<int>(0);
for (const auto& well_name : well_names)
makeSegmentNodes(last_timestep, segID, keyword, schedule.getWellatEnd(well_name), list);
for (const auto& well_name : well_names) {
makeSegmentNodes(segID, keyword, schedule.getWellatEnd(well_name), list);
}
}
}
@ -1244,18 +1249,16 @@ inline void keywordMISC( SummaryConfig::keyword_list& list,
return;
}
const auto last_timestep = schedule.size() - 1;
if (! keyword.empty()) {
// Keyword with explicit records.
// Handle as alternatives SOFR and SPR above
keywordSWithRecords(last_timestep, parseContext, errors,
// Keyword with explicit records. Handle as alternatives SOFR
// and SPR above
keywordSWithRecords(parseContext, errors,
keyword, schedule, list);
}
else {
// Keyword with no explicit records.
// Handle as alternative SGFR above.
keywordSNoRecords(last_timestep, keyword, schedule, list);
// Keyword with no explicit records. Handle as alternative SGFR
// above.
keywordSNoRecords(keyword, schedule, list);
}
}

View File

@ -5,10 +5,17 @@
],
"deck_names": [
"SGFR",
"SGFRF",
"SGFRS",
"SGOR",
"SOFR",
"SOFRF",
"SOFRS",
"SOGR",
"SPR",
"SWFR",
"SWCT",
"SWGR",
"SPRD",
"SPRDF",
"SPRDH",

View File

@ -999,13 +999,10 @@ quantity crate_resv( const fn_args& args ) {
return { v, rate_unit<rt::reservoir_oil>() };
}
template< rt phase>
inline quantity srate( const fn_args& args ) {
const quantity zero = { 0, rate_unit< phase >() };
// The args.num value is the literal value which will go to the
// NUMS array in the eclispe SMSPEC file; the values in this array
// are offset 1 - whereas we need to use this index here to look
// up a connection with offset 0.
template <rt phase>
inline quantity srate(const fn_args& args)
{
const quantity zero = { 0, rate_unit<phase>() };
if (args.schedule_wells.empty()) {
return zero;
}
@ -1020,22 +1017,22 @@ inline quantity srate( const fn_args& args ) {
const auto& well_data = xwPos->second;
const size_t segNumber = args.num;
const auto& segment = well_data.segments.find(segNumber);
if (segment == well_data.segments.end())
const auto segNumber = static_cast<std::size_t>(args.num);
auto segPos = well_data.segments.find(segNumber);
if (segPos == well_data.segments.end()) {
return zero;
}
const double eff_fac = efac(args.eff_factors, name);
auto v = segment->second.rates.get( phase, 0.0 ) * eff_fac;
const auto eff_fac = efac(args.eff_factors, name);
//switch sign of rate - opposite convention in flow vs eclipse
v *= -1;
// 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)
if ((phase == rt::polymer) || (phase == rt::brine)) {
return { v, measure::mass_rate };
}
return { v, rate_unit< phase >() };
return { v, rate_unit<phase>() };
}
inline quantity trans_factors ( const fn_args& args ) {
@ -2156,16 +2153,25 @@ static const std::unordered_map< std::string, ofun > funs = {
{ "RGPT" , mul( region_rate< rt::gas, producer >, duration ) },
{ "RWPT" , mul( region_rate< rt::wat, producer >, duration ) },
{ "RHPV" , rhpv },
//Multisegment well segment data
{ "SOFR", srate< rt::oil > },
{ "SWFR", srate< rt::wat > },
{ "SGFR", srate< rt::gas > },
{ "SWCT", div(srate<rt::wat>, sum(srate<rt::wat>, srate<rt::oil>)) },
{ "SPR", segpress<Opm::data::SegmentPressures::Value::Pressure> },
{ "SPRD", segpress<Opm::data::SegmentPressures::Value::PDrop> },
// Segment summary vectors for multi-segmented wells.
{ "SOFR" , srate<rt::oil> },
{ "SOFRF", sub(srate<rt::oil>, srate<rt::vaporized_oil>) }, // Free oil flow
{ "SOFRS", srate<rt::vaporized_oil> }, // Solution oil flow
{ "SGFR" , srate<rt::gas> },
{ "SGFRF", sub(srate<rt::gas>, srate<rt::dissolved_gas>) }, // Free gas flow
{ "SGFRS", srate<rt::dissolved_gas> }, // Solution gas flow
{ "SWFR" , srate<rt::wat> },
{ "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>)) },
{ "SWGR" , div(srate<rt::wat>, srate<rt::gas>) },
{ "SPR" , segpress<Opm::data::SegmentPressures::Value::Pressure> },
{ "SPRD" , segpress<Opm::data::SegmentPressures::Value::PDrop> },
{ "SPRDH", segpress<Opm::data::SegmentPressures::Value::PDropHydrostatic> },
{ "SPRDF", segpress<Opm::data::SegmentPressures::Value::PDropFriction> },
{ "SPRDA", segpress<Opm::data::SegmentPressures::Value::PDropAccel> },
// Well productivity index
{ "WPI", preferred_phase_productivty_index },
{ "WPIW", potential_rate< rt::productivity_index_water >},

View File

@ -111,10 +111,39 @@ SOFR
'PROD01' 21 /
/
SOFRF
'PROD01' 1 /
'PROD01' 10 /
'PROD01' 21 /
/
SOFRS
'PROD01' 1 /
'PROD01' 10 /
'PROD01' 21 /
/
SOGR
'PROD01' 5 /
'PROD01' 7 /
/
SGFR
'PROD01' /
/
SGFRF
'PROD01' 2 /
/
SGFRS
'PROD01' 3 /
/
SGOR
1* 10 /
/
SPR
1* 10 /
/
@ -122,6 +151,10 @@ SPR
SWFR
/
SWGR
1* 3 /
/
SPRD
/

View File

@ -1091,9 +1091,174 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK_MESSAGE(sofr->category() == SummaryConfigNode::Category::Segment,
R"("SOFR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sofr->type() == SummaryConfigNode::Type::Rate,
R"("SOFR" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sofr->namedEntity(), "PROD01");
}
// SOFRF PROD01 segments 1, 10, 21.
BOOST_CHECK(deck.hasKeyword("SOFRF"));
BOOST_CHECK(summary.hasKeyword("SOFRF"));
BOOST_CHECK(summary.hasSummaryKey("SOFRF:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:2"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:9"));
BOOST_CHECK(summary.hasSummaryKey("SOFRF:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:20"));
BOOST_CHECK(summary.hasSummaryKey("SOFRF:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:PROD01:27"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRF:INJE01:1"));
{
auto sofrf = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SOFRF";
});
BOOST_REQUIRE(sofrf != summary.end());
BOOST_CHECK_MESSAGE(sofrf->category() == SummaryConfigNode::Category::Segment,
R"("SOFRF" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sofrf->type() == SummaryConfigNode::Type::Rate,
R"("SOFRF" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sofrf->namedEntity(), "PROD01");
}
// SOFRS PROD01 segments 1, 10, 21.
BOOST_CHECK(deck.hasKeyword("SOFRS"));
BOOST_CHECK(summary.hasKeyword("SOFRS"));
BOOST_CHECK(summary.hasSummaryKey("SOFRS:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:2"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:9"));
BOOST_CHECK(summary.hasSummaryKey("SOFRS:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:20"));
BOOST_CHECK(summary.hasSummaryKey("SOFRS:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:PROD01:27"));
BOOST_CHECK(!summary.hasSummaryKey("SOFRS:INJE01:1"));
{
auto sofrs = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SOFRS";
});
BOOST_REQUIRE(sofrs != summary.end());
BOOST_CHECK_MESSAGE(sofrs->category() == SummaryConfigNode::Category::Segment,
R"("SOFRS" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sofrs->type() == SummaryConfigNode::Type::Rate,
R"("SOFRS" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sofrs->namedEntity(), "PROD01");
}
// SOGR PROD01 segments 5 and 7.
BOOST_CHECK(deck.hasKeyword("SOGR"));
BOOST_CHECK(summary.hasKeyword("SOGR"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:2"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:4"));
BOOST_CHECK(summary.hasSummaryKey("SOGR:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:6"));
BOOST_CHECK(summary.hasSummaryKey("SOGR:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:9"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:20"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:PROD01:27"));
BOOST_CHECK(!summary.hasSummaryKey("SOGR:INJE01:1"));
{
auto sogr = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SOGR";
});
BOOST_REQUIRE(sogr != summary.end());
BOOST_CHECK_MESSAGE(sogr->category() == SummaryConfigNode::Category::Segment,
R"("SOGR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sogr->type() == SummaryConfigNode::Type::Ratio,
R"("SOGR" keyword type must be "Ratio")"
);
BOOST_CHECK_EQUAL(sogr->namedEntity(), "PROD01");
}
// SGFR in all segments of PROD01
BOOST_CHECK(deck.hasKeyword("SGFR"));
BOOST_CHECK(summary.hasKeyword("SGFR"));
BOOST_CHECK(summary.hasSummaryKey("SGFR:PROD01:1"));
@ -1124,6 +1289,180 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(summary.hasSummaryKey("SGFR:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SGFR:PROD01:27")); // No such segment.
{
auto sgfr = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SGFR";
});
BOOST_REQUIRE(sgfr != summary.end());
BOOST_CHECK_MESSAGE(sgfr->category() == SummaryConfigNode::Category::Segment,
R"("SGFR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sgfr->type() == SummaryConfigNode::Type::Rate,
R"("SGFR" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sgfr->namedEntity(), "PROD01");
}
// SGFRF in segment 2 of PROD01
BOOST_CHECK(deck.hasKeyword("SGFRF"));
BOOST_CHECK(summary.hasKeyword("SGFRF"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:1"));
BOOST_CHECK(summary.hasSummaryKey("SGFRF:PROD01:2"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:9"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:20"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRF:PROD01:27")); // No such segment.
{
auto sgfrf = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SGFRF";
});
BOOST_REQUIRE(sgfrf != summary.end());
BOOST_CHECK_MESSAGE(sgfrf->category() == SummaryConfigNode::Category::Segment,
R"("SGFRF" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sgfrf->type() == SummaryConfigNode::Type::Rate,
R"("SGFRF" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sgfrf->namedEntity(), "PROD01");
}
// SGFRF in segment 3 of PROD01
BOOST_CHECK(deck.hasKeyword("SGFRS"));
BOOST_CHECK(summary.hasKeyword("SGFRS"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:2"));
BOOST_CHECK(summary.hasSummaryKey("SGFRS:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:9"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:20"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SGFRS:PROD01:27")); // No such segment.
{
auto sgfrs = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SGFRS";
});
BOOST_REQUIRE(sgfrs != summary.end());
BOOST_CHECK_MESSAGE(sgfrs->category() == SummaryConfigNode::Category::Segment,
R"("SGFRS" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sgfrs->type() == SummaryConfigNode::Type::Rate,
R"("SGFRS" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(sgfrs->namedEntity(), "PROD01");
}
// SGOR PROD01 segment 10 only.
BOOST_CHECK(deck.hasKeyword("SGOR"));
BOOST_CHECK(summary.hasKeyword("SGOR"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:2"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:9"));
BOOST_CHECK(summary.hasSummaryKey("SGOR:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:20"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SGOR:INJE01:10"));
{
auto sgor = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SGOR";
});
BOOST_REQUIRE(sgor != summary.end());
BOOST_CHECK_MESSAGE(sgor->category() == SummaryConfigNode::Category::Segment,
R"("SGOR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sgor->type() == SummaryConfigNode::Type::Ratio,
R"("SGOR" keyword type must be "Ratio")"
);
BOOST_CHECK_EQUAL(sgor->namedEntity(), "PROD01");
}
// SPR PROD01 segment 10 only.
BOOST_CHECK(deck.hasKeyword("SPR"));
BOOST_CHECK(summary.hasKeyword("SPR"));
@ -1156,6 +1495,26 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SPR:INJE01:10"));
{
auto spr = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SPR";
});
BOOST_REQUIRE(spr != summary.end());
BOOST_CHECK_MESSAGE(spr->category() == SummaryConfigNode::Category::Segment,
R"("SPR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(spr->type() == SummaryConfigNode::Type::Pressure,
R"("SPR" keyword type must be "Pressure")"
);
BOOST_CHECK_EQUAL(spr->namedEntity(), "PROD01");
}
// SWFR for all segments in all MS wells.
BOOST_CHECK(deck.hasKeyword("SWFR"));
BOOST_CHECK(summary.hasKeyword("SWFR"));
@ -1188,6 +1547,78 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SWFR:INJE01:1"));
{
auto swfr = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SWFR";
});
BOOST_REQUIRE(swfr != summary.end());
BOOST_CHECK_MESSAGE(swfr->category() == SummaryConfigNode::Category::Segment,
R"("SWFR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(swfr->type() == SummaryConfigNode::Type::Rate,
R"("SWFR" keyword type must be "Rate")"
);
BOOST_CHECK_EQUAL(swfr->namedEntity(), "PROD01");
}
// SWGR for segment 3 in all MS wells.
BOOST_CHECK(deck.hasKeyword("SWGR"));
BOOST_CHECK(summary.hasKeyword("SWGR"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:2"));
BOOST_CHECK(summary.hasSummaryKey("SWGR:PROD01:3"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:4"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:5"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:6"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:7"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:8"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:9"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:11"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:12"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:13"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:14"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:15"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:16"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:17"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:18"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:19"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:20"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:21"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:22"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:23"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:24"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:25"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:PROD01:26"));
BOOST_CHECK(!summary.hasSummaryKey("SWGR:INJE01:1"));
{
auto swgr = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SWGR";
});
BOOST_REQUIRE(swgr != summary.end());
BOOST_CHECK_MESSAGE(swgr->category() == SummaryConfigNode::Category::Segment,
R"("SWGR" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(swgr->type() == SummaryConfigNode::Type::Ratio,
R"("SWGR" keyword type must be "Ratio")"
);
BOOST_CHECK_EQUAL(swgr->namedEntity(), "PROD01");
}
// SPRD for all segments in all MS wells.
BOOST_CHECK(deck.hasKeyword("SPRD"));
BOOST_CHECK(summary.hasKeyword("SPRD"));
@ -1220,6 +1651,26 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SPRD:INJE01:1"));
{
auto sprd = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SPRD";
});
BOOST_REQUIRE(sprd != summary.end());
BOOST_CHECK_MESSAGE(sprd->category() == SummaryConfigNode::Category::Segment,
R"("SPRD" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sprd->type() == SummaryConfigNode::Type::Pressure,
R"("SPRD" keyword type must be "Pressure")"
);
BOOST_CHECK_EQUAL(sprd->namedEntity(), "PROD01");
}
// SPRDH for all segments of MS well PROD01.
BOOST_CHECK(deck.hasKeyword("SPRDH"));
BOOST_CHECK(summary.hasKeyword("SPRDH"));
@ -1252,6 +1703,26 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SPRDH:INJE01:1"));
{
auto sprdh = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SPRDH";
});
BOOST_REQUIRE(sprdh != summary.end());
BOOST_CHECK_MESSAGE(sprdh->category() == SummaryConfigNode::Category::Segment,
R"("SPRDH" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sprdh->type() == SummaryConfigNode::Type::Pressure,
R"("SPRDH" keyword type must be "Pressure")"
);
BOOST_CHECK_EQUAL(sprdh->namedEntity(), "PROD01");
}
// SPRDF for segments 10 and 16 of MS well PROD01.
BOOST_CHECK(deck.hasKeyword("SPRDF"));
BOOST_CHECK(summary.hasKeyword("SPRDF"));
@ -1284,6 +1755,26 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SPRDF:INJE01:1"));
{
auto sprdf = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SPRDF";
});
BOOST_REQUIRE(sprdf != summary.end());
BOOST_CHECK_MESSAGE(sprdf->category() == SummaryConfigNode::Category::Segment,
R"("SPRDF" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sprdf->type() == SummaryConfigNode::Type::Pressure,
R"("SPRDF" keyword type must be "Pressure")"
);
BOOST_CHECK_EQUAL(sprdf->namedEntity(), "PROD01");
}
// SPRDA for segments 10 and 16 of all MS wells
BOOST_CHECK(deck.hasKeyword("SPRDA"));
BOOST_CHECK(summary.hasKeyword("SPRDA"));
@ -1317,6 +1808,26 @@ BOOST_AUTO_TEST_CASE(Summary_Segment)
BOOST_CHECK(!summary.hasSummaryKey("SPRDA:INJE01:1"));
BOOST_CHECK(!summary.hasSummaryKey("SPRDA:INJE01:10"));
BOOST_CHECK(!summary.hasSummaryKey("SPRDA:INJE01:16"));
{
auto sprda = std::find_if(summary.begin(), summary.end(),
[](const SummaryConfigNode& node)
{
return node.keyword() == "SPRDA";
});
BOOST_REQUIRE(sprda != summary.end());
BOOST_CHECK_MESSAGE(sprda->category() == SummaryConfigNode::Category::Segment,
R"("SPRDA" keyword category must be "Segment")"
);
BOOST_CHECK_MESSAGE(sprda->type() == SummaryConfigNode::Type::Pressure,
R"("SPRDA" keyword type must be "Pressure")"
);
BOOST_CHECK_EQUAL(sprda->namedEntity(), "PROD01");
}
}
BOOST_AUTO_TEST_CASE(Summary_Network) {