diff --git a/opm/input/eclipse/Schedule/MSW/Valve.hpp b/opm/input/eclipse/Schedule/MSW/Valve.hpp index 8a884ddbc..003efc2eb 100644 --- a/opm/input/eclipse/Schedule/MSW/Valve.hpp +++ b/opm/input/eclipse/Schedule/MSW/Valve.hpp @@ -69,6 +69,7 @@ namespace Opm { // Status: OPEN or SHUT ICDStatus status() const; + int ecl_status() const; void setConMaxCrossArea(const double area); diff --git a/opm/output/eclipse/AggregateMSWData.hpp b/opm/output/eclipse/AggregateMSWData.hpp index c5400a905..4bb9e7646 100644 --- a/opm/output/eclipse/AggregateMSWData.hpp +++ b/opm/output/eclipse/AggregateMSWData.hpp @@ -36,39 +36,18 @@ namespace Opm { namespace Opm { namespace RestartIO { namespace Helpers { - struct BranchSegmentPar { - int outletS; - int noSegInBranch; - int firstSeg; - int lastSeg; - int branch; - }; - - struct SegmentSetSourceSinkTerms { - std::vector qosc; - std::vector qwsc; - std::vector qgsc; - }; - - struct SegmentSetFlowRates { - std::vector sofr; - std::vector swfr; - std::vector sgfr; - }; - class AggregateMSWData { public: explicit AggregateMSWData(const std::vector& inteHead); - void captureDeclaredMSWData(const Opm::Schedule& sched, - const std::size_t rptStep, - const Opm::UnitSystem& units, - const std::vector& inteHead, - const Opm::EclipseGrid& grid, - const Opm::SummaryState& smry, - const Opm::data::Wells& wr - ); + void captureDeclaredMSWData(const Opm::Schedule& sched, + const std::size_t rptStep, + const Opm::UnitSystem& units, + const std::vector& inteHead, + const Opm::EclipseGrid& grid, + const Opm::SummaryState& smry, + const Opm::data::Wells& wr); /// Retrieve Integer Multisegment well data Array. const std::vector& getISeg() const @@ -94,7 +73,6 @@ namespace Opm { namespace RestartIO { namespace Helpers { return this->iLBR_.data(); } - private: /// Aggregate 'ISEG' array (Integer) for all multisegment wells WindowedArray iSeg_; @@ -106,8 +84,7 @@ namespace Opm { namespace RestartIO { namespace Helpers { WindowedArray iLBS_; /// Aggregate 'ILBR' array (Integer) for all multisegment wells - WindowedArray iLBR_; - + WindowedMatrix iLBR_; }; }}} // Opm::RestartIO::Helpers diff --git a/opm/output/eclipse/VectorItems/msw.hpp b/opm/output/eclipse/VectorItems/msw.hpp index 9b321b9bf..bc4145d39 100644 --- a/opm/output/eclipse/VectorItems/msw.hpp +++ b/opm/output/eclipse/VectorItems/msw.hpp @@ -40,6 +40,16 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems } // ISeg + namespace ILbr { + enum index : std::vector::size_type { + OutletSegment = 0, // Branch's outlet segment (one-based) + NumBranchSegments = 1, // Number of segments on branch + FirstSegment = 2, // First segment on branch (kick-off, heel) + LastSegment = 3, // Last segment on branch (toe) + KickOffDiscoveryOffset = 4, // Segment traversal order at which this branch was encountered + }; + } // ILbr + namespace RSeg { enum index : std::vector::size_type { DistOutlet = 0, // Segment's distance to outlet diff --git a/src/opm/input/eclipse/Schedule/MSW/Valve.cpp b/src/opm/input/eclipse/Schedule/MSW/Valve.cpp index fae47e64a..ab86b1d77 100644 --- a/src/opm/input/eclipse/Schedule/MSW/Valve.cpp +++ b/src/opm/input/eclipse/Schedule/MSW/Valve.cpp @@ -18,9 +18,11 @@ */ #include + #include #include +#include "icd_convert.hpp" namespace Opm { @@ -130,6 +132,11 @@ namespace Opm { return m_status; } + int Valve::ecl_status() const + { + return to_int(this->status()); + } + double Valve::conFlowCoefficient() const { return m_con_flow_coeff; } diff --git a/src/opm/output/eclipse/AggregateMSWData.cpp b/src/opm/output/eclipse/AggregateMSWData.cpp index 4e7be694a..6443968a1 100644 --- a/src/opm/output/eclipse/AggregateMSWData.cpp +++ b/src/opm/output/eclipse/AggregateMSWData.cpp @@ -18,31 +18,43 @@ */ #include + #include #include #include +#include +#include #include #include -#include +#include #include +#include #include #include #include -#include -#include + #include #include +#include #include #include #include -#include +#include +#include #include #include +#include +#include #include #include +#include +#include +#include + +#include // ##################################################################### // Class Opm::RestartIO::Helpers::AggregateMSWData @@ -50,6 +62,18 @@ namespace { + struct SegmentSetSourceSinkTerms { + std::vector qosc; + std::vector qwsc; + std::vector qgsc; + }; + + struct SegmentSetFlowRates { + std::vector sofr; + std::vector swfr; + std::vector sgfr; + }; + std::size_t nswlmx(const std::vector& inteHead) { // inteHead(175) = NSWLMX @@ -75,56 +99,38 @@ namespace { } std::vector - inflowSegmentsIndex(const Opm::WellSegments& segSet, const std::size_t& segIndex) { - const auto& segNumber = segSet[segIndex].segmentNumber(); + inflowSegmentsIndex(const Opm::WellSegments& segSet, + const std::size_t segIndex) + { std::vector inFlowSegInd; + + const auto segNumber = segSet[segIndex].segmentNumber(); + for (std::size_t ind = 0; ind < segSet.size(); ind++) { const auto& i_outletSeg = segSet[ind].outletSegment(); if (segNumber == i_outletSeg) { inFlowSegInd.push_back(ind); } } + return inFlowSegInd; } - Opm::RestartIO::Helpers::BranchSegmentPar - getBranchSegmentParam(const Opm::WellSegments& segSet, const int branch) + std::vector + segmentIndFromOrderedSegmentInd(const Opm::WellSegments& segSet, + const std::vector& ordSegNo) { - int noSegInBranch = 0; - int firstSeg = -1; - int lastSeg = -1; - int outletS = 0; - for (std::size_t segInd = 0; segInd < segSet.size(); segInd++) { - const auto& segNo = segSet[segInd].segmentNumber(); - const auto& i_branch = segSet[segInd].branchNumber(); - const auto& i_outS = segSet[segInd].outletSegment(); - if (i_branch == branch) { - noSegInBranch +=1; - if (firstSeg < 0) { - firstSeg = segNo; - outletS = (branch > 1) ? i_outS : 0; - } - lastSeg = segNo; - } - } - - return { - outletS, - noSegInBranch, - firstSeg, - lastSeg, - branch - }; - } - - std::vector segmentIndFromOrderedSegmentInd(const Opm::WellSegments& segSet, const std::vector& ordSegNo) { std::vector sNFOSN (segSet.size(),0); for (std::size_t segInd = 0; segInd < segSet.size(); segInd++) { sNFOSN[ordSegNo[segInd]] = segInd; } return sNFOSN; } - std::vector segmentOrder(const Opm::WellSegments& segSet, const std::size_t segIndex) { + + std::vector + segmentOrder(const Opm::WellSegments& segSet, + const std::size_t segIndex) + { std::vector ordSegNumber; std::vector segIndCB; // Store "heel" segment since that will not always be at the end of the list @@ -177,16 +183,18 @@ namespace { return ordSegNumber; } - std::vector segmentOrder(const Opm::WellSegments& segSet) { + std::vector + segmentOrder(const Opm::WellSegments& segSet) + { return segmentOrder(segSet, 0); } /// Accumulate connection flow rates (surface conditions) to their connecting segment. - Opm::RestartIO::Helpers::SegmentSetSourceSinkTerms - getSegmentSetSSTerms(const Opm::WellSegments& segSet, + SegmentSetSourceSinkTerms + getSegmentSetSSTerms(const Opm::WellSegments& segSet, const std::vector& rateConns, - const Opm::WellConnections& welConns, - const Opm::UnitSystem& units) + const Opm::WellConnections& welConns, + const Opm::UnitSystem& units) { std::vector qosc (segSet.size(), 0.); std::vector qwsc (segSet.size(), 0.); @@ -232,11 +240,11 @@ namespace { }; } - Opm::RestartIO::Helpers::SegmentSetFlowRates - getSegmentSetFlowRates(const Opm::WellSegments& segSet, + SegmentSetFlowRates + getSegmentSetFlowRates(const Opm::WellSegments& segSet, const std::vector& rateConns, - const Opm::WellConnections& welConns, - const Opm::UnitSystem& units) + const Opm::WellConnections& welConns, + const Opm::UnitSystem& units) { std::vector sofr (segSet.size(), 0.); std::vector swfr (segSet.size(), 0.); @@ -273,31 +281,6 @@ namespace { }; } - - std::vector SegmentSetBranches(const Opm::WellSegments& segSet) { - std::vector branches; - for (std::size_t segInd = 0; segInd < segSet.size(); segInd++) { - const auto& i_branch = segSet[segInd].branchNumber(); - if (std::find(branches.begin(), branches.end(), i_branch) == branches.end()) { - branches.push_back(i_branch); - } - } - return branches; - } - - int firstSegmentInBranch(const Opm::WellSegments& segSet, const int branch) { - int firstSegInd = 0; - std::size_t segInd = 0; - while ((segInd < segSet.size()) && (firstSegInd == 0)) { - const auto& i_branch = segSet[segInd].branchNumber(); - if (branch == i_branch) { - firstSegInd = segInd; - } - segInd+=1; - } - return firstSegInd; - } - int noConnectionsSegment(const Opm::WellConnections& compSet, const Opm::WellSegments& segSet, const std::size_t segIndex) @@ -332,9 +315,12 @@ namespace { return sumConn; } - int noInFlowBranches(const Opm::WellSegments& segSet, std::size_t segIndex) { - const auto& segNumber = segSet[segIndex].segmentNumber(); - const auto& branch = segSet[segIndex].branchNumber(); + int noInFlowBranches(const Opm::WellSegments& segSet, + const std::size_t segIndex) + { + const auto segNumber = segSet[segIndex].segmentNumber(); + const auto branch = segSet[segIndex].branchNumber(); + int noIFBr = 0; for (std::size_t ind = 0; ind < segSet.size(); ind++) { const auto& o_segNum = segSet[ind].outletSegment(); @@ -343,12 +329,16 @@ namespace { noIFBr+=1; } } + return noIFBr; } + //find the number of inflow branch-segments (segments that has a branch) from the // first segment to the current segment for segments that has at least one inflow branch // Segments with no inflow branches get the value zero - int sumNoInFlowBranches(const Opm::WellSegments& segSet, const std::size_t& segIndex) { + int sumNoInFlowBranches(const Opm::WellSegments& segSet, + const std::size_t segIndex) + { int sumIFB = 0; //auto segInd = segIndex; for (int segInd = static_cast(segIndex); segInd >= 0; segInd--) { @@ -362,15 +352,19 @@ namespace { } } } + // check if the segment has inflow branches - if yes return sumIFB else return zero - return (noInFlowBranches(segSet, segIndex) >= 1) + return (noInFlowBranches(segSet, segIndex) >= 1) ? sumIFB : 0; } + int inflowSegmentCurBranch(const std::string& wname, + const Opm::WellSegments& segSet, + const std::size_t segIndex) + { + const auto branch = segSet[segIndex].branchNumber(); + const auto segNumber = segSet[segIndex].segmentNumber(); - int inflowSegmentCurBranch(const std::string& wname, const Opm::WellSegments& segSet, std::size_t segIndex) { - const auto& branch = segSet[segIndex].branchNumber(); - const auto& segNumber = segSet[segIndex].segmentNumber(); int inFlowSegInd = -1; for (std::size_t ind = 0; ind < segSet.size(); ind++) { const auto& i_segNum = segSet[ind].segmentNumber(); @@ -390,6 +384,7 @@ namespace { } } } + return (inFlowSegInd == -1) ? 0 : inFlowSegInd; } @@ -435,7 +430,6 @@ namespace { VectorItems::ISeg::index; const auto& sicd = segment.spiralICD(); - iSeg[baseIndex + Ix::SegmentType] = segment.ecl_type_id(); iSeg[baseIndex + Ix::ICDScalingMode] = sicd.methodFlowScaling(); iSeg[baseIndex + Ix::ICDOpenShutFlag] = sicd.ecl_status(); } @@ -449,11 +443,21 @@ namespace { VectorItems::ISeg::index; const auto& aicd = segment.autoICD(); - iSeg[baseIndex + Ix::SegmentType] = segment.ecl_type_id(); iSeg[baseIndex + Ix::ICDScalingMode] = aicd.methodFlowScaling(); iSeg[baseIndex + Ix::ICDOpenShutFlag] = aicd.ecl_status(); } + template + void assignValveCharacteristics(const Opm::Segment& segment, + const std::size_t baseIndex, + ISegArray& iSeg) + { + using Ix = ::Opm::RestartIO::Helpers::VectorItems::ISeg::index; + + const auto& valve = segment.valve(); + iSeg[baseIndex + Ix::ICDOpenShutFlag] = valve.ecl_status(); + } + template void assignSegmentTypeCharacteristics(const Opm::Segment& segment, const std::size_t baseIndex, @@ -462,9 +466,14 @@ namespace { if (segment.isSpiralICD()) { assignSpiralICDCharacteristics(segment, baseIndex, iSeg); } + if (segment.isAICD()) { assignAICDCharacteristics(segment, baseIndex, iSeg); } + + if (segment.isValve()) { + assignValveCharacteristics(segment, baseIndex, iSeg); + } } template @@ -491,7 +500,7 @@ namespace { const auto& segment = welSegSet[ind]; auto segNumber = segment.segmentNumber(); auto iS = (segNumber-1)*noElmSeg; - iSeg[iS + Ix::SegNo] = welSegSet[orderedSegmentNo[ind]].segmentNumber(); + iSeg[ind*noElmSeg + Ix::SegNo] = welSegSet[orderedSegmentNo[ind]].segmentNumber(); iSeg[iS + Ix::OutSeg] = segment.outletSegment(); iSeg[iS + Ix::InSegCurBranch] = (inflowSegmentCurBranch(well.name(), welSegSet, ind) == 0) ? 0 : welSegSet[inflowSegmentCurBranch(well.name(), welSegSet, ind)].segmentNumber(); iSeg[iS + Ix::BranchNo] = segment.branchNumber(); @@ -764,6 +773,7 @@ namespace { bool haveWellRes = (well.getStatus() != Opm::Well::Status::SHUT) ? (wRatesIt != wr.end()) : false; const auto volFromLengthUnitConv = units.from_si(M::length, units.from_si(M::length, units.from_si(M::length, 1.))); const auto areaFromLengthUnitConv = units.from_si(M::length, units.from_si(M::length, 1.)); + // //Initialize temporary variables double temp_o = 0.; @@ -771,10 +781,9 @@ namespace { double temp_g = 0.; // find well connections and calculate segment rates based on well connection production/injection terms - auto sSFR = Opm::RestartIO::Helpers::SegmentSetFlowRates{}; - if (haveWellRes) { - sSFR = getSegmentSetFlowRates(welSegSet, wRatesIt->second.connections, welConns, units); - } + const auto sSFR = haveWellRes + ? getSegmentSetFlowRates(welSegSet, wRatesIt->second.connections, welConns, units) + : SegmentSetFlowRates{}; auto get = [&smry, &wname](const std::string& vector, const std::string& segment_nr) { @@ -782,7 +791,6 @@ namespace { return smry.get(key, 0.0); }; - // Treat the top segment individually { const int segNumber = segment0.segmentNumber(); @@ -904,6 +912,287 @@ namespace { } } // RSeg + namespace LateralBranch { + /// Discover segment and branch tree structure through traversal. + /// Uses Segment::inletSegments() as the primary link in the tree + /// structure. + /// + /// Information conveyed to the user through callback routines. + /// + /// As an example, the segments in the following tree will be + /// visited in the order + /// + /// 1, 2, 3, 4, 5, 6 -- Branch (1) + /// 11, 12, 13, 14, 15, 16 -- Branch (2) + /// 7, 8, 9, 10 -- Branch (3) + /// 20, 22, 23, 24 -- Branch (5) + /// 21, -- Branch (6) + /// 17, 18, 19 -- Branch (4) + /// + /// +------------------------------------------------------------+ + /// | | + /// | 12 13 14 15 16 | + /// | o----o----o-----o------o-----o (2) | + /// | 11 / 20 \ 21 \ | + /// | / o o (6) | + /// | / \ | + /// | / 22 \ 23 24 | + /// | 1 2 3 / 4 5 6 o----o----o (5) | + /// | ---o---o---o-----o---o---o (1) | + /// | \ | + /// | 7 \ 8 9 10 | + /// | o---o---o-----o (3) | + /// | \ | + /// | 17 \ 18 19 | + /// | o----o----o (4) | + /// | | + /// +------------------------------------------------------------+ + /// + class Topology + { + public: + /// Callback for discovering/visiting a new segment. + using NewSegmentCallback = std::function; + + /// Callback for discovering/creating a new branch. + using NewBranchCallback = std::function< + void(std::string_view well, + const int branchId, + const int kickOffSegment, + const int outletSegment) + >; + + /// Constructor. + /// + /// \param[in] well Name of current MS well. + /// \param[in] segSet Well's segments and branches. + explicit Topology(std::string_view well, + const ::Opm::WellSegments& segSet) + : well_ { well } + , segSet_ { std::cref(segSet) } + {} + + /// Set callback for visiting a new segment. + /// + /// \param[in] callback New callback routine. + /// \return \c *this. + Topology& setNewSegmentCallback(NewSegmentCallback callback) + { + this->runNewSegmentCallback_ = std::move(callback); + return *this; + } + + /// Set callback for visiting a new branch. + /// + /// \param[in] callback New callback routine. + /// \return \c *this. + Topology& setNewBranchCallback(NewBranchCallback callback) + { + this->runNewBranchCallback_ = std::move(callback); + return *this; + } + + /// Walk well's segment tree from top (segment 1, branch 1). + /// + /// New branches and segments are searched in a depth first + /// order. Furthermore, new branches are visited in order of + /// discovery, but we always search to the end of the current + /// branch, visiting all of its segments, before visiting the + /// first segment of a new branch. Each segment is visited + /// exactly once. + /// + /// Invokes the user-defined callback routines for new segments + /// and branches and imparts segment tree structure to caller + /// through these routines. + void traverseStructure(); + + private: + /// Name of well being explored. + std::string_view well_{}; + + /// Well's segments and branches. + std::reference_wrapper segSet_; + + /// Callback routine for visiting a new segment. + NewSegmentCallback runNewSegmentCallback_{}; + + /// Callback routine for visiting a new branch. + NewBranchCallback runNewBranchCallback_{}; + + /// Segments from which to kick off searching new branches. + std::queue kickOffSegments_{}; + + /// One-based segment number of currently visited segment. + int currentSegment_{}; + + /// Find all segments on current branch, in order from heel to + /// toe. + /// + /// Invokes new segment callback, once for each segment. + void buildCurrentBranch(); + + /// Enqueue collection of new branches from common kick-off + /// point. + /// + /// \param[in] outletSegment Segment from which new branches + /// kick off. + /// + /// \param[in] children Collection of new branch start segments. + /// One child/kick-off segment for each new branch. + void discoverNewBranches(const int outletSegment, + const std::vector& children); + + /// Enqueue new branch. + /// + /// Will be visited later. Invokes new branch callback. + /// + /// \param[in] branchId Branch number for new branch. + /// + /// \param[in] kickOffSegment First segment on new branch. + /// + /// \param[in] outletSegment Segment on branch from which the + /// new branch kicks off. + void discoverNewBranch(const int branchId, + const int kickOffSegment, + const int outletSegment); + + /// Split child segments of current segment into groups + /// based on their associate branch number. + /// + /// \return Child segment grouping. The \c .first group + /// contains child segments associated to branches different to + /// that of the current segment. This collection is empty if + /// there are no child segments on other branches. The \c + /// .second group is the single child segment on the same branch + /// as the current segment. This will be \c nullopt if there is + /// no such child segment, thus signifiying the end of the + /// current branch. + std::pair, std::optional> + characteriseChildSegments() const; + + /// Get current segment object. + const Opm::Segment& currentSegment() const; + + /// Get segment object from one-based segment number. + /// + /// \param[in] segNum One-based segment number. + /// + /// \return Segment object corresponding to \p segNum. + const Opm::Segment& segment(const int segNum) const; + }; + + void Topology::traverseStructure() + { + this->kickOffSegments_.push(1); + + while (! this->kickOffSegments_.empty()) { + this->currentSegment_ = this->kickOffSegments_.front(); + this->kickOffSegments_.pop(); + + this->buildCurrentBranch(); + } + } + + void Topology::buildCurrentBranch() + { + while (true) { + const auto& seg = this->currentSegment(); + + this->runNewSegmentCallback_(seg); + + const auto& [newBranchChildren, sameBranchChild] = + this->characteriseChildSegments(); + + this->discoverNewBranches(seg.segmentNumber(), newBranchChildren); + + if (sameBranchChild.has_value()) { + // Child on same branch as currentSegment(). This child + // will be the next segment in our search order. + this->currentSegment_ = *sameBranchChild; + } + else { + // Branch completed. + return; + } + } + } + + void Topology::discoverNewBranches(const int outletSegment, + const std::vector& children) + { + for (const auto& child : children) { + const auto branch = this->segment(child).branchNumber(); + this->discoverNewBranch(branch, child, outletSegment); + } + } + + void Topology::discoverNewBranch(const int branchId, + const int kickOffSegment, + const int outletSegment) + { + this->runNewBranchCallback_(this->well_, + branchId, + kickOffSegment, + outletSegment); + + this->kickOffSegments_.push(kickOffSegment); + } + + std::pair, std::optional> + Topology::characteriseChildSegments() const + { + auto children = this->currentSegment().inletSegments(); + + auto sameBranchPos = + std::stable_partition(children.begin(), children.end(), + [this, currBranch = this->currentSegment().branchNumber()] + (const int segNum) + { + return this->segment(segNum).branchNumber() != currBranch; + }); + + if (sameBranchPos == children.end()) { + // Every child is on another branch--or there are no children + return { + std::piecewise_construct, + std::forward_as_tuple(std::move(children)), + std::forward_as_tuple() + }; + } + else { + if (const auto numSameBranch = std::distance(sameBranchPos, children.end()); + numSameBranch != std::vector::difference_type{1}) + { + throw std::invalid_argument { + fmt::format("Segment {} of well {} has {} " + "inlet segments on branch {}", + this->currentSegment().segmentNumber(), + this->well_, numSameBranch, + this->currentSegment().branchNumber()) + }; + } + + // Common case: The segment at *sameBranchPos continues the + // current branch. All other child segments start new + // branches. + return { + std::piecewise_construct, + std::forward_as_tuple(children.begin(), sameBranchPos), + std::forward_as_tuple(*sameBranchPos) + }; + } + } + + const Opm::Segment& Topology::currentSegment() const + { + return this->segment(this->currentSegment_); + } + + const Opm::Segment& Topology::segment(const int segNum) const + { + return this->segSet_.get().getFromSegmentNumber(segNum); + } + } // LateralBranch namespace ILBS { std::size_t entriesPerMSW(const std::vector& inteHead) @@ -922,70 +1211,46 @@ namespace { WV::WindowSize{ entriesPerMSW(inteHead) } }; } - - template - void staticContrib(const Opm::Well& well, - ILBSArray& iLBS) - { - if (well.isMultiSegment()) { - // - // Store the segment number of the first segment in branch for branch number - // 2 and upwards - const auto& welSegSet = well.getSegments(); - const auto& branches = SegmentSetBranches(welSegSet); - for (auto it = branches.begin()+1; it != branches.end(); it++){ - iLBS[*it-2] = welSegSet[firstSegmentInBranch(welSegSet, *it)].segmentNumber(); - } - } - else { - throw std::invalid_argument("No such multisegment well: " + well.name()); - } - } } // ILBS namespace ILBR { - std::size_t entriesPerMSW(const std::vector& inteHead) + class Array { - // inteHead(177) = NLBRMX - // inteHead(180) = NILBRZ - return inteHead[177] * inteHead[180]; + public: + using Matrix = Opm::RestartIO::Helpers::WindowedMatrix; + + explicit Array(Matrix& ilbr, + const Matrix::Idx msWellID) + : ilbr_ { std::ref(ilbr) } + , well_ { msWellID } + {} + + decltype(auto) operator[](const Matrix::Idx branch) + { + return this->ilbr_.get()(this->well_, branch - 1); + } + + private: + std::reference_wrapper ilbr_; + Matrix::Idx well_; + }; + + std::size_t maxBranchesPerMSWell(const std::vector& inteHead) + { + return inteHead[177]; } - Opm::RestartIO::Helpers::WindowedArray + Opm::RestartIO::Helpers::WindowedMatrix allocate(const std::vector& inteHead) { - using WV = Opm::RestartIO::Helpers::WindowedArray; + using WM = Opm::RestartIO::Helpers::WindowedMatrix; - return WV { - WV::NumWindows{ nswlmx(inteHead) }, - WV::WindowSize{ entriesPerMSW(inteHead) } + return WM { + WM::NumRows { nswlmx(inteHead) }, + WM::NumCols { maxBranchesPerMSWell(inteHead) }, + WM::WindowSize{ nilbrz(inteHead) } }; } - - template - void staticContrib(const Opm::Well& well, - const std::vector& inteHead, - ILBRArray& iLBR) - { - if (well.isMultiSegment()) { - // - const auto& welSegSet = well.getSegments(); - const auto& branches = SegmentSetBranches(welSegSet); - const auto& noElmBranch = nilbrz(inteHead); - for (auto it = branches.begin(); it != branches.end(); it++){ - const auto iB = (*it-1)*noElmBranch; - const auto& branchParam = getBranchSegmentParam(welSegSet, *it); - iLBR[iB ] = branchParam.outletS; - iLBR[iB+1] = branchParam.noSegInBranch; - iLBR[iB+2] = branchParam.firstSeg; - iLBR[iB+3] = branchParam.lastSeg; - iLBR[iB+4] = branchParam.branch - 1; - } - } - else { - throw std::invalid_argument("No such multisegment well: " + well.name()); - } - } } // ILBR } // Anonymous @@ -1004,60 +1269,90 @@ AggregateMSWData(const std::vector& inteHead) void Opm::RestartIO::Helpers::AggregateMSWData:: -captureDeclaredMSWData(const Schedule& sched, - const std::size_t rptStep, - const Opm::UnitSystem& units, - const std::vector& inteHead, +captureDeclaredMSWData(const Schedule& sched, + const std::size_t rptStep, + const Opm::UnitSystem& units, + const std::vector& inteHead, const Opm::EclipseGrid& grid, const Opm::SummaryState& smry, - const Opm::data::Wells& wr - ) + const Opm::data::Wells& wr) { const auto& wells = sched.getWells(rptStep); auto msw = std::vector{}; - //msw.reserve(wells.size()); for (const auto& well : wells) { - if (well.isMultiSegment()) + if (well.isMultiSegment()) { msw.push_back(&well); + } } - // Extract Contributions to ISeg Array - { - MSWLoop(msw, [&inteHead, this] - (const Well& well, const std::size_t mswID) -> void - { - auto imsw = this->iSeg_[mswID]; - ISeg::staticContrib(well, inteHead, imsw); - }); - } - // Extract Contributions to RSeg Array + // Extract contributions to the ISEG and RSEG arrays. + MSWLoop(msw, [&units, &inteHead, &sched, &grid, &smry, &wr, this] + (const Well& well, const std::size_t mswID) { - MSWLoop(msw, [&units, &inteHead, &sched, &grid, &smry, this, &wr] - (const Well& well, const std::size_t mswID) -> void - { - auto rmsw = this->rSeg_[mswID]; - RSeg::staticContrib_useMSW(sched.runspec(), well, inteHead, grid, units, smry, wr, rmsw); - }); - } - // Extract Contributions to ILBS Array - { - MSWLoop(msw, [this] - (const Well& well, const std::size_t mswID) -> void - { - auto ilbs_msw = this->iLBS_[mswID]; + auto imsw = this->iSeg_[mswID]; + auto rmsw = this->rSeg_[mswID]; - ILBS::staticContrib(well, ilbs_msw); - }); - } - // Extract Contributions to ILBR Array - { - MSWLoop(msw, [&inteHead, this] - (const Well& well, const std::size_t mswID) -> void - { - auto ilbr_msw = this->iLBR_[mswID]; + ISeg::staticContrib(well, inteHead, imsw); + RSeg::staticContrib_useMSW(sched.runspec(), well, inteHead, + grid, units, smry, wr, rmsw); + }); - ILBR::staticContrib(well, inteHead, ilbr_msw); - }); - } + // Extract contributions to the ILBS and ILBR arrays. + MSWLoop(msw, [this](const Well& well, const std::size_t mswID) + { + using Ix = VectorItems::ILbr::index; + + auto ilbs = this->iLBS_[mswID]; + auto ilbr = ILBR::Array { this->iLBR_, mswID }; + + // The top segment (segment 1) is always the first segment of branch + // 1, at an offset of 0 with no outlet segment. Describe it as such. + ilbr[1][Ix::OutletSegment] = 0; + ilbr[1][Ix::NumBranchSegments] = 0; + ilbr[1][Ix::FirstSegment] = 1; + ilbr[1][Ix::KickOffDiscoveryOffset] = 0; + + LateralBranch::Topology { well.name(), well.getSegments() } + .setNewSegmentCallback([&ilbr](const Segment& seg) + { + auto currBranch = ilbr[seg.branchNumber()]; + + // Attribute 'seg' to current branch. The LastSegment is + // intentionally updated on every call since every new + // segment is the last segment along the branch until it + // isn't anymore. + // + // We do it this way since the branch traversal visits each + // segment exactly once. + currBranch[Ix::LastSegment] = seg.segmentNumber(); + currBranch[Ix::NumBranchSegments] += 1; + }) + .setNewBranchCallback([&ilbr, &ilbs, insertIndex = 0] + (std::string_view wellName, + const int newBranchId, + const int kickOffSegment, + const int outletSegment) mutable + { + ilbs[insertIndex] = kickOffSegment; + + auto newBranch = ilbr[newBranchId]; + + // Add one to the kick-off discovery offset to account for + // branch 1 which is not in ILBS. + newBranch[Ix::OutletSegment] = outletSegment; + newBranch[Ix::FirstSegment] = kickOffSegment; + newBranch[Ix::KickOffDiscoveryOffset] = insertIndex + 1; + + if (newBranch[Ix::NumBranchSegments] > 0) { + throw std::invalid_argument { + fmt::format("Looped branch {} for well {} " + "is not supported", newBranchId, wellName) + }; + } + + ++insertIndex; + }) + .traverseStructure(); + }); } diff --git a/tests/test_AggregateMSWData.cpp b/tests/test_AggregateMSWData.cpp index 6c71e8a1c..0fcc69853 100644 --- a/tests/test_AggregateMSWData.cpp +++ b/tests/test_AggregateMSWData.cpp @@ -18,41 +18,50 @@ */ #define BOOST_TEST_MODULE Aggregate_MSW_Data + #include -#include #include -#include -#include - #include -#include #include +#include + +#include #include #include -#include -#include + #include +#include + #include #include + #include -#include +#include + +#include + +#include + +#include +#include +#include #include +#include #include #include -#include -#include namespace { namespace VI = ::Opm::RestartIO::Helpers::VectorItems; -Opm::Deck first_sim(std::string fname) { - return Opm::Parser {} .parseFile(fname); +Opm::Deck first_sim(const std::string& fname) +{ + return Opm::Parser {}.parseFile(fname); } Opm::SummaryState sim_state() @@ -92,6 +101,7 @@ Opm::SummaryState sim_state() state.update_well_var("WINJ", "WBHP", 234.); return state; } + Opm::data::Wells wr() { using o = ::Opm::data::Rates::opt; @@ -142,21 +152,110 @@ Opm::data::Wells wr() } return xw; } + +//------------------------------------------------------------------+ +// Models a multi-lateral well with the following segment structure | +//------------------------------------------------------------------+ +// | +// 12 13 14 15 16 | +// o----o----o-----o------o-----o (2) | +// 11 / 20 \ 21 \ | +// / o o (6) | +// / \ | +// / 22 \ 23 24 | +// 1 2 3 / 4 5 6 o----o----o (5) | +// ---o---o---o-----o---o---o (1) | +// \ | +// 7 \ 8 9 10 | +// o---o---o-----o (3) | +// \ | +// 17 \ 18 19 | +// o----o----o (4) | +//------------------------------------------------------------------+ +// Branch (1): 1, 2, 3, 4, 5, 6 | +// Branch (2): 11, 12, 13, 14, 15, 16 | +// Branch (3): 7, 8, 9, 10 | +// Branch (4): 17, 18, 19 | +// Branch (5): 20, 22, 23, 24 | +// Branch (6): 21 | +//------------------------------------------------------------------+ +Opm::Deck multilaterals() +{ + return Opm::Parser{}.parseString(R"(RUNSPEC +START +29 'SEP' 2023 / +DIMENS +10 10 3 / +OIL +GAS +WATER +DISGAS +VAPOIL +GRID +DXV +10*100.0 / +DYV +10*100.0 / +DZV +3*5.0 / +PERMX +300*100.0 / +COPY +PERMX PERMY / +PERMX PERMZ / +/ +MULTIPLY +PERMZ 0.1 / +/ +PORO +300*0.3 / +DEPTHZ +121*2000.0 / +SCHEDULE +WELSPECS + 'MLP' 'G' 10 10 2002.5 'OIL' / +/ +COMPDAT + 'MLP' 10 10 3 3 'OPEN' 1* 123.4 / +/ +WELSEGS + 'MLP' 2002.5 0.0 1* 'INC' 'H--' / +-- + 2 6 1 1 0.1 0.1 0.2 0.01 / + 7 10 3 5 0.1 0.1 0.2 0.01 / + 11 16 2 3 0.1 0.1 0.2 0.01 / + 17 19 4 10 0.1 0.1 0.2 0.01 / + 20 20 5 14 0.1 0.1 0.2 0.01 / + 21 21 6 15 0.1 0.1 0.2 0.01 / + 22 24 5 20 0.1 0.1 0.2 0.01 / +/ +COMPSEGS + 'MLP' / +-- + 10 10 3 5 0.0 1.0 'Z' / +/ +WCONPROD + 'MLP' 'OPEN' 'ORAT' 321.0 4* 10.0 / +/ +TSTEP +5*30 / +END +)"); } +} // Anonymous namespace + struct SimulationCase { explicit SimulationCase(const Opm::Deck& deck) - : es ( deck ) - , grid ( deck ) - , python( std::make_shared() ) - , sched( deck, es, python ) + : es (deck) + , grid (deck) + , sched(deck, es, std::make_shared()) {} // Order requirement: 'es' must be declared/initialised before 'sched'. Opm::EclipseState es; Opm::EclipseGrid grid; - std::shared_ptr python; Opm::Schedule sched; }; @@ -164,7 +263,6 @@ struct SimulationCase BOOST_AUTO_TEST_SUITE(Aggregate_MSW) - // test dimensions of multisegment data BOOST_AUTO_TEST_CASE (Constructor) { @@ -191,46 +289,36 @@ BOOST_AUTO_TEST_CASE (Constructor) const auto nrsegz = VI::intehead::NRSEGZ; const auto nlbrmx = VI::intehead::NLBRMX; const auto nilbrz = VI::intehead::NILBRZ; + BOOST_CHECK_EQUAL(static_cast(amswd.getISeg().size()), ih[nswlmx] * ih[nsegmx] * ih[nisegz]); BOOST_CHECK_EQUAL(static_cast(amswd.getRSeg().size()), ih[nswlmx] * ih[nsegmx] * ih[nrsegz]); BOOST_CHECK_EQUAL(static_cast(amswd.getILBs().size()), ih[nswlmx] * ih[nlbrmx]); BOOST_CHECK_EQUAL(static_cast(amswd.getILBr().size()), ih[nswlmx] * ih[nlbrmx] * ih[nilbrz]); } - BOOST_AUTO_TEST_CASE (Declared_MSW_Data) { - const auto simCase = SimulationCase {first_sim("TEST_AGGREGATE_MSW.DATA")}; - Opm::EclipseState es = simCase.es; - Opm::Runspec rspec = es.runspec(); - Opm::SummaryState smry = sim_state(); - Opm::Schedule sched = simCase.sched; - Opm::EclipseGrid grid = simCase.grid; - const auto& units = es.getUnits(); - + const auto& es = simCase.es; + const auto& grid = simCase.grid; + const auto& sched = simCase.sched; + const auto& units = es.getUnits(); + const auto smry = sim_state(); // Report Step 1: 2008-10-10 --> 2011-01-20 const auto rptStep = std::size_t {1}; - double secs_elapsed = 3.1536E07; + const double secs_elapsed = 3.1536E07; const auto ih = Opm::RestartIO::Helpers:: - createInteHead(es, grid, sched, secs_elapsed, - rptStep, rptStep+1, rptStep); - - //BOOST_CHECK_EQUAL(ih.nwells, MockIH::Sz{2}); + createInteHead(es, grid, sched, secs_elapsed, + rptStep, rptStep + 1, rptStep); const Opm::data::Wells wrc = wr(); + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; - amswd.captureDeclaredMSWData(simCase.sched, - rptStep, - units, - ih, - grid, - smry, - wrc - ); + amswd.captureDeclaredMSWData(sched, rptStep, units, + ih, grid, smry, wrc); // ISEG (PROD) { @@ -409,39 +497,214 @@ BOOST_AUTO_TEST_CASE (Declared_MSW_Data) } } +// The segments and branches must appear in the following order in the +// ILBS/ILBR output arrays. +// +// 1, 2, 3, 4, 5, 6 -- Branch (1) +// 11, 12, 13, 14, 15, 16 -- Branch (2) +// 7, 8, 9, 10 -- Branch (3) +// 20, 22, 23, 24 -- Branch (5) +// 21, -- Branch (6) +// 17, 18, 19 -- Branch (4) +// +BOOST_AUTO_TEST_CASE(Multilateral_Branches) +{ + const auto cse = SimulationCase { multilaterals() }; -BOOST_AUTO_TEST_CASE(MSW_AICD) { + const auto& es = cse.es; + const auto& grid = cse.grid; + const auto& sched = cse.sched; + const auto& units = es.getUnits(); + const auto smry = Opm::SummaryState { Opm::TimeService::now() }; + + // Report Step 1: 2023-09-29 --> 2023-10-23 + const auto rptStep = std::size_t {1}; + + const double secs_elapsed = 30 * 86'400.0; + const auto ih = Opm::RestartIO::Helpers:: + createInteHead(es, grid, sched, secs_elapsed, + rptStep, rptStep + 1, rptStep); + + const auto xw = Opm::data::Wells {}; + + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; + amswd.captureDeclaredMSWData(sched, rptStep, units, + ih, grid, smry, xw); + + // ILBS--First segment on each branch other than branch 1. Ordered by + // discovery. + { + const auto& ilbs = amswd.getILBs(); + + // No WSEGDIMS => size = maximum branch number + BOOST_CHECK_EQUAL(ilbs.size(), std::vector::size_type{6}); + + const auto expect = std::vector { + 11, 7, 20, 21, 17, 0, + }; + + BOOST_CHECK_EQUAL_COLLECTIONS(ilbs .begin(), ilbs .end(), + expect.begin(), expect.end()); + } + + auto ilbrOffset = [&ih](const int branch) + { + return ih[VI::intehead::NILBRZ] * (branch - 1); + }; + + // ILBR, branch 1 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(1)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 0); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 6); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 1); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 6); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 0); + } + + // ILBR, branch 2 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(2)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 3); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 6); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 11); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 16); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 1); + } + + // ILBR, branch 3 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(3)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 5); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 4); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 7); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 10); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 2); + } + + // ILBR, branch 4 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(4)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 10); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 3); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 17); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 19); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 5); + } + + // ILBR, branch 5 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(5)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 14); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 4); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 20); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 24); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 3); + } + + // ILBR, branch 6 + { + const auto* ilbr = &amswd.getILBr()[ilbrOffset(6)]; + + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::OutletSegment], 15); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::NumBranchSegments], 1); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::FirstSegment], 21); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::LastSegment], 21); + BOOST_CHECK_EQUAL(ilbr[VI::ILbr::KickOffDiscoveryOffset], 4); + } +} + +// The segments must appear in the following depth first search toe-to-heel +// order in ISEG[0]. We furthermore, go along kick-off branches before +// searching the main branch. Note that this order is *different* from +// ILBS/ILBR. +// +// 24, 23, 22, 20, -- Branch (5) +// 21, -- Branch (6) +// 16, 15, 14, 13, 12, 11, -- Branch (2) +// 19, 18, 17, -- Branch (4) +// 10, 9, 8, 7, -- Branch (3) +// 6, 5, 4, 3, 2, 1, -- Branch (1) +// +BOOST_AUTO_TEST_CASE(Multilateral_Segments_ISEG_0) +{ + const auto cse = SimulationCase { multilaterals() }; + + const auto& es = cse.es; + const auto& grid = cse.grid; + const auto& sched = cse.sched; + const auto& units = es.getUnits(); + const auto smry = Opm::SummaryState { Opm::TimeService::now() }; + + // Report Step 1: 2023-09-29 --> 2023-10-23 + const auto rptStep = std::size_t {1}; + + const double secs_elapsed = 30 * 86'400.0; + const auto ih = Opm::RestartIO::Helpers:: + createInteHead(es, grid, sched, secs_elapsed, + rptStep, rptStep + 1, rptStep); + + const auto xw = Opm::data::Wells {}; + + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; + amswd.captureDeclaredMSWData(sched, rptStep, units, + ih, grid, smry, xw); + + auto isegOffset = [&ih](const int ix) + { + return ih[VI::intehead::NISEGZ] * ix; + }; + + const auto expect = std::vector { + 24, 23, 22, 20, // Branch (5) + 21, // Branch (6) + 16, 15, 14, 13, 12, 11, // Branch (2) + 19, 18, 17, // Branch (4) + 10, 9, 8, 7, // Branch (3) + 6, 5, 4, 3, 2, 1, // Branch (1) + }; + + const auto& iseg = amswd.getISeg(); + + for (auto i = 0*expect.size(); i < expect.size(); ++i) { + BOOST_CHECK_MESSAGE(iseg[isegOffset(i)] == expect[i], + "ISEG[0](" << i << ") == " + << iseg[isegOffset(i)] + << " differs from expected value " + << expect[i]); + } +} + +BOOST_AUTO_TEST_CASE(MSW_AICD) +{ const auto simCase = SimulationCase {first_sim("TEST_AGGREGATE_MSW.DATA")}; - Opm::EclipseState es = simCase.es; - Opm::Runspec rspec = es.runspec(); - Opm::SummaryState smry = sim_state(); - Opm::Schedule sched = simCase.sched; - Opm::EclipseGrid grid = simCase.grid; - const auto& units = es.getUnits(); - + const auto& es = simCase.es; + const auto& grid = simCase.grid; + const auto& sched = simCase.sched; + const auto& units = es.getUnits(); + const auto smry = sim_state(); // Report Step 1: 2008-10-10 --> 2011-01-20 const auto rptStep = std::size_t {1}; - double secs_elapsed = 3.1536E07; + const double secs_elapsed = 3.1536E07; const auto ih = Opm::RestartIO::Helpers:: - createInteHead(es, grid, sched, secs_elapsed, - rptStep, rptStep+1, rptStep); - + createInteHead(es, grid, sched, secs_elapsed, + rptStep, rptStep + 1, rptStep); const Opm::data::Wells wrc = wr(); - auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; - amswd.captureDeclaredMSWData(simCase.sched, - rptStep, - units, - ih, - grid, - smry, - wrc - ); -// ISEG (PROD) + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; + amswd.captureDeclaredMSWData(sched, rptStep, units, + ih, grid, smry, wrc); + + // ISEG (PROD) { const auto& iSeg = amswd.getISeg(); auto start = 7*ih[VI::intehead::NISEGZ]; @@ -507,48 +770,38 @@ BOOST_AUTO_TEST_CASE(MSW_AICD) { BOOST_CHECK_CLOSE(rseg[i0 + VI::RSeg::index::flowFractionOilViscosityExponent], 1.01 , 1.0e-10); BOOST_CHECK_CLOSE(rseg[i0 + VI::RSeg::index::flowFractionWaterViscosityExponent], 1.02 , 1.0e-10); BOOST_CHECK_CLOSE(rseg[i0 + VI::RSeg::index::flowFractionGasViscosityExponent], 1.03 , 1.0e-10); - } - } - -BOOST_AUTO_TEST_CASE(MSW_RST) { +BOOST_AUTO_TEST_CASE(MSW_RST) +{ const auto simCase = SimulationCase {first_sim("TEST_AGGREGATE_MSW.DATA")}; - Opm::EclipseState es = simCase.es; - Opm::Runspec rspec = es.runspec(); - Opm::SummaryState smry = sim_state(); - Opm::Schedule sched = simCase.sched; - Opm::EclipseGrid grid = simCase.grid; - const auto& units = es.getUnits(); - + const auto& es = simCase.es; + const auto& grid = simCase.grid; + const auto& sched = simCase.sched; + const auto& units = es.getUnits(); + const auto smry = sim_state(); // Report Step 1: 2008-10-10 --> 2011-01-20 const auto rptStep = std::size_t {1}; - double secs_elapsed = 3.1536E07; + const double secs_elapsed = 3.1536E07; const auto ih = Opm::RestartIO::Helpers:: - createInteHead(es, grid, sched, secs_elapsed, - rptStep, rptStep+1, rptStep); - + createInteHead(es, grid, sched, secs_elapsed, + rptStep, rptStep + 1, rptStep); const Opm::data::Wells wrc = wr(); + auto amswd = Opm::RestartIO::Helpers::AggregateMSWData {ih}; - amswd.captureDeclaredMSWData(simCase.sched, - rptStep, - units, - ih, - grid, - smry, - wrc - ); + amswd.captureDeclaredMSWData(sched, rptStep, units, + ih, grid, smry, wrc); const auto& iseg = amswd.getISeg(); const auto& rseg = amswd.getRSeg(); - auto segment = Opm::RestartIO::RstSegment(simCase.es.getUnits(), 1, iseg.data(), rseg.data()); + + auto segment = Opm::RestartIO::RstSegment(simCase.es.getUnits(), 1, + iseg.data(), rseg.data()); } - - -BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE_END() // Aggregate_MSW