Merge pull request #1811 from joakim-hove/rst-segment-connection-refactor
Reshuffle segments and connections after restart
This commit is contained in:
commit
b73f4aa5dc
@ -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<class Serializer>
|
||||
@ -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;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <opm/parser/eclipse/Deck/DeckItem.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
|
||||
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
|
||||
#include <opm/io/eclipse/rst/well.hpp>
|
||||
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
|
||||
@ -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<WellConnections, WellSegments>
|
||||
rstUpdate(const RestartIO::RstWell& rst_well,
|
||||
std::vector<Connection> rst_connections,
|
||||
const std::unordered_map<int, Segment>& 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<Segment> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,9 +21,13 @@
|
||||
#ifndef COMPSEGS_HPP_
|
||||
#define COMPSEGS_HPP_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
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<WellConnections, WellSegments>
|
||||
rstUpdate(const RestartIO::RstWell& rst_well,
|
||||
std::vector<Connection> input_connections,
|
||||
const std::unordered_map<int, Segment>& input_segments);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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>(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;
|
||||
}
|
||||
|
@ -77,6 +77,7 @@
|
||||
#include <opm/parser/eclipse/Units/Units.hpp>
|
||||
|
||||
#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<Opm::Connection> connections;
|
||||
std::unordered_map<int, Opm::Segment> segments;
|
||||
std::vector<Opm::Connection> 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<WellConnections>( std::move(connections) ), grid, fp.get_int("PVTNUM"));
|
||||
} else {
|
||||
std::unordered_map<int, Opm::Segment> 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<Opm::WellConnections> well_connections = std::make_shared<Opm::WellConnections>(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<Segment> 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<Opm::WellSegments> well_segments = std::make_shared<Opm::WellSegments>(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<WellConnections>(std::move(connections)), grid, fp.get_int("PVTNUM"));
|
||||
well.updateSegments( std::make_shared<WellSegments>(std::move(segments) ));
|
||||
}
|
||||
|
||||
this->addWell(well, report_step);
|
||||
|
Loading…
Reference in New Issue
Block a user