From 14c566d99bbf13b816cd0391cfe9b20cd43095e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Thu, 29 Oct 2020 17:08:01 +0100 Subject: [PATCH 1/2] MSW: Support Connection Results for All Connections The current code that aggregates flow rates from connection to segment levels assumes that the simulator generates connection results for the open connections only. Relax this restriction as upcoming work in the context of WELPI will require generating at least the CTFs even for shut connections. --- src/opm/output/eclipse/AggregateMSWData.cpp | 55 ++++++++++++--------- tests/test_AggregateMSWData.cpp | 3 ++ 2 files changed, 35 insertions(+), 23 deletions(-) diff --git a/src/opm/output/eclipse/AggregateMSWData.cpp b/src/opm/output/eclipse/AggregateMSWData.cpp index 68e315228..b2bc98aba 100644 --- a/src/opm/output/eclipse/AggregateMSWData.cpp +++ b/src/opm/output/eclipse/AggregateMSWData.cpp @@ -181,29 +181,35 @@ namespace { } Opm::RestartIO::Helpers::SegmentSetSourceSinkTerms - getSegmentSetSSTerms(const std::string& wname, const Opm::WellSegments& segSet, const std::vector& rateConns, - const Opm::WellConnections& welConns, const Opm::UnitSystem& units) + getSegmentSetSSTerms(const Opm::WellSegments& segSet, + const std::vector& rateConns, + const Opm::WellConnections& welConns, + const Opm::UnitSystem& units) { std::vector qosc (segSet.size(), 0.); std::vector qwsc (segSet.size(), 0.); std::vector qgsc (segSet.size(), 0.); - std::vector openConnections; - using M = ::Opm::UnitSystem::measure; - using R = ::Opm::data::Rates::opt; - for (auto nConn = welConns.size(), connID = 0*nConn; connID < nConn; connID++) { - if (welConns[connID].state() == Opm::Connection::State::OPEN) openConnections.push_back(&welConns[connID]); - } - if (openConnections.size() != rateConns.size()) { - throw std::invalid_argument { - "Inconsistent number of open connections I in Opm::WellConnections (" + - std::to_string(welConns.size()) + ") and vector (" + - std::to_string(rateConns.size()) + ") in Well " + wname - }; - } - for (auto nConn = openConnections.size(), connID = 0*nConn; connID < nConn; connID++) { - const auto& segNo = openConnections[connID]->segment(); - const auto& segInd = segSet.segmentNumberToIndex(segNo); - const auto& Q = rateConns[connID].rates; + + using M = ::Opm::UnitSystem::measure; + using R = ::Opm::data::Rates::opt; + + for (const auto& conn : welConns) { + if (conn.state() != Opm::Connection::State::OPEN) { + continue; + } + + auto xcPos = std::find_if(rateConns.begin(), rateConns.end(), + [&conn](const Opm::data::Connection& xconn) -> bool + { + return xconn.index == conn.global_index(); + }); + + if (xcPos == rateConns.end()) { + continue; + } + + const auto segInd = segSet.segmentNumberToIndex(conn.segment()); + const auto& Q = xcPos->rates; auto get = [&units, &Q](const M u, const R q) -> double { @@ -225,15 +231,17 @@ namespace { } Opm::RestartIO::Helpers::SegmentSetFlowRates - getSegmentSetFlowRates(const std::string& wname, const Opm::WellSegments& segSet, const std::vector& rateConns, - const Opm::WellConnections& welConns, const Opm::UnitSystem& units) + getSegmentSetFlowRates(const Opm::WellSegments& segSet, + const std::vector& rateConns, + const Opm::WellConnections& welConns, + const Opm::UnitSystem& units) { std::vector sofr (segSet.size(), 0.); std::vector swfr (segSet.size(), 0.); std::vector sgfr (segSet.size(), 0.); // //call function to calculate the individual segment source/sink terms - auto sSSST = getSegmentSetSSTerms(wname, segSet, rateConns, welConns, units); + auto sSSST = getSegmentSetSSTerms(segSet, rateConns, welConns, units); // find an ordered list of segments auto orderedSegmentInd = segmentOrder(segSet); @@ -255,6 +263,7 @@ namespace { sgfr[segInd] += sgfr[ifSegInd]; } } + return { sofr, swfr, @@ -655,7 +664,7 @@ namespace { // find well connections and calculate segment rates based on well connection production/injection terms auto sSFR = Opm::RestartIO::Helpers::SegmentSetFlowRates{}; if (haveWellRes) { - sSFR = getSegmentSetFlowRates(well.name(), welSegSet, wRatesIt->second.connections, welConns, units); + sSFR = getSegmentSetFlowRates(welSegSet, wRatesIt->second.connections, welConns, units); } std::string stringSegNum = std::to_string(segment0.segmentNumber()); diff --git a/tests/test_AggregateMSWData.cpp b/tests/test_AggregateMSWData.cpp index b495febda..cb6d4937c 100644 --- a/tests/test_AggregateMSWData.cpp +++ b/tests/test_AggregateMSWData.cpp @@ -558,6 +558,8 @@ END c.rates.set(o::wat, qw*(float(i)+1.)) .set(o::oil, qo*(float(i)+1.)) .set(o::gas, qg*(float(i)+1.)); + + c.index = 90 + i; // zero-based global index } auto seg = Opm::data::Segment{}; for (std::size_t i = 1; i < 5; i++) { @@ -576,6 +578,7 @@ END c.rates.set(o::wat, qw*(float(i)+1.)) .set(o::oil, 0.) .set(o::gas, 0.); + c.index = 409 - i; // zero-based global index } } return xw; From 62a39877bedaa6622da4d93d0149cbe313dd0d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Fri, 30 Oct 2020 11:23:50 +0100 Subject: [PATCH 2/2] Address Review Comments Add comments on a function and rename a variable. --- src/opm/output/eclipse/AggregateMSWData.cpp | 9 +++++---- tests/test_AggregateMSWData.cpp | 7 +++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/opm/output/eclipse/AggregateMSWData.cpp b/src/opm/output/eclipse/AggregateMSWData.cpp index b2bc98aba..e07a33d39 100644 --- a/src/opm/output/eclipse/AggregateMSWData.cpp +++ b/src/opm/output/eclipse/AggregateMSWData.cpp @@ -180,6 +180,7 @@ namespace { return segmentOrder(segSet, 0); } + /// Accumulate connection flow rates (surface conditions) to their connecting segment. Opm::RestartIO::Helpers::SegmentSetSourceSinkTerms getSegmentSetSSTerms(const Opm::WellSegments& segSet, const std::vector& rateConns, @@ -241,7 +242,7 @@ namespace { std::vector sgfr (segSet.size(), 0.); // //call function to calculate the individual segment source/sink terms - auto sSSST = getSegmentSetSSTerms(segSet, rateConns, welConns, units); + auto segmentSources = getSegmentSetSSTerms(segSet, rateConns, welConns, units); // find an ordered list of segments auto orderedSegmentInd = segmentOrder(segSet); @@ -252,9 +253,9 @@ namespace { const auto& segInd = sNFOSN[indOSN]; // the segment flow rates is the sum of the the source/sink terms for each segment plus the flow rates from the inflow segments // add source sink terms - sofr[segInd] += sSSST.qosc[segInd]; - swfr[segInd] += sSSST.qwsc[segInd]; - sgfr[segInd] += sSSST.qgsc[segInd]; + sofr[segInd] += segmentSources.qosc[segInd]; + swfr[segInd] += segmentSources.qwsc[segInd]; + sgfr[segInd] += segmentSources.qgsc[segInd]; // add flow from all inflow segments for (const auto& segNo : segSet[segInd].inletSegments()) { const auto & ifSegInd = segSet.segmentNumberToIndex(segNo); diff --git a/tests/test_AggregateMSWData.cpp b/tests/test_AggregateMSWData.cpp index cb6d4937c..c94cad37b 100644 --- a/tests/test_AggregateMSWData.cpp +++ b/tests/test_AggregateMSWData.cpp @@ -551,6 +551,7 @@ END double qo = 5.; double qw = 4.; double qg = 50.; + int firstConnectedCell = 90; // zero-based linear index of (1,5,2) for (int i = 0; i < 5; i++) { xw["PROD"].connections.emplace_back(); auto& c = xw["PROD"].connections.back(); @@ -559,7 +560,7 @@ END .set(o::oil, qo*(float(i)+1.)) .set(o::gas, qg*(float(i)+1.)); - c.index = 90 + i; // zero-based global index + c.index = firstConnectedCell + i; } auto seg = Opm::data::Segment{}; for (std::size_t i = 1; i < 5; i++) { @@ -571,6 +572,7 @@ END xw["WINJ"].rates.set(o::oil, 0.0); xw["WINJ"].rates.set(o::gas, 0.0); qw = 7.; + firstConnectedCell = 409; // zero-based linear index of (10,1,9) for (int i = 0; i < 5; i++) { xw["WINJ"].connections.emplace_back(); auto& c = xw["WINJ"].connections.back(); @@ -578,7 +580,8 @@ END c.rates.set(o::wat, qw*(float(i)+1.)) .set(o::oil, 0.) .set(o::gas, 0.); - c.index = 409 - i; // zero-based global index + + c.index = firstConnectedCell - i; } } return xw;