Load D-Factor Correlation Parameters From Restart File
This commit loads the connection level Peaceman denominator value, static D-factor correlation coefficient, and connection interval length from the restart file and forwards these values from the RstConnection type to the regular Connection type. Furthermore, we load the well-level D-factor correlation parameters 'A', 'B', and 'C' of the WDFACCOR keyword into the WDFAC type at restart time. Collectively, these changes enable restarting simulation runs using the WDFACCOR keyword.
This commit is contained in:
parent
ce512f03a7
commit
9b034978bd
@ -101,6 +101,17 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Default constructor
|
||||||
|
WDFAC() = default;
|
||||||
|
|
||||||
|
/// Constructor
|
||||||
|
///
|
||||||
|
/// Creates an object from restart information
|
||||||
|
///
|
||||||
|
/// \param[in] rst_well Linearised well-level restart information,
|
||||||
|
/// including D-factor parameters.
|
||||||
|
explicit WDFAC(const RestartIO::RstWell& rst_well);
|
||||||
|
|
||||||
/// Serialisation test object
|
/// Serialisation test object
|
||||||
static WDFAC serializationTestObject();
|
static WDFAC serializationTestObject();
|
||||||
|
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
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
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
@ -19,19 +20,27 @@
|
|||||||
#ifndef RST_CONNECTION
|
#ifndef RST_CONNECTION
|
||||||
#define RST_CONNECTION
|
#define RST_CONNECTION
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
class UnitSystem;
|
class UnitSystem;
|
||||||
|
|
||||||
namespace RestartIO {
|
} // namespace Opm
|
||||||
|
|
||||||
class Header;
|
namespace Opm { namespace RestartIO {
|
||||||
|
|
||||||
|
struct RstConnection
|
||||||
|
{
|
||||||
|
RstConnection(const UnitSystem& unit_system,
|
||||||
|
std::size_t rst_index,
|
||||||
|
int nsconz,
|
||||||
|
const int* icon,
|
||||||
|
const float* scon,
|
||||||
|
const double *xcon);
|
||||||
|
|
||||||
struct RstConnection {
|
|
||||||
RstConnection(const ::Opm::UnitSystem& unit_system, std::size_t rst_index, int nsconz, const int* icon, const float* scon, const double *xcon);
|
|
||||||
static double inverse_peaceman(double cf, double kh, double rw, double skin);
|
static double inverse_peaceman(double cf, double kh, double rw, double skin);
|
||||||
|
|
||||||
std::size_t rst_index;
|
std::size_t rst_index;
|
||||||
@ -49,6 +58,9 @@ struct RstConnection {
|
|||||||
float depth;
|
float depth;
|
||||||
float diameter;
|
float diameter;
|
||||||
float kh;
|
float kh;
|
||||||
|
float denom;
|
||||||
|
float length;
|
||||||
|
float static_dfac_corr_coeff;
|
||||||
float segdist_end;
|
float segdist_end;
|
||||||
float segdist_start;
|
float segdist_start;
|
||||||
|
|
||||||
@ -60,11 +72,6 @@ struct RstConnection {
|
|||||||
double r0;
|
double r0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
}} // namespace Opm::RestartIO
|
||||||
|
|
||||||
}
|
#endif // RST_CONNECTION
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -126,6 +126,9 @@ struct RstWell
|
|||||||
float glift_min_rate;
|
float glift_min_rate;
|
||||||
float glift_weight_factor;
|
float glift_weight_factor;
|
||||||
float glift_inc_weight_factor;
|
float glift_inc_weight_factor;
|
||||||
|
float dfac_corr_coeff_a{};
|
||||||
|
float dfac_corr_exponent_b{};
|
||||||
|
float dfac_corr_exponent_c{};
|
||||||
std::vector<float> tracer_concentration_injection;
|
std::vector<float> tracer_concentration_injection;
|
||||||
|
|
||||||
double oil_rate;
|
double oil_rate;
|
||||||
|
@ -31,12 +31,15 @@
|
|||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@ -53,9 +56,11 @@ namespace {
|
|||||||
props.rw = rst_conn.diameter / 2;
|
props.rw = rst_conn.diameter / 2;
|
||||||
props.r0 = rst_conn.r0;
|
props.r0 = rst_conn.r0;
|
||||||
props.re = 0.0;
|
props.re = 0.0;
|
||||||
props.connection_length = 0.0;
|
props.connection_length = rst_conn.length;
|
||||||
props.skin_factor = rst_conn.skin_factor;
|
props.skin_factor = rst_conn.skin_factor;
|
||||||
props.d_factor = 0.0;
|
props.d_factor = 0.0;
|
||||||
|
props.static_dfac_corr_coeff = rst_conn.static_dfac_corr_coeff;
|
||||||
|
props.peaceman_denom = rst_conn.denom;
|
||||||
|
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
@ -155,7 +160,7 @@ namespace Opm
|
|||||||
rst_connection.segdist_end);
|
rst_connection.segdist_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO recompute re and perf_length from the grid
|
// TODO: recompute re from the grid
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection Connection::serializationTestObject()
|
Connection Connection::serializationTestObject()
|
||||||
|
@ -72,6 +72,18 @@ namespace Opm {
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
WDFAC::WDFAC(const RestartIO::RstWell& rst_well)
|
||||||
|
: m_type { WDFacType::NONE }
|
||||||
|
, m_d { 0.0 }
|
||||||
|
, m_corr { rst_well.dfac_corr_coeff_a ,
|
||||||
|
rst_well.dfac_corr_exponent_b ,
|
||||||
|
rst_well.dfac_corr_exponent_c }
|
||||||
|
{
|
||||||
|
if (m_corr.coeff_a > 0.0) {
|
||||||
|
this->m_type = WDFacType::DAKEMODEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
WDFAC WDFAC::serializationTestObject()
|
WDFAC WDFAC::serializationTestObject()
|
||||||
{
|
{
|
||||||
WDFAC result;
|
WDFAC result;
|
||||||
|
@ -313,7 +313,7 @@ Well::Well(const RestartIO::RstWell& rst_well,
|
|||||||
injection(std::make_shared<WellInjectionProperties>(unit_system_arg, wname)),
|
injection(std::make_shared<WellInjectionProperties>(unit_system_arg, wname)),
|
||||||
wvfpdp(std::make_shared<WVFPDP>()),
|
wvfpdp(std::make_shared<WVFPDP>()),
|
||||||
wvfpexp(explicitTHPOptions(rst_well)),
|
wvfpexp(explicitTHPOptions(rst_well)),
|
||||||
wdfac(std::make_shared<WDFAC>()),
|
wdfac(std::make_shared<WDFAC>(rst_well)),
|
||||||
status(status_from_int(rst_well.well_status)),
|
status(status_from_int(rst_well.well_status)),
|
||||||
well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue),
|
well_temperature(Metric::TemperatureOffset + ParserKeywords::STCOND::TEMPERATURE::defaultValue),
|
||||||
well_inj_mult(std::nullopt)
|
well_inj_mult(std::nullopt)
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
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
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
@ -16,99 +17,129 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cmath>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/header.hpp>
|
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
|
|
||||||
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
|
||||||
namespace Opm {
|
|
||||||
namespace RestartIO {
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T from_int(int);
|
T from_int(int);
|
||||||
|
|
||||||
template <>
|
template<> Opm::Connection::State from_int(int int_state)
|
||||||
Connection::State from_int(int int_state) {
|
{
|
||||||
if (int_state == 1)
|
return (int_state == 1)
|
||||||
return Connection::State::OPEN;
|
? Opm::Connection::State::OPEN
|
||||||
|
: Opm::Connection::State::SHUT;
|
||||||
return Connection::State::SHUT;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template<> Opm::Connection::Direction from_int(int int_dir)
|
||||||
Connection::Direction from_int(int int_dir) {
|
{
|
||||||
switch (int_dir) {
|
switch (int_dir) {
|
||||||
case 1:
|
case 1: return Opm::Connection::Direction::X;
|
||||||
return Connection::Direction::X;
|
case 2: return Opm::Connection::Direction::Y;
|
||||||
case 2:
|
case 3: return Opm::Connection::Direction::Z;
|
||||||
return Connection::Direction::Y;
|
|
||||||
case 3:
|
|
||||||
return Connection::Direction::Z;
|
|
||||||
default:
|
|
||||||
throw std::invalid_argument("Can not convert: " + std::to_string(int_dir) + " to string");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unable to convert direction value: " +
|
||||||
|
std::to_string(int_dir) + " to Direction category"
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Note: CTFKind originates in SCON and is indeed a float.
|
||||||
That the CTFKind variable comes from a float looks extremely suspicious; but
|
Opm::Connection::CTFKind from_float(float float_kind)
|
||||||
it has been double checked ...
|
{
|
||||||
*/
|
return (float_kind == 0.0f)
|
||||||
Connection::CTFKind from_float(float float_kind) {
|
? Opm::Connection::CTFKind::Defaulted
|
||||||
if (float_kind == 0)
|
: Opm::Connection::CTFKind::DeckValue;
|
||||||
return Connection::CTFKind::Defaulted;
|
|
||||||
|
|
||||||
return Connection::CTFKind::DeckValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double RstConnection::inverse_peaceman(double cf, double kh, double rw, double skin) {
|
float as_float(const double x)
|
||||||
|
{
|
||||||
|
return static_cast<float>(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
float staticDFactorCorrCoeff(const Opm::UnitSystem& usys,
|
||||||
|
const float coeff)
|
||||||
|
{
|
||||||
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
|
// Coefficient's units are [D] * [viscosity]
|
||||||
|
return as_float(usys.to_si(M::viscosity, usys.to_si(M::dfactor, coeff)));
|
||||||
|
}
|
||||||
|
|
||||||
|
double pressEquivRadius(const float denom,
|
||||||
|
const float skin,
|
||||||
|
const float rw)
|
||||||
|
{
|
||||||
|
// Recall: denom = log(r0 / rw) + skin
|
||||||
|
return rw * std::exp(denom - skin);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
double Opm::RestartIO::RstConnection::inverse_peaceman(double cf, double kh, double rw, double skin)
|
||||||
|
{
|
||||||
auto alpha = 3.14159265 * 2 * kh / cf - skin;
|
auto alpha = 3.14159265 * 2 * kh / cf - skin;
|
||||||
return rw * std::exp(alpha);
|
return rw * std::exp(alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
using M = ::Opm::UnitSystem::measure;
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
RstConnection::RstConnection(const ::Opm::UnitSystem& unit_system, std::size_t rst_index_, int nsconz, const int* icon, const float* scon, const double* xcon) :
|
Opm::RestartIO::RstConnection::RstConnection(const UnitSystem& unit_system,
|
||||||
rst_index( rst_index_),
|
const std::size_t rst_index_,
|
||||||
ijk( {icon[VI::IConn::CellI] - 1, icon[VI::IConn::CellJ] - 1, icon[VI::IConn::CellK] - 1}),
|
const int nsconz,
|
||||||
state( from_int<Connection::State>(icon[VI::IConn::ConnStat])),
|
const int* icon,
|
||||||
drain_sat_table( icon[VI::IConn::Drainage]),
|
const float* scon,
|
||||||
imb_sat_table( icon[VI::IConn::Imbibition]),
|
const double* xcon)
|
||||||
completion( icon[VI::IConn::ComplNum]),
|
: rst_index { rst_index_ }
|
||||||
dir( from_int<Connection::Direction>(icon[VI::IConn::ConnDir])),
|
// -----------------------------------------------------------------
|
||||||
segment( icon[VI::IConn::Segment]),
|
// Integer values (ICON)
|
||||||
cf_kind( from_float(1.0)),
|
, ijk { icon[VI::IConn::CellI] - 1 ,
|
||||||
skin_factor( scon[VI::SConn::SkinFactor]),
|
icon[VI::IConn::CellJ] - 1 ,
|
||||||
cf( unit_system.to_si(M::transmissibility, scon[VI::SConn::ConnTrans])),
|
icon[VI::IConn::CellK] - 1 }
|
||||||
depth( unit_system.to_si(M::length, scon[VI::SConn::Depth])),
|
, state { from_int<Connection::State>(icon[VI::IConn::ConnStat]) }
|
||||||
diameter( unit_system.to_si(M::length, scon[VI::SConn::Diameter])),
|
, drain_sat_table { icon[VI::IConn::Drainage] }
|
||||||
kh( unit_system.to_si(M::effective_Kh, scon[VI::SConn::EffectiveKH])),
|
, imb_sat_table { icon[VI::IConn::Imbibition] }
|
||||||
segdist_end( unit_system.to_si(M::length, scon[VI::SConn::SegDistEnd])),
|
, completion { icon[VI::IConn::ComplNum] }
|
||||||
segdist_start( unit_system.to_si(M::length, scon[VI::SConn::SegDistStart])),
|
, dir { from_int<Connection::Direction>(icon[VI::IConn::ConnDir]) }
|
||||||
oil_rate( unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::OilRate])),
|
, segment { icon[VI::IConn::Segment] }
|
||||||
water_rate( unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::WaterRate])),
|
// -----------------------------------------------------------------
|
||||||
gas_rate( unit_system.to_si(M::gas_surface_rate, xcon[VI::XConn::GasRate])),
|
// Float values (SCON)
|
||||||
pressure( unit_system.to_si(M::pressure, xcon[VI::XConn::Pressure])),
|
, cf_kind { from_float(1.0f) }
|
||||||
resv_rate( unit_system.to_si(M::rate, xcon[VI::XConn::ResVRate])),
|
, skin_factor { scon[VI::SConn::SkinFactor] }
|
||||||
r0( RstConnection::inverse_peaceman(this->cf, this->kh, this->diameter/2, this->skin_factor) )
|
, cf { as_float(unit_system.to_si(M::transmissibility, scon[VI::SConn::ConnTrans])) }
|
||||||
/*
|
, depth { as_float(unit_system.to_si(M::length, scon[VI::SConn::Depth])) }
|
||||||
r0: The r0 quantity is currently not written or read from the restart
|
, diameter { as_float(unit_system.to_si(M::length, scon[VI::SConn::Diameter])) }
|
||||||
file. If the r0 value is given explicitly in the deck it is possible
|
, kh { as_float(unit_system.to_si(M::effective_Kh, scon[VI::SConn::EffectiveKH])) }
|
||||||
to give a value which is not consistent with the Peaceman formula -
|
, denom { scon[VI::SConn::CFDenom] }
|
||||||
that value will be lost when loading back from a restart file.
|
, length { as_float(unit_system.to_si(M::length, scon[VI::SConn::EffectiveLength])) }
|
||||||
*/
|
, static_dfac_corr_coeff { staticDFactorCorrCoeff(unit_system, scon[VI::SConn::StaticDFacCorrCoeff]) }
|
||||||
|
, segdist_end { as_float(unit_system.to_si(M::length, scon[VI::SConn::SegDistEnd])) }
|
||||||
|
, segdist_start { as_float(unit_system.to_si(M::length, scon[VI::SConn::SegDistStart])) }
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Double values (XCON)
|
||||||
|
, oil_rate { unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::OilRate]) }
|
||||||
|
, water_rate { unit_system.to_si(M::liquid_surface_rate, xcon[VI::XConn::WaterRate]) }
|
||||||
|
, gas_rate { unit_system.to_si(M::gas_surface_rate, xcon[VI::XConn::GasRate]) }
|
||||||
|
, pressure { unit_system.to_si(M::pressure, xcon[VI::XConn::Pressure]) }
|
||||||
|
, resv_rate { unit_system.to_si(M::rate, xcon[VI::XConn::ResVRate]) }
|
||||||
|
// -----------------------------------------------------------------
|
||||||
|
// Derived quantities
|
||||||
|
, r0 { pressEquivRadius(this->denom, this->skin_factor, this->diameter / 2) }
|
||||||
{
|
{
|
||||||
if (static_cast<std::size_t>(nsconz) > VI::SConn::CFInDeck)
|
if (static_cast<std::size_t>(nsconz) > VI::SConn::CFInDeck) {
|
||||||
this->cf_kind = from_float(scon[VI::SConn::CFInDeck]);
|
this->cf_kind = from_float(scon[VI::SConn::CFInDeck]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
This file is part of the Open Porous Media project (OPM).
|
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
|
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
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
(at your option) any later version.
|
(at your option) any later version.
|
||||||
|
|
||||||
|
@ -17,17 +17,24 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <opm/common/utility/String.hpp>
|
#include <opm/io/eclipse/rst/well.hpp>
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/header.hpp>
|
#include <opm/io/eclipse/rst/header.hpp>
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
#include <opm/io/eclipse/rst/well.hpp>
|
|
||||||
|
|
||||||
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
#include <opm/output/eclipse/VectorItems/connection.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/msw.hpp>
|
#include <opm/output/eclipse/VectorItems/msw.hpp>
|
||||||
#include <opm/output/eclipse/VectorItems/well.hpp>
|
#include <opm/output/eclipse/VectorItems/well.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <opm/common/utility/String.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/ParserItem.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeyword.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserRecord.hpp>
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
@ -54,28 +61,34 @@ namespace {
|
|||||||
{
|
{
|
||||||
return is_sentinel(raw_value) ? raw_value : convert(raw_value);
|
return is_sentinel(raw_value) ? raw_value : convert(raw_value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
float dfactor_correlation_coefficient_a(const Opm::UnitSystem& unit_system,
|
||||||
|
const float coeff_a)
|
||||||
|
{
|
||||||
|
const auto dimension = Opm::ParserKeywords::WDFACCOR{}
|
||||||
|
.getRecord(0).get(Opm::ParserKeywords::WDFACCOR::A::itemName)
|
||||||
|
.dimensions().front();
|
||||||
|
|
||||||
|
return static_cast<float>(unit_system.to_si(dimension, coeff_a));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int def_ecl_phase = 1;
|
||||||
|
constexpr int def_pvt_table = 0;
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
namespace VI = ::Opm::RestartIO::Helpers::VectorItems;
|
||||||
|
using M = ::Opm::UnitSystem::measure;
|
||||||
|
|
||||||
namespace Opm {
|
Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system,
|
||||||
namespace RestartIO {
|
const RstHeader& header,
|
||||||
|
const std::string& group_arg,
|
||||||
constexpr int def_ecl_phase = 1;
|
const std::string* zwel,
|
||||||
constexpr int def_pvt_table = 0;
|
const int* iwel,
|
||||||
|
const float* swel,
|
||||||
using M = ::Opm::UnitSystem::measure;
|
const double* xwel,
|
||||||
|
const int* icon,
|
||||||
RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
const float* scon,
|
||||||
const RstHeader& header,
|
const double* xcon) :
|
||||||
const std::string& group_arg,
|
|
||||||
const std::string* zwel,
|
|
||||||
const int * iwel,
|
|
||||||
const float * swel,
|
|
||||||
const double * xwel,
|
|
||||||
const int * icon,
|
|
||||||
const float * scon,
|
|
||||||
const double * xcon) :
|
|
||||||
name(rtrim_copy(zwel[0])),
|
name(rtrim_copy(zwel[0])),
|
||||||
group(group_arg),
|
group(group_arg),
|
||||||
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
|
ij( {iwel[VI::IWell::IHead] - 1, iwel[VI::IWell::JHead] - 1}),
|
||||||
@ -139,6 +152,9 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
|||||||
glift_min_rate( unit_system.to_si(M::gas_surface_rate, swel[VI::SWell::LOminRate])),
|
glift_min_rate( unit_system.to_si(M::gas_surface_rate, swel[VI::SWell::LOminRate])),
|
||||||
glift_weight_factor( swel[VI::SWell::LOweightFac]),
|
glift_weight_factor( swel[VI::SWell::LOweightFac]),
|
||||||
glift_inc_weight_factor( swel[VI::SWell::LOincFac]),
|
glift_inc_weight_factor( swel[VI::SWell::LOincFac]),
|
||||||
|
dfac_corr_coeff_a(dfactor_correlation_coefficient_a(unit_system, swel[VI::SWell::DFacCorrCoeffA])),
|
||||||
|
dfac_corr_exponent_b( swel[VI::SWell::DFacCorrExpB]),
|
||||||
|
dfac_corr_exponent_c( swel[VI::SWell::DFacCorrExpC]),
|
||||||
//
|
//
|
||||||
oil_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::OilPrRate])),
|
oil_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::OilPrRate])),
|
||||||
water_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::WatPrRate])),
|
water_rate( unit_system.to_si(M::liquid_surface_rate, xwel[VI::XWell::WatPrRate])),
|
||||||
@ -167,66 +183,81 @@ RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
|||||||
gas_void_rate( unit_system.to_si(M::gas_surface_volume, xwel[VI::XWell::GasVoidPrRate]))
|
gas_void_rate( unit_system.to_si(M::gas_surface_volume, xwel[VI::XWell::GasVoidPrRate]))
|
||||||
{
|
{
|
||||||
|
|
||||||
for (std::size_t tracer_index = 0; tracer_index < static_cast<std::size_t>(header.runspec.tracers().water_tracers()); tracer_index++)
|
for (std::size_t tracer_index = 0;
|
||||||
this->tracer_concentration_injection.push_back( swel[VI::SWell::TracerOffset + tracer_index] );
|
tracer_index < static_cast<std::size_t>(header.runspec.tracers().water_tracers());
|
||||||
|
++tracer_index)
|
||||||
|
{
|
||||||
|
this->tracer_concentration_injection.push_back(swel[VI::SWell::TracerOffset + tracer_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int ic = 0; ic < iwel[VI::IWell::NConn]; ++ic) {
|
||||||
|
const std::size_t icon_offset = ic * header.niconz;
|
||||||
|
const std::size_t scon_offset = ic * header.nsconz;
|
||||||
|
const std::size_t xcon_offset = ic * header.nxconz;
|
||||||
|
|
||||||
for (int ic = 0; ic < iwel[VI::IWell::NConn]; ic++) {
|
this->connections.emplace_back(unit_system, ic, header.nsconz,
|
||||||
std::size_t icon_offset = ic * header.niconz;
|
icon + icon_offset,
|
||||||
std::size_t scon_offset = ic * header.nsconz;
|
scon + scon_offset,
|
||||||
std::size_t xcon_offset = ic * header.nxconz;
|
xcon + xcon_offset);
|
||||||
this->connections.emplace_back( unit_system, ic, header.nsconz, icon + icon_offset, scon + scon_offset, xcon + xcon_offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
RstWell::RstWell(const ::Opm::UnitSystem& unit_system,
|
Opm::RestartIO::RstWell::RstWell(const UnitSystem& unit_system,
|
||||||
const RstHeader& header,
|
const RstHeader& header,
|
||||||
const std::string& group_arg,
|
const std::string& group_arg,
|
||||||
const std::string* zwel,
|
const std::string* zwel,
|
||||||
const int * iwel,
|
const int* iwel,
|
||||||
const float * swel,
|
const float* swel,
|
||||||
const double * xwel,
|
const double* xwel,
|
||||||
const int * icon,
|
const int* icon,
|
||||||
const float * scon,
|
const float* scon,
|
||||||
const double * xcon,
|
const double* xcon,
|
||||||
const std::vector<int>& iseg,
|
const std::vector<int>& iseg,
|
||||||
const std::vector<double>& rseg) :
|
const std::vector<double>& rseg)
|
||||||
RstWell(unit_system, header, group_arg, zwel, iwel, swel, xwel, icon, scon, xcon)
|
: RstWell { unit_system, header, group_arg,
|
||||||
|
zwel, iwel, swel, xwel,
|
||||||
|
icon, scon, xcon }
|
||||||
{
|
{
|
||||||
|
if (this->msw_index == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this->msw_index) {
|
std::unordered_map<int, std::size_t> segment_map;
|
||||||
std::unordered_map<int, std::size_t> segment_map;
|
for (int is = 0; is < header.nsegmx; ++is) {
|
||||||
for (int is=0; is < header.nsegmx; is++) {
|
const std::size_t iseg_offset = header.nisegz * (is + (this->msw_index - 1)*header.nsegmx);
|
||||||
std::size_t iseg_offset = header.nisegz * (is + (this->msw_index - 1) * header.nsegmx);
|
const std::size_t rseg_offset = header.nrsegz * (is + (this->msw_index - 1)*header.nsegmx);
|
||||||
std::size_t rseg_offset = header.nrsegz * (is + (this->msw_index - 1) * header.nsegmx);
|
const auto other_segment_number = iseg[iseg_offset + VI::ISeg::SegNo];
|
||||||
auto other_segment_number = iseg[iseg_offset + VI::ISeg::SegNo];
|
|
||||||
if (other_segment_number != 0) {
|
if (other_segment_number != 0) {
|
||||||
auto segment_number = is + 1;
|
auto segment_number = is + 1;
|
||||||
segment_map.insert({segment_number, this->segments.size()});
|
segment_map.insert({segment_number, this->segments.size()});
|
||||||
this->segments.emplace_back( unit_system, segment_number, iseg.data() + iseg_offset, rseg.data() + rseg_offset);
|
this->segments.emplace_back(unit_system, segment_number,
|
||||||
}
|
iseg.data() + iseg_offset,
|
||||||
|
rseg.data() + rseg_offset);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& segment : this->segments) {
|
for (auto& segment : this->segments) {
|
||||||
if (segment.outlet_segment != 0) {
|
if (segment.outlet_segment != 0) {
|
||||||
auto& outlet_segment = this->segments[ segment_map[segment.outlet_segment] ];
|
auto& outlet_segment = this->segments[ segment_map[segment.outlet_segment] ];
|
||||||
outlet_segment.inflow_segments.push_back(segment.segment);
|
outlet_segment.inflow_segments.push_back(segment.segment);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const RstSegment&
|
|
||||||
RstWell::segment(int segment_number) const
|
|
||||||
{
|
|
||||||
const auto& iter = std::find_if(this->segments.begin(), this->segments.end(), [segment_number](const RstSegment& segment) { return segment.segment == segment_number; });
|
|
||||||
|
|
||||||
if (iter == this->segments.end())
|
const Opm::RestartIO::RstSegment&
|
||||||
|
Opm::RestartIO::RstWell::segment(int segment_number) const
|
||||||
|
{
|
||||||
|
auto iter = std::find_if(this->segments.begin(), this->segments.end(),
|
||||||
|
[segment_number](const RstSegment& segment)
|
||||||
|
{ return segment.segment == segment_number; });
|
||||||
|
|
||||||
|
if (iter == this->segments.end()) {
|
||||||
throw std::invalid_argument("No such segment");
|
throw std::invalid_argument("No such segment");
|
||||||
|
}
|
||||||
|
|
||||||
return *iter;
|
return *iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
}} // namepace Opm::RestartIO
|
|
||||||
|
Loading…
Reference in New Issue
Block a user