Merge pull request #1811 from joakim-hove/rst-segment-connection-refactor

Reshuffle segments and connections after restart
This commit is contained in:
Joakim Hove 2020-06-09 07:08:37 +02:00 committed by GitHub
commit b73f4aa5dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 110 additions and 55 deletions

View File

@ -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;

View File

@ -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));
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);