From 31b6baa676eb3d2861ff62a8208ce9d3c3c53dc7 Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Sat, 6 Jun 2020 08:54:04 +0200 Subject: [PATCH 1/2] Reshuffle segments and connections after restart --- .../EclipseState/Schedule/MSW/Compsegs.cpp | 61 ++++++++++++++++++- .../EclipseState/Schedule/MSW/Compsegs.hpp | 13 ++++ .../EclipseState/Schedule/Schedule.cpp | 58 ++++++------------ 3 files changed, 91 insertions(+), 41 deletions(-) diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.cpp index e02fc6481..7599cbca7 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -306,7 +307,7 @@ namespace { const EclipseGrid& grid, const ParseContext& parseContext, ErrorGuard& errors) - { + { const auto& compsegs_vector = Compsegs::compsegsFromCOMPSEGSKeyword( compsegs, input_segments, grid, parseContext, errors); WellSegments new_segment_set = input_segments; WellConnections new_connection_set = input_connections; @@ -333,6 +334,64 @@ namespace { return std::make_pair( WellConnections( std::move( new_connection_set ) ), WellSegments( std::move(new_segment_set))); + } + +namespace { + // Duplicated from Well.cpp + Connection::Order order_from_int(int int_value) { + switch(int_value) { + case 0: + return Connection::Order::TRACK; + case 1: + return Connection::Order::DEPTH; + case 2: + return Connection::Order::INPUT; + default: + throw std::invalid_argument("Invalid integer value: " + std::to_string(int_value) + " encountered when determining connection ordering"); } } + +} + + std::pair + rstUpdate(const RestartIO::RstWell& rst_well, + std::vector rst_connections, + const std::unordered_map& rst_segments) + { + for (auto& connection : rst_connections) { + int segment_id = connection.segment(); + if (segment_id > 0) { + const auto& segment = rst_segments.at(segment_id); + connection.updateSegmentRST(segment.segmentNumber(), + segment.depth()); + } + } + WellConnections connections(order_from_int(rst_well.completion_ordering), + rst_well.ij[0], + rst_well.ij[1], + rst_connections); + + + std::vector segments_list; + /* + The ordering of the segments in the WellSegments structure seems a + bit random; in some parts of the code the segment_number seems to + be treated like a random integer ID, whereas in other parts it + seems to be treated like a running index. Here the segments in + WellSegments are sorted according to the segment number - observe + that this is somewhat important because the first top segment is + treated differently from the other segment. + */ + for (const auto& segment_pair : rst_segments) + segments_list.push_back( std::move(segment_pair.second) ); + + std::sort( segments_list.begin(), segments_list.end(),[](const Segment& seg1, const Segment& seg2) { return seg1.segmentNumber() < seg2.segmentNumber(); } ); + auto comp_pressure_drop = WellSegments::CompPressureDrop::HFA; + + WellSegments segments( comp_pressure_drop, segments_list); + segments.updatePerfLength( connections ); + + return std::make_pair( std::move(connections), std::move(segments)); + } +} } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.hpp b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.hpp index f0bb1b4b5..fa243e0cd 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.hpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.hpp @@ -21,9 +21,13 @@ #ifndef COMPSEGS_HPP_ #define COMPSEGS_HPP_ +#include +#include namespace Opm { + class Segment; + class Connection; class WellConnections; class DeckKeyword; class WellSegments; @@ -31,6 +35,10 @@ namespace Opm { class ParseContext; class ErrorGuard; +namespace RestartIO { + class RstWell; +} + namespace Compsegs { @@ -50,6 +58,11 @@ namespace Compsegs { const ParseContext& parseContext, ErrorGuard& errors); + + std::pair + rstUpdate(const RestartIO::RstWell& rst_well, + std::vector input_connections, + const std::unordered_map& input_segments); } } diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp index e06a8fc7e..ad3fdd309 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/Schedule.cpp @@ -77,6 +77,7 @@ #include #include "Well/injection.hpp" +#include "MSW/Compsegs.hpp" namespace Opm { @@ -3044,6 +3045,7 @@ void Schedule::invalidNamePattern( const std::string& namePattern, std::size_t this->restart_config == data.restart_config && this->wellgroup_events == data.wellgroup_events; } + namespace { // Duplicated from Well.cpp Connection::Order order_from_int(int int_value) { @@ -3058,7 +3060,6 @@ Connection::Order order_from_int(int int_value) { throw std::invalid_argument("Invalid integer value: " + std::to_string(int_value) + " encountered when determining connection ordering"); } } - } void Schedule::load_rst(const RestartIO::RstState& rst_state, const EclipseGrid& grid, const FieldPropsManager& fp, const UnitSystem& unit_system) @@ -3071,50 +3072,27 @@ void Schedule::load_rst(const RestartIO::RstState& rst_state, const EclipseGrid& for (const auto& rst_well : rst_state.wells) { Opm::Well well(rst_well, report_step, unit_system, udq_undefined); - std::vector connections; - std::unordered_map segments; + std::vector rst_connections; for (const auto& rst_conn : rst_well.connections) - connections.emplace_back(rst_conn, grid, fp); + rst_connections.emplace_back(rst_conn, grid, fp); - for (const auto& rst_segment : rst_well.segments) { - Opm::Segment segment(rst_segment); - segments.insert(std::make_pair(rst_segment.segment, std::move(segment))); - } - - for (auto& connection : connections) { - int segment_id = connection.segment(); - if (segment_id > 0) { - const auto& segment = segments.at(segment_id); - connection.updateSegmentRST(segment.segmentNumber(), - segment.depth()); + if (rst_well.segments.empty()) { + Opm::WellConnections connections(order_from_int(rst_well.completion_ordering), + rst_well.ij[0], + rst_well.ij[1], + rst_connections); + well.updateConnections( std::make_shared( std::move(connections) ), grid, fp.get_int("PVTNUM")); + } else { + std::unordered_map rst_segments; + for (const auto& rst_segment : rst_well.segments) { + Opm::Segment segment(rst_segment); + rst_segments.insert(std::make_pair(rst_segment.segment, std::move(segment))); } - } - { - std::shared_ptr well_connections = std::make_shared(order_from_int(rst_well.completion_ordering), rst_well.ij[0], rst_well.ij[1], connections); - well.updateConnections( std::move(well_connections), grid, fp.get_int("PVTNUM") ); - } - - if (!segments.empty()) { - std::vector segments_list; - /* - The ordering of the segments in the WellSegments structure seems a - bit random; in some parts of the code the segment_number seems to - be treated like a random integer ID, whereas in other parts it - seems to be treated like a running index. Here the segments in - WellSegments are sorted according to the segment number - observe - that this is somewhat important because the first top segment is - treated differently from the other segment. - */ - for (const auto& segment_pair : segments) - segments_list.push_back( std::move(segment_pair.second) ); - - std::sort( segments_list.begin(), segments_list.end(),[](const Segment& seg1, const Segment& seg2) { return seg1.segmentNumber() < seg2.segmentNumber(); } ); - auto comp_pressure_drop = WellSegments::CompPressureDrop::HFA; - std::shared_ptr well_segments = std::make_shared(comp_pressure_drop, segments_list); - well_segments->updatePerfLength( well.getConnections() ); - well.updateSegments( std::move(well_segments) ); + auto [connections, segments] = Compsegs::rstUpdate(rst_well, rst_connections, rst_segments); + well.updateConnections( std::make_shared(std::move(connections)), grid, fp.get_int("PVTNUM")); + well.updateSegments( std::make_shared(std::move(segments) )); } this->addWell(well, report_step); From 7a88808ccb8072edbd0b7b128e7145a8f9e8bbee Mon Sep 17 00:00:00 2001 From: Joakim Hove Date: Sun, 7 Jun 2020 09:09:26 +0200 Subject: [PATCH 2/2] Add Segment::updateValve() overload which does not take length arg --- .../EclipseState/Schedule/MSW/Segment.hpp | 2 ++ .../EclipseState/Schedule/MSW/Segment.cpp | 31 ++++++++++--------- 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp b/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp index e04fdf929..d53026d87 100644 --- a/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp +++ b/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp @@ -86,6 +86,7 @@ namespace Opm { void updatePerfLength(double perf_length); void updateSpiralICD(const SICD& spiral_icd); void updateValve(const Valve& valve, const double segment_length); + void updateValve(const Valve& valve); void addInletSegment(const int segment_number); template @@ -109,6 +110,7 @@ namespace Opm { } private: + void updateValve__(Valve& valve, const double segment_length); // segment number // it should work as a ID. int m_segment_number; diff --git a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp index 6ea846023..ed72b31b7 100644 --- a/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp +++ b/src/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp @@ -113,15 +113,7 @@ namespace { pipeCrossA, rst_segment.icd_status); - /* - The segment length argument should be the length of this - particular segment; in the input phase that is calculated from the - WellSegments::segmentLength() function which also uses the outlet - segment. - */ - double segment_length = -1; - throw std::logic_error("Sorry can not create a Valve segment from restart file"); - this->updateValve(valve, segment_length); + this->updateValve(valve); } } @@ -278,15 +270,13 @@ namespace { return m_spiral_icd; } + void Segment::updateValve(const Valve& valve) { + if (valve.pipeAdditionalLength() < 0) + throw std::logic_error("Bug in handling of pipe length for valves"); - void Segment::updateValve(const Valve& valve, const double segment_length) { // we need to update some values for the vale auto valve_ptr = std::make_shared(valve); - if (valve_ptr->pipeAdditionalLength() < 0.) { // defaulted for this - valve_ptr->setPipeAdditionalLength(segment_length); - } - if (valve_ptr->pipeDiameter() < 0.) { valve_ptr->setPipeDiameter(m_internal_diameter); } else { @@ -315,6 +305,19 @@ namespace { } + void Segment::updateValve__(Valve& valve, const double segment_length) { + if (valve.pipeAdditionalLength() < 0) + valve.setPipeAdditionalLength(segment_length); + + this->updateValve(valve); + } + + void Segment::updateValve(const Valve& valve, const double segment_length) { + auto new_valve = valve; + this->updateValve__(new_valve, segment_length); + } + + void Segment::updatePerfLength(double perf_length) { this->m_perf_length = perf_length; }