Merge pull request #3684 from vkip/wsegvalv_uda_item4

Facilitate UDA for WSEGVALV item 4
This commit is contained in:
Bård Skaflestad
2023-10-17 15:14:22 +02:00
committed by GitHub
6 changed files with 72 additions and 17 deletions

View File

@@ -24,8 +24,11 @@
#include <utility>
#include <vector>
#include <string>
#include <optional>
#include <opm/input/eclipse/Schedule/MSW/icd.hpp>
#include <opm/input/eclipse/Deck/UDAValue.hpp>
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
namespace Opm {
@@ -34,11 +37,24 @@ namespace Opm {
class DeckKeyword;
class Segment;
struct ValveUDAEval {
const SummaryState& summary_state;
const std::string& well_name;
const size_t segment_number;
ValveUDAEval(const SummaryState& summary_state_,
const std::string& well_name_,
const size_t segment_number_);
double value(const UDAValue& value, const double udq_default = 0.0) const;
};
class Valve {
public:
Valve();
explicit Valve(const DeckRecord& record);
explicit Valve(const DeckRecord& record, const double udq_default = 0.0);
Valve(double conFlowCoeff,
double conCrossA,
double conMaxCrossA,
@@ -54,11 +70,12 @@ namespace Opm {
// [
// "WELL1" : [<seg1, valv1>, <seg2, valv2> ...]
// ....
static std::map<std::string, std::vector<std::pair<int, Valve> > > fromWSEGVALV(const DeckKeyword& keyword);
static std::map<std::string, std::vector<std::pair<int, Valve> > > fromWSEGVALV(const DeckKeyword& keyword, const double udq_default = 0.0);
// parameters for constriction pressure loss
double conFlowCoefficient() const;
double conCrossArea() const;
double conCrossArea(const std::optional<const ValveUDAEval>& uda_eval = std::nullopt) const;
inline double conCrossAreaValue() const { return m_con_cross_area_value; }
double conMaxCrossArea() const;
double pipeDiameter() const;
double pipeRoughness() const;
@@ -85,17 +102,20 @@ namespace Opm {
{
serializer(m_con_flow_coeff);
serializer(m_con_cross_area);
serializer(m_con_cross_area_value);
serializer(m_con_max_cross_area);
serializer(m_pipe_additional_length);
serializer(m_pipe_diameter);
serializer(m_pipe_roughness);
serializer(m_pipe_cross_area);
serializer(m_status);
serializer(m_udq_default);
}
private:
double m_con_flow_coeff;
double m_con_cross_area;
UDAValue m_con_cross_area;
mutable double m_con_cross_area_value;
double m_con_max_cross_area;
double m_pipe_additional_length;
@@ -103,6 +123,8 @@ namespace Opm {
double m_pipe_roughness;
double m_pipe_cross_area;
ICDStatus m_status;
double m_udq_default{0.0};
};
}

View File

@@ -2226,7 +2226,8 @@ Well{0} entered with 'FIELD' parent group:
}
void Schedule::handleWSEGVALV(HandlerContext& handlerContext) {
const std::map<std::string, std::vector<std::pair<int, Valve> > > valves = Valve::fromWSEGVALV(handlerContext.keyword);
const double udq_default = this->getUDQConfig(handlerContext.currentStep).params().undefinedValue();
const std::map<std::string, std::vector<std::pair<int, Valve> > > valves = Valve::fromWSEGVALV(handlerContext.keyword, udq_default);
for (const auto& map_elem : valves) {
const std::string& well_name_pattern = map_elem.first;

View File

@@ -26,6 +26,30 @@
namespace Opm {
ValveUDAEval::ValveUDAEval(const SummaryState& summary_state_, const std::string& well_name_,
const size_t segment_number_) :
summary_state(summary_state_),
well_name(well_name_),
segment_number(segment_number_)
{}
double ValveUDAEval::value(const UDAValue& value, const double udq_default) const {
if (value.is<double>())
return value.getSI();
const std::string& string_var = value.get<std::string>();
double output_value = udq_default;
if (summary_state.has_segment_var(well_name, string_var, segment_number))
output_value = summary_state.get_segment_var(well_name, string_var, segment_number);
else if (summary_state.has(string_var))
output_value = summary_state.get(string_var);
return value.get_dim().convertRawToSi(output_value);
}
Valve::Valve()
: Valve(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, ICDStatus::SHUT)
{
@@ -40,7 +64,8 @@ namespace Opm {
double pipeCrossA,
ICDStatus stat)
: m_con_flow_coeff(conFlowCoeff)
, m_con_cross_area(conCrossA)
, m_con_cross_area(UDAValue(conCrossA))
, m_con_cross_area_value(conCrossA)
, m_con_max_cross_area(conMaxCrossA)
, m_pipe_additional_length(pipeAddLength)
, m_pipe_diameter(pipeDiam)
@@ -50,9 +75,11 @@ namespace Opm {
{
}
Valve::Valve(const DeckRecord& record)
Valve::Valve(const DeckRecord& record, const double udq_default)
: m_con_flow_coeff(record.getItem("CV").get<double>(0))
, m_con_cross_area(record.getItem("AREA").getSIDouble(0))
, m_con_cross_area(record.getItem("AREA").get<UDAValue>(0))
, m_con_cross_area_value(m_con_cross_area.is<double>() ? m_con_cross_area.getSI() : -1.0)
, m_udq_default(udq_default)
{
// we initialize negative values for the values are defaulted
const double value_for_default = -1.e100;
@@ -100,7 +127,8 @@ namespace Opm {
{
Valve result;
result.m_con_flow_coeff = 1.0;
result.m_con_cross_area = 2.0;
result.m_con_cross_area = UDAValue(2.0);
result.m_con_cross_area_value = 2.0;
result.m_con_max_cross_area = 3.0;
result.m_pipe_additional_length = 4.0;
result.m_pipe_diameter = 5.0;
@@ -112,7 +140,7 @@ namespace Opm {
}
std::map<std::string, std::vector<std::pair<int, Valve> > >
Valve::fromWSEGVALV(const DeckKeyword& keyword)
Valve::fromWSEGVALV(const DeckKeyword& keyword, const double udq_default)
{
std::map<std::string, std::vector<std::pair<int, Valve> > > res;
@@ -121,7 +149,7 @@ namespace Opm {
const int segment_number = record.getItem("SEGMENT_NUMBER").get<int>(0);
const Valve valve(record);
const Valve valve(record, udq_default);
res[well_name].push_back(std::make_pair(segment_number, valve));
}
@@ -141,8 +169,11 @@ namespace Opm {
return m_con_flow_coeff;
}
double Valve::conCrossArea() const {
return m_con_cross_area;
double Valve::conCrossArea(const std::optional<const ValveUDAEval>& uda_eval_optional) const {
m_con_cross_area_value = uda_eval_optional.has_value() ?
uda_eval_optional.value().value(m_con_cross_area, m_udq_default) :
m_con_cross_area.getSI();
return m_con_cross_area_value;
}
double Valve::pipeAdditionalLength() const {
@@ -187,7 +218,8 @@ namespace Opm {
bool Valve::operator==(const Valve& data) const {
return this->conFlowCoefficient() == data.conFlowCoefficient() &&
this->conCrossArea() == data.conCrossArea() &&
this->m_con_cross_area == data.m_con_cross_area &&
this->conCrossAreaValue() == data.conCrossAreaValue() &&
this->conMaxCrossArea() == data.conMaxCrossArea() &&
this->pipeAdditionalLength() == data.pipeAdditionalLength() &&
this->pipeDiameter() == data.pipeDiameter() &&

View File

@@ -22,7 +22,7 @@
{
"item": 4,
"name": "AREA",
"value_type": "DOUBLE",
"value_type": "UDA",
"dimension": "Length*Length"
},
{

View File

@@ -586,7 +586,7 @@ namespace {
usys.from_si(M::length, valve.pipeAdditionalLength());
rSeg[baseIndex + Ix::ValveArea] =
usys.from_si(M::length, usys.from_si(M::length, valve.conCrossArea()));
usys.from_si(M::length, usys.from_si(M::length, valve.conCrossAreaValue()));
rSeg[baseIndex + Ix::ValveFlowCoeff] = valve.conFlowCoefficient();
rSeg[baseIndex + Ix::ValveMaxArea] =

View File

@@ -1445,7 +1445,7 @@ namespace {
{
assert ((segment.segmentNumber() > 1) && segment.isValve());
const auto Ac = segment.valve().conCrossArea();
const auto Ac = segment.valve().conCrossAreaValue();
const auto Ac_max = valveMaximumCrossSectionalArea(segment);
return Ac / Ac_max;