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/>.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMPLETION_HPP_
|
||||
#define COMPLETION_HPP_
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <limits>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Well/FilterCake.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WINJMULT.hpp>
|
||||
|
||||
namespace Opm {
|
||||
|
||||
namespace RestartIO {
|
||||
struct RstConnection;
|
||||
}
|
||||
|
||||
class DeckKeyword;
|
||||
class DeckRecord;
|
||||
class ScheduleGrid;
|
||||
class FieldPropsManager;
|
||||
} // namespace Opm
|
||||
|
||||
class Connection {
|
||||
namespace Opm { namespace RestartIO {
|
||||
struct RstConnection;
|
||||
}} // namespace Opm::RestartIO
|
||||
|
||||
namespace Opm {
|
||||
|
||||
class Connection
|
||||
{
|
||||
public:
|
||||
enum class State {
|
||||
OPEN = 1,
|
||||
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 State StateFromString( const std::string& stringValue );
|
||||
static std::string State2String(State enumValue);
|
||||
static State StateFromString(std::string_view stringValue);
|
||||
|
||||
|
||||
enum class Direction {
|
||||
X = 1,
|
||||
Y = 2,
|
||||
Z = 3
|
||||
Z = 3,
|
||||
};
|
||||
|
||||
static std::string Direction2String(const Direction enumValue);
|
||||
static Direction DirectionFromString(const std::string& stringValue);
|
||||
static Direction DirectionFromString(std::string_view stringValue);
|
||||
|
||||
|
||||
enum class Order {
|
||||
DEPTH,
|
||||
INPUT,
|
||||
TRACK
|
||||
TRACK,
|
||||
};
|
||||
|
||||
static const std::string Order2String( Order enumValue );
|
||||
static Order OrderFromString(const std::string& comporderStringValue);
|
||||
static std::string Order2String(Order enumValue);
|
||||
static Order OrderFromString(std::string_view comporderStringValue);
|
||||
|
||||
|
||||
enum class CTFKind {
|
||||
DeckValue,
|
||||
Defaulted,
|
||||
};
|
||||
|
||||
Connection();
|
||||
|
||||
/// 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,
|
||||
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,
|
||||
Direction direction,
|
||||
CTFKind ctf_kind,
|
||||
const int satTableId,
|
||||
const Direction direction,
|
||||
const CTFKind ctf_kind,
|
||||
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);
|
||||
Connection(const RestartIO::RstConnection& rst_connection,
|
||||
const ScheduleGrid& grid,
|
||||
const FieldPropsManager& fp);
|
||||
|
||||
static Connection serializationTestObject();
|
||||
|
||||
@ -117,104 +193,104 @@ namespace RestartIO {
|
||||
int satTableId() const;
|
||||
int complnum() const;
|
||||
int segment() const;
|
||||
double CF() const;
|
||||
double wpimult() const;
|
||||
double CF() const;
|
||||
double Kh() const;
|
||||
double Ke() const;
|
||||
double rw() const;
|
||||
double r0() const;
|
||||
double re() const;
|
||||
double connectionLength() const;
|
||||
double skinFactor() const;
|
||||
double dFactor() const;
|
||||
double Ke() const;
|
||||
CTFKind kind() const;
|
||||
const InjMult& injmult() const;
|
||||
bool activeInjMult() const;
|
||||
void setInjMult(const InjMult& inj_mult);
|
||||
void setFilterCake(const FilterCake& filter_cake);
|
||||
const FilterCake& getFilterCake() const;
|
||||
bool filterCakeActive() const;
|
||||
double getFilterCakeRadius() const;
|
||||
double getFilterCakeArea() const;
|
||||
|
||||
void setState(State state);
|
||||
void setComplnum(int compnum);
|
||||
void setSkinFactor(double skin_factor);
|
||||
void setDFactor(double d_factor);
|
||||
void setKe(double Ke);
|
||||
void setCF(double CF);
|
||||
void scaleWellPi(double wellPi);
|
||||
bool prepareWellPIScaling();
|
||||
bool applyWellPIScaling(const double scaleFactor);
|
||||
void updateSegmentRST(int segment_number_arg,
|
||||
double center_depth_arg);
|
||||
void updateSegment(int segment_number_arg,
|
||||
double center_depth_arg,
|
||||
std::size_t compseg_insert_index,
|
||||
const std::optional<std::pair<double,double>>& perf_range);
|
||||
const CTFProperties& ctfProperties() const
|
||||
{
|
||||
return this->ctf_properties_;
|
||||
}
|
||||
|
||||
std::size_t sort_value() const;
|
||||
const bool& getDefaultSatTabId() const;
|
||||
void setDefaultSatTabId(bool id);
|
||||
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& ) 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 setComplnum(int compnum);
|
||||
void setSkinFactor(double skin_factor);
|
||||
void setDFactor(double d_factor);
|
||||
void setKe(double Ke);
|
||||
void setCF(double CF);
|
||||
void setDefaultSatTabId(bool id);
|
||||
|
||||
void scaleWellPi(double wellPi);
|
||||
bool prepareWellPIScaling();
|
||||
bool applyWellPIScaling(const double scaleFactor);
|
||||
|
||||
void updateSegmentRST(int segment_number_arg,
|
||||
double center_depth_arg);
|
||||
void updateSegment(int segment_number_arg,
|
||||
double center_depth_arg,
|
||||
std::size_t compseg_insert_index,
|
||||
const std::optional<std::pair<double,double>>& perf_range);
|
||||
|
||||
template<class Serializer>
|
||||
void serializeOp(Serializer& serializer)
|
||||
{
|
||||
serializer(direction);
|
||||
serializer(center_depth);
|
||||
serializer(open_state);
|
||||
serializer(sat_tableId);
|
||||
serializer(m_complnum);
|
||||
serializer(m_CF);
|
||||
serializer(m_Kh);
|
||||
serializer(m_rw);
|
||||
serializer(m_r0);
|
||||
serializer(m_re);
|
||||
serializer(m_connection_length);
|
||||
serializer(m_skin_factor);
|
||||
serializer(m_d_factor);
|
||||
serializer(m_Ke);
|
||||
serializer(ijk);
|
||||
serializer(m_global_index);
|
||||
serializer(m_ctfkind);
|
||||
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);
|
||||
serializer(this->direction);
|
||||
serializer(this->center_depth);
|
||||
serializer(this->open_state);
|
||||
serializer(this->sat_tableId);
|
||||
serializer(this->m_complnum);
|
||||
serializer(this->ctf_properties_);
|
||||
serializer(this->ijk);
|
||||
serializer(this->m_ctfkind);
|
||||
serializer(this->m_global_index);
|
||||
serializer(this->m_injmult);
|
||||
serializer(this->m_sort_value);
|
||||
serializer(this->m_perf_range);
|
||||
serializer(this->m_defaultSatTabId);
|
||||
serializer(this->segment_number);
|
||||
serializer(this->m_wpimult);
|
||||
serializer(this->m_subject_to_welpi);
|
||||
serializer(this->m_filter_cake);
|
||||
}
|
||||
|
||||
private:
|
||||
Direction direction;
|
||||
double center_depth;
|
||||
State open_state;
|
||||
int sat_tableId;
|
||||
int m_complnum;
|
||||
double m_CF;
|
||||
double m_Kh;
|
||||
double m_rw;
|
||||
double m_r0;
|
||||
double m_re;
|
||||
double m_connection_length;
|
||||
double m_skin_factor;
|
||||
double m_d_factor;
|
||||
double m_Ke;
|
||||
// Note to maintainer: If you add new members to this list, then
|
||||
// please also update the operator==(), serializeOp(), and
|
||||
// serializationTestObject() member functions.
|
||||
Direction direction { Direction::Z };
|
||||
double center_depth { 0.0 };
|
||||
State open_state { State::SHUT };
|
||||
int sat_tableId { -1 };
|
||||
int m_complnum { -1 };
|
||||
CTFProperties ctf_properties_{};
|
||||
|
||||
std::array<int,3> ijk{};
|
||||
CTFKind m_ctfkind { CTFKind::DeckValue };
|
||||
std::optional<InjMult> m_injmult{};
|
||||
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
|
||||
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
|
||||
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;
|
||||
bool m_defaultSatTabId;
|
||||
std::optional<std::pair<double,double>> m_perf_range{};
|
||||
bool m_defaultSatTabId{true};
|
||||
|
||||
// related segment number
|
||||
// 0 means the completion is not related to segment
|
||||
int segment_number = 0;
|
||||
// Associate segment number
|
||||
//
|
||||
// 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.
|
||||
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
|
||||
double m_wpimult = 1.0;
|
||||
|
||||
std::optional<FilterCake> m_filter_cake;
|
||||
std::optional<FilterCake> m_filter_cake{};
|
||||
|
||||
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 handleCOMPSEGS(const DeckKeyword& keyword, const ScheduleGrid& grid, const ParseContext& parseContext, ErrorGuard& errors);
|
||||
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 handleWPIMULT(const DeckRecord& record);
|
||||
bool handleWINJCLN(const DeckRecord& record, const KeywordLocation& location);
|
||||
|
@ -23,9 +23,11 @@
|
||||
#include <opm/input/eclipse/Schedule/Well/Connection.hpp>
|
||||
#include <external/resinsight/LibGeometry/cvfBoundingBoxTree.h>
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <stddef.h>
|
||||
@ -33,10 +35,10 @@
|
||||
namespace Opm {
|
||||
class ActiveGridCells;
|
||||
class DeckRecord;
|
||||
class EclipseGrid;
|
||||
class FieldPropsManager;
|
||||
class KeywordLocation;
|
||||
class ScheduleGrid;
|
||||
class EclipseGrid;
|
||||
} // 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,
|
||||
const std::size_t global_index,
|
||||
const double depth,
|
||||
const Connection::State state,
|
||||
const double CF,
|
||||
const double Kh,
|
||||
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 double depth,
|
||||
const Connection::CTFProperties& ctf_props,
|
||||
const int satTableId,
|
||||
const Connection::Direction direction = Connection::Direction::Z,
|
||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
||||
@ -91,14 +90,20 @@ namespace Opm {
|
||||
const std::string& wname,
|
||||
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 getHeadJ() const;
|
||||
const std::vector<double>& getMD() const;
|
||||
void add(Connection);
|
||||
std::size_t size() const;
|
||||
bool empty() const;
|
||||
std::size_t num_open() const;
|
||||
@ -165,39 +170,32 @@ namespace Opm {
|
||||
serializer(this->coord);
|
||||
serializer(this->md);
|
||||
}
|
||||
|
||||
private:
|
||||
Connection::Order m_ordering { Connection::Order::TRACK };
|
||||
int headI{0};
|
||||
int headJ{0};
|
||||
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{};
|
||||
|
||||
void addConnection(const int i, const int j, const int k,
|
||||
const std::size_t global_index,
|
||||
const int complnum,
|
||||
const double depth,
|
||||
const Connection::State state,
|
||||
const double CF,
|
||||
const double Kh,
|
||||
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 double depth,
|
||||
const Connection::CTFProperties& ctf_props,
|
||||
const int satTableId,
|
||||
const Connection::Direction direction = Connection::Direction::Z,
|
||||
const Connection::CTFKind ctf_kind = Connection::CTFKind::DeckValue,
|
||||
const std::size_t seqIndex = 0,
|
||||
const bool defaultSatTabId = true);
|
||||
const Connection::Direction direction,
|
||||
const Connection::CTFKind ctf_kind,
|
||||
const std::size_t seqIndex,
|
||||
const bool defaultSatTabId);
|
||||
|
||||
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
|
||||
void orderTRACK();
|
||||
void orderMSW();
|
||||
void orderDEPTH();
|
||||
|
||||
};
|
||||
|
||||
std::optional<int>
|
||||
|
@ -377,7 +377,10 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
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
|
||||
const auto& keyword = handlerContext.keyword;
|
||||
const auto& currentStep = handlerContext.currentStep;
|
||||
@ -385,18 +388,21 @@ File {} line {}.)", wname, location.keyword, location.filename, location.lineno)
|
||||
// Loop over records in CSKIN
|
||||
for (const auto& record : keyword) {
|
||||
// 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);
|
||||
|
||||
// Loop over well(s) in record
|
||||
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);
|
||||
well.handleCSKINConnections(record);
|
||||
|
||||
if (well.handleCSKIN(record, handlerContext.keyword.location())) {
|
||||
this->snapshots[currentStep].wells.update(std::move(well));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Schedule::handleDRSDT(HandlerContext& handlerContext) {
|
||||
std::size_t numPvtRegions = this->m_static.m_runspec.tabdims().getNumPVTTables();
|
||||
|
@ -17,125 +17,157 @@
|
||||
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 <cassert>
|
||||
#include <exception>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#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 {
|
||||
constexpr bool restartDefaultSatTabId = true;
|
||||
|
||||
namespace Opm {
|
||||
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;
|
||||
|
||||
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,
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Opm
|
||||
{
|
||||
|
||||
Connection::CTFProperties
|
||||
Connection::CTFProperties::serializationTestObject()
|
||||
{
|
||||
auto props = Opm::Connection::CTFProperties{};
|
||||
|
||||
props.CF = 1.0;
|
||||
props.Kh = 2.0;
|
||||
props.Ke = 3.0;
|
||||
props.rw = 4.0;
|
||||
props.r0 = 5.0;
|
||||
props.re = 6.0;
|
||||
props.connection_length = 7.0;
|
||||
props.skin_factor = 8.0;
|
||||
props.d_factor = 9.0;
|
||||
props.peaceman_denom = 10.0;
|
||||
|
||||
return props;
|
||||
}
|
||||
|
||||
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( 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)
|
||||
{
|
||||
}
|
||||
: 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)
|
||||
{}
|
||||
|
||||
namespace {
|
||||
constexpr bool defaultSatTabId = true;
|
||||
}
|
||||
|
||||
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),
|
||||
m_CF(rst_connection.cf),
|
||||
m_Kh(rst_connection.kh),
|
||||
m_rw(rst_connection.diameter / 2),
|
||||
m_r0(rst_connection.r0),
|
||||
m_re(0.0),
|
||||
m_connection_length(0.0),
|
||||
m_skin_factor(rst_connection.skin_factor),
|
||||
m_d_factor(0.0),
|
||||
m_Ke(0.0),
|
||||
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(defaultSatTabId),
|
||||
segment_number(rst_connection.segment)
|
||||
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) {
|
||||
const auto& satnum = fp.get_int("SATNUM");
|
||||
auto active_index = grid.get_cell(this->ijk[0], this->ijk[1], this->ijk[2]).active_index();
|
||||
this->sat_tableId = satnum[active_index];
|
||||
const auto active_index = grid
|
||||
.get_cell(this->ijk[0], this->ijk[1], this->ijk[2])
|
||||
.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
|
||||
}
|
||||
|
||||
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 result;
|
||||
|
||||
result.direction = Direction::Y;
|
||||
result.center_depth = 1.0;
|
||||
result.open_state = State::OPEN;
|
||||
result.sat_tableId = 2;
|
||||
result.m_complnum = 3;
|
||||
result.m_CF = 4.0;
|
||||
result.m_Kh = 5.0;
|
||||
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.ctf_properties_ = CTFProperties::serializationTestObject();
|
||||
|
||||
result.ijk = {9, 10, 11};
|
||||
result.m_ctfkind = CTFKind::Defaulted;
|
||||
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_defaultSatTabId = true;
|
||||
result.segment_number = 16;
|
||||
result.m_wpimult = 0.123;
|
||||
result.m_subject_to_welpi = true;
|
||||
result.m_filter_cake = FilterCake::serializationTestObject();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
bool Connection::sameCoordinate(const int i, const int j, const int k) const
|
||||
{
|
||||
return this->ijk == std::array { i, j, k };
|
||||
}
|
||||
|
||||
int Connection::getI() const {
|
||||
int Connection::getI() const
|
||||
{
|
||||
return ijk[0];
|
||||
}
|
||||
|
||||
int Connection::getJ() const {
|
||||
int Connection::getJ() const
|
||||
{
|
||||
return ijk[1];
|
||||
}
|
||||
|
||||
int Connection::getK() const {
|
||||
int Connection::getK() const
|
||||
{
|
||||
return ijk[2];
|
||||
}
|
||||
|
||||
std::size_t Connection::global_index() const {
|
||||
std::size_t Connection::global_index() const
|
||||
{
|
||||
return this->m_global_index;
|
||||
}
|
||||
|
||||
bool Connection::attachedToSegment() const {
|
||||
return (segment_number > 0);
|
||||
bool Connection::attachedToSegment() const
|
||||
{
|
||||
return this->segment_number > 0;
|
||||
}
|
||||
|
||||
std::size_t Connection::sort_value() const {
|
||||
std::size_t Connection::sort_value() const
|
||||
{
|
||||
return m_sort_value;
|
||||
}
|
||||
|
||||
const bool& Connection::getDefaultSatTabId() const {
|
||||
bool Connection::getDefaultSatTabId() const
|
||||
{
|
||||
return m_defaultSatTabId;
|
||||
}
|
||||
|
||||
Connection::Direction Connection::dir() const {
|
||||
Connection::Direction Connection::dir() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void Connection::setDefaultSatTabId(bool id) {
|
||||
void Connection::setDefaultSatTabId(bool id)
|
||||
{
|
||||
m_defaultSatTabId = id;
|
||||
}
|
||||
|
||||
double Connection::depth() const {
|
||||
double Connection::depth() const
|
||||
{
|
||||
return this->center_depth;
|
||||
}
|
||||
|
||||
Connection::State Connection::state() const {
|
||||
Connection::State Connection::state() const
|
||||
{
|
||||
return this->open_state;
|
||||
}
|
||||
|
||||
int Connection::satTableId() const {
|
||||
int Connection::satTableId() const
|
||||
{
|
||||
return this->sat_tableId;
|
||||
}
|
||||
|
||||
int Connection::complnum() const {
|
||||
int Connection::complnum() const
|
||||
{
|
||||
return this->m_complnum;
|
||||
}
|
||||
|
||||
void Connection::setComplnum(int complnum) {
|
||||
void Connection::setComplnum(int complnum)
|
||||
{
|
||||
this->m_complnum = complnum;
|
||||
}
|
||||
|
||||
void Connection::setSkinFactor(double skin_factor) {
|
||||
this->m_skin_factor = skin_factor;
|
||||
void Connection::setSkinFactor(double 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) {
|
||||
this->m_d_factor = d_factor;
|
||||
void Connection::setDFactor(double d_factor)
|
||||
{
|
||||
this->ctf_properties_.d_factor = d_factor;
|
||||
}
|
||||
|
||||
void Connection::setKe(double Ke) {
|
||||
this->m_Ke = Ke;
|
||||
void Connection::setKe(double Ke)
|
||||
{
|
||||
this->ctf_properties_.Ke = Ke;
|
||||
}
|
||||
|
||||
void Connection::setCF(double CF) {
|
||||
this->m_CF = CF;
|
||||
void Connection::setCF(double CF)
|
||||
{
|
||||
this->ctf_properties_.CF = CF;
|
||||
}
|
||||
|
||||
double Connection::CF() const {
|
||||
return this->m_CF;
|
||||
}
|
||||
|
||||
double Connection::wpimult() const {
|
||||
double Connection::wpimult() const
|
||||
{
|
||||
return this->m_wpimult;
|
||||
}
|
||||
|
||||
double Connection::Kh() const {
|
||||
return this->m_Kh;
|
||||
double Connection::CF() const
|
||||
{
|
||||
return this->ctf_properties_.CF;
|
||||
}
|
||||
|
||||
double Connection::rw() const {
|
||||
return this->m_rw;
|
||||
double Connection::Kh() const
|
||||
{
|
||||
return this->ctf_properties_.Kh;
|
||||
}
|
||||
|
||||
double Connection::r0() const {
|
||||
return this->m_r0;
|
||||
double Connection::rw() const
|
||||
{
|
||||
return this->ctf_properties_.rw;
|
||||
}
|
||||
|
||||
double Connection::re() const {
|
||||
return this->m_re;
|
||||
double Connection::r0() const
|
||||
{
|
||||
return this->ctf_properties_.r0;
|
||||
}
|
||||
|
||||
double Connection::connectionLength() const {
|
||||
return this->m_connection_length;
|
||||
double Connection::re() const
|
||||
{
|
||||
return this->ctf_properties_.re;
|
||||
}
|
||||
|
||||
double Connection::skinFactor() const {
|
||||
return this->m_skin_factor;
|
||||
double Connection::connectionLength() const
|
||||
{
|
||||
return this->ctf_properties_.connection_length;
|
||||
}
|
||||
|
||||
double Connection::dFactor() const {
|
||||
return this->m_d_factor;
|
||||
double Connection::skinFactor() const
|
||||
{
|
||||
return this->ctf_properties_.skin_factor;
|
||||
}
|
||||
|
||||
double Connection::Ke() const {
|
||||
return this->m_Ke;
|
||||
double Connection::dFactor() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
void Connection::updateSegment(int segment_number_arg,
|
||||
double center_depth_arg,
|
||||
std::size_t compseg_insert_index,
|
||||
const std::optional<std::pair<double, double>>& perf_range) {
|
||||
void Connection::updateSegment(const int segment_number_arg,
|
||||
const double center_depth_arg,
|
||||
const std::size_t compseg_insert_index,
|
||||
const std::optional<std::pair<double, double>>& perf_range)
|
||||
{
|
||||
this->segment_number = segment_number_arg;
|
||||
this->center_depth = center_depth_arg;
|
||||
this->m_sort_value = compseg_insert_index;
|
||||
@ -289,21 +358,25 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
||||
}
|
||||
|
||||
void Connection::updateSegmentRST(int segment_number_arg,
|
||||
double center_depth_arg) {
|
||||
double center_depth_arg)
|
||||
{
|
||||
this->segment_number = segment_number_arg;
|
||||
this->center_depth = center_depth_arg;
|
||||
}
|
||||
|
||||
int Connection::segment() const {
|
||||
int Connection::segment() const
|
||||
{
|
||||
return this->segment_number;
|
||||
}
|
||||
|
||||
void Connection::scaleWellPi(double wellPi) {
|
||||
void Connection::scaleWellPi(double 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;
|
||||
|
||||
this->m_subject_to_welpi = true;
|
||||
@ -311,102 +384,111 @@ const std::optional<std::pair<double, double>>& Connection::perf_range() const {
|
||||
return update;
|
||||
}
|
||||
|
||||
|
||||
bool Connection::applyWellPIScaling(const double scaleFactor) {
|
||||
if (! this->m_subject_to_welpi)
|
||||
bool Connection::applyWellPIScaling(const double scaleFactor)
|
||||
{
|
||||
if (! this->m_subject_to_welpi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this->scaleWellPi(scaleFactor);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Connection::str() const {
|
||||
std::string Connection::str() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "ijk: " << this->ijk[0] << "," << this->ijk[1] << "," << this->ijk[2] << std::endl;
|
||||
ss << "COMPLNUM " << this->m_complnum << std::endl;
|
||||
ss << "CF " << this->m_CF << std::endl;
|
||||
ss << "RW " << this->m_rw << std::endl;
|
||||
ss << "R0 " << this->m_r0 << std::endl;
|
||||
ss << "Re " << this->m_re << std::endl;
|
||||
ss << "connection length " << this->m_connection_length << std::endl;
|
||||
ss << "skinf " << this->m_skin_factor << std::endl;
|
||||
ss << "dfactor " << this->m_d_factor << std::endl;
|
||||
ss << "Ke " << this->m_Ke << std::endl;
|
||||
ss << "kh " << this->m_Kh << std::endl;
|
||||
ss << "sat_tableId " << this->sat_tableId << std::endl;
|
||||
ss << "open_state " << Connection::State2String(this->open_state) << std::endl;
|
||||
ss << "direction " << Connection::Direction2String(this->direction) << std::endl;
|
||||
ss << "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n';
|
||||
ss << "segment_nr " << this->segment_number << std::endl;
|
||||
ss << "center_depth " << this->center_depth << std::endl;
|
||||
ss << "sort_value" << this->m_sort_value<< std::endl;
|
||||
|
||||
ss << "ijk: " << this->ijk[0] << ',' << this->ijk[1] << ',' << this->ijk[2] << '\n'
|
||||
<< "COMPLNUM " << this->m_complnum << '\n'
|
||||
<< "CF " << this->CF() << '\n'
|
||||
<< "RW " << this->rw() << '\n'
|
||||
<< "R0 " << this->r0() << '\n'
|
||||
<< "Re " << this->re() << '\n'
|
||||
<< "connection length " << this->connectionLength() << '\n'
|
||||
<< "skinf " << this->skinFactor() << '\n'
|
||||
<< "dfactor " << this->dFactor() << '\n'
|
||||
<< "Ke " << this->Ke() << '\n'
|
||||
<< "kh " << this->Kh() << '\n'
|
||||
<< "sat_tableId " << this->sat_tableId << '\n'
|
||||
<< "open_state " << Connection::State2String(this->open_state) << '\n'
|
||||
<< "direction " << Connection::Direction2String(this->direction) << '\n'
|
||||
<< "CTF Source " << Connection::CTFKindToString(this->m_ctfkind) << '\n'
|
||||
<< "segment_nr " << this->segment_number << '\n'
|
||||
<< "center_depth " << this->center_depth << '\n'
|
||||
<< "sort_value" << this->m_sort_value<< '\n';
|
||||
|
||||
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()) {
|
||||
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << std::endl;
|
||||
ss << "FilterCake " << FilterCake::filterCakeToString(this->m_filter_cake.value()) << '\n';
|
||||
}
|
||||
|
||||
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 {
|
||||
return !( *this == rhs );
|
||||
bool Connection::operator==(const Connection& that) const
|
||||
{
|
||||
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)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::string Connection::State2String( State enumValue ) {
|
||||
std::string Connection::State2String(State enumValue)
|
||||
{
|
||||
switch (enumValue) {
|
||||
case State::OPEN:
|
||||
return "OPEN";
|
||||
|
||||
case State::AUTO:
|
||||
return "AUTO";
|
||||
|
||||
case State::SHUT:
|
||||
return "SHUT";
|
||||
|
||||
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::StateFromString( const std::string& stringValue ) {
|
||||
Connection::State
|
||||
Connection::StateFromString(std::string_view stringValue)
|
||||
{
|
||||
if (stringValue == "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)
|
||||
@ -434,8 +516,7 @@ std::string Connection::Direction2String(const Direction enumValue)
|
||||
return stringValue;
|
||||
}
|
||||
|
||||
|
||||
Connection::Direction Connection::DirectionFromString(const std::string& s )
|
||||
Connection::Direction Connection::DirectionFromString(std::string_view s)
|
||||
{
|
||||
Direction direction;
|
||||
|
||||
@ -443,39 +524,53 @@ Connection::Direction Connection::DirectionFromString(const std::string& s )
|
||||
else if ((s == "Y") || (s == "y")) { direction = Direction::Y; }
|
||||
else if ((s == "Z") || (s == "z")) { direction = Direction::Z; }
|
||||
else {
|
||||
std::string msg = "Unsupported completion direction " + s;
|
||||
throw std::invalid_argument(msg);
|
||||
throw std::invalid_argument {
|
||||
"Unsupported completion direction "
|
||||
+ std::string { s }
|
||||
};
|
||||
}
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
|
||||
const std::string Connection::Order2String( Order enumValue ) {
|
||||
std::string Connection::Order2String(Order enumValue)
|
||||
{
|
||||
switch (enumValue) {
|
||||
case Order::DEPTH:
|
||||
return "DEPTH";
|
||||
|
||||
case Order::INPUT:
|
||||
return "INPUT";
|
||||
|
||||
case Order::TRACK:
|
||||
return "TRACK";
|
||||
|
||||
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(const std::string& stringValue ) {
|
||||
Connection::Order Connection::OrderFromString(std::string_view stringValue)
|
||||
{
|
||||
if (stringValue == "DEPTH")
|
||||
return Order::DEPTH;
|
||||
else if (stringValue == "INPUT")
|
||||
|
||||
if (stringValue == "INPUT")
|
||||
return Order::INPUT;
|
||||
else if (stringValue == "TRACK")
|
||||
|
||||
if (stringValue == "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)
|
||||
{
|
||||
switch (ctf_kind) {
|
||||
@ -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;
|
||||
}
|
||||
|
||||
const InjMult& Connection::injmult() const {
|
||||
const InjMult& Connection::injmult() const
|
||||
{
|
||||
assert(this->activeInjMult());
|
||||
return m_injmult.value();
|
||||
}
|
||||
|
||||
bool Connection::activeInjMult() const {
|
||||
bool Connection::activeInjMult() const
|
||||
{
|
||||
return this->m_injmult.has_value();
|
||||
}
|
||||
|
||||
void Connection::setInjMult(const InjMult& inj_mult) {
|
||||
void Connection::setInjMult(const 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;
|
||||
}
|
||||
|
||||
bool Connection::filterCakeActive() const {
|
||||
bool Connection::filterCakeActive() const
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
double Connection::getFilterCakeRadius() const {
|
||||
if (this->getFilterCake().radius.has_value()) {
|
||||
return this->getFilterCake().radius.value();
|
||||
} else {
|
||||
return this->m_rw;
|
||||
double Connection::getFilterCakeRadius() const
|
||||
{
|
||||
if (const auto& radius = this->getFilterCake().radius; radius.has_value()) {
|
||||
return *radius;
|
||||
}
|
||||
else {
|
||||
return this->rw();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double Connection::getFilterCakeArea() const {
|
||||
if (this->getFilterCake().flow_area.has_value()) {
|
||||
return this->getFilterCake().flow_area.value();
|
||||
} else {
|
||||
const double radius = this->getFilterCakeRadius();
|
||||
const double length = this->m_connection_length;
|
||||
constexpr double pi = 3.14159265;
|
||||
return 2. * pi * radius * length;
|
||||
double Connection::getFilterCakeArea() const
|
||||
{
|
||||
if (const auto& flow_area = this->getFilterCake().flow_area; flow_area.has_value()) {
|
||||
return *flow_area;
|
||||
}
|
||||
else {
|
||||
constexpr double two_pi = 2 * 3.14159265358979323846264;
|
||||
return two_pi * this->getFilterCakeRadius() * this->connectionLength();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // end of namespace Opm
|
||||
|
@ -40,13 +40,12 @@
|
||||
#include <opm/input/eclipse/Schedule/Well/WVFPDP.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
||||
|
||||
|
||||
|
||||
#include <opm/input/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/common/utility/OpmInputError.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/W.hpp>
|
||||
|
||||
@ -1300,42 +1299,60 @@ bool Well::handleWELOPENConnections(const DeckRecord& record, Connection::State
|
||||
return this->updateConnections(std::move(new_connections), false);
|
||||
}
|
||||
|
||||
bool Well::handleCSKINConnections(const DeckRecord& record) {
|
||||
// Lambda expression to check if record coordinates match connection coordinates
|
||||
auto match = [=]( const Connection &c) -> bool {
|
||||
if (!match_eq(c.getI(), record, "I" , -1)) return false;
|
||||
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;
|
||||
bool Well::handleCSKIN(const DeckRecord& record,
|
||||
const KeywordLocation& location)
|
||||
{
|
||||
using Kw = ParserKeywords::CSKIN;
|
||||
|
||||
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
|
||||
auto new_connections = std::make_shared<WellConnections>(this->connections->ordering(), this->headI, this->headJ);
|
||||
// New connection set which will be updated with new connection level
|
||||
// skin factors.
|
||||
auto new_connections = std::make_shared<WellConnections>
|
||||
(this->connections->ordering(), this->headI, this->headJ);
|
||||
|
||||
// Update skin factor
|
||||
double skin_factor = record.getItem("CONNECTION_SKIN_FACTOR").get<double>(0);
|
||||
const double angle = 6.2831853071795864769252867665590057683943387987502116419498;
|
||||
for (auto c : *this->connections) {
|
||||
if (match(c)) {
|
||||
// Check for potential negative new CF
|
||||
if ((std::log(c.r0() / std::min(c.rw(), c.r0())) + skin_factor) < 0.0) {
|
||||
throw std::runtime_error("Negative connection transmissibility factor produced by CSKIN for well "
|
||||
+ name());
|
||||
const auto skin_factor = record.getItem<Kw::CONNECTION_SKIN_FACTOR>().getSIDouble(0);
|
||||
for (const auto& connection : *this->connections) {
|
||||
if (! need_skin_adjustment(connection)) {
|
||||
// No CSKIN adjustment needed here. Include connection as-is
|
||||
// into new connection set.
|
||||
new_connections->add(connection);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 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);
|
||||
// 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
|
||||
};
|
||||
}
|
||||
new_connections->add(c);
|
||||
|
||||
auto connection_copy = connection;
|
||||
connection_copy.setSkinFactor(skin_factor);
|
||||
|
||||
new_connections->add(connection_copy);
|
||||
}
|
||||
|
||||
return this->updateConnections(std::move(new_connections), false);
|
||||
@ -1390,6 +1407,7 @@ bool Well::handleWPIMULT(const DeckRecord& record) {
|
||||
|
||||
new_connections->add(c);
|
||||
}
|
||||
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <ostream>
|
||||
|
||||
#define BOOST_TEST_MODULE CompletionTests
|
||||
#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/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/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/CompletedCells.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/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 {
|
||||
double cp_rm3_per_db()
|
||||
@ -51,17 +57,28 @@ namespace {
|
||||
/ (Opm::unit::day * Opm::unit::barsa);
|
||||
}
|
||||
|
||||
Opm::WellConnections loadCOMPDAT(const std::string& compdat_keyword) {
|
||||
Opm::EclipseGrid grid(10,10,10);
|
||||
Opm::TableManager tables;
|
||||
Opm::Parser parser;
|
||||
const auto deck = parser.parseString(compdat_keyword);
|
||||
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", {});
|
||||
Opm::WellConnections
|
||||
loadCOMPDAT(const std::string& compdat_keyword)
|
||||
{
|
||||
Opm::WellConnections connections {
|
||||
Opm::Connection::Order::TRACK, 10, 10
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
@ -94,12 +111,22 @@ BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect)
|
||||
{
|
||||
const auto dir = Opm::Connection::Direction::Z;
|
||||
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::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 );
|
||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||
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) {
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows)
|
||||
{
|
||||
const auto dir = Opm::Connection::Direction::Z;
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
completionSet.add( completion1 );
|
||||
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
|
||||
@ -148,15 +185,23 @@ BOOST_AUTO_TEST_CASE(Compdat_Direction) {
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
||||
Opm::WellConnections completionSet(Opm::Connection::Order::TRACK, 10,10);
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(AddCompletionCopy)
|
||||
{
|
||||
const auto dir = Opm::Connection::Direction::Z;
|
||||
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);
|
||||
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);
|
||||
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, 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( completion2 );
|
||||
completionSet.add( completion3 );
|
||||
@ -171,15 +216,25 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
||||
Opm::EclipseGrid grid(10,20,20);
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
const auto kind = Opm::Connection::CTFKind::Defaulted;
|
||||
Opm::WellConnections completions(Opm::Connection::Order::TRACK, 10,10);
|
||||
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);
|
||||
BOOST_AUTO_TEST_CASE(ActiveCompletions)
|
||||
{
|
||||
const auto dir = Opm::Connection::Direction::Z;
|
||||
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;
|
||||
|
||||
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( completion2 );
|
||||
completions.add( completion3 );
|
||||
@ -188,14 +243,16 @@ BOOST_AUTO_TEST_CASE(ActiveCompletions) {
|
||||
actnum[0] = 0;
|
||||
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( completion2, active_completions.get(0));
|
||||
BOOST_CHECK_EQUAL( completion3, active_completions.get(1));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST) {
|
||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
||||
BOOST_AUTO_TEST_CASE(loadCOMPDATTEST)
|
||||
{
|
||||
const Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC); // Unit system used in deck FIRST_SIM.DATA.
|
||||
|
||||
{
|
||||
const std::string deck = R"(GRID
|
||||
|
||||
@ -212,7 +269,8 @@ COMPDAT
|
||||
-- CF Diam Kh Skin Df
|
||||
'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];
|
||||
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));
|
||||
@ -236,7 +294,8 @@ COMPDAT
|
||||
-- CF Diam Kh Skin Df
|
||||
'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];
|
||||
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));
|
||||
@ -460,20 +519,16 @@ END
|
||||
}
|
||||
|
||||
// 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
|
||||
199,
|
||||
2015.0,
|
||||
Opm::Connection::State::OPEN,
|
||||
50.0*cp_rm3_per_db(),
|
||||
0.123,
|
||||
0.234,
|
||||
0.157,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1);
|
||||
2015.0, ctf_props, 1);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{3});
|
||||
|
||||
@ -507,18 +562,8 @@ END
|
||||
// Reset CF -- simulating COMPDAT record (active cell)
|
||||
connP.addConnection(8, 9, 1, // 10, 10, 2
|
||||
198,
|
||||
2015.0,
|
||||
Opm::Connection::State::OPEN,
|
||||
50.0*cp_rm3_per_db(),
|
||||
0.123,
|
||||
0.234,
|
||||
0.157,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
0.0,
|
||||
1);
|
||||
2015.0, ctf_props, 1);
|
||||
|
||||
BOOST_REQUIRE_EQUAL(connP.size(), std::size_t{4});
|
||||
|
||||
|
@ -55,20 +55,32 @@
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
BOOST_AUTO_TEST_CASE(AICDWellTest) {
|
||||
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(AICDWellTest)
|
||||
{
|
||||
const auto dir_z = Opm::Connection::Direction::Z;
|
||||
const auto dir_x = Opm::Connection::Direction::X;
|
||||
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) );
|
||||
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) );
|
||||
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 Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||
|
||||
const auto depth = 0.0;
|
||||
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() );
|
||||
|
||||
@ -212,23 +224,33 @@ WSEGAICD
|
||||
const double center_depth_connection7 = connection7.depth();
|
||||
BOOST_CHECK_EQUAL(segment_number_connection7, 8);
|
||||
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
|
||||
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(MultisegmentWellTest)
|
||||
{
|
||||
const auto dir_z = Opm::Connection::Direction::Z;
|
||||
const auto dir_x = Opm::Connection::Direction::X;
|
||||
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) );
|
||||
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||
|
||||
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) );
|
||||
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) );
|
||||
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 depth = 0.0;
|
||||
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() );
|
||||
|
||||
@ -383,19 +405,32 @@ WSEGSICD
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS) {
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(WrongDistanceCOMPSEGS)
|
||||
{
|
||||
const auto dir_z = Opm::Connection::Direction::Z;
|
||||
const auto dir_x = Opm::Connection::Direction::X;
|
||||
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) );
|
||||
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) );
|
||||
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 Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25., 2500.0 };
|
||||
|
||||
const auto depth = 0.0;
|
||||
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() );
|
||||
|
||||
@ -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_AUTO_TEST_CASE(NegativeDepthCOMPSEGS) {
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(NegativeDepthCOMPSEGS)
|
||||
{
|
||||
const auto dir_z = Opm::Connection::Direction::Z;
|
||||
const auto dir_x = Opm::Connection::Direction::X;
|
||||
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) );
|
||||
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) );
|
||||
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 Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||
|
||||
const auto depth = 0.0;
|
||||
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() );
|
||||
|
||||
@ -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_AUTO_TEST_CASE(testwsegvalv) {
|
||||
auto dir = Opm::Connection::Direction::Z;
|
||||
BOOST_AUTO_TEST_CASE(testwsegvalv)
|
||||
{
|
||||
const auto dir_z = Opm::Connection::Direction::Z;
|
||||
const auto dir_x = Opm::Connection::Direction::X;
|
||||
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) );
|
||||
const Opm::EclipseGrid grid { 20,20,20, 1.0, 1.0, 25.0, 2500.0 };
|
||||
|
||||
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) );
|
||||
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) );
|
||||
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 depth = 0.0;
|
||||
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() );
|
||||
|
||||
|
@ -17,15 +17,6 @@
|
||||
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#define BOOST_TEST_MODULE ScheduleTests
|
||||
|
||||
#include <boost/test/unit_test.hpp>
|
||||
@ -37,6 +28,8 @@
|
||||
#include <boost/test/tools/floating_point_comparison.hpp>
|
||||
#endif
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
|
||||
#include <opm/common/utility/ActiveGridCells.hpp>
|
||||
#include <opm/common/utility/TimeService.hpp>
|
||||
#include <opm/common/utility/OpmInputError.hpp>
|
||||
@ -45,49 +38,62 @@
|
||||
#include <opm/io/eclipse/RestartFileView.hpp>
|
||||
#include <opm/io/eclipse/rst/state.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Python/Python.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/EclipseState.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/SimulationConfig/BCConfig.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/OilVaporizationProperties.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Python/Python.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||
#include <opm/input/eclipse/Schedule/GasLiftOpt.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GTNode.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Network/Balance.hpp>
|
||||
#include <opm/input/eclipse/Schedule/OilVaporizationProperties.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||
#include <opm/input/eclipse/Schedule/SummaryState.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellMatcher.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/NameOrder.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/PAvg.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WDFAC.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellConnections.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellFoamProperties.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellMatcher.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellPolymerProperties.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellTestConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WVFPEXP.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/SimulationConfig/BCConfig.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Units/Dimension.hpp>
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/input/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.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/Parser/ErrorGuard.hpp>
|
||||
#include <opm/input/eclipse/Parser/InputErrorAction.hpp>
|
||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
||||
#include <opm/input/eclipse/Units/Dimension.hpp>
|
||||
#include <opm/input/eclipse/Units/UnitSystem.hpp>
|
||||
#include <opm/input/eclipse/Units/Units.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRateConfig.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GuideRate.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Group/GTNode.hpp>
|
||||
#include <opm/input/eclipse/Schedule/CompletedCells.hpp>
|
||||
#include <opm/input/eclipse/Schedule/ScheduleGrid.hpp>
|
||||
#include <opm/input/eclipse/Parser/Parser.hpp>
|
||||
|
||||
#include "tests/WorkArea.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <fstream>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
namespace {
|
||||
@ -100,32 +106,33 @@ namespace {
|
||||
{
|
||||
return UnitSystem::newMETRIC().to_si(UnitSystem::measure::transmissibility, 1.0);
|
||||
}
|
||||
|
||||
Schedule make_schedule(const std::string& deck_string)
|
||||
{
|
||||
const auto deck = Parser{}.parseString(deck_string);
|
||||
|
||||
const EclipseGrid grid(10, 10, 10);
|
||||
const TableManager table (deck);
|
||||
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
const Runspec runspec (deck);
|
||||
|
||||
return { deck, grid, fp, runspec, std::make_shared<Python>() };
|
||||
}
|
||||
|
||||
static Schedule make_schedule(const std::string& deck_string) {
|
||||
const auto& deck = Parser{}.parseString(deck_string);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
return Schedule(deck, grid , fp, runspec, python);
|
||||
}
|
||||
|
||||
|
||||
static std::string createDeck() {
|
||||
std::string input = R"(
|
||||
std::string createDeck()
|
||||
{
|
||||
return { R"(
|
||||
START
|
||||
8 MAR 1998 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
static std::string createDeckWithWells() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWithWells()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
10 MAI 2007 /
|
||||
SCHEDULE
|
||||
@ -143,13 +150,12 @@ WELSPECS
|
||||
'WX2' 'OP' 30 37 3.33 'OIL' 7* /
|
||||
'W_3' 'OP' 20 51 3.92 'OIL' 7* /
|
||||
/;
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
|
||||
static std::string createDeckWTEST() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWTEST()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
10 MAI 2007 /
|
||||
GRID
|
||||
@ -246,12 +252,12 @@ DATES -- 5
|
||||
WCONINJH
|
||||
'BAN' 'WATER' 1* 1.0 /
|
||||
/
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
static std::string createDeckForTestingCrossFlow() {
|
||||
std::string input = R"(
|
||||
std::string createDeckForTestingCrossFlow()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
10 MAI 2007 /
|
||||
GRID
|
||||
@ -318,12 +324,12 @@ DATES -- 4
|
||||
WCONINJH
|
||||
'BAN' 'WATER' 1* 1.0 /
|
||||
/
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
static std::string createDeckWithWellsOrdered() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWithWellsOrdered()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
10 MAI 2007 /
|
||||
WELLDIMS
|
||||
@ -334,12 +340,12 @@ WELSPECS
|
||||
'BW_2' 'BG' 3 3 3.33 'OIL' 7* /
|
||||
'AW_3' 'AG' 2 5 3.92 'OIL' 7* /
|
||||
/
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
static std::string createDeckWithWellsOrderedGRUPTREE() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWithWellsOrderedGRUPTREE()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
10 MAI 2007 /
|
||||
SCHEDULE
|
||||
@ -355,13 +361,12 @@ WELSPECS
|
||||
'BW_2' 'CG2' 3 3 3.33 'OIL' 7* /
|
||||
'AW_3' 'CG2' 2 5 3.92 'OIL' 7* /
|
||||
/
|
||||
)";
|
||||
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
static std::string createDeckWithWellsAndCompletionData() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWithWellsAndCompletionData()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
1 NOV 1979 /
|
||||
GRID
|
||||
@ -398,17 +403,20 @@ DATES -- 2,3
|
||||
COMPDAT // with defaulted I and J
|
||||
'OP_1' 0 * 3 9 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||
/
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool has_name(const std::vector<std::string>& names, const std::string& name) {
|
||||
auto find_iter = std::find(names.begin(), names.end(), name);
|
||||
return (find_iter != names.end());
|
||||
bool has_name(const std::vector<std::string>& names,
|
||||
const std::string& name)
|
||||
{
|
||||
return std::any_of(names.begin(), names.end(),
|
||||
[&name](const std::string& search)
|
||||
{
|
||||
return search == name;
|
||||
});
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckMissingReturnsDefaults) {
|
||||
Deck deck;
|
||||
@ -448,14 +456,16 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrdered) {
|
||||
BOOST_CHECK_EQUAL(field_ptr->name(), "FIELD");
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static bool has_well( const std::vector<Well>& wells, const std::string& well_name) {
|
||||
bool has_well( const std::vector<Well>& wells, const std::string& well_name) {
|
||||
for (const auto& well : wells )
|
||||
if (well.name( ) == well_name)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsOrderedGRUPTREE) {
|
||||
const auto& schedule = make_schedule( createDeckWithWellsOrderedGRUPTREE() );
|
||||
@ -527,7 +537,6 @@ BOOST_AUTO_TEST_CASE(GroupTree2TEST) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWithStart) {
|
||||
const auto& schedule = make_schedule( createDeck() );
|
||||
BOOST_CHECK_EQUAL( schedule.getStartTime() , asTimeT(TimeStampUTC(1998, 3 , 8 )));
|
||||
@ -685,8 +694,11 @@ BOOST_AUTO_TEST_CASE(TestCrossFlowHandling) {
|
||||
BOOST_CHECK(Well::Status::OPEN == schedule.getWell("BAN", 5).getStatus());
|
||||
}
|
||||
|
||||
static std::string createDeckWithWellsAndSkinFactorChanges() {
|
||||
std::string input = R"(
|
||||
namespace {
|
||||
|
||||
std::string createDeckWithWellsAndSkinFactorChanges()
|
||||
{
|
||||
return { R"(RUNSPEC
|
||||
START -- 0
|
||||
1 NOV 1979 /
|
||||
GRID
|
||||
@ -708,6 +720,7 @@ WELSPECS
|
||||
'OP_3' 'OP' 7 7 1* 'OIL' 1* 1* 1* 1* 1* 1* 1* /
|
||||
/
|
||||
COMPDAT
|
||||
-- Well I J K1 K2 Status SATNUM CTF Diam Kh Skin D Dir PER (r0)
|
||||
'OP_1' 9 9 1 1 'OPEN' 1* 32.948 0.311 3047.839 1* 1* 'X' 22.100 /
|
||||
'OP_1' 9 9 2 2 'OPEN' 1* 46.825 0.311 4332.346 1* 1* 'X' 22.123 /
|
||||
'OP_2' 8 8 1 3 'OPEN' 1* 1.168 0.311 107.872 1* 1* 'Y' 21.925 /
|
||||
@ -727,21 +740,33 @@ CSKIN
|
||||
'OP_3' 7 7 1 1 -1.15 /
|
||||
/
|
||||
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndSkinFactorChanges) {
|
||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
||||
const auto& schedule = make_schedule(createDeckWithWellsAndSkinFactorChanges());
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndSkinFactorChanges)
|
||||
{
|
||||
auto metricCF = [units = Opm::UnitSystem::newMETRIC()]
|
||||
(const double ctf)
|
||||
{
|
||||
return units.from_si(Opm::UnitSystem::measure::transmissibility, ctf);
|
||||
};
|
||||
|
||||
const auto schedule = make_schedule(createDeckWithWellsAndSkinFactorChanges());
|
||||
|
||||
// OP_1
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 2).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).skinFactor(), 1.5, 1e-10);
|
||||
double CF = 25.290608354096133;
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.95609889
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 32.948 * 4.95609889 / (4.95609889 + 1.5)
|
||||
const double expectCF = 25.292912792;
|
||||
BOOST_CHECK_CLOSE(metricCF(cs.getFromIJK(8, 8, 0).CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
|
||||
// OP_2
|
||||
{
|
||||
const auto& well = schedule.getWell("OP_2", 2);
|
||||
@ -749,24 +774,40 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndSkinFactorChanges) {
|
||||
for (size_t i = 0; i < cs.size(); i++) {
|
||||
BOOST_CHECK_CLOSE(cs.get(i).skinFactor(), -1.0, 1e-10);
|
||||
}
|
||||
double CF = 7.822338909386947;
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(7, 6, 2).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.947899898
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 6.242 * 4.947899898 / (4.947899898 - 1.0)
|
||||
const double expectCF = 7.82309378689;
|
||||
BOOST_CHECK_CLOSE(metricCF(cs.getFromIJK(7, 6, 2).CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
|
||||
// OP_3
|
||||
{
|
||||
const auto& well = schedule.getWell("OP_3", 2);
|
||||
const auto& cs = well.getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(6, 6, 0).skinFactor(), - 1.15, 1e-10);
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(6, 6, 1).skinFactor(), 10.0, 1e-10);
|
||||
double CF1 = 36.09169888375442;
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(6, 6, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF1), 1e-5);
|
||||
double CF2 = 17.848489977420336;
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(6, 6, 1).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF2), 1e-5);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.7794177751
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 27.412 * 4.7794177751 / (4.7794177751 - 1.15)
|
||||
const double expectCF1 = 36.09763553531;
|
||||
BOOST_CHECK_CLOSE(metricCF(cs.getFromIJK(6, 6, 0).CF()), expectCF1, 1.0e-5);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.7794879307
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 55.195 * 4.7794879307 / (4.7794879307 + 10)
|
||||
const double expectCF2 = 17.84932181501;
|
||||
BOOST_CHECK_CLOSE(metricCF(cs.getFromIJK(6, 6, 1).CF()), expectCF2, 1.0e-5);
|
||||
}
|
||||
}
|
||||
|
||||
static std::string createDeckWithWPIMULTandWELPIandCSKIN() {
|
||||
std::string input = R"(
|
||||
namespace {
|
||||
|
||||
std::string createDeckWithWPIMULTandWELPIandCSKIN()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
1 NOV 1979 /
|
||||
GRID
|
||||
@ -848,22 +889,33 @@ CSKIN
|
||||
'OP_1' 9 9 1 1 -1.0 /
|
||||
/
|
||||
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWPIMULTandWELPIandCSKIN) {
|
||||
// Setup
|
||||
Opm::UnitSystem units(Opm::UnitSystem::UnitType::UNIT_TYPE_METRIC);
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWPIMULTandWELPIandCSKIN)
|
||||
{
|
||||
auto metricCF = [units = Opm::UnitSystem::newMETRIC()](const double ctf)
|
||||
{
|
||||
return units.from_si(Opm::UnitSystem::measure::transmissibility, ctf);
|
||||
};
|
||||
|
||||
// Note: Schedule must be mutable for WELPI scaling.
|
||||
auto schedule = make_schedule(createDeckWithWPIMULTandWELPIandCSKIN());
|
||||
|
||||
// Report step 2
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 2).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).skinFactor(), 1.5, 1e-10);
|
||||
double CF = 25.290608354096133;
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).wpimult(), 1.0, 1e-5);
|
||||
const auto& conn = cs.getFromIJK(8, 8, 0);
|
||||
|
||||
BOOST_CHECK_CLOSE(conn.skinFactor(), 1.5, 1e-10);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.95609889
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 32.948 * 4.95609889 / (4.95609889 + 1.5)
|
||||
const double expectCF = 25.292912792376;
|
||||
BOOST_CHECK_CLOSE(metricCF(conn.CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
|
||||
// Report step 3
|
||||
@ -871,15 +923,22 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWPIMULTandWELPIandCSKIN) {
|
||||
const auto& cs_prev = schedule.getWell("OP_1", 2).getConnections();
|
||||
const auto& cs_curr = schedule.getWell("OP_1", 3).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).CF() / cs_prev.getFromIJK(8, 8, 0).CF(), 1.3, 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).wpimult(), 1.3, 1e-5);
|
||||
}
|
||||
|
||||
// Report step 4
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 4).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).skinFactor(), 0.5, 1e-10);
|
||||
double CF = 38.90302007377862; // CF from CSKIN multiplied by 1.3 from WPIMULT
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
const auto& conn = cs.getFromIJK(8, 8, 0);
|
||||
|
||||
BOOST_CHECK_CLOSE(conn.skinFactor(), 0.5, 1e-10);
|
||||
|
||||
// CF from CSKIN multiplied by 1.3 from WPIMULT
|
||||
// denom = 2*pi*Kh / CTF = 4.95609889
|
||||
// mult = 1.3
|
||||
//
|
||||
// New CTF = mult * CTF * denom / (denom + S) = 1.3 * 32.948 * 4.95609889 / (4.95609889 + 0.5)
|
||||
const double expectCF = 38.90721454349;
|
||||
BOOST_CHECK_CLOSE(metricCF(conn.CF()), expectCF, 1e-5);
|
||||
}
|
||||
|
||||
// Report step 5
|
||||
@ -887,49 +946,69 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWPIMULTandWELPIandCSKIN) {
|
||||
const auto& cs_prev = schedule.getWell("OP_1", 4).getConnections();
|
||||
const auto& cs_curr = schedule.getWell("OP_1", 5).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).CF() / cs_prev.getFromIJK(8, 8, 0).CF(), 1.3, 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).wpimult(), 1.3 * 1.3, 1e-5);
|
||||
}
|
||||
|
||||
// Report step 6
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 6).getConnections();
|
||||
double init_pi = 100.0;
|
||||
schedule.applyWellProdIndexScaling("OP_1", 6, units.to_si(Opm::UnitSystem::measure::liquid_productivity_index, init_pi));
|
||||
const auto& target_pi = schedule[6].target_wellpi.at("OP_1");
|
||||
BOOST_CHECK_CLOSE(target_pi, 50.0, 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).wpimult(), 1.3 * 1.3 * (target_pi / init_pi), 1e-5);
|
||||
auto cvrtPI = [units = Opm::UnitSystem::newMETRIC()](const double pi)
|
||||
{
|
||||
return units.to_si(Opm::UnitSystem::measure::liquid_productivity_index, pi);
|
||||
};
|
||||
|
||||
const auto init_pi = cvrtPI(100.0);
|
||||
schedule.applyWellProdIndexScaling("OP_1", 6, init_pi);
|
||||
|
||||
const auto target_pi = schedule[6].target_wellpi.at("OP_1");
|
||||
BOOST_CHECK_CLOSE(target_pi, 50.0, 1.0e-5);
|
||||
}
|
||||
|
||||
// Report step 7
|
||||
{
|
||||
const auto& cs_prev = schedule.getWell("OP_1", 6).getConnections();
|
||||
const auto& cs_curr = schedule.getWell("OP_1", 7).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).skinFactor(), 5.0, 1e-10);
|
||||
double CF = 13.858329011932668; // CF from CSKIN multiplied by 0.845 from WPIMULT and WELPI previous
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs_curr.getFromIJK(8, 8, 0).wpimult(), cs_prev.getFromIJK(8, 8, 0).wpimult(), 1e-5);
|
||||
const auto& cs = schedule.getWell("OP_1", 7).getConnections();
|
||||
const auto& conn = cs.getFromIJK(8, 8, 0);
|
||||
|
||||
BOOST_CHECK_CLOSE(conn.skinFactor(), 5.0, 1e-10);
|
||||
|
||||
// denom = 2*pi*Kh / CTF = 4.95609889
|
||||
// mult = 1.3 * 1.3 * (50 / 100) = 0.845
|
||||
//
|
||||
// New CTF = mult * CTF * denom / (denom + S) = 0.845 * 32.948 * 4.95609889 / (4.95609889 + 5)
|
||||
|
||||
const auto expectCF = 13.8591478493;
|
||||
BOOST_CHECK_CLOSE(metricCF(conn.CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
|
||||
// Report step 8
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 8).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, 32.948), 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).wpimult(), 1.0, 1e-5);
|
||||
const auto& conn = cs.getFromIJK(8, 8, 0);
|
||||
|
||||
const auto expectCF = 32.948;
|
||||
BOOST_CHECK_CLOSE(metricCF(conn.CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
|
||||
// Report step 9
|
||||
{
|
||||
const auto& cs = schedule.getWell("OP_1", 9).getConnections();
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).skinFactor(), -1.0, 1e-10);
|
||||
double CF = 41.27026972084714; // CF from CSKIN with WPIMULT and WELLPI multiplier reset to 1.0
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).CF(), units.to_si(Opm::UnitSystem::measure::transmissibility, CF), 1e-5);
|
||||
BOOST_CHECK_CLOSE(cs.getFromIJK(8, 8, 0).wpimult(), 1.0, 1e-5);
|
||||
const auto& conn = cs.getFromIJK(8, 8, 0);
|
||||
|
||||
BOOST_CHECK_CLOSE(conn.skinFactor(), -1.0, 1e-10);
|
||||
|
||||
// CF from CSKIN with WPIMULT and WELLPI multiplier reset to 1.0
|
||||
//
|
||||
// denom = 2*pi*Kh / CTF = 4.95609889
|
||||
//
|
||||
// New CTF = CTF * denom / (denom + S) = 32.948 * 4.95609889 / (4.95609889 - 1)
|
||||
const auto expectCF = 41.276406579873;
|
||||
BOOST_CHECK_CLOSE(metricCF(conn.CF()), expectCF, 1.0e-5);
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
static std::string createDeckWithWellsAndConnectionDataWithWELOPEN() {
|
||||
std::string input = R"(
|
||||
std::string createDeckWithWellsAndConnectionDataWithWELOPEN()
|
||||
{
|
||||
return { R"(
|
||||
START -- 0
|
||||
1 NOV 1979 /
|
||||
GRID
|
||||
@ -986,10 +1065,11 @@ DATES -- 5
|
||||
WELOPEN
|
||||
'OP_1' SHUT 0 0 0 0 0 /
|
||||
/
|
||||
)";
|
||||
return input;
|
||||
)" };
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndConnectionDataWithWELOPEN) {
|
||||
const auto& schedule = make_schedule(createDeckWithWellsAndConnectionDataWithWELOPEN());
|
||||
{
|
||||
@ -2617,10 +2697,12 @@ BOOST_AUTO_TEST_CASE(WTEMPINJ_well_template) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
19 JUN 2007 /
|
||||
GRID
|
||||
PORO
|
||||
1000*0.3 /
|
||||
PERMX
|
||||
1000*0.10/
|
||||
COPY
|
||||
@ -2648,15 +2730,15 @@ BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {
|
||||
COMPDAT
|
||||
'W1' 0 0 1 1 'SHUT' 1* / -- respecify, essentially ignore (1)
|
||||
/
|
||||
)";
|
||||
END
|
||||
)");
|
||||
|
||||
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>());
|
||||
|
||||
auto deck = Parser().parseString(input);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule schedule( deck, grid, fp, runspec, python);
|
||||
const auto& cs1 = schedule.getWell( "W1", 1 ).getConnections( );
|
||||
BOOST_CHECK_EQUAL( 1, cs1.get( 0 ).complnum() );
|
||||
BOOST_CHECK_EQUAL( 2, cs1.get( 1 ).complnum() );
|
||||
@ -2671,7 +2753,7 @@ BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
19 JUN 2007 /
|
||||
GRID
|
||||
@ -2681,6 +2763,9 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
SCHEDULE
|
||||
DATES -- 1
|
||||
10 OKT 2008 /
|
||||
@ -2699,15 +2784,13 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
'W*' 0 0 3 5 'SHUT' 1* / -- two completions, two wells (includes existing
|
||||
-- and adding for both wells)
|
||||
/
|
||||
)";
|
||||
)");
|
||||
|
||||
auto deck = Parser().parseString( input);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid( 10, 10, 10 );
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule schedule( deck, grid, fp, runspec, python);
|
||||
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>());
|
||||
|
||||
{
|
||||
const auto& w1cs = schedule.getWell( "W1", 1 ).getConnections();
|
||||
@ -2745,7 +2828,7 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
19 JUN 2007 /
|
||||
GRID
|
||||
@ -2755,6 +2838,8 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
SCHEDULE
|
||||
DATES -- 1
|
||||
10 OKT 2008 /
|
||||
@ -2769,15 +2854,14 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
|
||||
'W1' 0 0 2 2 'SHUT' 1* / -- updated completion (2)
|
||||
'W1' 0 0 3 3 'SHUT' 1* / -- regular completion (3)
|
||||
/
|
||||
)";
|
||||
)");
|
||||
|
||||
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>());
|
||||
|
||||
auto deck = Parser().parseString(input);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule schedule( deck, grid, fp, runspec, python);
|
||||
const auto& cs = schedule.getWell( "W1", 1 ).getConnections();
|
||||
BOOST_CHECK_EQUAL( 3U, cs.size() );
|
||||
BOOST_CHECK_EQUAL( 1, cs.get( 0 ).complnum() );
|
||||
@ -2822,7 +2906,7 @@ BOOST_AUTO_TEST_CASE( complump_less_than_1 ) {
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( complump ) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
19 JUN 2007 /
|
||||
GRID
|
||||
@ -2832,6 +2916,9 @@ BOOST_AUTO_TEST_CASE( complump ) {
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
WELSPECS
|
||||
@ -2860,18 +2947,16 @@ BOOST_AUTO_TEST_CASE( complump ) {
|
||||
WELOPEN
|
||||
'W1' 'OPEN' 0 0 0 1 1 /
|
||||
/
|
||||
)";
|
||||
)");
|
||||
|
||||
constexpr auto open = Connection::State::OPEN;
|
||||
constexpr auto shut = Connection::State::SHUT;
|
||||
|
||||
auto deck = Parser().parseString(input);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule schedule( deck, grid, fp, runspec, python);
|
||||
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>());
|
||||
|
||||
const auto& sc0 = schedule.getWell("W1", 0).getConnections();
|
||||
/* complnum should be modified by COMPLNUM */
|
||||
@ -2932,10 +3017,8 @@ BOOST_AUTO_TEST_CASE( complump ) {
|
||||
BOOST_CHECK_THROW( all_connections.getFromGlobalIndex(100000), std::exception );
|
||||
}
|
||||
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
19 JUN 2007 /
|
||||
GRID
|
||||
@ -2945,6 +3028,9 @@ BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
SCHEDULE
|
||||
|
||||
WELSPECS
|
||||
@ -2980,18 +3066,16 @@ BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
|
||||
'W1' OPEN 0 0 0 2 2 / -- open the new 2 {2, 4, 5}
|
||||
'W1' OPEN 0 0 0 5 7 / -- open 5..7 {5, 6, 7, 8}
|
||||
/
|
||||
)";
|
||||
)");
|
||||
|
||||
constexpr auto open = Connection::State::OPEN;
|
||||
constexpr auto shut = Connection::State::SHUT;
|
||||
|
||||
auto deck = Parser().parseString( input);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid( 10, 10, 10 );
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule schedule( deck, grid, fp, runspec, python);
|
||||
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>());
|
||||
|
||||
const auto& cs1 = schedule.getWell("W1", 1).getConnections();
|
||||
const auto& cs2 = schedule.getWell("W1", 2).getConnections();
|
||||
@ -3843,9 +3927,16 @@ BOOST_AUTO_TEST_CASE(WTEST_CONFIG) {
|
||||
}
|
||||
|
||||
|
||||
static bool has(const std::vector<std::string>& l, const std::string& s) {
|
||||
auto f = std::find(l.begin(), l.end(), s);
|
||||
return (f != l.end());
|
||||
namespace {
|
||||
|
||||
bool has(const std::vector<std::string>& l, const std::string& s)
|
||||
{
|
||||
return std::any_of(l.begin(), l.end(),
|
||||
[&s](const std::string& search)
|
||||
{
|
||||
return search == s;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3885,18 +3976,8 @@ BOOST_AUTO_TEST_CASE(WELL_STATIC) {
|
||||
auto c2 = std::make_shared<WellConnections>(Connection::Order::TRACK, 1,1);
|
||||
c2->addConnection(1, 1, 1,
|
||||
grid1.getGlobalIndex(1, 1, 1),
|
||||
100,
|
||||
Connection::State::OPEN,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
10,
|
||||
100);
|
||||
100.0, Connection::CTFProperties{}, 10);
|
||||
|
||||
BOOST_CHECK( ws.updateConnections(c2, false) );
|
||||
BOOST_CHECK( !ws.updateConnections(c2, false) );
|
||||
@ -4869,12 +4950,16 @@ END
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
void cmp_vector(const std::vector<double>&v1, const std::vector<double>& v2) {
|
||||
BOOST_CHECK_EQUAL(v1.size(), v2.size());
|
||||
for (std::size_t i = 0; i < v1.size(); i++)
|
||||
BOOST_CHECK_CLOSE(v1[i], v2[i], 1e-4);
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(VFPPROD_SCALING) {
|
||||
const auto deck = Parser{}.parseFile("VFP_CASE.DATA");
|
||||
const auto es = EclipseState{ deck };
|
||||
@ -5128,6 +5213,8 @@ END
|
||||
BOOST_CHECK_EQUAL( netbalan1.thp_max_iter(), 5 );
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
bool compare_dates(const time_point& t, int year, int month, int day) {
|
||||
return t == TimeService::from_time_t( asTimeT( TimeStampUTC(year, month, day)));
|
||||
}
|
||||
@ -5141,6 +5228,7 @@ std::string dates_msg(const time_point& t, std::array<int,3>& ymd) {
|
||||
return fmt::format("Different dates: {}-{}-{} != {}-{}-{}", ts.year(), ts.month(), ts.day(), ymd[0], ymd[1], ymd[2]);
|
||||
}
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(ScheduleStateDatesTest) {
|
||||
const auto& sched = make_schedule(createDeckWTEST());
|
||||
@ -5692,7 +5780,7 @@ END
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(Test_wdfac) {
|
||||
std::string input = R"(
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
DIMENS
|
||||
10 10 10 /
|
||||
|
||||
@ -5768,51 +5856,59 @@ COMPDAT
|
||||
'W2' 3 3 3 3 'OPEN' 1* 1 0.216 200 1* 11 'X' /
|
||||
/
|
||||
|
||||
|
||||
END
|
||||
)");
|
||||
|
||||
)";
|
||||
Deck deck = Parser{}.parseString(input);
|
||||
const auto es = EclipseState { deck };
|
||||
const auto sched = Schedule { deck, es, std::make_shared<const Python>() };
|
||||
|
||||
const auto dFacUnit = 1*unit::day/unit::cubic(unit::meter);
|
||||
|
||||
const double rho = 1.0;
|
||||
const double mu = 0.01*prefix::centi*unit::Poise;
|
||||
const double phi = 0.3;
|
||||
|
||||
{
|
||||
const auto& well11 = sched.getWell("W1", 1);
|
||||
const auto& well21 = sched.getWell("W2", 1);
|
||||
const auto& wdfac11 = well11.getWDFAC();
|
||||
const auto& wdfac21 = well21.getWDFAC();
|
||||
|
||||
double rho = 1.0;
|
||||
double mu = 0.01*Opm::prefix::centi * Opm::unit::Poise;
|
||||
double phi = 0.3;
|
||||
|
||||
// WDFAC overwrites D factor in COMDAT
|
||||
BOOST_CHECK(wdfac11.useDFactor());
|
||||
BOOST_CHECK_MESSAGE(wdfac11.useDFactor(),
|
||||
R"(Well "W1" must use D-Factors at step 1)");
|
||||
|
||||
// well d factor scaled by connection CF.
|
||||
BOOST_CHECK_CLOSE(wdfac11.getDFactor(well11.getConnections()[0], mu, rho, phi), 6*1*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(wdfac21.getDFactor(well21.getConnections()[0], mu, rho, phi), 2*Opm::unit::day, 1e-12);
|
||||
// Well-level D-factor scaled by connection transmissibility factor.
|
||||
BOOST_CHECK_CLOSE(wdfac11.getDFactor(well11.getConnections()[0], mu, rho, phi), 6*1.0*dFacUnit, 1e-12);
|
||||
BOOST_CHECK_CLOSE(wdfac21.getDFactor(well21.getConnections()[0], mu, rho, phi), 2.0*dFacUnit, 1e-12);
|
||||
}
|
||||
|
||||
{
|
||||
const auto& well12 = sched.getWell("W1", 2);
|
||||
const auto& well22 = sched.getWell("W2", 2);
|
||||
const auto& wdfac12 = well12.getWDFAC();
|
||||
const auto& wdfac22 = well22.getWDFAC();
|
||||
|
||||
BOOST_CHECK_CLOSE(wdfac12.getDFactor(well12.getConnections()[0], mu, rho, phi), 5.19e-1, 3);
|
||||
BOOST_CHECK_CLOSE(wdfac22.getDFactor(well22.getConnections()[0], mu, rho, phi), 2*Opm::unit::day, 1e-12);
|
||||
|
||||
BOOST_CHECK_CLOSE(wdfac22.getDFactor(well22.getConnections()[0], mu, rho, phi), 2.0*dFacUnit, 1e-12);
|
||||
}
|
||||
|
||||
{
|
||||
const auto& well13 = sched.getWell("W1", 3);
|
||||
const auto& well23 = sched.getWell("W2", 3);
|
||||
const auto& wdfac13 = well13.getWDFAC();
|
||||
const auto& wdfac23 = well23.getWDFAC();
|
||||
BOOST_CHECK(wdfac13.useDFactor());
|
||||
|
||||
BOOST_CHECK_MESSAGE(wdfac13.useDFactor(),
|
||||
R"(Well "W1" must use D-Factors at step 3)");
|
||||
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[0].dFactor(), 0*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[1].dFactor(), 0*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[2].dFactor(), 11*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(wdfac13.getDFactor(well13.getConnections()[2], mu, rho, phi), 6/3*11*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(wdfac23.getDFactor(well23.getConnections()[0], mu, rho, phi), 2*Opm::unit::day, 1e-12);
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[0].dFactor(), 0.0*dFacUnit, 1e-12);
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[1].dFactor(), 0.0*dFacUnit, 1e-12);
|
||||
BOOST_CHECK_CLOSE(well13.getConnections()[2].dFactor(), 11.0*dFacUnit, 1e-12);
|
||||
|
||||
BOOST_CHECK_CLOSE(wdfac13.getDFactor(well13.getConnections()[2], mu, rho, phi), 6.0/3.0*11.0*dFacUnit, 1e-12);
|
||||
BOOST_CHECK_CLOSE(wdfac23.getDFactor(well23.getConnections()[0], mu, rho, phi), 2.0*dFacUnit, 1e-12);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(createDeckWithBC) {
|
||||
|
@ -22,192 +22,219 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Python/Python.hpp>
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.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/Parser/Parser.hpp>
|
||||
#include <opm/input/eclipse/Parser/ParseContext.hpp>
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
static Deck createDeckWithOutSolvent() {
|
||||
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";
|
||||
namespace {
|
||||
|
||||
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() {
|
||||
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' 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";
|
||||
Deck createDeckWithGasInjector()
|
||||
{
|
||||
return Parser{}.parseString(R"(
|
||||
GRID
|
||||
PERMX
|
||||
1000*0.25/
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
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() {
|
||||
Opm::Parser parser;
|
||||
std::string input =
|
||||
"START -- 0 \n"
|
||||
"1 JAN 2000 / \n"
|
||||
"GRID\n"
|
||||
"PERMX\n"
|
||||
" 1000*0.25/\n"
|
||||
"COPY\n"
|
||||
" PERMX PERMY /\n"
|
||||
" PERMX PERMZ /\n"
|
||||
"/\n"
|
||||
"SCHEDULE\n"
|
||||
"WELSPECS\n"
|
||||
" '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";
|
||||
Deck createDeckWithDynamicWSOLVENT()
|
||||
{
|
||||
return Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
1 JAN 2000 /
|
||||
GRID
|
||||
PERMX
|
||||
1000*0.25/
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
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() {
|
||||
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' 'OIL' 'OPEN' 'BHP' 1 2 3/\n/\n"
|
||||
"WSOLVENT\n"
|
||||
" 'W_1' 1 / \n "
|
||||
"/\n";
|
||||
|
||||
return parser.parseString(input);
|
||||
Deck createDeckWithOilInjector()
|
||||
{
|
||||
return Parser{}.parseString(R"(
|
||||
GRID
|
||||
PERMX
|
||||
1000*0.25/
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
SCHEDULE
|
||||
WELSPECS
|
||||
'W_1' 'OP' 2 2 1* 'OIL' 7* /
|
||||
/
|
||||
COMPDAT
|
||||
'W_1' 2* 1 1 'OPEN' /
|
||||
/
|
||||
WCONINJE
|
||||
'W_1' 'OIL' 'OPEN' 'BHP' 1 2 3/
|
||||
/
|
||||
WSOLVENT
|
||||
'W_1' 1 /
|
||||
/
|
||||
END
|
||||
)");
|
||||
}
|
||||
|
||||
static Deck createDeckWithWaterInjector() {
|
||||
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"
|
||||
"WSOLVENT\n"
|
||||
" 'W_1' 1 / \n "
|
||||
"/\n";
|
||||
|
||||
return parser.parseString(input);
|
||||
Deck createDeckWithWaterInjector()
|
||||
{
|
||||
return Parser{}.parseString(R"(
|
||||
GRID
|
||||
PERMX
|
||||
1000*0.25/
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
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/
|
||||
/
|
||||
WSOLVENT
|
||||
'W_1' 1 /
|
||||
/
|
||||
END
|
||||
)");
|
||||
}
|
||||
BOOST_AUTO_TEST_CASE(TestNoSolvent) {
|
||||
auto deck = createDeckWithOutSolvent();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec(deck);
|
||||
Schedule schedule(deck, grid , fp, runspec, python);
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestNoSolvent)
|
||||
{
|
||||
const auto deck = createDeckWithOutSolvent();
|
||||
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_CHECK(!deck.hasKeyword("WSOLVENT"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestGasInjector) {
|
||||
auto deck = createDeckWithGasInjector();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec(deck);
|
||||
Schedule schedule(deck, grid , fp, runspec, python);
|
||||
const auto deck = createDeckWithGasInjector();
|
||||
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_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT) {
|
||||
auto deck = createDeckWithDynamicWSOLVENT();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec(deck);
|
||||
Schedule schedule(deck, grid , fp, runspec, python);
|
||||
BOOST_AUTO_TEST_CASE(TestDynamicWSOLVENT)
|
||||
{
|
||||
const auto deck = createDeckWithDynamicWSOLVENT();
|
||||
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_CHECK(deck.hasKeyword("WSOLVENT"));
|
||||
|
||||
const auto& keyword = deck["WSOLVENT"].back();
|
||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||
|
||||
const auto& record = keyword.getRecord(0);
|
||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||
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_AUTO_TEST_CASE(TestOilInjector) {
|
||||
auto deck = createDeckWithOilInjector();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec(deck);
|
||||
BOOST_CHECK_THROW (Schedule(deck , grid , fp, runspec, python), std::exception);
|
||||
BOOST_AUTO_TEST_CASE(TestOilInjector)
|
||||
{
|
||||
const auto deck = createDeckWithOilInjector();
|
||||
const EclipseGrid grid(10,10,10);
|
||||
const TableManager table (deck);
|
||||
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
const Runspec runspec(deck);
|
||||
|
||||
BOOST_CHECK_THROW (Schedule(deck, grid, fp, runspec, std::make_shared<Python>()), std::exception);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestWaterInjector) {
|
||||
auto deck = createDeckWithWaterInjector();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec(deck);
|
||||
BOOST_CHECK_THROW (Schedule(deck, grid , fp, runspec, python), std::exception);
|
||||
BOOST_AUTO_TEST_CASE(TestWaterInjector)
|
||||
{
|
||||
const auto deck = createDeckWithWaterInjector();
|
||||
const EclipseGrid grid(10,10,10);
|
||||
const TableManager table ( deck );
|
||||
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
const Runspec runspec(deck);
|
||||
|
||||
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 <opm/common/utility/OpmInputError.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Python/Python.hpp>
|
||||
|
||||
#include <opm/input/eclipse/EclipseState/Grid/FieldPropsManager.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Grid/EclipseGrid.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Runspec.hpp>
|
||||
#include <opm/input/eclipse/EclipseState/Tables/TableManager.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Schedule/Schedule.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/Well.hpp>
|
||||
#include <opm/input/eclipse/Schedule/Well/WellTracerProperties.hpp>
|
||||
|
||||
#include <opm/input/eclipse/Deck/Deck.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/Parser/Parser.hpp>
|
||||
|
||||
using namespace Opm;
|
||||
|
||||
static Deck createDeckWithOutTracer() {
|
||||
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";
|
||||
namespace {
|
||||
|
||||
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() {
|
||||
Opm::Parser parser;
|
||||
std::string input =
|
||||
"START -- 0 \n"
|
||||
"1 JAN 2000 / \n"
|
||||
"GRID\n"
|
||||
"PERMX\n"
|
||||
" 1000*0.25/\n"
|
||||
"COPY\n"
|
||||
" PERMX PERMY /\n"
|
||||
" PERMX PERMZ /\n"
|
||||
"/\n"
|
||||
"SCHEDULE\n"
|
||||
"WELSPECS\n"
|
||||
" '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 -- 1\n"
|
||||
" 1 MAY 2000 / \n"
|
||||
"/\n"
|
||||
"WTRACER\n"
|
||||
" 'W_1' 'I1' 1 / \n "
|
||||
" '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";
|
||||
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 -- 1
|
||||
1 MAY 2000 /
|
||||
/
|
||||
WTRACER
|
||||
'W_1' 'I1' 1 /
|
||||
'W_1' 'I2' 1 /
|
||||
/
|
||||
DATES -- 2, 3
|
||||
1 JUL 2000 /
|
||||
1 AUG 2000 /
|
||||
/
|
||||
WTRACER
|
||||
'W_1' 'I1' 0 /
|
||||
/
|
||||
DATES -- 4
|
||||
1 SEP 2000 /
|
||||
/
|
||||
|
||||
return parser.parseString(input);
|
||||
END
|
||||
)");
|
||||
}
|
||||
|
||||
static Deck createDeckWithTracerInProducer() {
|
||||
Opm::Parser parser;
|
||||
std::string input =
|
||||
"START -- 0 \n"
|
||||
"1 JAN 2000 / \n"
|
||||
"GRID\n"
|
||||
"PERMX\n"
|
||||
" 1000*0.25/\n"
|
||||
"COPY\n"
|
||||
" PERMX PERMY /\n"
|
||||
" PERMX PERMZ /\n"
|
||||
"/\n"
|
||||
"SCHEDULE\n"
|
||||
"WELSPECS\n"
|
||||
" '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";
|
||||
Deck createDeckWithTracerInProducer()
|
||||
{
|
||||
return Parser{}.parseString(R"(
|
||||
START -- 0
|
||||
1 JAN 2000 /
|
||||
GRID
|
||||
PERMX
|
||||
1000*0.25/
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
1000*0.3 /
|
||||
|
||||
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_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
||||
auto deck = createDeckWithDynamicWTRACER();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec ( deck );
|
||||
Schedule schedule(deck, grid , fp, runspec, python);
|
||||
BOOST_AUTO_TEST_CASE(TestDynamicWTRACER)
|
||||
{
|
||||
const auto deck = createDeckWithDynamicWTRACER();
|
||||
|
||||
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_CHECK(deck.hasKeyword("WTRACER"));
|
||||
|
||||
const auto& keyword = deck["WTRACER"].back();
|
||||
BOOST_CHECK_EQUAL(keyword.size(),1U);
|
||||
|
||||
const auto& record = keyword.getRecord(0);
|
||||
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
|
||||
BOOST_CHECK_EQUAL(well_name, "W_1");
|
||||
@ -169,13 +194,13 @@ BOOST_AUTO_TEST_CASE(TestDynamicWTRACER) {
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW) {
|
||||
auto deck = createDeckWithTracerInProducer();
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(10,10,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp( deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec ( deck );
|
||||
BOOST_AUTO_TEST_CASE(TestTracerInProducerTHROW)
|
||||
{
|
||||
const auto deck = createDeckWithTracerInProducer();
|
||||
const EclipseGrid grid(10,10,10);
|
||||
const TableManager table (deck);
|
||||
const FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
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) {
|
||||
Parser parser;
|
||||
const char * deckString = "\n\
|
||||
START\n\
|
||||
\n\
|
||||
10 MAI 2007 /\n\
|
||||
\n\
|
||||
GRID\n\
|
||||
PERMX\n\
|
||||
9000*0.25 /\n\
|
||||
COPY \n\
|
||||
PERMX PERMY /\n\
|
||||
PERMX PERMZ /\n\
|
||||
/\n\
|
||||
SCHEDULE\n\
|
||||
WELSPECS \n\
|
||||
'W1' 'OP' 11 21 3.33 'OIL' 7* / \n\
|
||||
/\n\
|
||||
COMPDAT \n\
|
||||
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /\n\
|
||||
/\n";
|
||||
auto deck = parser.parseString(deckString);
|
||||
auto python = std::make_shared<Python>();
|
||||
EclipseGrid grid(30,30,10);
|
||||
TableManager table ( deck );
|
||||
FieldPropsManager fp(deck, Phases{true, true, true}, grid, table);
|
||||
Runspec runspec (deck);
|
||||
Schedule sched(deck, grid , fp, runspec, python);
|
||||
BOOST_AUTO_TEST_CASE(TestDefaultedCOMPDATIJ)
|
||||
{
|
||||
const auto deck = Parser{}.parseString(R"(
|
||||
START
|
||||
|
||||
10 MAI 2007 /
|
||||
|
||||
GRID
|
||||
PERMX
|
||||
9000*0.25 /
|
||||
COPY
|
||||
PERMX PERMY /
|
||||
PERMX PERMZ /
|
||||
/
|
||||
PORO
|
||||
9000*0.3 /
|
||||
|
||||
SCHEDULE
|
||||
WELSPECS
|
||||
'W1' 'OP' 11 21 3.33 'OIL' 7* /
|
||||
/
|
||||
COMPDAT
|
||||
'W1' 2* 1 1 'OPEN' 1* 32.948 0.311 3047.839 2* 'X' 22.100 /
|
||||
/
|
||||
END
|
||||
)");
|
||||
|
||||
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();
|
||||
BOOST_CHECK_EQUAL( 10 , connections.get(0).getI() );
|
||||
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[5].wellgroup_events().hasEvent( "W_1", ScheduleEvents::COMPLETION_CHANGE));
|
||||
}
|
||||
|
||||
|
@ -57,12 +57,22 @@ namespace {
|
||||
const auto j = (dims[1] - 1) - 1;
|
||||
|
||||
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,
|
||||
2000 + (2*k + 1) / static_cast<double>(2),
|
||||
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::CTFKind::DeckValue, k, false);
|
||||
Opm::Connection::CTFKind::DeckValue,
|
||||
0, depth, ctf_props, k, false);
|
||||
}
|
||||
|
||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||
@ -87,18 +97,28 @@ namespace {
|
||||
};
|
||||
|
||||
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,
|
||||
2000 + (2*k + 1) / static_cast<double>(2),
|
||||
|
||||
// Open, Shut, Open, Open, Shut, ...
|
||||
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::CTFKind::DeckValue, k - topConn, false);
|
||||
Opm::Connection::CTFKind::DeckValue,
|
||||
0, depth, ctf_props, k - topConn, false);
|
||||
}
|
||||
|
||||
return { Opm::Connection::Order::INPUT, i, j, conns };
|
||||
@ -115,12 +135,22 @@ namespace {
|
||||
const auto iMax = std::min(dims[0] - 1, left + numConns);
|
||||
|
||||
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,
|
||||
2000 + (2*k + 1) / static_cast<double>(2),
|
||||
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::CTFKind::DeckValue, i - left, false);
|
||||
Opm::Connection::CTFKind::DeckValue,
|
||||
0, depth, ctf_props, i - left, false);
|
||||
}
|
||||
|
||||
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(BrineDensityTable)
|
||||
TEST_FOR_TYPE(ColumnSchema)
|
||||
TEST_FOR_TYPE_NAMED(Connection::CTFProperties, CTFProperties)
|
||||
TEST_FOR_TYPE(Connection)
|
||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_CarterTracy, serializationTestObjectC)
|
||||
TEST_FOR_TYPE_NAMED_OBJ(data::AquiferData, AquiferData_Fetkovich, serializationTestObjectF)
|
||||
|
Loading…
Reference in New Issue
Block a user