Merge pull request #1463 from joakim-hove/segment-updates

Segment updates
This commit is contained in:
Joakim Hove 2020-02-13 07:47:27 +01:00 committed by GitHub
commit 921a68fc73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 202 additions and 90 deletions

View File

@ -103,6 +103,7 @@ if(ENABLE_ECL_INPUT)
src/opm/parser/eclipse/EclipseState/Schedule/Group/GTNode.cpp
src/opm/parser/eclipse/EclipseState/Schedule/Well/injection.cpp
src/opm/parser/eclipse/EclipseState/Schedule/MessageLimits.cpp
src/opm/parser/eclipse/EclipseState/Schedule/MSW/icd.cpp
src/opm/parser/eclipse/EclipseState/Schedule/MSW/Compsegs.cpp
src/opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.cpp
src/opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.cpp
@ -656,6 +657,8 @@ if(ENABLE_ECL_INPUT)
opm/parser/eclipse/EclipseState/Schedule/Events.hpp
opm/parser/eclipse/EclipseState/Schedule/OilVaporizationProperties.hpp
opm/parser/eclipse/EclipseState/Schedule/DynamicState.hpp
opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp
opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp
opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp
opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp
opm/parser/eclipse/EclipseState/Schedule/MSW/updatingConnectionsWithSegments.hpp

View File

@ -21,6 +21,10 @@
#include <vector>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/Segment.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/SpiralICD.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
namespace Opm {
namespace RestartIO {
@ -30,9 +34,9 @@ struct RstSegment {
int segment;
int outlet_segment;
int branch;
int segment_type;
Segment::SegmentType segment_type;
int icd_scaling_mode;
int icd_open_flag;
ICDStatus icd_status;
double dist_outlet;
double outlet_dz;

View File

@ -37,19 +37,6 @@ namespace Opm { namespace RestartIO { namespace Helpers { namespace VectorItems
ICDOpenShutFlag = 19,
};
namespace Value {
enum SegmentType : int {
REGULAR = -1,
AICD = -8,
SICD = -7,
Valve = -5,
};
enum SICDStatus : int {
Open = 0, // Yes, Open = 0 is correct
Shut = 1,
};
} // Value
} // ISeg
namespace RSeg {

View File

@ -36,13 +36,14 @@ namespace Opm {
enum class SegmentType {
REGULAR,
SICD,
AICD, // Not really supported - just included to complete the enum
VALVE,
};
Segment();
Segment(int segment_number_in, int branch_in, int outlet_segment_in, double length_in, double depth_in,
double internal_diameter_in, double roughness_in, double cross_area_in, double volume_in, bool data_ready_in);
double internal_diameter_in, double roughness_in, double cross_area_in, double volume_in, bool data_ready_in, SegmentType segment_type_in);
Segment(int segmentNumber, int branchNumber, int outlegSegment,
const std::vector<int>& inletSegments,
@ -64,6 +65,8 @@ namespace Opm {
bool dataReady() const;
SegmentType segmentType() const;
int ecl_type_id() const;
void setVolume(const double volume_in);
void setDepthAndLength(const double depth_in, const double length_in);
@ -72,6 +75,7 @@ namespace Opm {
void addInletSegment(const int segment_number);
static double invalidValue();
static SegmentType type_from_int(int ecl_id);
bool operator==( const Segment& ) const;
bool operator!=( const Segment& ) const;
@ -133,7 +137,7 @@ namespace Opm {
// indicate the type of the segment
// regular, spiral ICD, or Valve.
SegmentType m_segment_type = SegmentType::REGULAR;
SegmentType m_segment_type;
// information related to SpiralICD. It is nullptr for segments are not
// spiral ICD type
@ -143,7 +147,6 @@ namespace Opm {
// of type of Valve
std::shared_ptr<Valve> m_valve;
static constexpr double invalid_value = -1.e100;
// We are not handling the length of segment projected onto the X-axis and Y-axis.
// They are not used in the simulations and we are not supporting the plotting.
// There are other three properties for segment related to thermal conduction,

View File

@ -25,6 +25,7 @@
#include <utility>
#include <vector>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
namespace Opm {
@ -34,11 +35,6 @@ namespace Opm {
class SpiralICD {
public:
enum class Status {
OPEN,
SHUT
};
SpiralICD();
explicit SpiralICD(const DeckRecord& record);
SpiralICD(double strength,
@ -50,7 +46,7 @@ namespace Opm {
double maxViscosityRatio,
int methodFlowScaling,
double maxAbsoluteRate,
Status status,
ICDStatus status,
double scalingFactor);
// the function will return a map
@ -61,7 +57,7 @@ namespace Opm {
fromWSEGSICD(const DeckKeyword& wsegsicd);
double maxAbsoluteRate() const;
Status status() const;
ICDStatus status() const;
double strength() const;
double length() const;
double densityCalibration() const;
@ -73,7 +69,7 @@ namespace Opm {
void updateScalingFactor(const double segment_length, const double completion_length);
double scalingFactor() const;
int ecl_status() const;
bool operator==(const SpiralICD& data) const;
private:
@ -86,7 +82,7 @@ namespace Opm {
double m_max_viscosity_ratio;
int m_method_flow_scaling;
double m_max_absolute_rate;
Status m_status;
ICDStatus m_status;
// scaling factor is the only one can not be gotten from deck directly, needs to be
// updated afterwards
double m_scaling_factor;

View File

@ -24,6 +24,8 @@
#include <utility>
#include <vector>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
namespace Opm {
@ -33,10 +35,6 @@ namespace Opm {
class Valve {
public:
enum class Status {
OPEN,
SHUT
};
Valve();
explicit Valve(const DeckRecord& record);
@ -47,7 +45,7 @@ namespace Opm {
double pipeDiam,
double pipeRough,
double pipeCrossA,
Status stat);
ICDStatus stat);
// the function will return a map
// [
@ -67,7 +65,7 @@ namespace Opm {
double pipeCrossArea() const;
// Status: OPEN or SHUT
Status status() const;
ICDStatus status() const;
void setConMaxCrossArea(const double area);
@ -87,7 +85,7 @@ namespace Opm {
double m_pipe_diameter;
double m_pipe_roughness;
double m_pipe_cross_area;
Status m_status;
ICDStatus m_status;
};
}

View File

@ -0,0 +1,40 @@
/*
Copyright 2020 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_ICD_HPP
#define OPM_ICD_HPP
namespace Opm {
enum class ICDStatus {
OPEN,
SHUT
};
template<typename T>
T from_int(int int_status);
template<typename T>
int to_int(T status);
}
#endif

View File

@ -19,19 +19,35 @@
#include <opm/io/eclipse/rst/segment.hpp>
#include <opm/output/eclipse/VectorItems/msw.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
namespace Opm {
namespace {
template <typename T>
T from_ecl(int ecl_value);
template <>
Segment::SegmentType from_ecl(int int_type) {
return Segment::type_from_int(int_type);
}
}
namespace RestartIO {
RstSegment::RstSegment(const int * iseg, const double * rseg) :
segment(iseg[VI::ISeg::SegNo]),
outlet_segment(iseg[VI::ISeg::OutSeg]),
branch(iseg[VI::ISeg::BranchNo]),
segment_type(iseg[VI::ISeg::SegmentType]),
segment_type(from_ecl<Segment::SegmentType>(iseg[VI::ISeg::SegmentType])),
icd_scaling_mode(iseg[VI::ISeg::ICDScalingMode]),
icd_open_flag(iseg[VI::ISeg::ICDOpenShutFlag]),
icd_status(from_int<ICDStatus>(iseg[VI::ISeg::ICDOpenShutFlag])),
dist_outlet(rseg[VI::RSeg::DistOutlet]),
outlet_dz(rseg[VI::RSeg::OutletDepthDiff]),
diameter(rseg[VI::RSeg::SegDiam]),

View File

@ -418,34 +418,12 @@ namespace {
const std::size_t baseIndex,
ISegArray& iSeg)
{
namespace ISegValue = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::Value;
using Ix = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::index;
const auto& sicd = segment.spiralICD();
iSeg[baseIndex + Ix::SegmentType] = ISegValue::SegmentType::SICD;
iSeg[baseIndex + Ix::ICDScalingMode] = sicd->methodFlowScaling();
iSeg[baseIndex + Ix::ICDOpenShutFlag] =
(sicd->status() == Opm::SpiralICD::Status::OPEN)
? ISegValue::SICDStatus::Open
: ISegValue::SICDStatus::Shut;
}
template <class ISegArray>
void assignValveCharacteristics(const std::size_t baseIndex,
ISegArray& iSeg)
{
namespace ISegValue = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::Value;
using Ix = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::index;
iSeg[baseIndex + Ix::SegmentType] = ISegValue::SegmentType::Valve;
iSeg[baseIndex + Ix::ICDOpenShutFlag] = sicd->ecl_status();
}
template <class ISegArray>
@ -456,10 +434,6 @@ namespace {
if (isSpiralICD(segment)) {
assignSpiralICDCharacteristics(segment, baseIndex, iSeg);
}
if (isValve(segment)) {
assignValveCharacteristics(baseIndex, iSeg);
}
}
template <class ISegArray>
@ -467,12 +441,9 @@ namespace {
const std::vector<int>& inteHead,
ISegArray& iSeg)
{
using IsTyp = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::Value::SegmentType;
using Ix = ::Opm::RestartIO::Helpers::
VectorItems::ISeg::index;
if (well.isMultiSegment()) {
//loop over segment set and print out information
const auto& welSegSet = well.getSegments();
@ -501,12 +472,10 @@ namespace {
iSeg[iS + 7] = sumConnectionsSegment(completionSet, welSegSet, ind);
iSeg[iS + 8] = seg_reorder[ind];
iSeg[iS + Ix::SegmentType] = segment.ecl_type_id();
if (! isRegular(segment)) {
assignSegmentTypeCharacteristics(segment, iS, iSeg);
}
if (segment.segmentType() == Opm::Segment::SegmentType::REGULAR) {
iSeg[iS + Ix::SegmentType] = IsTyp::REGULAR;
}
}
}
else {

View File

@ -24,6 +24,13 @@
#include <cassert>
namespace Opm {
namespace {
static constexpr double invalid_value = -1.e100;
}
Segment::Segment()
: m_segment_number(-1),
@ -42,7 +49,7 @@ namespace Opm {
Segment::Segment(int segment_number_in, int branch_in, int outlet_segment_in, double length_in, double depth_in,
double internal_diameter_in, double roughness_in, double cross_area_in,
double volume_in, bool data_ready_in)
double volume_in, bool data_ready_in, SegmentType segment_type_in)
: m_segment_number(segment_number_in),
m_branch(branch_in),
m_outlet_segment(outlet_segment_in),
@ -52,7 +59,8 @@ namespace Opm {
m_roughness(roughness_in),
m_cross_area(cross_area_in),
m_volume(volume_in),
m_data_ready(data_ready_in)
m_data_ready(data_ready_in),
m_segment_type(segment_type_in)
{
}
@ -225,4 +233,35 @@ namespace Opm {
return m_valve;
}
int Segment::ecl_type_id() const {
switch (this->m_segment_type) {
case SegmentType::REGULAR:
return -1;
case SegmentType::SICD:
return -7;
case SegmentType::AICD:
return -8;
case SegmentType::VALVE:
return -5;
default:
throw std::invalid_argument("Unhanedled segment type");
}
}
Segment::SegmentType Segment::type_from_int(int ecl_id) {
switch(ecl_id) {
case -1:
return SegmentType::REGULAR;
case -7:
return SegmentType::SICD;
case -8:
return SegmentType::AICD;
case -5:
return SegmentType::VALVE;
default:
throw std::invalid_argument("Unhanedled segment type");
}
}
}

View File

@ -18,6 +18,7 @@
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/SpiralICD.hpp>
#include <opm/parser/eclipse/Deck/DeckRecord.hpp>
#include <opm/parser/eclipse/Deck/DeckKeyword.hpp>
@ -29,7 +30,7 @@
namespace Opm {
SpiralICD::SpiralICD()
: SpiralICD(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0, Status::SHUT, 1.0)
: SpiralICD(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, 0.0, ICDStatus::SHUT, 1.0)
{
}
@ -42,7 +43,7 @@ namespace Opm {
double maxViscosityRatio,
int flowScaling,
double maxAbsoluteRate,
Status status,
ICDStatus status,
double scalingFactor)
: m_strength(strength),
m_length(length),
@ -73,9 +74,9 @@ namespace Opm {
: std::numeric_limits<double>::max()), m_scaling_factor(std::numeric_limits<double>::lowest())
{
if (record.getItem("STATUS").getTrimmedString(0) == "OPEN") {
m_status = Status::OPEN;
m_status = ICDStatus::OPEN;
} else {
m_status = Status::SHUT;
m_status = ICDStatus::SHUT;
}
}
@ -111,7 +112,7 @@ namespace Opm {
return m_max_absolute_rate;
}
SpiralICD::Status SpiralICD::status() const {
ICDStatus SpiralICD::status() const {
return m_status;
}
@ -200,4 +201,10 @@ namespace Opm {
this->status() == data.status() &&
this->scalingFactor() == data.scalingFactor();
}
int SpiralICD::ecl_status() const {
return to_int(this->m_status);
}
}

View File

@ -27,7 +27,7 @@
namespace Opm {
Valve::Valve()
: Valve(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, Status::SHUT)
: Valve(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ICDStatus::SHUT)
{
}
@ -38,7 +38,7 @@ namespace Opm {
double pipeDiam,
double pipeRough,
double pipeCrossA,
Status stat)
ICDStatus stat)
: m_con_flow_coeff(conFlowCoeff)
, m_con_cross_area(conCrossA)
, m_con_max_cross_area(conMaxCrossA)
@ -83,9 +83,9 @@ namespace Opm {
}
if (record.getItem("STATUS").getTrimmedString(0) == "OPEN") {
m_status = Status::OPEN;
m_status = ICDStatus::OPEN;
} else {
m_status = Status::SHUT;
m_status = ICDStatus::SHUT;
// TODO: should we check illegal input here
}
@ -113,7 +113,7 @@ namespace Opm {
return res;
}
Valve::Status Valve::status() const {
ICDStatus Valve::status() const {
return m_status;
}

View File

@ -137,12 +137,12 @@ namespace Opm {
if (m_length_depth_type == LengthDepth::INC) {
m_segments.emplace_back( 1, 1, 0, 0., 0.,
invalid_value, invalid_value, invalid_value,
m_volume_top, false );
m_volume_top, false , Segment::SegmentType::REGULAR);
} else if (m_length_depth_type == LengthDepth::ABS) {
m_segments.emplace_back( 1, 1, 0, m_length_top, m_depth_top,
invalid_value, invalid_value, invalid_value,
m_volume_top, true );
m_volume_top, true , Segment::SegmentType::REGULAR);
}
// read all the information out from the DECK first then process to get all the required information
@ -202,13 +202,13 @@ namespace Opm {
if (m_length_depth_type == LengthDepth::INC) {
m_segments.emplace_back( i, branch, outlet_segment, segment_length, depth_change,
diameter, roughness, area, volume, false );
diameter, roughness, area, volume, false , Segment::SegmentType::REGULAR);
} else if (i == segment2) {
m_segments.emplace_back( i, branch, outlet_segment, segment_length, depth_change,
diameter, roughness, area, volume, true );
diameter, roughness, area, volume, true , Segment::SegmentType::REGULAR);
} else {
m_segments.emplace_back( i, branch, outlet_segment, invalid_value, invalid_value,
diameter, roughness, area, volume, false );
diameter, roughness, area, volume, false , Segment::SegmentType::REGULAR);
}
}
}

View File

@ -0,0 +1,50 @@
/*
Copyright 2020 Equinor ASA.
This file is part of the Open Porous Media project (OPM).
OPM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OPM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with OPM. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdexcept>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/icd.hpp>
namespace Opm {
template <>
ICDStatus from_int(int int_status) {
switch (int_status) {
case 0:
return ICDStatus::OPEN;
case 1:
return ICDStatus::SHUT;
default:
throw std::invalid_argument("Invalid status value");
}
}
template <>
int to_int(ICDStatus status) {
switch (status) {
case ICDStatus::OPEN:
return 0;
case ICDStatus::SHUT:
return 1;
default:
throw std::invalid_argument("Invalid status value");
}
}
}

View File

@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
const std::shared_ptr<Opm::SpiralICD> sicd_ptr = segment.spiralICD();
BOOST_CHECK_GT(sicd_ptr->maxAbsoluteRate(), 1.e99);
BOOST_CHECK(sicd_ptr->status()==Opm::SpiralICD::Status::SHUT);
BOOST_CHECK(sicd_ptr->status()==Opm::ICDStatus::SHUT);
// 0.002 bars*day*day/Volume^2
BOOST_CHECK_EQUAL(sicd_ptr->strength(), 0.002*1.e5*86400.*86400.);
BOOST_CHECK_EQUAL(sicd_ptr->length(), -0.7);
@ -413,7 +413,7 @@ BOOST_AUTO_TEST_CASE(testwsegvalv) {
BOOST_CHECK_EQUAL(valv1->pipeDiameter(), 0.2);
BOOST_CHECK_EQUAL(valv1->pipeRoughness(), 0.00015);
BOOST_CHECK_EQUAL(valv1->pipeCrossArea(), 0.031415926535897934);
BOOST_CHECK(valv1->status()==Opm::Valve::Status::OPEN);
BOOST_CHECK(valv1->status()==Opm::ICDStatus::OPEN);
const int segment_number2 = segvalv_vector[1].first;
BOOST_CHECK_EQUAL(9, segment_number2);
@ -436,7 +436,7 @@ BOOST_AUTO_TEST_CASE(testwsegvalv) {
BOOST_CHECK_EQUAL(valv2->pipeDiameter(), 1.2);
BOOST_CHECK_EQUAL(valv2->pipeRoughness(), 0.1);
BOOST_CHECK_EQUAL(valv2->pipeCrossArea(), 8.);
BOOST_CHECK(valv2->status()==Opm::Valve::Status::SHUT);
BOOST_CHECK(valv2->status()==Opm::ICDStatus::SHUT);
// valve changes the segment data
BOOST_CHECK_EQUAL(segment2.internalDiameter(), valv2->pipeDiameter());