Well State FIBO: Report() Segment Results by Seg-Numbers

This commit adds a new data member, seg_number_, that maps a linear
segment index (0 .. #segments - 1) to the appropriate segment number
(segment ID).  This ensures that member function report() is able to
produce segment results in terms of user-assigned segment numbers
rather than linear indices internal to the simulator and its state
variables.  This, in turn, decouples the well state object from the
output (summary/restart) code and makes the restart facility more
self contained.

Rewrite the unit test for WellStateFullyImplicitBlackoil to account
for the new indexing scheme when assigning the synthetic segment
results.

While here, also abide by the file's naming convention for data
members and locals.
This commit is contained in:
Bård Skaflestad
2018-10-15 19:52:54 +02:00
parent 45689f3ade
commit 55e452c605
2 changed files with 82 additions and 42 deletions

View File

@@ -281,9 +281,12 @@ namespace Opm
// we need to create a trival segment related values to avoid there will be some
// multi-segment wells added later.
nseg_ = nw;
seg_number_.clear();
top_segment_index_.reserve(nw);
seg_number_.reserve(nw);
for (int w = 0; w < nw; ++w) {
top_segment_index_.push_back(w);
seg_number_.push_back(1); // Top segment is segment #1
}
segpress_ = bhp();
segrates_ = wellRates();
@@ -581,10 +584,11 @@ namespace Opm
}
assert(local_comp_index == this->wells_->well_connpos[ w + 1 ] - this->wells_->well_connpos[ w ]);
const auto nSeg = this->numSegments(w);
for (auto segID = 0*nSeg; segID < nSeg; ++segID) {
well.segments[segID + 1] =
this->reportSegmentResults(pu, w, segID);
const auto nseg = this->numSegments(w);
for (auto seg_ix = 0*nseg; seg_ix < nseg; ++seg_ix) {
const auto seg_no = this->segmentNumber(w, seg_ix);
well.segments[seg_no] =
this->reportSegmentResults(pu, w, seg_ix, seg_no);
}
}
@@ -609,6 +613,7 @@ namespace Opm
segpress_.reserve(nw);
segrates_.clear();
segrates_.reserve(nw * numPhases());
seg_number_.clear();
nseg_ = 0;
// in the init function, the well rates and perforation rates have been initialized or copied from prevState
@@ -632,6 +637,7 @@ namespace Opm
top_segment_index_.push_back(nseg_);
if ( !well_ecl->isMultiSegment(time_step) ) { // not multi-segment well
nseg_ += 1;
seg_number_.push_back(1); // Assign single segment (top) as number 1.
segpress_.push_back(bhp()[w]);
const int np = numPhases();
for (int p = 0; p < np; ++p) {
@@ -645,6 +651,9 @@ namespace Opm
const int well_nseg = segment_set.size();
const int nperf = completion_set.size();
nseg_ += well_nseg;
for (auto segID = 0*well_nseg; segID < well_nseg; ++segID) {
this->seg_number_.push_back(segment_set[segID].segmentNumber());
}
// we need to know for each segment, how many perforation it has and how many segments using it as outlet_segment
// that is why I think we should use a well model to initialize the WellState here
std::vector<std::vector<int>> segment_perforations(well_nseg);
@@ -942,48 +951,65 @@ namespace Opm
// Well potentials
std::vector<double> well_potentials_;
/// Map segment index to segment number, mostly for MS wells.
///
/// Segment number (one-based) of j-th segment in i-th well is
/// \code
/// const auto top = topSegmentIndex(i);
/// const auto seg_No = seg_number_[top + j];
/// \end
std::vector<int> seg_number_;
::Opm::data::Segment
reportSegmentResults(const PhaseUsage& pu,
const int wellID,
const int segmentID) const
const int well_id,
const int seg_ix,
const int seg_no) const
{
auto segRes = ::Opm::data::Segment{};
auto seg_res = ::Opm::data::Segment{};
const auto segDoF =
this->topSegmentIndex(wellID) + segmentID;
const auto seg_dof =
this->topSegmentIndex(well_id) + seg_ix;
const auto* rate =
&this->segRates()[segDoF * this->numPhases()];
&this->segRates()[seg_dof * this->numPhases()];
segRes.pressure = this->segPress()[segDoF];
seg_res.pressure = this->segPress()[seg_dof];
if (pu.phase_used[Water]) {
segRes.rates.set(data::Rates::opt::wat,
rate[pu.phase_pos[Water]]);
seg_res.rates.set(data::Rates::opt::wat,
rate[pu.phase_pos[Water]]);
}
if (pu.phase_used[Oil]) {
segRes.rates.set(data::Rates::opt::oil,
rate[pu.phase_pos[Oil]]);
seg_res.rates.set(data::Rates::opt::oil,
rate[pu.phase_pos[Oil]]);
}
if (pu.phase_used[Gas]) {
segRes.rates.set(data::Rates::opt::gas,
rate[pu.phase_pos[Gas]]);
seg_res.rates.set(data::Rates::opt::gas,
rate[pu.phase_pos[Gas]]);
}
segRes.segNumber = segmentID + 1;
seg_res.segNumber = seg_no;
return segRes;
return seg_res;
}
int numSegments(const int wellID) const
int numSegments(const int well_id) const
{
const auto topSeg = this->topSegmentIndex(wellID);
const auto topseg = this->topSegmentIndex(well_id);
return (wellID + 1 == this->numWells()) // Last well?
? (this->numSegment() - topSeg)
: (this->topSegmentIndex(wellID + 1) - topSeg);
return (well_id + 1 == this->numWells()) // Last well?
? (this->numSegment() - topseg)
: (this->topSegmentIndex(well_id + 1) - topseg);
}
int segmentNumber(const int well_id, const int seg_id) const
{
const auto top_offset = this->topSegmentIndex(well_id);
return this->seg_number_[top_offset + seg_id];
}
};

View File

@@ -98,16 +98,21 @@ namespace {
const auto topSegIx = wstate.topSegmentIndex(wellID);
const auto pressTop = 100.0 * wellID;
segPress[topSegIx] = pressTop;
auto* press = &segPress[topSegIx];
press[0] = pressTop;
if (! well->isMultiSegment(tstep)) {
continue;
}
const auto nSeg = well->getWellSegments(tstep).size();
const auto& segSet = well->getWellSegments(tstep);
const auto nSeg = segSet.size();
for (auto segID = 0*nSeg + 1; segID < nSeg; ++segID) {
segPress[topSegIx + segID] = pressTop + 1.0*segID;
// One-based numbering scheme for segments.
const auto segNo = segSet[segID].segmentNumber();
press[segNo - 1] = pressTop + 1.0*(segNo - 1);
}
}
}
@@ -136,7 +141,7 @@ namespace {
for (auto wellID = 0*nWell; wellID < nWell; ++wellID) {
const auto* well = wells[wellID];
const auto topSegIx = wstate.topSegmentIndex(wellID);
const auto rateTop = 1000.0 * wellID;
const auto rateTop = 1000.0 * wellID;
if (wat) { segRates[np*topSegIx + iw] = rateTop; }
if (oil) { segRates[np*topSegIx + io] = rateTop; }
@@ -146,14 +151,18 @@ namespace {
continue;
}
const auto nSeg = well->getWellSegments(tstep).size();
const auto& segSet = well->getWellSegments(tstep);
const auto nSeg = segSet.size();
for (auto segID = 0*nSeg + 1; segID < nSeg; ++segID) {
auto* rates = &segRates[(topSegIx + segID) * np];
// One-based numbering scheme for segments.
const auto segNo = segSet[segID].segmentNumber();
if (wat) { rates[iw] = rateTop + 100.0*segID; }
if (oil) { rates[io] = rateTop + 200.0*segID; }
if (gas) { rates[ig] = rateTop + 400.0*segID; }
auto* rates = &segRates[(topSegIx + segNo - 1) * np];
if (wat) { rates[iw] = rateTop + 100.0*(segNo - 1); }
if (oil) { rates[io] = rateTop + 200.0*(segNo - 1); }
if (gas) { rates[ig] = rateTop + 400.0*(segNo - 1); }
}
}
}
@@ -260,9 +269,14 @@ BOOST_AUTO_TEST_CASE(Rates)
const auto& xseg = xw.segments.at(1);
BOOST_CHECK_EQUAL(xseg.segNumber, 1);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::wat), rateTop, 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::oil), rateTop, 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::gas), rateTop, 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::wat),
rateTop, 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::oil),
rateTop, 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::gas),
rateTop, 1.0e-10);
}
{
@@ -273,19 +287,19 @@ BOOST_AUTO_TEST_CASE(Rates)
const auto rateTop = prod01_first ? 0.0 : 1000.0;
for (auto segID = 0; segID < expect_nSeg; ++segID) {
const auto& xseg = xw.segments.at(segID + 1);
for (auto segNum = 1; segNum <= expect_nSeg; ++segNum) {
const auto& xseg = xw.segments.at(segNum);
BOOST_CHECK_EQUAL(xseg.segNumber, segID + 1);
BOOST_CHECK_EQUAL(xseg.segNumber, segNum);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::wat),
rateTop + 100.0*segID, 1.0e-10);
rateTop + 100.0*(segNum - 1), 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::oil),
rateTop + 200.0*segID, 1.0e-10);
rateTop + 200.0*(segNum - 1), 1.0e-10);
BOOST_CHECK_CLOSE(xseg.rates.get(Opm::data::Rates::opt::gas),
rateTop + 400.0*segID, 1.0e-10);
rateTop + 400.0*(segNum - 1), 1.0e-10);
}
}
}