Extract CTF Input Data to Separate Structure
This commit creates a new helper structure, Opm::Connection::CTFProperties that holds all of the individual items which go into calculating the final connection transmissibility factor (CTF). These include the 'Kh' product, the pressure equivalent radius ('r0'), the well-bore radius ('rw'), and the skin factor. We reimplement the Connection constructor in terms of this new helper structure and this changes the API of the constructor. As an additional helper for the implementation, and with a view towards simulation restart support, we also store the value of the Peaceman formula denominator in CTFProperties as double CTFProperties::peaceman_denom This, in turn, simplifies the implementation of CSKIN. It also fixes a latent problem in the current CSKIN implementation which would ignore any explicitly input CTF values in favour of the pressure equivalent radius. By updating the explicit denominator with a new skin factor instead we do not need to recompute the logarithmic term involving 'r0' as part of CSKIN handling.
This commit is contained in:
parent
9a0ccfd853
commit
73c58dba48
@ -17,91 +17,167 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#ifndef COMPLETION_HPP_
|
#ifndef COMPLETION_HPP_
|
||||||
#define COMPLETION_HPP_
|
#define COMPLETION_HPP_
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
|
|
||||||
namespace RestartIO {
|
|
||||||
struct RstConnection;
|
|
||||||
}
|
|
||||||
|
|
||||||
class DeckKeyword;
|
class DeckKeyword;
|
||||||
class DeckRecord;
|
class DeckRecord;
|
||||||
class ScheduleGrid;
|
class ScheduleGrid;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
|
} // namespace Opm
|
||||||
|
|
||||||
class Connection {
|
namespace Opm { namespace RestartIO {
|
||||||
|
struct RstConnection;
|
||||||
|
}} // namespace Opm::RestartIO
|
||||||
|
|
||||||
|
namespace Opm {
|
||||||
|
|
||||||
|
class Connection
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
enum class State {
|
enum class State {
|
||||||
OPEN = 1,
|
OPEN = 1,
|
||||||
SHUT = 2,
|
SHUT = 2,
|
||||||
AUTO = 3 // Seems like the AUTO state can not be serialized to restart files.
|
AUTO = 3, // Seems like the AUTO state can not be serialized to restart files.
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string State2String( State enumValue );
|
static std::string State2String(State enumValue);
|
||||||
static State StateFromString( const std::string& stringValue );
|
static State StateFromString(std::string_view stringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class Direction{
|
enum class Direction {
|
||||||
X = 1,
|
X = 1,
|
||||||
Y = 2,
|
Y = 2,
|
||||||
Z = 3
|
Z = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string Direction2String(const Direction enumValue);
|
static std::string Direction2String(const Direction enumValue);
|
||||||
static Direction DirectionFromString(const std::string& stringValue);
|
static Direction DirectionFromString(std::string_view stringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class Order {
|
enum class Order {
|
||||||
DEPTH,
|
DEPTH,
|
||||||
INPUT,
|
INPUT,
|
||||||
TRACK
|
TRACK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const std::string Order2String( Order enumValue );
|
static std::string Order2String(Order enumValue);
|
||||||
static Order OrderFromString(const std::string& comporderStringValue);
|
static Order OrderFromString(std::string_view comporderStringValue);
|
||||||
|
|
||||||
|
|
||||||
enum class CTFKind {
|
enum class CTFKind {
|
||||||
DeckValue,
|
DeckValue,
|
||||||
Defaulted,
|
Defaulted,
|
||||||
};
|
};
|
||||||
|
|
||||||
Connection();
|
|
||||||
Connection(int i, int j , int k ,
|
|
||||||
std::size_t global_index,
|
|
||||||
int complnum,
|
|
||||||
double depth,
|
|
||||||
State state,
|
|
||||||
double CF,
|
|
||||||
double Kh,
|
|
||||||
double rw,
|
|
||||||
double r0,
|
|
||||||
double re,
|
|
||||||
double connection_length,
|
|
||||||
double skin_factor,
|
|
||||||
double d_factor,
|
|
||||||
double Ke,
|
|
||||||
const int satTableId,
|
|
||||||
const Direction direction,
|
|
||||||
const CTFKind ctf_kind,
|
|
||||||
const std::size_t sort_value,
|
|
||||||
const bool defaultSatTabId);
|
|
||||||
|
|
||||||
Connection(const RestartIO::RstConnection& rst_connection, const ScheduleGrid& grid, const FieldPropsManager& fp);
|
/// Quantities that go into calculating the connection
|
||||||
|
/// transmissibility factor.
|
||||||
|
struct CTFProperties
|
||||||
|
{
|
||||||
|
/// Static connection transmissibility factor calculated from
|
||||||
|
/// input quantities.
|
||||||
|
double CF{};
|
||||||
|
|
||||||
|
/// Static 'Kh' product
|
||||||
|
double Kh{};
|
||||||
|
|
||||||
|
/// Effective permeability.
|
||||||
|
double Ke{};
|
||||||
|
|
||||||
|
/// Connection's wellbore radius
|
||||||
|
double rw{};
|
||||||
|
|
||||||
|
/// Connection's pressure equivalent radius
|
||||||
|
double r0{};
|
||||||
|
|
||||||
|
/// Connection's area equivalent radius--mostly for use by the
|
||||||
|
/// polymer code.
|
||||||
|
double re{};
|
||||||
|
|
||||||
|
/// Length of connection's perfororation interval
|
||||||
|
double connection_length{};
|
||||||
|
|
||||||
|
/// Connection's skin factor.
|
||||||
|
double skin_factor{};
|
||||||
|
|
||||||
|
/// Connection's D factor-i.e., the flow-dependent skin factor
|
||||||
|
/// for gas.
|
||||||
|
double d_factor{};
|
||||||
|
|
||||||
|
/// Denominator in peaceman's formula-i.e., log(r0/rw) + skin.
|
||||||
|
double peaceman_denom{};
|
||||||
|
|
||||||
|
/// Serialisation test object.
|
||||||
|
static CTFProperties serializationTestObject();
|
||||||
|
|
||||||
|
/// Equality operator
|
||||||
|
///
|
||||||
|
/// \param[in] that Property object to which \c *this will be compared.
|
||||||
|
bool operator==(const CTFProperties& that) const;
|
||||||
|
|
||||||
|
/// Inequality operator
|
||||||
|
///
|
||||||
|
/// \param[in] that Property object to which \c *this will be compared.
|
||||||
|
bool operator!=(const CTFProperties& that) const
|
||||||
|
{
|
||||||
|
return ! (*this == that);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serialisation operator
|
||||||
|
///
|
||||||
|
/// \tparam Serializer Protocol for serialising and
|
||||||
|
/// deserialising objects between memory and character
|
||||||
|
/// buffers.
|
||||||
|
///
|
||||||
|
/// \param[in,out] serializer Serialisation object.
|
||||||
|
template <class Serializer>
|
||||||
|
void serializeOp(Serializer& serializer)
|
||||||
|
{
|
||||||
|
serializer(this->CF);
|
||||||
|
serializer(this->Kh);
|
||||||
|
serializer(this->Ke);
|
||||||
|
serializer(this->rw);
|
||||||
|
serializer(this->r0);
|
||||||
|
serializer(this->re);
|
||||||
|
serializer(this->connection_length);
|
||||||
|
serializer(this->skin_factor);
|
||||||
|
serializer(this->d_factor);
|
||||||
|
serializer(this->peaceman_denom);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Connection() = default;
|
||||||
|
Connection(int i, int j, int k,
|
||||||
|
std::size_t global_index,
|
||||||
|
int complnum,
|
||||||
|
State state,
|
||||||
|
Direction direction,
|
||||||
|
CTFKind ctf_kind,
|
||||||
|
const int satTableId,
|
||||||
|
double depth,
|
||||||
|
const CTFProperties& ctf_properties,
|
||||||
|
const std::size_t sort_value,
|
||||||
|
const bool defaultSatTabId);
|
||||||
|
|
||||||
|
Connection(const RestartIO::RstConnection& rst_connection,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const FieldPropsManager& fp);
|
||||||
|
|
||||||
static Connection serializationTestObject();
|
static Connection serializationTestObject();
|
||||||
|
|
||||||
@ -117,104 +193,104 @@ namespace RestartIO {
|
|||||||
int satTableId() const;
|
int satTableId() const;
|
||||||
int complnum() const;
|
int complnum() const;
|
||||||
int segment() const;
|
int segment() const;
|
||||||
double CF() const;
|
|
||||||
double wpimult() const;
|
double wpimult() const;
|
||||||
|
double CF() const;
|
||||||
double Kh() const;
|
double Kh() const;
|
||||||
|
double Ke() const;
|
||||||
double rw() const;
|
double rw() const;
|
||||||
double r0() const;
|
double r0() const;
|
||||||
double re() const;
|
double re() const;
|
||||||
double connectionLength() const;
|
double connectionLength() const;
|
||||||
double skinFactor() const;
|
double skinFactor() const;
|
||||||
double dFactor() const;
|
double dFactor() const;
|
||||||
double Ke() const;
|
|
||||||
CTFKind kind() const;
|
CTFKind kind() const;
|
||||||
const InjMult& injmult() const;
|
const InjMult& injmult() const;
|
||||||
bool activeInjMult() const;
|
bool activeInjMult() const;
|
||||||
void setInjMult(const InjMult& inj_mult);
|
|
||||||
void setFilterCake(const FilterCake& filter_cake);
|
|
||||||
const FilterCake& getFilterCake() const;
|
const FilterCake& getFilterCake() const;
|
||||||
bool filterCakeActive() const;
|
bool filterCakeActive() const;
|
||||||
double getFilterCakeRadius() const;
|
double getFilterCakeRadius() const;
|
||||||
double getFilterCakeArea() const;
|
double getFilterCakeArea() const;
|
||||||
|
|
||||||
|
const CTFProperties& ctfProperties() const
|
||||||
|
{
|
||||||
|
return this->ctf_properties_;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t sort_value() const;
|
||||||
|
bool getDefaultSatTabId() const;
|
||||||
|
const std::optional<std::pair<double, double>>& perf_range() const;
|
||||||
|
std::string str() const;
|
||||||
|
|
||||||
|
bool ctfAssignedFromInput() const
|
||||||
|
{
|
||||||
|
return this->m_ctfkind == CTFKind::DeckValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Connection&) const;
|
||||||
|
bool operator!=(const Connection& that) const
|
||||||
|
{
|
||||||
|
return ! (*this == that);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInjMult(const InjMult& inj_mult);
|
||||||
|
void setFilterCake(const FilterCake& filter_cake);
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
void setComplnum(int compnum);
|
void setComplnum(int compnum);
|
||||||
void setSkinFactor(double skin_factor);
|
void setSkinFactor(double skin_factor);
|
||||||
void setDFactor(double d_factor);
|
void setDFactor(double d_factor);
|
||||||
void setKe(double Ke);
|
void setKe(double Ke);
|
||||||
void setCF(double CF);
|
void setCF(double CF);
|
||||||
|
void setDefaultSatTabId(bool id);
|
||||||
|
|
||||||
void scaleWellPi(double wellPi);
|
void scaleWellPi(double wellPi);
|
||||||
bool prepareWellPIScaling();
|
bool prepareWellPIScaling();
|
||||||
bool applyWellPIScaling(const double scaleFactor);
|
bool applyWellPIScaling(const double scaleFactor);
|
||||||
|
|
||||||
void updateSegmentRST(int segment_number_arg,
|
void updateSegmentRST(int segment_number_arg,
|
||||||
double center_depth_arg);
|
double center_depth_arg);
|
||||||
void updateSegment(int segment_number_arg,
|
void updateSegment(int segment_number_arg,
|
||||||
double center_depth_arg,
|
double center_depth_arg,
|
||||||
std::size_t compseg_insert_index,
|
std::size_t compseg_insert_index,
|
||||||
const std::optional<std::pair<double,double>>& perf_range);
|
const std::optional<std::pair<double,double>>& perf_range);
|
||||||
std::size_t sort_value() const;
|
|
||||||
const bool& getDefaultSatTabId() const;
|
|
||||||
void setDefaultSatTabId(bool id);
|
|
||||||
const std::optional<std::pair<double, double>>& perf_range() const;
|
|
||||||
std::string str() const;
|
|
||||||
bool ctfAssignedFromInput() const
|
|
||||||
{
|
|
||||||
return this->m_ctfkind == CTFKind::DeckValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==( const Connection& ) const;
|
|
||||||
bool operator!=( const Connection& ) const;
|
|
||||||
|
|
||||||
template<class Serializer>
|
template<class Serializer>
|
||||||
void serializeOp(Serializer& serializer)
|
void serializeOp(Serializer& serializer)
|
||||||
{
|
{
|
||||||
serializer(direction);
|
serializer(this->direction);
|
||||||
serializer(center_depth);
|
serializer(this->center_depth);
|
||||||
serializer(open_state);
|
serializer(this->open_state);
|
||||||
serializer(sat_tableId);
|
serializer(this->sat_tableId);
|
||||||
serializer(m_complnum);
|
serializer(this->m_complnum);
|
||||||
serializer(m_CF);
|
serializer(this->ctf_properties_);
|
||||||
serializer(m_Kh);
|
serializer(this->ijk);
|
||||||
serializer(m_rw);
|
serializer(this->m_ctfkind);
|
||||||
serializer(m_r0);
|
serializer(this->m_global_index);
|
||||||
serializer(m_re);
|
serializer(this->m_injmult);
|
||||||
serializer(m_connection_length);
|
serializer(this->m_sort_value);
|
||||||
serializer(m_skin_factor);
|
serializer(this->m_perf_range);
|
||||||
serializer(m_d_factor);
|
serializer(this->m_defaultSatTabId);
|
||||||
serializer(m_Ke);
|
serializer(this->segment_number);
|
||||||
serializer(ijk);
|
serializer(this->m_wpimult);
|
||||||
serializer(m_global_index);
|
serializer(this->m_subject_to_welpi);
|
||||||
serializer(m_ctfkind);
|
serializer(this->m_filter_cake);
|
||||||
serializer(m_injmult);
|
|
||||||
serializer(m_sort_value);
|
|
||||||
serializer(m_perf_range);
|
|
||||||
serializer(m_defaultSatTabId);
|
|
||||||
serializer(segment_number);
|
|
||||||
serializer(m_subject_to_welpi);
|
|
||||||
serializer(m_filter_cake);
|
|
||||||
serializer(m_wpimult);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Direction direction;
|
// Note to maintainer: If you add new members to this list, then
|
||||||
double center_depth;
|
// please also update the operator==(), serializeOp(), and
|
||||||
State open_state;
|
// serializationTestObject() member functions.
|
||||||
int sat_tableId;
|
Direction direction { Direction::Z };
|
||||||
int m_complnum;
|
double center_depth { 0.0 };
|
||||||
double m_CF;
|
State open_state { State::SHUT };
|
||||||
double m_Kh;
|
int sat_tableId { -1 };
|
||||||
double m_rw;
|
int m_complnum { -1 };
|
||||||
double m_r0;
|
CTFProperties ctf_properties_{};
|
||||||
double m_re;
|
|
||||||
double m_connection_length;
|
std::array<int,3> ijk{};
|
||||||
double m_skin_factor;
|
CTFKind m_ctfkind { CTFKind::DeckValue };
|
||||||
double m_d_factor;
|
std::optional<InjMult> m_injmult{};
|
||||||
double m_Ke;
|
std::size_t m_global_index{};
|
||||||
|
|
||||||
std::array<int,3> ijk;
|
|
||||||
CTFKind m_ctfkind;
|
|
||||||
std::optional<InjMult> m_injmult;
|
|
||||||
std::size_t m_global_index;
|
|
||||||
/*
|
/*
|
||||||
The sort_value member is a peculiar quantity. The connections are
|
The sort_value member is a peculiar quantity. The connections are
|
||||||
assembled in the WellConnections class. During the lifetime of the
|
assembled in the WellConnections class. During the lifetime of the
|
||||||
@ -266,26 +342,26 @@ namespace RestartIO {
|
|||||||
explicitly, so the truth is probably that the storage order
|
explicitly, so the truth is probably that the storage order
|
||||||
during simulation makes no difference?
|
during simulation makes no difference?
|
||||||
*/
|
*/
|
||||||
|
std::size_t m_sort_value{};
|
||||||
|
|
||||||
std::size_t m_sort_value;
|
std::optional<std::pair<double,double>> m_perf_range{};
|
||||||
std::optional<std::pair<double,double>> m_perf_range;
|
bool m_defaultSatTabId{true};
|
||||||
bool m_defaultSatTabId;
|
|
||||||
|
|
||||||
// related segment number
|
// Associate segment number
|
||||||
// 0 means the completion is not related to segment
|
//
|
||||||
int segment_number = 0;
|
// 0 means the connection is not associated to a segment.
|
||||||
|
int segment_number { 0 };
|
||||||
|
|
||||||
|
double m_wpimult { 1.0 };
|
||||||
|
|
||||||
// Whether or not this Connection is subject to WELPI scaling.
|
// Whether or not this Connection is subject to WELPI scaling.
|
||||||
bool m_subject_to_welpi = false;
|
bool m_subject_to_welpi { false };
|
||||||
|
|
||||||
// For applying last known WPIMULT to when calculating connection transmissibilty factor in CSKIN
|
std::optional<FilterCake> m_filter_cake{};
|
||||||
double m_wpimult = 1.0;
|
|
||||||
|
|
||||||
std::optional<FilterCake> m_filter_cake;
|
|
||||||
|
|
||||||
static std::string CTFKindToString(const CTFKind);
|
static std::string CTFKindToString(const CTFKind);
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* COMPLETION_HPP_ */
|
} // namespace Opm
|
||||||
|
|
||||||
|
#endif // COMPLETION_HPP_
|
||||||
|
@ -527,7 +527,7 @@ public:
|
|||||||
bool handleWELSEGS(const DeckKeyword& keyword);
|
bool handleWELSEGS(const DeckKeyword& keyword);
|
||||||
bool handleCOMPSEGS(const DeckKeyword& keyword, const ScheduleGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
|
bool handleCOMPSEGS(const DeckKeyword& keyword, const ScheduleGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
|
||||||
bool handleWELOPENConnections(const DeckRecord& record, Connection::State status);
|
bool handleWELOPENConnections(const DeckRecord& record, Connection::State status);
|
||||||
bool handleCSKINConnections(const DeckRecord& record);
|
bool handleCSKIN(const DeckRecord& record, const KeywordLocation& location);
|
||||||
bool handleCOMPLUMP(const DeckRecord& record);
|
bool handleCOMPLUMP(const DeckRecord& record);
|
||||||
bool handleWPIMULT(const DeckRecord& record);
|
bool handleWPIMULT(const DeckRecord& record);
|
||||||
bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location);
|
bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location);
|
||||||
|
@ -23,9 +23,11 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
#include <external/resinsight/LibGeometry/cvfBoundingBoxTree.h>
|
#include <external/resinsight/LibGeometry/cvfBoundingBoxTree.h>
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@ -33,10 +35,10 @@
|
|||||||
namespace Opm {
|
namespace Opm {
|
||||||
class ActiveGridCells;
|
class ActiveGridCells;
|
||||||
class DeckRecord;
|
class DeckRecord;
|
||||||
|
class EclipseGrid;
|
||||||
class FieldPropsManager;
|
class FieldPropsManager;
|
||||||
class KeywordLocation;
|
class KeywordLocation;
|
||||||
class ScheduleGrid;
|
class ScheduleGrid;
|
||||||
class EclipseGrid;
|
|
||||||
} // namespace Opm
|
} // namespace Opm
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
@ -67,19 +69,16 @@ namespace Opm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void add(const Connection& conn)
|
||||||
|
{
|
||||||
|
this->m_connections.push_back(conn);
|
||||||
|
}
|
||||||
|
|
||||||
void addConnection(const int i, const int j, const int k,
|
void addConnection(const int i, const int j, const int k,
|
||||||
const std::size_t global_index,
|
const std::size_t global_index,
|
||||||
const double depth,
|
|
||||||
const Connection::State state,
|
const Connection::State state,
|
||||||
const double CF,
|
const double depth,
|
||||||
const double Kh,
|
const Connection::CTFProperties& ctf_props,
|
||||||
const double rw,
|
|
||||||
const double r0,
|
|
||||||
const double re,
|
|
||||||
const double connection_length,
|
|
||||||
const double skin_factor,
|
|
||||||
const double d_factor,
|
|
||||||
const double Ke,
|
|
||||||
const int satTableId,
|
const int satTableId,
|
||||||
const Connection::Direction direction = Connection::Direction::Z,
|
const Connection::Direction direction = Connection::Direction::Z,
|
||||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
||||||
@ -91,14 +90,20 @@ namespace Opm {
|
|||||||
const std::string& wname,
|
const std::string& wname,
|
||||||
const KeywordLocation& location);
|
const KeywordLocation& location);
|
||||||
|
|
||||||
void loadCOMPTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location, external::cvf::ref<external::cvf::BoundingBoxTree>& cellSearchTree);
|
void loadCOMPTRAJ(const DeckRecord& record,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const std::string& wname,
|
||||||
|
const KeywordLocation& location,
|
||||||
|
external::cvf::ref<external::cvf::BoundingBoxTree>& cellSearchTree);
|
||||||
|
|
||||||
void loadWELTRAJ(const DeckRecord& record, const ScheduleGrid& grid, const std::string& wname, const KeywordLocation& location);
|
void loadWELTRAJ(const DeckRecord& record,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const std::string& wname,
|
||||||
|
const KeywordLocation& location);
|
||||||
|
|
||||||
int getHeadI() const;
|
int getHeadI() const;
|
||||||
int getHeadJ() const;
|
int getHeadJ() const;
|
||||||
const std::vector<double>& getMD() const;
|
const std::vector<double>& getMD() const;
|
||||||
void add(Connection);
|
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
std::size_t num_open() const;
|
std::size_t num_open() const;
|
||||||
@ -165,39 +170,32 @@ namespace Opm {
|
|||||||
serializer(this->coord);
|
serializer(this->coord);
|
||||||
serializer(this->md);
|
serializer(this->md);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Connection::Order m_ordering { Connection::Order::TRACK };
|
Connection::Order m_ordering { Connection::Order::TRACK };
|
||||||
int headI{0};
|
int headI{0};
|
||||||
int headJ{0};
|
int headJ{0};
|
||||||
std::vector<Connection> m_connections{};
|
std::vector<Connection> m_connections{};
|
||||||
std::vector<std::vector<double>> coord{3, std::vector<double>(0, 0.0) };
|
|
||||||
|
std::array<std::vector<double>, 3> coord{};
|
||||||
std::vector<double> md{};
|
std::vector<double> md{};
|
||||||
|
|
||||||
void addConnection(const int i, const int j, const int k,
|
void addConnection(const int i, const int j, const int k,
|
||||||
const std::size_t global_index,
|
const std::size_t global_index,
|
||||||
const int complnum,
|
const int complnum,
|
||||||
const double depth,
|
|
||||||
const Connection::State state,
|
const Connection::State state,
|
||||||
const double CF,
|
const double depth,
|
||||||
const double Kh,
|
const Connection::CTFProperties& ctf_props,
|
||||||
const double rw,
|
|
||||||
const double r0,
|
|
||||||
const double re,
|
|
||||||
const double connection_length,
|
|
||||||
const double skin_factor,
|
|
||||||
const double d_factor,
|
|
||||||
const double Ke,
|
|
||||||
const int satTableId,
|
const int satTableId,
|
||||||
const Connection::Direction direction = Connection::Direction::Z,
|
const Connection::Direction direction,
|
||||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
const Connection::CTFKind ctf_kind,
|
||||||
const std::size_t seqIndex = 0,
|
const std::size_t seqIndex,
|
||||||
const bool defaultSatTabId = true);
|
const bool defaultSatTabId);
|
||||||
|
|
||||||
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
||||||
void orderTRACK();
|
void orderTRACK();
|
||||||
void orderMSW();
|
void orderMSW();
|
||||||
void orderDEPTH();
|
void orderDEPTH();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<int>
|
std::optional<int>
|
||||||
|
@ -377,23 +377,29 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
|||||||
handlerContext.compsegs_handled(wname);
|
handlerContext.compsegs_handled(wname);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Schedule::handleCSKIN(HandlerContext& handlerContext) {
|
void Schedule::handleCSKIN(HandlerContext& handlerContext)
|
||||||
|
{
|
||||||
|
using Kw = ParserKeywords::CSKIN;
|
||||||
|
|
||||||
// Get CSKIN keyword info and current step
|
// Get CSKIN keyword info and current step
|
||||||
const auto& keyword = handlerContext.keyword;
|
const auto& keyword = handlerContext.keyword;
|
||||||
const auto& currentStep = handlerContext.currentStep;
|
const auto& currentStep = handlerContext.currentStep;
|
||||||
|
|
||||||
// Loop over records in CSKIN
|
// Loop over records in CSKIN
|
||||||
for (const auto& record: keyword) {
|
for (const auto& record : keyword) {
|
||||||
// Get well names
|
// Get well names
|
||||||
const auto& wellNamePattern = record.getItem( "WELL" ).getTrimmedString(0);
|
const auto wellNamePattern = record.getItem<Kw::WELL>().getTrimmedString(0);
|
||||||
const auto well_names = this->wellNames(wellNamePattern, handlerContext);
|
const auto well_names = this->wellNames(wellNamePattern, handlerContext);
|
||||||
|
|
||||||
// Loop over well(s) in record
|
// Loop over well(s) in record
|
||||||
for (const auto& wname : well_names) {
|
for (const auto& wname : well_names) {
|
||||||
// Get well information, modify connection skin factor, and update well
|
// Get well information, modify connection skin factor, and
|
||||||
|
// update well.
|
||||||
auto well = this->snapshots[currentStep].wells.get(wname);
|
auto well = this->snapshots[currentStep].wells.get(wname);
|
||||||
well.handleCSKINConnections(record);
|
|
||||||
this->snapshots[currentStep].wells.update( std::move(well) );
|
if (well.handleCSKIN(record, handlerContext.keyword.location())) {
|
||||||
|
this->snapshots[currentStep].wells.update(std::move(well));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,125 +17,157 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
|
|
||||||
|
#include <opm/io/eclipse/rst/connection.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <opm/io/eclipse/rst/connection.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
|
||||||
|
|
||||||
namespace Opm {
|
|
||||||
|
|
||||||
|
|
||||||
Connection::Connection(int i, int j , int k ,
|
|
||||||
std::size_t global_index,
|
|
||||||
int compnum,
|
|
||||||
double depth,
|
|
||||||
State stateArg ,
|
|
||||||
double CF,
|
|
||||||
double Kh,
|
|
||||||
double rw,
|
|
||||||
double r0,
|
|
||||||
double re,
|
|
||||||
double connection_length,
|
|
||||||
double skin_factor,
|
|
||||||
double d_factor,
|
|
||||||
double Ke,
|
|
||||||
const int satTableId,
|
|
||||||
const Direction directionArg,
|
|
||||||
const CTFKind ctf_kind,
|
|
||||||
const std::size_t sort_value,
|
|
||||||
const bool defaultSatTabId)
|
|
||||||
: direction(directionArg),
|
|
||||||
center_depth(depth),
|
|
||||||
open_state(stateArg),
|
|
||||||
sat_tableId(satTableId),
|
|
||||||
m_complnum( compnum ),
|
|
||||||
m_CF(CF),
|
|
||||||
m_Kh(Kh),
|
|
||||||
m_rw(rw),
|
|
||||||
m_r0(r0),
|
|
||||||
m_re(re),
|
|
||||||
m_connection_length(connection_length),
|
|
||||||
m_skin_factor(skin_factor),
|
|
||||||
m_d_factor(d_factor),
|
|
||||||
m_Ke(Ke),
|
|
||||||
ijk({i,j,k}),
|
|
||||||
m_ctfkind(ctf_kind),
|
|
||||||
m_global_index(global_index),
|
|
||||||
m_sort_value(sort_value),
|
|
||||||
m_defaultSatTabId(defaultSatTabId)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
constexpr bool defaultSatTabId = true;
|
constexpr bool restartDefaultSatTabId = true;
|
||||||
|
|
||||||
|
Opm::Connection::CTFProperties
|
||||||
|
collectCTFProps(const Opm::RestartIO::RstConnection& rst_conn)
|
||||||
|
{
|
||||||
|
auto props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
props.CF = rst_conn.cf;
|
||||||
|
props.Kh = rst_conn.kh;
|
||||||
|
props.Ke = 0.0;
|
||||||
|
props.rw = rst_conn.diameter / 2;
|
||||||
|
props.r0 = rst_conn.r0;
|
||||||
|
props.re = 0.0;
|
||||||
|
props.connection_length = 0.0;
|
||||||
|
props.skin_factor = rst_conn.skin_factor;
|
||||||
|
props.d_factor = 0.0;
|
||||||
|
|
||||||
|
return props;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection(const RestartIO::RstConnection& rst_connection, const ScheduleGrid& grid, const FieldPropsManager& fp) :
|
namespace Opm
|
||||||
direction(rst_connection.dir),
|
{
|
||||||
center_depth(rst_connection.depth),
|
|
||||||
open_state(rst_connection.state),
|
Connection::CTFProperties
|
||||||
sat_tableId(rst_connection.drain_sat_table),
|
Connection::CTFProperties::serializationTestObject()
|
||||||
m_complnum(rst_connection.completion),
|
{
|
||||||
m_CF(rst_connection.cf),
|
auto props = Opm::Connection::CTFProperties{};
|
||||||
m_Kh(rst_connection.kh),
|
|
||||||
m_rw(rst_connection.diameter / 2),
|
props.CF = 1.0;
|
||||||
m_r0(rst_connection.r0),
|
props.Kh = 2.0;
|
||||||
m_re(0.0),
|
props.Ke = 3.0;
|
||||||
m_connection_length(0.0),
|
props.rw = 4.0;
|
||||||
m_skin_factor(rst_connection.skin_factor),
|
props.r0 = 5.0;
|
||||||
m_d_factor(0.0),
|
props.re = 6.0;
|
||||||
m_Ke(0.0),
|
props.connection_length = 7.0;
|
||||||
ijk(rst_connection.ijk),
|
props.skin_factor = 8.0;
|
||||||
m_ctfkind(rst_connection.cf_kind),
|
props.d_factor = 9.0;
|
||||||
m_global_index(grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).global_index),
|
props.peaceman_denom = 10.0;
|
||||||
m_sort_value(rst_connection.rst_index),
|
|
||||||
m_defaultSatTabId(defaultSatTabId),
|
return props;
|
||||||
segment_number(rst_connection.segment)
|
}
|
||||||
|
|
||||||
|
bool Connection::CTFProperties::operator==(const CTFProperties& that) const
|
||||||
|
{
|
||||||
|
return (this->CF == that.CF)
|
||||||
|
&& (this->Kh == that.Kh)
|
||||||
|
&& (this->Ke == that.Ke)
|
||||||
|
&& (this->rw == that.rw)
|
||||||
|
&& (this->r0 == that.r0)
|
||||||
|
&& (this->re == that.re)
|
||||||
|
&& (this->connection_length == that.connection_length)
|
||||||
|
&& (this->skin_factor == that.skin_factor)
|
||||||
|
&& (this->d_factor == that.d_factor)
|
||||||
|
&& (this->peaceman_denom == that.peaceman_denom)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================================================================
|
||||||
|
|
||||||
|
Connection::Connection(const int i, const int j, const int k,
|
||||||
|
const std::size_t global_index,
|
||||||
|
const int complnum,
|
||||||
|
const State stateArg,
|
||||||
|
const Direction directionArg,
|
||||||
|
const CTFKind ctf_kind,
|
||||||
|
const int satTableId,
|
||||||
|
const double depth,
|
||||||
|
const CTFProperties& ctf_props,
|
||||||
|
const std::size_t sort_value,
|
||||||
|
const bool defaultSatTabId)
|
||||||
|
: direction (directionArg)
|
||||||
|
, center_depth (depth)
|
||||||
|
, open_state (stateArg)
|
||||||
|
, sat_tableId (satTableId)
|
||||||
|
, m_complnum (complnum)
|
||||||
|
, ctf_properties_ { ctf_props }
|
||||||
|
, ijk { i, j, k }
|
||||||
|
, m_ctfkind (ctf_kind)
|
||||||
|
, m_global_index (global_index)
|
||||||
|
, m_sort_value (sort_value)
|
||||||
|
, m_defaultSatTabId(defaultSatTabId)
|
||||||
|
{}
|
||||||
|
|
||||||
|
Connection::Connection(const RestartIO::RstConnection& rst_connection,
|
||||||
|
const ScheduleGrid& grid,
|
||||||
|
const FieldPropsManager& fp)
|
||||||
|
: direction (rst_connection.dir)
|
||||||
|
, center_depth (rst_connection.depth)
|
||||||
|
, open_state (rst_connection.state)
|
||||||
|
, sat_tableId (rst_connection.drain_sat_table)
|
||||||
|
, m_complnum (rst_connection.completion)
|
||||||
|
, ctf_properties_ (collectCTFProps(rst_connection))
|
||||||
|
, ijk (rst_connection.ijk)
|
||||||
|
, m_ctfkind (rst_connection.cf_kind)
|
||||||
|
, m_global_index (grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).global_index)
|
||||||
|
, m_sort_value (rst_connection.rst_index)
|
||||||
|
, m_defaultSatTabId(restartDefaultSatTabId)
|
||||||
|
, segment_number (rst_connection.segment)
|
||||||
{
|
{
|
||||||
if (this->m_defaultSatTabId) {
|
if (this->m_defaultSatTabId) {
|
||||||
const auto& satnum = fp.get_int("SATNUM");
|
const auto active_index = grid
|
||||||
auto active_index = grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).active_index();
|
.get_cell(this->ijk[0], this->ijk[1], this->ijk[2])
|
||||||
this->sat_tableId = satnum[active_index];
|
.active_index();
|
||||||
|
|
||||||
|
this->sat_tableId = fp.get_int("SATNUM")[active_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->segment_number > 0) {
|
||||||
|
this->m_perf_range = std::make_pair(rst_connection.segdist_start,
|
||||||
|
rst_connection.segdist_end);
|
||||||
}
|
}
|
||||||
if (this->segment_number > 0)
|
|
||||||
this->m_perf_range = std::make_pair(rst_connection.segdist_start, rst_connection.segdist_end);
|
|
||||||
|
|
||||||
//TODO recompute re and perf_length from the grid
|
//TODO recompute re and perf_length from the grid
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Connection()
|
|
||||||
: Connection(0, 0, 0, 0, 0, 0.0, State::SHUT, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
|
|
||||||
0, Direction::X, CTFKind::DeckValue, 0, false)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Connection Connection::serializationTestObject()
|
Connection Connection::serializationTestObject()
|
||||||
{
|
{
|
||||||
Connection result;
|
Connection result;
|
||||||
|
|
||||||
result.direction = Direction::Y;
|
result.direction = Direction::Y;
|
||||||
result.center_depth = 1.0;
|
result.center_depth = 1.0;
|
||||||
result.open_state = State::OPEN;
|
result.open_state = State::OPEN;
|
||||||
result.sat_tableId = 2;
|
result.sat_tableId = 2;
|
||||||
result.m_complnum = 3;
|
result.m_complnum = 3;
|
||||||
result.m_CF = 4.0;
|
|
||||||
result.m_Kh = 5.0;
|
result.ctf_properties_ = CTFProperties::serializationTestObject();
|
||||||
result.m_rw = 6.0;
|
|
||||||
result.m_r0 = 7.0;
|
|
||||||
result.m_re = 7.1;
|
|
||||||
result.m_connection_length = 7.2;
|
|
||||||
result.m_skin_factor = 8.0;
|
|
||||||
result.m_d_factor = 8.5;
|
|
||||||
result.m_Ke = 8.9;
|
|
||||||
result.ijk = {9, 10, 11};
|
result.ijk = {9, 10, 11};
|
||||||
result.m_ctfkind = CTFKind::Defaulted;
|
result.m_ctfkind = CTFKind::Defaulted;
|
||||||
result.m_global_index = 12;
|
result.m_global_index = 12;
|
||||||
@ -144,144 +176,181 @@ Connection::Connection(const RestartIO::RstConnection& rst_connection, const Sch
|
|||||||
result.m_sort_value = 14;
|
result.m_sort_value = 14;
|
||||||
result.m_defaultSatTabId = true;
|
result.m_defaultSatTabId = true;
|
||||||
result.segment_number = 16;
|
result.segment_number = 16;
|
||||||
|
result.m_wpimult = 0.123;
|
||||||
result.m_subject_to_welpi = true;
|
result.m_subject_to_welpi = true;
|
||||||
result.m_filter_cake = FilterCake::serializationTestObject();
|
result.m_filter_cake = FilterCake::serializationTestObject();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::sameCoordinate(const int i, const int j, const int k) const {
|
bool Connection::sameCoordinate(const int i, const int j, const int k) const
|
||||||
if ((ijk[0] == i) && (ijk[1] == j) && (ijk[2] == k)) {
|
{
|
||||||
return true;
|
return this->ijk == std::array { i, j, k };
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getI() const {
|
int Connection::getI() const
|
||||||
|
{
|
||||||
return ijk[0];
|
return ijk[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getJ() const {
|
int Connection::getJ() const
|
||||||
|
{
|
||||||
return ijk[1];
|
return ijk[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::getK() const {
|
int Connection::getK() const
|
||||||
|
{
|
||||||
return ijk[2];
|
return ijk[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Connection::global_index() const {
|
std::size_t Connection::global_index() const
|
||||||
|
{
|
||||||
return this->m_global_index;
|
return this->m_global_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::attachedToSegment() const {
|
bool Connection::attachedToSegment() const
|
||||||
return (segment_number > 0);
|
{
|
||||||
|
return this->segment_number > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t Connection::sort_value() const {
|
std::size_t Connection::sort_value() const
|
||||||
|
{
|
||||||
return m_sort_value;
|
return m_sort_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool& Connection::getDefaultSatTabId() const {
|
bool Connection::getDefaultSatTabId() const
|
||||||
|
{
|
||||||
return m_defaultSatTabId;
|
return m_defaultSatTabId;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::Direction Connection::dir() const {
|
Connection::Direction Connection::dir() const
|
||||||
|
{
|
||||||
return this->direction;
|
return this->direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
const std::optional<std::pair<double, double>>&
|
||||||
|
Connection::perf_range() const
|
||||||
|
{
|
||||||
return this->m_perf_range;
|
return this->m_perf_range;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setDefaultSatTabId(bool id) {
|
void Connection::setDefaultSatTabId(bool id)
|
||||||
|
{
|
||||||
m_defaultSatTabId = id;
|
m_defaultSatTabId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::depth() const {
|
double Connection::depth() const
|
||||||
|
{
|
||||||
return this->center_depth;
|
return this->center_depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::State Connection::state() const {
|
Connection::State Connection::state() const
|
||||||
|
{
|
||||||
return this->open_state;
|
return this->open_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::satTableId() const {
|
int Connection::satTableId() const
|
||||||
|
{
|
||||||
return this->sat_tableId;
|
return this->sat_tableId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::complnum() const {
|
int Connection::complnum() const
|
||||||
|
{
|
||||||
return this->m_complnum;
|
return this->m_complnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setComplnum(int complnum) {
|
void Connection::setComplnum(int complnum)
|
||||||
|
{
|
||||||
this->m_complnum = complnum;
|
this->m_complnum = complnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setSkinFactor(double skin_factor) {
|
void Connection::setSkinFactor(double skin_factor)
|
||||||
this->m_skin_factor = skin_factor;
|
{
|
||||||
|
auto& ctf_p = this->ctf_properties_;
|
||||||
|
|
||||||
|
const auto peaceman_denom = ctf_p.peaceman_denom
|
||||||
|
- ctf_p.skin_factor + skin_factor;
|
||||||
|
|
||||||
|
ctf_p.skin_factor = skin_factor;
|
||||||
|
ctf_p.CF *= ctf_p.peaceman_denom / peaceman_denom;
|
||||||
|
ctf_p.peaceman_denom = peaceman_denom;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setDFactor(double d_factor) {
|
void Connection::setDFactor(double d_factor)
|
||||||
this->m_d_factor = d_factor;
|
{
|
||||||
|
this->ctf_properties_.d_factor = d_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setKe(double Ke) {
|
void Connection::setKe(double Ke)
|
||||||
this->m_Ke = Ke;
|
{
|
||||||
|
this->ctf_properties_.Ke = Ke;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setCF(double CF) {
|
void Connection::setCF(double CF)
|
||||||
this->m_CF = CF;
|
{
|
||||||
|
this->ctf_properties_.CF = CF;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::CF() const {
|
double Connection::wpimult() const
|
||||||
return this->m_CF;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
double Connection::wpimult() const {
|
|
||||||
return this->m_wpimult;
|
return this->m_wpimult;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::Kh() const {
|
double Connection::CF() const
|
||||||
return this->m_Kh;
|
{
|
||||||
|
return this->ctf_properties_.CF;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::rw() const {
|
double Connection::Kh() const
|
||||||
return this->m_rw;
|
{
|
||||||
|
return this->ctf_properties_.Kh;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::r0() const {
|
double Connection::rw() const
|
||||||
return this->m_r0;
|
{
|
||||||
|
return this->ctf_properties_.rw;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::re() const {
|
double Connection::r0() const
|
||||||
return this->m_re;
|
{
|
||||||
|
return this->ctf_properties_.r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::connectionLength() const {
|
double Connection::re() const
|
||||||
return this->m_connection_length;
|
{
|
||||||
|
return this->ctf_properties_.re;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::skinFactor() const {
|
double Connection::connectionLength() const
|
||||||
return this->m_skin_factor;
|
{
|
||||||
|
return this->ctf_properties_.connection_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::dFactor() const {
|
double Connection::skinFactor() const
|
||||||
return this->m_d_factor;
|
{
|
||||||
|
return this->ctf_properties_.skin_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Connection::Ke() const {
|
double Connection::dFactor() const
|
||||||
return this->m_Ke;
|
{
|
||||||
|
return this->ctf_properties_.d_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setState(State state) {
|
double Connection::Ke() const
|
||||||
|
{
|
||||||
|
return this->ctf_properties_.Ke;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::setState(State state)
|
||||||
|
{
|
||||||
this->open_state = state;
|
this->open_state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::updateSegment(int segment_number_arg,
|
void Connection::updateSegment(const int segment_number_arg,
|
||||||
double center_depth_arg,
|
const double center_depth_arg,
|
||||||
std::size_t compseg_insert_index,
|
const std::size_t compseg_insert_index,
|
||||||
const std::optional<std::pair<double, double>>& perf_range) {
|
const std::optional<std::pair<double, double>>& perf_range)
|
||||||
|
{
|
||||||
this->segment_number = segment_number_arg;
|
this->segment_number = segment_number_arg;
|
||||||
this->center_depth = center_depth_arg;
|
this->center_depth = center_depth_arg;
|
||||||
this->m_sort_value = compseg_insert_index;
|
this->m_sort_value = compseg_insert_index;
|
||||||
@ -289,124 +358,137 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Connection::updateSegmentRST(int segment_number_arg,
|
void Connection::updateSegmentRST(int segment_number_arg,
|
||||||
double center_depth_arg) {
|
double center_depth_arg)
|
||||||
|
{
|
||||||
this->segment_number = segment_number_arg;
|
this->segment_number = segment_number_arg;
|
||||||
this->center_depth = center_depth_arg;
|
this->center_depth = center_depth_arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Connection::segment() const {
|
int Connection::segment() const
|
||||||
|
{
|
||||||
return this->segment_number;
|
return this->segment_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::scaleWellPi(double wellPi) {
|
void Connection::scaleWellPi(double wellPi)
|
||||||
|
{
|
||||||
this->m_wpimult *= wellPi;
|
this->m_wpimult *= wellPi;
|
||||||
this->m_CF *= wellPi;
|
this->ctf_properties_.CF *= wellPi;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::prepareWellPIScaling() {
|
bool Connection::prepareWellPIScaling()
|
||||||
|
{
|
||||||
const auto update = !this->m_subject_to_welpi;
|
const auto update = !this->m_subject_to_welpi;
|
||||||
|
|
||||||
this->m_subject_to_welpi = true;
|
this->m_subject_to_welpi = true;
|
||||||
|
|
||||||
return update;
|
return update;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Connection::applyWellPIScaling(const double scaleFactor) {
|
bool Connection::applyWellPIScaling(const double scaleFactor)
|
||||||
if (! this->m_subject_to_welpi)
|
{
|
||||||
|
if (! this->m_subject_to_welpi) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
this->scaleWellPi(scaleFactor);
|
this->scaleWellPi(scaleFactor);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Connection::str() const {
|
std::string Connection::str() const
|
||||||
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "ijk: " << this->ijk[0] << "," << this->ijk[1] << "," << this->ijk[2] << std::endl;
|
|
||||||
ss << "COMPLNUM " << this->m_complnum << std::endl;
|
ss << "ijk: " << this->ijk[0] << ',' << this->ijk[1] << ',' << this->ijk[2] << '\n'
|
||||||
ss << "CF " << this->m_CF << std::endl;
|
<< "COMPLNUM " << this->m_complnum << '\n'
|
||||||
ss << "RW " << this->m_rw << std::endl;
|
<< "CF " << this->CF() << '\n'
|
||||||
ss << "R0 " << this->m_r0 << std::endl;
|
<< "RW " << this->rw() << '\n'
|
||||||
ss << "Re " << this->m_re << std::endl;
|
<< "R0 " << this->r0() << '\n'
|
||||||
ss << "connection length " << this->m_connection_length << std::endl;
|
<< "Re " << this->re() << '\n'
|
||||||
ss << "skinf " << this->m_skin_factor << std::endl;
|
<< "connection length " << this->connectionLength() << '\n'
|
||||||
ss << "dfactor " << this->m_d_factor << std::endl;
|
<< "skinf " << this->skinFactor() << '\n'
|
||||||
ss << "Ke " << this->m_Ke << std::endl;
|
<< "dfactor " << this->dFactor() << '\n'
|
||||||
ss << "kh " << this->m_Kh << std::endl;
|
<< "Ke " << this->Ke() << '\n'
|
||||||
ss << "sat_tableId " << this->sat_tableId << std::endl;
|
<< "kh " << this->Kh() << '\n'
|
||||||
ss << "open_state " << Connection::State2String(this->open_state) << std::endl;
|
<< "sat_tableId " << this->sat_tableId << '\n'
|
||||||
ss << "direction " << Connection::Direction2String(this->direction) << std::endl;
|
<< "open_state " << Connection::State2String(this->open_state) << '\n'
|
||||||
ss << "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n';
|
<< "direction " << Connection::Direction2String(this->direction) << '\n'
|
||||||
ss << "segment_nr " << this->segment_number << std::endl;
|
<< "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n'
|
||||||
ss << "center_depth " << this->center_depth << std::endl;
|
<< "segment_nr " << this->segment_number << '\n'
|
||||||
ss << "sort_value" << this->m_sort_value<< std::endl;
|
<< "center_depth " << this->center_depth << '\n'
|
||||||
|
<< "sort_value" << this->m_sort_value<< '\n';
|
||||||
|
|
||||||
if (this->m_injmult.has_value()) {
|
if (this->m_injmult.has_value()) {
|
||||||
ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << std::endl;
|
ss << "INJMULT " << InjMult::InjMultToString(this->m_injmult.value()) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->m_filter_cake.has_value()) {
|
if (this->m_filter_cake.has_value()) {
|
||||||
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << std::endl;
|
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
|
||||||
|
|
||||||
bool Connection::operator==( const Connection& rhs ) const {
|
|
||||||
return this->ijk == rhs.ijk
|
|
||||||
&& this->m_global_index == rhs.m_global_index
|
|
||||||
&& this->m_complnum == rhs.m_complnum
|
|
||||||
&& this->m_CF == rhs.m_CF
|
|
||||||
&& this->m_rw == rhs.m_rw
|
|
||||||
&& this->m_r0 == rhs.m_r0
|
|
||||||
&& this->m_re == rhs.m_re
|
|
||||||
&& this->m_connection_length == rhs.m_connection_length
|
|
||||||
&& this->m_skin_factor == rhs.m_skin_factor
|
|
||||||
&& this->m_d_factor == rhs.m_d_factor
|
|
||||||
&& this->m_Ke == rhs.m_Ke
|
|
||||||
&& this->m_injmult == rhs.m_injmult
|
|
||||||
&& this->m_Kh == rhs.m_Kh
|
|
||||||
&& this->sat_tableId == rhs.sat_tableId
|
|
||||||
&& this->open_state == rhs.open_state
|
|
||||||
&& this->direction == rhs.direction
|
|
||||||
&& this->segment_number == rhs.segment_number
|
|
||||||
&& this->center_depth == rhs.center_depth
|
|
||||||
&& this->m_sort_value == rhs.m_sort_value
|
|
||||||
&& this->m_subject_to_welpi == rhs.m_subject_to_welpi
|
|
||||||
&& this->m_filter_cake == rhs.m_filter_cake;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::operator!=( const Connection& rhs ) const {
|
bool Connection::operator==(const Connection& that) const
|
||||||
return !( *this == rhs );
|
{
|
||||||
|
return (this->direction == that.direction)
|
||||||
|
&& (this->open_state == that.open_state)
|
||||||
|
&& (this->sat_tableId == that.sat_tableId)
|
||||||
|
&& (this->m_complnum == that.m_complnum)
|
||||||
|
&& (this->m_ctfkind == that.m_ctfkind)
|
||||||
|
&& (this->m_global_index == that.m_global_index)
|
||||||
|
&& (this->m_sort_value == that.m_sort_value)
|
||||||
|
&& (this->m_defaultSatTabId == that.m_defaultSatTabId)
|
||||||
|
&& (this->segment_number == that.segment_number)
|
||||||
|
&& (this->m_subject_to_welpi == that.m_subject_to_welpi)
|
||||||
|
&& (this->ijk == that.ijk)
|
||||||
|
&& (this->m_injmult == that.m_injmult)
|
||||||
|
&& (this->center_depth == that.center_depth)
|
||||||
|
&& (this->m_perf_range == that.m_perf_range)
|
||||||
|
&& (this->ctf_properties_ == that.ctf_properties_)
|
||||||
|
&& (this->m_filter_cake == that.m_filter_cake)
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string Connection::State2String(State enumValue)
|
||||||
const std::string Connection::State2String( State enumValue ) {
|
{
|
||||||
switch( enumValue ) {
|
switch (enumValue) {
|
||||||
case State::OPEN:
|
case State::OPEN:
|
||||||
return "OPEN";
|
return "OPEN";
|
||||||
|
|
||||||
case State::AUTO:
|
case State::AUTO:
|
||||||
return "AUTO";
|
return "AUTO";
|
||||||
|
|
||||||
case State::SHUT:
|
case State::SHUT:
|
||||||
return "SHUT";
|
return "SHUT";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Unhandled enum value");
|
throw std::invalid_argument {
|
||||||
|
"Unhandled Connection::State value " +
|
||||||
|
std::to_string(static_cast<int>(enumValue))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::State
|
||||||
Connection::State Connection::StateFromString( const std::string& stringValue ) {
|
Connection::StateFromString(std::string_view stringValue)
|
||||||
|
{
|
||||||
if (stringValue == "OPEN")
|
if (stringValue == "OPEN")
|
||||||
return State::OPEN;
|
return State::OPEN;
|
||||||
else if (stringValue == "SHUT")
|
|
||||||
return State::SHUT;
|
|
||||||
else if (stringValue == "STOP")
|
|
||||||
return State::SHUT;
|
|
||||||
else if (stringValue == "AUTO")
|
|
||||||
return State::AUTO;
|
|
||||||
else
|
|
||||||
throw std::invalid_argument("Unknown enum state string: " + stringValue );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (stringValue == "SHUT")
|
||||||
|
return State::SHUT;
|
||||||
|
|
||||||
|
if (stringValue == "STOP")
|
||||||
|
return State::SHUT;
|
||||||
|
|
||||||
|
if (stringValue == "AUTO")
|
||||||
|
return State::AUTO;
|
||||||
|
|
||||||
|
throw std::invalid_argument {
|
||||||
|
"Unknown Connection::State string: " + std::string { stringValue }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Connection::Direction2String(const Direction enumValue)
|
std::string Connection::Direction2String(const Direction enumValue)
|
||||||
@ -434,8 +516,7 @@ std::string Connection::Direction2String(const Direction enumValue)
|
|||||||
return stringValue;
|
return stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::Direction Connection::DirectionFromString(std::string_view s)
|
||||||
Connection::Direction Connection::DirectionFromString(const std::string& s )
|
|
||||||
{
|
{
|
||||||
Direction direction;
|
Direction direction;
|
||||||
|
|
||||||
@ -443,47 +524,61 @@ Connection::Direction Connection::DirectionFromString(const std::string& s )
|
|||||||
else if ((s == "Y") || (s == "y")) { direction = Direction::Y; }
|
else if ((s == "Y") || (s == "y")) { direction = Direction::Y; }
|
||||||
else if ((s == "Z") || (s == "z")) { direction = Direction::Z; }
|
else if ((s == "Z") || (s == "z")) { direction = Direction::Z; }
|
||||||
else {
|
else {
|
||||||
std::string msg = "Unsupported completion direction " + s;
|
throw std::invalid_argument {
|
||||||
throw std::invalid_argument(msg);
|
"Unsupported completion direction "
|
||||||
|
+ std::string { s }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string Connection::Order2String( Order enumValue ) {
|
std::string Connection::Order2String(Order enumValue)
|
||||||
switch( enumValue ) {
|
{
|
||||||
|
switch (enumValue) {
|
||||||
case Order::DEPTH:
|
case Order::DEPTH:
|
||||||
return "DEPTH";
|
return "DEPTH";
|
||||||
|
|
||||||
case Order::INPUT:
|
case Order::INPUT:
|
||||||
return "INPUT";
|
return "INPUT";
|
||||||
|
|
||||||
case Order::TRACK:
|
case Order::TRACK:
|
||||||
return "TRACK";
|
return "TRACK";
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw std::invalid_argument("Unhandled enum value");
|
throw std::invalid_argument {
|
||||||
|
"Unhandled Connection::Order value " +
|
||||||
|
std::to_string(static_cast<int>(enumValue))
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connection::Order Connection::OrderFromString(std::string_view stringValue)
|
||||||
Connection::Order Connection::OrderFromString(const std::string& stringValue ) {
|
{
|
||||||
if (stringValue == "DEPTH")
|
if (stringValue == "DEPTH")
|
||||||
return Order::DEPTH;
|
return Order::DEPTH;
|
||||||
else if (stringValue == "INPUT")
|
|
||||||
|
if (stringValue == "INPUT")
|
||||||
return Order::INPUT;
|
return Order::INPUT;
|
||||||
else if (stringValue == "TRACK")
|
|
||||||
|
if (stringValue == "TRACK")
|
||||||
return Order::TRACK;
|
return Order::TRACK;
|
||||||
else
|
|
||||||
throw std::invalid_argument("Unknown enum state string: " + stringValue );
|
throw std::invalid_argument {
|
||||||
|
"Unknown Connection::Order string: " + std::string { stringValue }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
||||||
{
|
{
|
||||||
switch (ctf_kind) {
|
switch (ctf_kind) {
|
||||||
case CTFKind::DeckValue:
|
case CTFKind::DeckValue:
|
||||||
return "DeckValue";
|
return "DeckValue";
|
||||||
|
|
||||||
case CTFKind::Defaulted:
|
case CTFKind::Defaulted:
|
||||||
return "Defaulted";
|
return "Defaulted";
|
||||||
}
|
}
|
||||||
|
|
||||||
throw std::invalid_argument {
|
throw std::invalid_argument {
|
||||||
@ -492,58 +587,62 @@ std::string Connection::CTFKindToString(const CTFKind ctf_kind)
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Connection::CTFKind Connection::kind() const {
|
Connection::CTFKind Connection::kind() const
|
||||||
|
{
|
||||||
return m_ctfkind;
|
return m_ctfkind;
|
||||||
}
|
}
|
||||||
|
|
||||||
const InjMult& Connection::injmult() const {
|
const InjMult& Connection::injmult() const
|
||||||
|
{
|
||||||
assert(this->activeInjMult());
|
assert(this->activeInjMult());
|
||||||
return m_injmult.value();
|
return m_injmult.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::activeInjMult() const {
|
bool Connection::activeInjMult() const
|
||||||
|
{
|
||||||
return this->m_injmult.has_value();
|
return this->m_injmult.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::setInjMult(const InjMult& inj_mult) {
|
void Connection::setInjMult(const InjMult& inj_mult)
|
||||||
|
{
|
||||||
m_injmult = inj_mult;
|
m_injmult = inj_mult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::setFilterCake(const FilterCake& filter_cake)
|
||||||
void Connection::setFilterCake(const FilterCake& filter_cake) {
|
{
|
||||||
this->m_filter_cake = filter_cake;
|
this->m_filter_cake = filter_cake;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Connection::filterCakeActive() const {
|
bool Connection::filterCakeActive() const
|
||||||
|
{
|
||||||
return this->m_filter_cake.has_value();
|
return this->m_filter_cake.has_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
const FilterCake& Connection::getFilterCake() const {
|
const FilterCake& Connection::getFilterCake() const
|
||||||
assert(this->filterCakeActive());
|
{
|
||||||
return this->m_filter_cake.value();
|
assert(this->filterCakeActive());
|
||||||
|
return this->m_filter_cake.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Connection::getFilterCakeRadius() const
|
||||||
double Connection::getFilterCakeRadius() const {
|
{
|
||||||
if (this->getFilterCake().radius.has_value()) {
|
if (const auto& radius = this->getFilterCake().radius; radius.has_value()) {
|
||||||
return this->getFilterCake().radius.value();
|
return *radius;
|
||||||
} else {
|
}
|
||||||
return this->m_rw;
|
else {
|
||||||
|
return this->rw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double Connection::getFilterCakeArea() const
|
||||||
double Connection::getFilterCakeArea() const {
|
{
|
||||||
if (this->getFilterCake().flow_area.has_value()) {
|
if (const auto& flow_area = this->getFilterCake().flow_area; flow_area.has_value()) {
|
||||||
return this->getFilterCake().flow_area.value();
|
return *flow_area;
|
||||||
} else {
|
}
|
||||||
const double radius = this->getFilterCakeRadius();
|
else {
|
||||||
const double length = this->m_connection_length;
|
constexpr double two_pi = 2 * 3.14159265358979323846264;
|
||||||
constexpr double pi = 3.14159265;
|
return two_pi * this->getFilterCakeRadius() * this->connectionLength();
|
||||||
return 2. * pi * radius * length;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // end of namespace Opm
|
} // end of namespace Opm
|
||||||
|
@ -40,13 +40,12 @@
|
|||||||
#include <opm/input/eclipse/Schedule/Well/WVFPDP.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WVFPDP.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/OpmInputError.hpp>
|
#include <opm/common/utility/OpmInputError.hpp>
|
||||||
#include <opm/common/utility/shmatch.hpp>
|
#include <opm/common/utility/shmatch.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/ParserKeywords/C.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParserKeywords/S.hpp>
|
#include <opm/input/eclipse/Parser/ParserKeywords/S.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
#include <opm/input/eclipse/Parser/ParserKeywords/W.hpp>
|
||||||
|
|
||||||
@ -1300,42 +1299,60 @@ bool Well::handleWELOPENConnections(const DeckRecord& record, Connection::State
|
|||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Well::handleCSKINConnections(const DeckRecord& record) {
|
bool Well::handleCSKIN(const DeckRecord& record,
|
||||||
// Lambda expression to check if record coordinates match connection coordinates
|
const KeywordLocation& location)
|
||||||
auto match = [=]( const Connection &c) -> bool {
|
{
|
||||||
if (!match_eq(c.getI(), record, "I" , -1)) return false;
|
using Kw = ParserKeywords::CSKIN;
|
||||||
if (!match_eq(c.getJ(), record, "J" , -1)) return false;
|
|
||||||
if (!match_ge(c.getK(), record, "K_UPPER", -1)) return false;
|
|
||||||
if (!match_le(c.getK(), record, "K_LOWER", -1)) return false;
|
|
||||||
|
|
||||||
return true;
|
auto need_skin_adjustment = [&record](const Connection &c) {
|
||||||
|
const auto value_shift = -1;
|
||||||
|
|
||||||
|
return match_eq(c.getI(), record, Kw::I::itemName, value_shift)
|
||||||
|
&& match_eq(c.getJ(), record, Kw::J::itemName, value_shift)
|
||||||
|
&& match_ge(c.getK(), record, Kw::K_UPPER::itemName, value_shift)
|
||||||
|
&& match_le(c.getK(), record, Kw::K_LOWER::itemName, value_shift);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generate a new connection which will be updated with new connection skin factor
|
// New connection set which will be updated with new connection level
|
||||||
auto new_connections = std::make_shared<WellConnections>(this->connections->ordering(), this->headI, this->headJ);
|
// skin factors.
|
||||||
|
auto new_connections = std::make_shared<WellConnections>
|
||||||
|
(this->connections->ordering(), this->headI, this->headJ);
|
||||||
|
|
||||||
// Update skin factor
|
const auto skin_factor = record.getItem<Kw::CONNECTION_SKIN_FACTOR>().getSIDouble(0);
|
||||||
double skin_factor = record.getItem("CONNECTION_SKIN_FACTOR").get<double>(0);
|
for (const auto& connection : *this->connections) {
|
||||||
const double angle = 6.2831853071795864769252867665590057683943387987502116419498;
|
if (! need_skin_adjustment(connection)) {
|
||||||
for (auto c : *this->connections) {
|
// No CSKIN adjustment needed here. Include connection as-is
|
||||||
if (match(c)) {
|
// into new connection set.
|
||||||
// Check for potential negative new CF
|
new_connections->add(connection);
|
||||||
if ((std::log(c.r0() / std::min(c.rw(), c.r0())) + skin_factor) < 0.0) {
|
continue;
|
||||||
throw std::runtime_error("Negative connection transmissibility factor produced by CSKIN for well "
|
|
||||||
+ name());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate new connection transmissibility factor
|
|
||||||
double CF = angle * c.Kh() / (std::log(c.r0() / std::min(c.rw(), c.r0())) + skin_factor);
|
|
||||||
|
|
||||||
// Apply last known WPIMULT (defaulted to 1.0)
|
|
||||||
CF *= c.wpimult();
|
|
||||||
|
|
||||||
// Set skin factor and connection factor
|
|
||||||
c.setSkinFactor(skin_factor);
|
|
||||||
c.setCF(CF);
|
|
||||||
}
|
}
|
||||||
new_connections->add(c);
|
|
||||||
|
// If we get here, we must make the connection's skin factor be
|
||||||
|
// 'skin_factor'.
|
||||||
|
//
|
||||||
|
// First guard against this adjustment making the CTF go negative,
|
||||||
|
// typically because the 'skin_factor' value is large and negative
|
||||||
|
// itself.
|
||||||
|
if (const auto& ctf_props = connection.ctfProperties();
|
||||||
|
ctf_props.peaceman_denom + skin_factor - ctf_props.skin_factor < 0.0)
|
||||||
|
{
|
||||||
|
throw OpmInputError {
|
||||||
|
fmt::format("Negative connection transmissibility "
|
||||||
|
"factor generated by skin factor {} "
|
||||||
|
"in connection ({},{},{}) for well {}.",
|
||||||
|
skin_factor,
|
||||||
|
connection.getI() + 1,
|
||||||
|
connection.getJ() + 1,
|
||||||
|
connection.getK() + 1,
|
||||||
|
this->name()),
|
||||||
|
location
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto connection_copy = connection;
|
||||||
|
connection_copy.setSkinFactor(skin_factor);
|
||||||
|
|
||||||
|
new_connections->add(connection_copy);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
@ -1390,6 +1407,7 @@ bool Well::handleWPIMULT(const DeckRecord& record) {
|
|||||||
|
|
||||||
new_connections->add(c);
|
new_connections->add(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this->updateConnections(std::move(new_connections), false);
|
return this->updateConnections(std::move(new_connections), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,32 +17,38 @@
|
|||||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <ostream>
|
|
||||||
|
|
||||||
#define BOOST_TEST_MODULE CompletionTests
|
#define BOOST_TEST_MODULE CompletionTests
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/ActiveGridCells.hpp>
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
#include <opm/common/utility/ActiveGridCells.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
|
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||||
|
|
||||||
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
#include <opm/common/OpmLog/KeywordLocation.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Units/Units.hpp>
|
#include <opm/input/eclipse/Units/Units.hpp>
|
||||||
|
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
|
|
||||||
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
double cp_rm3_per_db()
|
double cp_rm3_per_db()
|
||||||
@ -51,20 +57,31 @@ namespace {
|
|||||||
/ (Opm::unit::day * Opm::unit::barsa);
|
/ (Opm::unit::day * Opm::unit::barsa);
|
||||||
}
|
}
|
||||||
|
|
||||||
Opm::WellConnections loadCOMPDAT(const std::string& compdat_keyword) {
|
Opm::WellConnections
|
||||||
Opm::EclipseGrid grid(10,10,10);
|
loadCOMPDAT(const std::string& compdat_keyword)
|
||||||
Opm::TableManager tables;
|
{
|
||||||
Opm::Parser parser;
|
Opm::WellConnections connections {
|
||||||
const auto deck = parser.parseString(compdat_keyword);
|
Opm::Connection::Order::TRACK, 10, 10
|
||||||
Opm::FieldPropsManager field_props(deck, Opm::Phases{true, true, true}, grid, Opm::TableManager());
|
};
|
||||||
const auto& keyword = deck["COMPDAT"][0];
|
|
||||||
Opm::WellConnections connections(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::CompletedCells cells(grid);
|
|
||||||
for (const auto& rec : keyword)
|
|
||||||
connections.loadCOMPDAT(rec, Opm::ScheduleGrid(grid, field_props, cells), "WELL", {});
|
|
||||||
|
|
||||||
return connections;
|
const auto deck = Opm::Parser{}.parseString(compdat_keyword);
|
||||||
}
|
const auto loc = Opm::KeywordLocation{};
|
||||||
|
|
||||||
|
const Opm::EclipseGrid grid { 10, 10, 10 };
|
||||||
|
const Opm::FieldPropsManager field_props {
|
||||||
|
deck, Opm::Phases{true, true, true}, grid, Opm::TableManager{}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Must be mutable.
|
||||||
|
Opm::CompletedCells completed_cells(grid);
|
||||||
|
const auto sg = Opm::ScheduleGrid { grid, field_props, completed_cells };
|
||||||
|
|
||||||
|
for (const auto& rec : deck["COMPDAT"][0]) {
|
||||||
|
connections.loadCOMPDAT(rec, sg, "WELL", loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
return connections;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Opm {
|
namespace Opm {
|
||||||
@ -94,12 +111,22 @@ BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
|
const auto depth = 0.0;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion2( 10,10,11, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||||
BOOST_CHECK_MESSAGE( !completionSet.empty(), "Non-empty completion set must not be empty" );
|
BOOST_CHECK_MESSAGE( !completionSet.empty(), "Non-empty completion set must not be empty" );
|
||||||
@ -111,11 +138,21 @@ BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows) {
|
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0,true);
|
const auto depth = 0.0;
|
||||||
Opm::Connection completion2( 10,10,11, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0,true);
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 1,1);
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||||
@ -148,15 +185,23 @@ BOOST_AUTO_TEST_CASE(Compdat_Direction) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
BOOST_AUTO_TEST_CASE(AddCompletionCopy)
|
||||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 10,10);
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
|
const auto depth = 0.0;
|
||||||
|
|
||||||
Opm::Connection completion1( 10,10,10, 100, 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
Opm::Connection completion2( 10,10,11, 101, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion3( 10,10,12, 102, 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 10,10,10, 100, 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 10,10,11, 101, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion3 = Opm::Connection { 10,10,12, 102, 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
|
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 10,10);
|
||||||
completionSet.add( completion1 );
|
completionSet.add( completion1 );
|
||||||
completionSet.add( completion2 );
|
completionSet.add( completion2 );
|
||||||
completionSet.add( completion3 );
|
completionSet.add( completion3 );
|
||||||
@ -171,31 +216,43 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
BOOST_AUTO_TEST_CASE(ActiveCompletions)
|
||||||
Opm::EclipseGrid grid(10,20,20);
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir = Opm::Connection::Direction::Z;
|
||||||
const auto kind = Opm::Connection::CTFKind::Defaulted;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections completions(Opm::Connection::Order::TRACK, 10,10);
|
const auto depth = 0.0;
|
||||||
Opm::Connection completion1( 0,0,0, grid.getGlobalIndex(0,0,0), 1, 0.0, Opm::Connection::State::OPEN , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion2( 0,0,1, grid.getGlobalIndex(0,0,1), 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
Opm::Connection completion3( 0,0,2, grid.getGlobalIndex(0,0,2), 1, 0.0, Opm::Connection::State::SHUT , 99.88, 355.113, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true);
|
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 99.88;
|
||||||
|
ctf_props.Kh = 355.113;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::EclipseGrid grid { 10, 20, 20 };
|
||||||
|
|
||||||
|
const auto completion1 = Opm::Connection { 0,0,0, grid.getGlobalIndex(0,0,0), 1, Opm::Connection::State::OPEN, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion2 = Opm::Connection { 0,0,1, grid.getGlobalIndex(0,0,1), 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
const auto completion3 = Opm::Connection { 0,0,2, grid.getGlobalIndex(0,0,2), 1, Opm::Connection::State::SHUT, dir, kind, 0, depth, ctf_props, 0, true };
|
||||||
|
|
||||||
|
Opm::WellConnections completions(Opm::Connection::Order::TRACK, 10,10);
|
||||||
completions.add( completion1 );
|
completions.add( completion1 );
|
||||||
completions.add( completion2 );
|
completions.add( completion2 );
|
||||||
completions.add( completion3 );
|
completions.add( completion3 );
|
||||||
|
|
||||||
std::vector<int> actnum(grid.getCartesianSize(), 1);
|
std::vector<int> actnum(grid.getCartesianSize(), 1);
|
||||||
actnum[0] = 0;
|
actnum[0] = 0;
|
||||||
grid.resetACTNUM( actnum);
|
grid.resetACTNUM(actnum);
|
||||||
|
|
||||||
Opm::WellConnections active_completions(completions, grid);
|
const Opm::WellConnections active_completions(completions, grid);
|
||||||
BOOST_CHECK_EQUAL( active_completions.size() , 2U);
|
BOOST_CHECK_EQUAL( active_completions.size() , 2U);
|
||||||
BOOST_CHECK_EQUAL( completion2, active_completions.get(0));
|
BOOST_CHECK_EQUAL( completion2, active_completions.get(0));
|
||||||
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST) {
|
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST)
|
||||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
{
|
||||||
|
const Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
||||||
|
|
||||||
{
|
{
|
||||||
const std::string deck = R"(GRID
|
const std::string deck = R"(GRID
|
||||||
|
|
||||||
@ -212,7 +269,8 @@ COMPDAT
|
|||||||
-- CF Diam Kh Skin Df
|
-- CF Diam Kh Skin Df
|
||||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 /
|
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Z' 21.925 /
|
||||||
/)";
|
/)";
|
||||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
|
||||||
|
const Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||||
const auto& conn0 = connections[0];
|
const auto& conn0 = connections[0];
|
||||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
||||||
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 107.872));
|
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 107.872));
|
||||||
@ -236,7 +294,8 @@ COMPDAT
|
|||||||
-- CF Diam Kh Skin Df
|
-- CF Diam Kh Skin Df
|
||||||
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 /
|
'WELL' 1 1 1 1 'OPEN' 1* 1.168 0.311 0 1* 1* 'Z' 21.925 /
|
||||||
/)";
|
/)";
|
||||||
Opm::WellConnections connections = loadCOMPDAT(deck);
|
|
||||||
|
const Opm::WellConnections connections = loadCOMPDAT(deck);
|
||||||
const auto& conn0 = connections[0];
|
const auto& conn0 = connections[0];
|
||||||
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
BOOST_CHECK_EQUAL(conn0.CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 1.168));
|
||||||
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 0.10 * 1.0));
|
BOOST_CHECK_EQUAL(conn0.Kh(), units.to_si(Opm::UnitSystem::measure::effective_Kh, 0.10 * 1.0));
|
||||||
@ -460,20 +519,16 @@ END
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Reset CF -- simulating COMPDAT record (inactive cell)
|
// Reset CF -- simulating COMPDAT record (inactive cell)
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = 50.0*cp_rm3_per_db();
|
||||||
|
ctf_props.Kh = 0.123;
|
||||||
|
ctf_props.rw = 0.234;
|
||||||
|
ctf_props.r0 = 0.157;
|
||||||
|
|
||||||
connP.addConnection(9, 9, 1, // 10, 10, 2
|
connP.addConnection(9, 9, 1, // 10, 10, 2
|
||||||
199,
|
199,
|
||||||
2015.0,
|
Opm::Connection::State::OPEN,
|
||||||
Opm::Connection::State::OPEN,
|
2015.0, ctf_props, 1);
|
||||||
50.0*cp_rm3_per_db(),
|
|
||||||
0.123,
|
|
||||||
0.234,
|
|
||||||
0.157,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
1);
|
|
||||||
|
|
||||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{3});
|
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{3});
|
||||||
|
|
||||||
@ -506,19 +561,9 @@ END
|
|||||||
|
|
||||||
// Reset CF -- simulating COMPDAT record (active cell)
|
// Reset CF -- simulating COMPDAT record (active cell)
|
||||||
connP.addConnection(8, 9, 1, // 10, 10, 2
|
connP.addConnection(8, 9, 1, // 10, 10, 2
|
||||||
198,
|
198,
|
||||||
2015.0,
|
Opm::Connection::State::OPEN,
|
||||||
Opm::Connection::State::OPEN,
|
2015.0, ctf_props, 1);
|
||||||
50.0*cp_rm3_per_db(),
|
|
||||||
0.123,
|
|
||||||
0.234,
|
|
||||||
0.157,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
0.0,
|
|
||||||
1);
|
|
||||||
|
|
||||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{4});
|
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{4});
|
||||||
|
|
||||||
|
@ -55,20 +55,32 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(AICDWellTest) {
|
BOOST_AUTO_TEST_CASE(AICDWellTest)
|
||||||
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25.0, 2500.0);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0,grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1,grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2,grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1,grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1,grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1,grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1,grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -212,23 +224,33 @@ WSEGAICD
|
|||||||
const double center_depth_connection7 = connection7.depth();
|
const double center_depth_connection7 = connection7.depth();
|
||||||
BOOST_CHECK_EQUAL(segment_number_connection7, 8);
|
BOOST_CHECK_EQUAL(segment_number_connection7, 8);
|
||||||
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
|
BOOST_AUTO_TEST_CASE(MultisegmentWellTest)
|
||||||
|
{
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25.0, 2500.0);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0,grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1,grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2,grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1,grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1,grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1,grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1,grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -383,19 +405,32 @@ WSEGSICD
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS) {
|
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25., 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -452,19 +487,32 @@ BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS) {
|
|||||||
BOOST_CHECK_NO_THROW(Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard));
|
BOOST_CHECK_NO_THROW(Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS) {
|
BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1),1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
@ -521,19 +569,31 @@ BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS) {
|
|||||||
BOOST_CHECK_NO_THROW( Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard) );
|
BOOST_CHECK_NO_THROW( Opm::Compsegs::processCOMPSEGS(compsegs, connection_set, segment_set, Opm::ScheduleGrid(grid, fp, cells), parseContext, errorGuard) );
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(testwsegvalv) {
|
BOOST_AUTO_TEST_CASE(testwsegvalv)
|
||||||
auto dir = Opm::Connection::Direction::Z;
|
{
|
||||||
|
const auto dir_z = Opm::Connection::Direction::Z;
|
||||||
|
const auto dir_x = Opm::Connection::Direction::X;
|
||||||
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
const auto kind = Opm::Connection::CTFKind::DeckValue;
|
||||||
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||||
Opm::EclipseGrid grid(20,20,20, 1., 1., 25., 2500.);
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, dir, kind, 0, true) );
|
|
||||||
|
|
||||||
connection_set.add(Opm::Connection( 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto depth = 0.0;
|
||||||
connection_set.add(Opm::Connection( 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
const auto state = Opm::Connection::State::OPEN;
|
||||||
connection_set.add(Opm::Connection( 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
|
||||||
connection_set.add(Opm::Connection( 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, 0.0, Opm::Connection::State::OPEN , 200, 17.29, 0.25, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0, Opm::Connection::Direction::X, kind, 0, true) );
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
ctf_props.CF = 200.0;
|
||||||
|
ctf_props.Kh = 17.29;
|
||||||
|
ctf_props.rw = 0.25;
|
||||||
|
|
||||||
|
Opm::WellConnections connection_set(Opm::Connection::Order::TRACK, 10,10);
|
||||||
|
connection_set.add({ 19, 0, 0, grid.getGlobalIndex(19,0,0), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 1, grid.getGlobalIndex(19,0,1), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 19, 0, 2, grid.getGlobalIndex(19,0,2), 1, state, dir_z, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
|
connection_set.add({ 18, 0, 1, grid.getGlobalIndex(18,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 17, 0, 1, grid.getGlobalIndex(17,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 16, 0, 1, grid.getGlobalIndex(16,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
connection_set.add({ 15, 0, 1, grid.getGlobalIndex(15,0,1), 1, state, dir_x, kind, 0, depth, ctf_props, 0, true });
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
BOOST_CHECK_EQUAL( 7U , connection_set.size() );
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -22,192 +22,219 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
||||||
|
|
||||||
using namespace Opm;
|
using namespace Opm;
|
||||||
|
|
||||||
static Deck createDeckWithOutSolvent() {
|
namespace {
|
||||||
Opm::Parser parser;
|
|
||||||
std::string input =
|
|
||||||
"GRID\n"
|
|
||||||
"PERMX\n"
|
|
||||||
" 1000*0.25/\n"
|
|
||||||
"COPY\n"
|
|
||||||
" PERMX PERMY /\n"
|
|
||||||
" PERMX PERMZ /\n"
|
|
||||||
"/\n"
|
|
||||||
"SCHEDULE\n"
|
|
||||||
"WELSPECS\n"
|
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
Deck createDeckWithOutSolvent()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithGasInjector() {
|
Deck createDeckWithGasInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 1 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 1 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithDynamicWSOLVENT() {
|
Deck createDeckWithDynamicWSOLVENT()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"START -- 0 \n"
|
START -- 0
|
||||||
"1 JAN 2000 / \n"
|
1 JAN 2000 /
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
|
||||||
"DATES -- 2\n"
|
|
||||||
" 1 MAY 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 1 / \n "
|
|
||||||
"/\n"
|
|
||||||
"DATES -- 3,4\n"
|
|
||||||
" 1 JUL 2000 / \n"
|
|
||||||
" 1 AUG 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WSOLVENT\n"
|
|
||||||
" 'W_1' 0 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
DATES -- 2
|
||||||
|
1 MAY 2000 /
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 1 /
|
||||||
|
/
|
||||||
|
DATES -- 3,4
|
||||||
|
1 JUL 2000 /
|
||||||
|
1 AUG 2000 /
|
||||||
|
/
|
||||||
|
WSOLVENT
|
||||||
|
'W_1' 0 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithOilInjector() {
|
Deck createDeckWithOilInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
SCHEDULE
|
||||||
"WELSPECS\n"
|
WELSPECS
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
"/\n"
|
/
|
||||||
"COMPDAT\n"
|
COMPDAT
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"/\n"
|
/
|
||||||
"WCONINJE\n"
|
WCONINJE
|
||||||
" 'W_1' 'OIL' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
'W_1' 'OIL' 'OPEN' 'BHP' 1 2 3/
|
||||||
"WSOLVENT\n"
|
/
|
||||||
" 'W_1' 1 / \n "
|
WSOLVENT
|
||||||
"/\n";
|
'W_1' 1 /
|
||||||
|
/
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithWaterInjector() {
|
Deck createDeckWithWaterInjector()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
SCHEDULE
|
||||||
"WELSPECS\n"
|
WELSPECS
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
'W_1' 'OP' 2 2 1* \'OIL\' 7* /
|
||||||
"/\n"
|
/
|
||||||
"COMPDAT\n"
|
COMPDAT
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"/\n"
|
/
|
||||||
"WCONINJE\n"
|
WCONINJE
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
"WSOLVENT\n"
|
/
|
||||||
" 'W_1' 1 / \n "
|
WSOLVENT
|
||||||
"/\n";
|
'W_1' 1 /
|
||||||
|
/
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
BOOST_AUTO_TEST_CASE(TestNoSolvent) {
|
|
||||||
auto deck = createDeckWithOutSolvent();
|
} // Anonymous namespace
|
||||||
auto python = std::make_shared<Python>();
|
|
||||||
EclipseGrid grid(10,10,10);
|
BOOST_AUTO_TEST_CASE(TestNoSolvent)
|
||||||
TableManager table ( deck );
|
{
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const auto deck = createDeckWithOutSolvent();
|
||||||
Runspec runspec(deck);
|
const EclipseGrid grid(10,10,10);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec(deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(!deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(!deck.hasKeyword("WSOLVENT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestGasInjector) {
|
BOOST_AUTO_TEST_CASE(TestGasInjector) {
|
||||||
auto deck = createDeckWithGasInjector();
|
const auto deck = createDeckWithGasInjector();
|
||||||
auto python = std::make_shared<Python>();
|
const EclipseGrid grid(10,10,10);
|
||||||
EclipseGrid grid(10,10,10);
|
const TableManager table (deck);
|
||||||
TableManager table ( deck );
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const Runspec runspec(deck);
|
||||||
Runspec runspec(deck);
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT) {
|
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT)
|
||||||
auto deck = createDeckWithDynamicWSOLVENT();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithDynamicWSOLVENT();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
BOOST_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||||
|
|
||||||
const auto& keyword = deck["WSOLVENT"].back();
|
const auto& keyword = deck["WSOLVENT"].back();
|
||||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||||
|
|
||||||
const auto& record = keyword.getRecord(0);
|
const auto& record = keyword.getRecord(0);
|
||||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||||
BOOST_CHECK_EQUAL(well_name, "W_1");
|
BOOST_CHECK_EQUAL(well_name, "W_1");
|
||||||
@ -217,22 +244,24 @@ BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT) {
|
|||||||
BOOST_CHECK_EQUAL(schedule.getWell("W_1", 3).getSolventFraction(),0);
|
BOOST_CHECK_EQUAL(schedule.getWell("W_1", 3).getSolventFraction(),0);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestOilInjector) {
|
BOOST_AUTO_TEST_CASE(TestOilInjector)
|
||||||
auto deck = createDeckWithOilInjector();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithOilInjector();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
BOOST_CHECK_THROW (Schedule(deck , grid , fp, runspec, python), std::exception);
|
|
||||||
|
BOOST_CHECK_THROW (Schedule(deck, grid, fp, runspec, std::make_shared<Python>()), std::exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestWaterInjector) {
|
BOOST_AUTO_TEST_CASE(TestWaterInjector)
|
||||||
auto deck = createDeckWithWaterInjector();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithWaterInjector();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table ( deck );
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec(deck);
|
const Runspec runspec(deck);
|
||||||
BOOST_CHECK_THROW (Schedule(deck, grid , fp, runspec, python), std::exception);
|
|
||||||
|
BOOST_CHECK_THROW (Schedule(deck, grid , fp, runspec, std::make_shared<Python>()), std::exception);
|
||||||
}
|
}
|
||||||
|
@ -22,141 +22,166 @@
|
|||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
#include <opm/common/utility/OpmInputError.hpp>
|
#include <opm/common/utility/OpmInputError.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Python/Python.hpp>
|
#include <opm/input/eclipse/Python/Python.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||||
#include <opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp>
|
#include <opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Deck/Deck.hpp>
|
#include <opm/input/eclipse/Deck/Deck.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
#include <opm/input/eclipse/Deck/DeckItem.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
#include <opm/input/eclipse/Deck/DeckKeyword.hpp>
|
||||||
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
#include <opm/input/eclipse/Deck/DeckRecord.hpp>
|
||||||
|
|
||||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||||
|
|
||||||
using namespace Opm;
|
using namespace Opm;
|
||||||
|
|
||||||
static Deck createDeckWithOutTracer() {
|
namespace {
|
||||||
Opm::Parser parser;
|
|
||||||
std::string input =
|
|
||||||
"GRID\n"
|
|
||||||
"PERMX\n"
|
|
||||||
" 1000*0.25/\n"
|
|
||||||
"COPY\n"
|
|
||||||
" PERMX PERMY /\n"
|
|
||||||
" PERMX PERMZ /\n"
|
|
||||||
"/\n"
|
|
||||||
"SCHEDULE\n"
|
|
||||||
"WELSPECS\n"
|
|
||||||
" 'W_1' 'OP' 2 2 1* \'OIL\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONINJE\n"
|
|
||||||
" 'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/\n/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
Deck createDeckWithOutTracer()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONINJE
|
||||||
|
'W_1' 'WATER' 'OPEN' 'BHP' 1 2 3/
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Deck createDeckWithDynamicWTRACER()
|
||||||
|
{
|
||||||
|
return Parser{}.parseString(R"(
|
||||||
|
START -- 0
|
||||||
|
1 JAN 2000 /
|
||||||
|
GRID
|
||||||
|
PERMX
|
||||||
|
1000*0.25/
|
||||||
|
COPY
|
||||||
|
PERMX PERMY /
|
||||||
|
PERMX PERMZ /
|
||||||
|
/
|
||||||
|
PORO
|
||||||
|
1000*0.3 /
|
||||||
|
|
||||||
static Deck createDeckWithDynamicWTRACER() {
|
SCHEDULE
|
||||||
Opm::Parser parser;
|
WELSPECS
|
||||||
std::string input =
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
"START -- 0 \n"
|
/
|
||||||
"1 JAN 2000 / \n"
|
COMPDAT
|
||||||
"GRID\n"
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
"PERMX\n"
|
/
|
||||||
" 1000*0.25/\n"
|
WCONINJE
|
||||||
"COPY\n"
|
'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/
|
||||||
" PERMX PERMY /\n"
|
/
|
||||||
" PERMX PERMZ /\n"
|
DATES -- 1
|
||||||
"/\n"
|
1 MAY 2000 /
|
||||||
"SCHEDULE\n"
|
/
|
||||||
"WELSPECS\n"
|
WTRACER
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
'W_1' 'I1' 1 /
|
||||||
"/\n"
|
'W_1' 'I2' 1 /
|
||||||
"COMPDAT\n"
|
/
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
DATES -- 2, 3
|
||||||
"/\n"
|
1 JUL 2000 /
|
||||||
"WCONINJE\n"
|
1 AUG 2000 /
|
||||||
" 'W_1' 'GAS' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
/
|
||||||
"DATES -- 1\n"
|
WTRACER
|
||||||
" 1 MAY 2000 / \n"
|
'W_1' 'I1' 0 /
|
||||||
"/\n"
|
/
|
||||||
"WTRACER\n"
|
DATES -- 4
|
||||||
" 'W_1' 'I1' 1 / \n "
|
1 SEP 2000 /
|
||||||
" 'W_1' 'I2' 1 / \n "
|
/
|
||||||
"/\n"
|
|
||||||
"DATES -- 2, 3\n"
|
|
||||||
" 1 JUL 2000 / \n"
|
|
||||||
" 1 AUG 2000 / \n"
|
|
||||||
"/\n"
|
|
||||||
"WTRACER\n"
|
|
||||||
" 'W_1' 'I1' 0 / \n "
|
|
||||||
"/\n"
|
|
||||||
"DATES -- 4\n"
|
|
||||||
" 1 SEP 2000 / \n"
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
static Deck createDeckWithTracerInProducer() {
|
Deck createDeckWithTracerInProducer()
|
||||||
Opm::Parser parser;
|
{
|
||||||
std::string input =
|
return Parser{}.parseString(R"(
|
||||||
"START -- 0 \n"
|
START -- 0
|
||||||
"1 JAN 2000 / \n"
|
1 JAN 2000 /
|
||||||
"GRID\n"
|
GRID
|
||||||
"PERMX\n"
|
PERMX
|
||||||
" 1000*0.25/\n"
|
1000*0.25/
|
||||||
"COPY\n"
|
COPY
|
||||||
" PERMX PERMY /\n"
|
PERMX PERMY /
|
||||||
" PERMX PERMZ /\n"
|
PERMX PERMZ /
|
||||||
"/\n"
|
/
|
||||||
"SCHEDULE\n"
|
PORO
|
||||||
"WELSPECS\n"
|
1000*0.3 /
|
||||||
" 'W_1' 'OP' 1 1 1* \'GAS\' 7* / \n"
|
|
||||||
"/\n"
|
|
||||||
"COMPDAT\n"
|
|
||||||
" 'W_1' 2* 1 1 'OPEN' / \n"
|
|
||||||
"/\n"
|
|
||||||
"WCONPROD\n"
|
|
||||||
"'W_1' 'OPEN' 'ORAT' 20000 4* 1000 /\n"
|
|
||||||
"WTRACER\n"
|
|
||||||
" 'W_1' 'I1' 1 / \n "
|
|
||||||
" 'W_1' 'I2' 1 / \n "
|
|
||||||
"/\n";
|
|
||||||
|
|
||||||
return parser.parseString(input);
|
SCHEDULE
|
||||||
|
WELSPECS
|
||||||
|
'W_1' 'OP' 1 1 1* 'GAS' 7* /
|
||||||
|
/
|
||||||
|
COMPDAT
|
||||||
|
'W_1' 2* 1 1 'OPEN' /
|
||||||
|
/
|
||||||
|
WCONPROD
|
||||||
|
'W_1' 'OPEN' 'ORAT' 20000 4* 1000 /
|
||||||
|
WTRACER
|
||||||
|
'W_1' 'I1' 1 /
|
||||||
|
'W_1' 'I2' 1 /
|
||||||
|
/
|
||||||
|
END
|
||||||
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(TestNoTracer)
|
||||||
|
{
|
||||||
|
const auto deck = createDeckWithOutTracer();
|
||||||
|
|
||||||
|
const EclipseGrid grid(10,10,10);
|
||||||
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec (deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestNoTracer) {
|
|
||||||
auto deck = createDeckWithOutTracer();
|
|
||||||
EclipseGrid grid(10,10,10);
|
|
||||||
TableManager table ( deck );
|
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
|
||||||
auto python = std::make_shared<Python>();
|
|
||||||
Runspec runspec ( deck );
|
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
|
||||||
BOOST_CHECK(!deck.hasKeyword("WTRACER"));
|
BOOST_CHECK(!deck.hasKeyword("WTRACER"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER)
|
||||||
auto deck = createDeckWithDynamicWTRACER();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithDynamicWTRACER();
|
||||||
EclipseGrid grid(10,10,10);
|
|
||||||
TableManager table ( deck );
|
const EclipseGrid grid(10,10,10);
|
||||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
const TableManager table (deck);
|
||||||
Runspec runspec ( deck );
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Schedule schedule(deck, grid , fp, runspec, python);
|
const Runspec runspec (deck);
|
||||||
|
const Schedule schedule(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
BOOST_CHECK(deck.hasKeyword("WTRACER"));
|
BOOST_CHECK(deck.hasKeyword("WTRACER"));
|
||||||
|
|
||||||
const auto& keyword = deck["WTRACER"].back();
|
const auto& keyword = deck["WTRACER"].back();
|
||||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||||
|
|
||||||
const auto& record = keyword.getRecord(0);
|
const auto& record = keyword.getRecord(0);
|
||||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||||
BOOST_CHECK_EQUAL(well_name, "W_1");
|
BOOST_CHECK_EQUAL(well_name, "W_1");
|
||||||
@ -169,13 +194,13 @@ BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW) {
|
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW)
|
||||||
auto deck = createDeckWithTracerInProducer();
|
{
|
||||||
auto python = std::make_shared<Python>();
|
const auto deck = createDeckWithTracerInProducer();
|
||||||
EclipseGrid grid(10,10,10);
|
const EclipseGrid grid(10,10,10);
|
||||||
TableManager table ( deck );
|
const TableManager table (deck);
|
||||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
Runspec runspec ( deck );
|
const Runspec runspec (deck);
|
||||||
|
|
||||||
BOOST_CHECK_THROW(Schedule(deck, grid, fp, runspec, python), OpmInputError);
|
BOOST_CHECK_THROW(Schedule(deck, grid, fp, runspec, std::make_shared<Python>()), OpmInputError);
|
||||||
}
|
}
|
||||||
|
@ -518,34 +518,39 @@ BOOST_AUTO_TEST_CASE(WellTestWGRUPCONWellPropertiesSet) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(TestDefaultedCOMPDATIJ) {
|
BOOST_AUTO_TEST_CASE(TestDefaultedCOMPDATIJ)
|
||||||
Parser parser;
|
{
|
||||||
const char * deckString = "\n\
|
const auto deck = Parser{}.parseString(R"(
|
||||||
START\n\
|
START
|
||||||
\n\
|
|
||||||
10 MAI 2007 /\n\
|
10 MAI 2007 /
|
||||||
\n\
|
|
||||||
GRID\n\
|
GRID
|
||||||
PERMX\n\
|
PERMX
|
||||||
9000*0.25 /\n\
|
9000*0.25 /
|
||||||
COPY \n\
|
COPY
|
||||||
PERMX PERMY /\n\
|
PERMX PERMY /
|
||||||
PERMX PERMZ /\n\
|
PERMX PERMZ /
|
||||||
/\n\
|
/
|
||||||
SCHEDULE\n\
|
PORO
|
||||||
WELSPECS \n\
|
9000*0.3 /
|
||||||
'W1' 'OP' 11 21 3.33 'OIL' 7* / \n\
|
|
||||||
/\n\
|
SCHEDULE
|
||||||
COMPDAT \n\
|
WELSPECS
|
||||||
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /\n\
|
'W1' 'OP' 11 21 3.33 'OIL' 7* /
|
||||||
/\n";
|
/
|
||||||
auto deck = parser.parseString(deckString);
|
COMPDAT
|
||||||
auto python = std::make_shared<Python>();
|
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /
|
||||||
EclipseGrid grid(30,30,10);
|
/
|
||||||
TableManager table ( deck );
|
END
|
||||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
)");
|
||||||
Runspec runspec (deck);
|
|
||||||
Schedule sched(deck, grid , fp, runspec, python);
|
const EclipseGrid grid(30,30,10);
|
||||||
|
const TableManager table (deck);
|
||||||
|
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||||
|
const Runspec runspec (deck);
|
||||||
|
const Schedule sched(deck, grid, fp, runspec, std::make_shared<Python>());
|
||||||
|
|
||||||
const auto& connections = sched.getWell("W1", 0).getConnections();
|
const auto& connections = sched.getWell("W1", 0).getConnections();
|
||||||
BOOST_CHECK_EQUAL( 10 , connections.get(0).getI() );
|
BOOST_CHECK_EQUAL( 10 , connections.get(0).getI() );
|
||||||
BOOST_CHECK_EQUAL( 20 , connections.get(0).getJ() );
|
BOOST_CHECK_EQUAL( 20 , connections.get(0).getJ() );
|
||||||
@ -907,4 +912,3 @@ BOOST_AUTO_TEST_CASE(TestWellEvents) {
|
|||||||
BOOST_CHECK( sched[0].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
BOOST_CHECK( sched[0].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
||||||
BOOST_CHECK( sched[5].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
BOOST_CHECK( sched[5].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,12 +57,22 @@ namespace {
|
|||||||
const auto j = (dims[1] - 1) - 1;
|
const auto j = (dims[1] - 1) - 1;
|
||||||
|
|
||||||
for (auto k = top; k < static_cast<int>(dims.size()); ++k) {
|
for (auto k = top; k < static_cast<int>(dims.size()); ++k) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = k / 100.0;
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
Opm::Connection::State::OPEN,
|
Opm::Connection::State::OPEN,
|
||||||
k / 100.0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::Z,
|
Opm::Connection::Direction::Z,
|
||||||
Opm::Connection::CTFKind::DeckValue, k, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, k, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||||
@ -87,18 +97,28 @@ namespace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (auto k = topConn; k < kMax; ++k) {
|
for (auto k = topConn; k < kMax; ++k) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
|
||||||
|
// 0.03, 0.0, 0.01, 0.02, 0.03, ...
|
||||||
|
ctf_props.CF = ((k + 3 - topConn) % 4) / 100.0;
|
||||||
|
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k - topConn,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), k - topConn,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
|
|
||||||
// Open, Shut, Open, Open, Shut, ...
|
// Open, Shut, Open, Open, Shut, ...
|
||||||
state[(k - topConn) % state.size()],
|
state[(k - topConn) % state.size()],
|
||||||
|
|
||||||
// 0.03, 0.0, 0.01, 0.02, 0.03, ...
|
|
||||||
((k + 3 - topConn) % 4) / 100.0,
|
|
||||||
|
|
||||||
1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::Z,
|
Opm::Connection::Direction::Z,
|
||||||
Opm::Connection::CTFKind::DeckValue, k - topConn, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, k - topConn, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||||
@ -115,12 +135,22 @@ namespace {
|
|||||||
const auto iMax = std::min(dims[0] - 1, left + numConns);
|
const auto iMax = std::min(dims[0] - 1, left + numConns);
|
||||||
|
|
||||||
for (auto i = left; i < iMax; ++i) {
|
for (auto i = left; i < iMax; ++i) {
|
||||||
|
const auto depth = 2000 + (2*k + 1) / static_cast<double>(2);
|
||||||
|
|
||||||
|
auto ctf_props = Opm::Connection::CTFProperties{};
|
||||||
|
ctf_props.CF = i / 100.0;
|
||||||
|
ctf_props.Kh = 1.0;
|
||||||
|
ctf_props.Ke = 1.0;
|
||||||
|
ctf_props.rw = 1.0;
|
||||||
|
ctf_props.r0 = 0.5;
|
||||||
|
ctf_props.re = 0.5;
|
||||||
|
ctf_props.connection_length = 1.0;
|
||||||
|
|
||||||
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), i - left,
|
conns.emplace_back(i, j, k, globIndex({i, j, k}, dims), i - left,
|
||||||
2000 + (2*k + 1) / static_cast<double>(2),
|
|
||||||
Opm::Connection::State::OPEN,
|
Opm::Connection::State::OPEN,
|
||||||
i / 100.0, 1.0, 1.0, 0.5, 0.5, 1.0, 0.0, 0.0, 0.0, 0,
|
|
||||||
Opm::Connection::Direction::X,
|
Opm::Connection::Direction::X,
|
||||||
Opm::Connection::CTFKind::DeckValue, i - left, false);
|
Opm::Connection::CTFKind::DeckValue,
|
||||||
|
0, depth, ctf_props, i - left, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return { Opm::Connection::Order::INPUT, left, j, conns };
|
return { Opm::Connection::Order::INPUT, left, j, conns };
|
||||||
|
@ -193,6 +193,7 @@ TEST_FOR_TYPE_NAMED(Action::State, ActionState)
|
|||||||
TEST_FOR_TYPE(BCConfig)
|
TEST_FOR_TYPE(BCConfig)
|
||||||
TEST_FOR_TYPE(BrineDensityTable)
|
TEST_FOR_TYPE(BrineDensityTable)
|
||||||
TEST_FOR_TYPE(ColumnSchema)
|
TEST_FOR_TYPE(ColumnSchema)
|
||||||
|
TEST_FOR_TYPE_NAMED(Connection::CTFProperties, CTFProperties)
|
||||||
TEST_FOR_TYPE(Connection)
|
TEST_FOR_TYPE(Connection)
|
||||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_CarterTracy, serializationTestObjectC)
|
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_CarterTracy, serializationTestObjectC)
|
||||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_Fetkovich, serializationTestObjectF)
|
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_Fetkovich, serializationTestObjectF)
|
||||||
|
Loading…
Reference in New Issue
Block a user