Merge pull request #435 from joakim-hove/completion-support2

Completion support2
This commit is contained in:
Joakim Hove 2018-06-28 09:58:36 +02:00 committed by GitHub
commit 1f7a2d5459
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
26 changed files with 653 additions and 849 deletions

View File

@ -34,10 +34,6 @@ namespace Opm {
class DeckKeyword;
class DeckRecord;
class Well;
class EclipseGrid;
class Eclipse3DProperties;
class Schedule;
class Connection {
public:
@ -49,62 +45,39 @@ namespace Opm {
const Value<double>& diameter,
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z);
const WellCompletion::DirectionEnum direction);
Connection(const Connection&, WellCompletion::StateEnum newStatus);
Connection(const Connection&, double wellPi);
Connection(const Connection&, int complnum );
Connection(const Connection& connection_initial, int segment_number, double center_depth);
bool sameCoordinate(const Connection& other) const;
bool sameCoordinate(const int i, const int j, const int k) const;
int getI() const;
int getJ() const;
int getK() const;
int complnum() const;
WellCompletion::StateEnum getState() const;
double getConnectionTransmissibilityFactor() const;
double getWellPi() const;
const Value<double>& getConnectionTransmissibilityFactorAsValueObject() const;
double getDiameter() const;
double getSkinFactor() const;
int getSatTableId() const;
void fixDefaultIJ(int wellHeadI , int wellHeadJ);
void shift_complnum( int );
int getSegmentNumber() const;
double getCenterDepth() const;
bool attachedToSegment() const;
WellCompletion::DirectionEnum getDirection() const;
static std::map< std::string, std::vector< Connection > >
fromCOMPDAT( const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties,
const DeckKeyword& compdatKeyword,
const std::vector< const Well* >&,
const ParseContext&,
const Schedule&);
const Value<double>& getConnectionTransmissibilityFactorAsValueObject() const;
bool operator==( const Connection& ) const;
bool operator!=( const Connection& ) const;
WellCompletion::DirectionEnum dir;
double center_depth;
WellCompletion::StateEnum state;
int sat_tableId;
int complnum;
private:
int m_i, m_j, m_k;
int m_complnum;
std::array<int,3> ijk;
Value<double> m_diameter;
Value<double> m_connectionTransmissibilityFactor;
double m_wellPi;
Value<double> m_skinFactor;
int m_satTableId;
WellCompletion::StateEnum m_state;
WellCompletion::DirectionEnum m_direction;
Value<double> getDiameterAsValueObject() const;
Value<double> getSkinFactorAsValueObject() const;
public:
// related segment number
// -1 means the completion is not related to segment
int m_segment_number = -1;
double m_center_depth;
int segment_number = -1;
double wellPi = 1.0;
};
}

View File

@ -58,7 +58,7 @@ namespace Opm {
private:
// segment number
// it should work as a ID.
int m_segment_number;
int segment_number;
// branch number
// for top segment, it should always be 1
int m_branch;

View File

@ -50,7 +50,7 @@ namespace Opm {
void addSegment(Segment new_segment);
void segmentsFromWELSEGSKeyword( const DeckKeyword& welsegsKeyword);
void loadWELSEGS( const DeckKeyword& welsegsKeyword);
const Segment& getFromSegmentNumber(const int segment_number) const;
@ -91,7 +91,7 @@ namespace Opm {
std::vector< Segment > m_segments;
// the mapping from the segment number to the
// storage index in the vector
std::map<int, int> m_segment_number_to_index;
std::map<int, int> segment_number_to_index;
};
}

View File

@ -26,7 +26,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
namespace Opm {
WellConnections updatingConnectionsWithSegments(const DeckKeyword& compsegs, const WellConnections& input_connections, const WellSegments& segments);
WellConnections * newConnectionsWithSegments(const DeckKeyword& compsegs, const WellConnections& input_connections, const WellSegments& segments);
}
#endif

View File

@ -94,11 +94,29 @@ namespace Opm {
bool isInjector(size_t timeStep) const;
void addWELSPECS(const DeckRecord& deckRecord);
void addConnections(size_t time_step, const std::vector< Connection >& );
void addWellConnections(size_t time_step, WellConnections );
/*
The getCompletions() function will return a map:
{
1 : [Connection, Connection],
2 : [Connection, Connection, Connecton],
-3 : [Connection]
-7 : [Connection]
}
The integer ID's correspond to the COMPLETION id given by the COMPLUMP
keyword. All positive id values come from COMPLUMP, whereas the
negative values are arbitrary negative id values for connections which
have not been lumped together in a completion. In the case of negative
id values the list of connections always has exactly one element.
*/
std::map<int, std::vector<Connection>> getCompletions(size_t time_step) const;
const WellConnections& getConnections(size_t timeStep) const;
const WellConnections& getConnections() const;
WellConnections getActiveConnections(size_t timeStep, const EclipseGrid& grid) const;
WellConnections * newWellConnections(size_t time_step);
void updateWellConnections(size_t time_step, WellConnections * new_set );
/* The rate of a given phase under the following assumptions:
* * Returns zero if production is requested for an injector (and vice
@ -164,6 +182,13 @@ namespace Opm {
const Events& getEvents() const;
void addEvent(ScheduleEvents::Events event, size_t reportStep);
bool hasEvent(uint64_t eventMask, size_t reportStep) const;
void handleCOMPLUMP(const DeckRecord& record, size_t time_step);
void handleCOMPDAT(size_t time_step, const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties);
void handleCOMPSEGS(const DeckKeyword& keyword, size_t time_step);
void handleWELOPEN(const DeckRecord& record, size_t time_step, WellCompletion::StateEnum status);
void handleWPIMULT(const DeckRecord& record, size_t time_step);
void handleWELSEGS(const DeckKeyword& keyword, size_t time_step);
/*
Will remove all completions which are attached to inactive cells. Will
@ -183,7 +208,7 @@ namespace Opm {
DynamicState< double > m_efficiencyFactors;
DynamicState< int > m_isProducer;
DynamicState< WellConnections > m_completions;
DynamicState< std::shared_ptr<WellConnections> > m_completions;
DynamicState< WellProductionProperties > m_productionProperties;
DynamicState< WellInjectionProperties > m_injectionProperties;
DynamicState< WellPolymerProperties > m_polymerProperties;

View File

@ -25,13 +25,22 @@
namespace Opm {
class EclipseGrid;
class Eclipse3DProperties;
class WellConnections {
public:
WellConnections() = default;
WellConnections(int headI, int headJ);
// cppcheck-suppress noExplicitConstructor
WellConnections( std::initializer_list< Connection > );
WellConnections(const WellConnections& src, const EclipseGrid& grid);
void addConnection(int i, int j , int k ,
double depth,
WellCompletion::StateEnum state ,
const Value<double>& connectionTransmissibilityFactor,
const Value<double>& diameter,
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z);
void loadCOMPDAT(const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties);
using const_iterator = std::vector< Connection >::const_iterator;
@ -39,6 +48,7 @@ namespace Opm {
size_t size() const;
const Connection& get(size_t index) const;
const Connection& getFromIJK(const int i, const int j, const int k) const;
Connection& getFromIJK(const int i, const int j, const int k);
const_iterator begin() const { return this->m_connections.begin(); }
const_iterator end() const { return this->m_connections.end(); }
@ -62,8 +72,19 @@ namespace Opm {
bool operator!=( const WellConnections& ) const;
private:
void addConnection(int i, int j , int k ,
int complnum,
double depth,
WellCompletion::StateEnum state ,
const Value<double>& connectionTransmissibilityFactor,
const Value<double>& diameter,
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnum::Z);
std::vector< Connection > m_connections;
size_t findClosestConnection(int oi, int oj, double oz, size_t start_pos);
int headI, headJ;
};
}

View File

@ -46,9 +46,10 @@ public:
int num_attempt;
};
struct ClosedCompletion {
std::string wellName;
size_t completion;
int complnum;
double last_test;
int num_attempt;
};
@ -63,7 +64,7 @@ public:
The simulator has decided to close a particular completion in a well; we then add it here
as a closed completions
*/
void addClosedCompletion(const std::string& well_name, size_t completionIdx, double sim_time);
void addClosedCompletion(const std::string& well_name, int complnum, double sim_time);
/*
The update will consult the WellTestConfig object and return a list of
@ -79,7 +80,7 @@ public:
update method will update the internal state of the object by counting up
the openiing attempts, and also set the time for the last attempt to open.
*/
std::vector<std::pair<std::string, size_t>> updateCompletion(const WellTestConfig& config, double sim_time);
std::vector<std::pair<std::string, int>> updateCompletion(const WellTestConfig& config, double sim_time);
/*
@ -94,12 +95,12 @@ public:
method should be called to indicate that this reason for keeping the well
closed is no longer active.
*/
void dropCompletion(const std::string& well_name, size_t completionIdx);
void dropCompletion(const std::string& well_name, int complnum);
bool hasWell(const std::string& well_name, WellTestConfig::Reason reason) const;
void openWell(const std::string& well_name);
bool hasCompletion(const std::string& well_name, const size_t completionIdx) const;
bool hasCompletion(const std::string& well_name, const int complnum) const;
size_t sizeWells() const;
size_t sizeCompletions() const;

View File

@ -194,7 +194,7 @@ data::Wells restore_wells( const ecl_kw_type * opm_xwel,
for( const auto& sc : sched_well->getConnections( sim_step ) ) {
const auto i = sc.getI(), j = sc.getJ(), k = sc.getK();
if( !grid.cellActive( i, j, k ) || sc.getState() == WellCompletion::SHUT ) {
if( !grid.cellActive( i, j, k ) || sc.state == WellCompletion::SHUT ) {
opm_xwel_data += data::Connection::restart_size + phases.size();
continue;
}
@ -298,10 +298,10 @@ std::vector<int> serialize_ICON( int sim_step,
data[ offset + ICON_I_INDEX ] = connection.getI() + 1;
data[ offset + ICON_J_INDEX ] = connection.getJ() + 1;
data[ offset + ICON_K_INDEX ] = connection.getK() + 1;
data[ offset + ICON_DIRECTION_INDEX ] = connection.getDirection();
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir;
{
const auto open = WellCompletion::StateEnum::OPEN;
data[ offset + ICON_STATUS_INDEX ] = connection.getState() == open
data[ offset + ICON_STATUS_INDEX ] = connection.state == open
? 1
: 0;
}
@ -396,7 +396,7 @@ std::vector< double > serialize_OPM_XWEL( const data::Wells& wells,
const auto i = sc.getI(), j = sc.getJ(), k = sc.getK();
const auto rs_size = phases.size() + data::Connection::restart_size;
if( !grid.cellActive( i, j, k ) || sc.getState() == WellCompletion::SHUT ) {
if( !grid.cellActive( i, j, k ) || sc.state == WellCompletion::SHUT ) {
xwel.insert( xwel.end(), rs_size, 0.0 );
continue;
}

View File

@ -94,17 +94,17 @@ serialize_ICON(int lookup_step,
for (const auto& connection : connections) {
const size_t offset = well_offset + connection_offset;
data[ offset + ICON_IC_INDEX ] = connection.complnum();
data[ offset + ICON_IC_INDEX ] = connection.complnum;
data[ offset + ICON_I_INDEX ] = connection.getI() + 1;
data[ offset + ICON_J_INDEX ] = connection.getJ() + 1;
data[ offset + ICON_K_INDEX ] = connection.getK() + 1;
data[ offset + ICON_DIRECTION_INDEX ] = connection.getDirection();
data[ offset + ICON_DIRECTION_INDEX ] = connection.dir;
data[ offset + ICON_STATUS_INDEX ] =
(connection.getState() == WellCompletion::StateEnum::OPEN) ?
(connection.state == WellCompletion::StateEnum::OPEN) ?
1 : -1000;
data[ offset + ICON_SEGMENT_INDEX ] =
connection.attachedToSegment() ?
connection.getSegmentNumber() : 0;
connection.segment_number : 0;
connection_offset += niconz;
}

View File

@ -45,59 +45,19 @@ namespace Opm {
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction)
: m_i(i), m_j(j), m_k(k),
m_complnum( compnum ),
: dir(direction),
center_depth(depth),
state(state),
sat_tableId(satTableId),
complnum( compnum ),
ijk({i,j,k}),
m_diameter(diameter),
m_connectionTransmissibilityFactor(connectionTransmissibilityFactor),
m_wellPi(1.0),
m_skinFactor(skinFactor),
m_satTableId(satTableId),
m_state(state),
m_direction(direction),
m_center_depth( depth )
m_skinFactor(skinFactor)
{}
Connection::Connection(const Connection& oldConnection, WellCompletion::StateEnum newStatus ) :
Connection( oldConnection )
{
this->m_state = newStatus;
}
Connection::Connection(const Connection& oldConnection, double wellPi) :
Connection( oldConnection )
{
if( this->m_wellPi != 0 ) {
this->m_wellPi *= wellPi;
} else {
this->m_wellPi = wellPi;
}
}
Connection::Connection( const Connection& c, int num ) :
Connection( c )
{
this->m_complnum = num;
}
Connection::Connection(const Connection& connection_initial, int segment_number, double center_depth)
: Connection(connection_initial)
{
assert(segment_number > 0);
this->m_segment_number = segment_number;
this->m_center_depth = center_depth;
}
bool Connection::sameCoordinate(const Connection& other) const {
if ((m_i == other.m_i) &&
(m_j == other.m_j) &&
(m_k == other.m_k))
return true;
else
return false;
}
bool Connection::sameCoordinate(const int i, const int j, const int k) const {
if ((m_i == i) && (m_j == j) && (m_k == k)) {
if ((ijk[0] == i) && (ijk[1] == j) && (ijk[2] == k)) {
return true;
} else {
return false;
@ -105,165 +65,19 @@ namespace Opm {
}
/**
This will break up one record and return a pair: <name ,
[Connection1, Connection2, ... , ConnectionN]>. The reason it
will return a list is that the 'K1 K2' structure is
disentangled, and each completion is returned separately.
*/
inline std::vector< Connection >
fromCOMPDAT( const EclipseGrid& grid,
const Eclipse3DProperties& eclipseProperties,
const DeckRecord& compdatRecord,
const Well& well,
int prev_complnum ) {
std::vector< Connection > completions;
// We change from eclipse's 1 - n, to a 0 - n-1 solution
// I and J can be defaulted with 0 or *, in which case they are fetched
// from the well head
const auto& itemI = compdatRecord.getItem( "I" );
const auto defaulted_I = itemI.defaultApplied( 0 ) || itemI.get< int >( 0 ) == 0;
const int I = !defaulted_I ? itemI.get< int >( 0 ) - 1 : well.getHeadI();
const auto& itemJ = compdatRecord.getItem( "J" );
const auto defaulted_J = itemJ.defaultApplied( 0 ) || itemJ.get< int >( 0 ) == 0;
const int J = !defaulted_J ? itemJ.get< int >( 0 ) - 1 : well.getHeadJ();
int K1 = compdatRecord.getItem("K1").get< int >(0) - 1;
int K2 = compdatRecord.getItem("K2").get< int >(0) - 1;
WellCompletion::StateEnum state = WellCompletion::StateEnumFromString( compdatRecord.getItem("STATE").getTrimmedString(0) );
Value<double> connectionTransmissibilityFactor("CompletionTransmissibilityFactor");
Value<double> diameter("Diameter");
Value<double> skinFactor("SkinFactor");
int satTableId;
const auto& satnum = eclipseProperties.getIntGridProperty("SATNUM");
bool defaultSatTable = true;
{
const auto& connectionTransmissibilityFactorItem = compdatRecord.getItem("CONNECTION_TRANSMISSIBILITY_FACTOR");
const auto& diameterItem = compdatRecord.getItem("DIAMETER");
const auto& skinFactorItem = compdatRecord.getItem("SKIN");
const auto& satTableIdItem = compdatRecord.getItem("SAT_TABLE");
if (connectionTransmissibilityFactorItem.hasValue(0) && connectionTransmissibilityFactorItem.getSIDouble(0) > 0)
connectionTransmissibilityFactor.setValue(connectionTransmissibilityFactorItem.getSIDouble(0));
if (diameterItem.hasValue(0))
diameter.setValue( diameterItem.getSIDouble(0));
if (skinFactorItem.hasValue(0))
skinFactor.setValue( skinFactorItem.get< double >(0));
if (satTableIdItem.hasValue(0) && satTableIdItem.get < int > (0) > 0)
{
satTableId = satTableIdItem.get< int >(0);
defaultSatTable = false;
}
}
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnumFromString(compdatRecord.getItem("DIR").getTrimmedString(0));
for (int k = K1; k <= K2; k++) {
if (defaultSatTable)
satTableId = satnum.iget(grid.getGlobalIndex(I,J,k));
completions.emplace_back( I, J, k,
int( completions.size() + prev_complnum ) + 1,
grid.getCellDepth( I,J,k ),
state,
connectionTransmissibilityFactor,
diameter,
skinFactor,
satTableId,
direction );
}
return completions;
}
/*
Will return a map:
{
"WELL1" : [ Connection1 , Connection2 , ... , ConnectionN ],
"WELL2" : [ Connection1 , Connection2 , ... , ConnectionN ],
...
}
*/
std::map< std::string, std::vector< Connection > >
Connection::fromCOMPDAT( const EclipseGrid& grid ,
const Eclipse3DProperties& eclipseProperties,
const DeckKeyword& compdatKeyword,
const std::vector< const Well* >& wells,
const ParseContext& parseContext,
const Schedule& schedule) {
std::map< std::string, std::vector< Connection > > res;
std::vector< int > prev_compls( wells.size(), 0 );
for( const auto& record : compdatKeyword ) {
const auto wellNamePattern = record.getItem( "WELL" ).getTrimmedString( 0 );
const auto& matched_wells = schedule.getWellsMatching(wellNamePattern);
if (matched_wells.empty())
schedule.invalidNamePattern(wellNamePattern, parseContext, compdatKeyword);
for (const auto& well : matched_wells){
const auto it_pos = std::find( wells.begin(), wells.end(), well);
const auto index = std::distance( wells.begin(), it_pos );
auto completions = Opm::fromCOMPDAT( grid,
eclipseProperties,
record,
*well,
prev_compls[ index ] );
prev_compls[ index ] += completions.size();
res[ well->name() ].insert( res[ well->name() ].end(),
std::make_move_iterator( completions.begin() ),
std::make_move_iterator( completions.end() ) );
}
}
return res;
}
void Connection::fixDefaultIJ(int wellHeadI , int wellHeadJ) {
if (m_i < 0)
m_i = wellHeadI;
if (m_j < 0)
m_j = wellHeadJ;
}
void Connection::shift_complnum( int shift ) {
this->m_complnum += shift;
}
int Connection::getI() const {
return m_i;
return ijk[0];
}
int Connection::getJ() const {
return m_j;
return ijk[1];
}
int Connection::getK() const {
return m_k;
return ijk[2];
}
int Connection::complnum() const {
return this->m_complnum;
}
WellCompletion::StateEnum Connection::getState() const {
return m_state;
}
double Connection::getConnectionTransmissibilityFactor() const {
return m_connectionTransmissibilityFactor.getValue();
@ -277,60 +91,26 @@ namespace Opm {
return m_skinFactor.getValue();
}
int Connection::getSatTableId() const {
return m_satTableId;
}
const Value<double>& Connection::getConnectionTransmissibilityFactorAsValueObject() const {
return m_connectionTransmissibilityFactor;
}
Value<double> Connection::getDiameterAsValueObject() const {
return m_diameter;
}
Value<double> Connection::getSkinFactorAsValueObject() const {
return m_skinFactor;
}
WellCompletion::DirectionEnum Connection::getDirection() const {
return m_direction;
}
double Connection::getWellPi() const {
return m_wellPi;
}
int Connection::getSegmentNumber() const {
if (!attachedToSegment()) {
throw std::runtime_error(" the completion is not attached to a segment!\n ");
}
return m_segment_number;
}
double Connection::getCenterDepth() const {
return m_center_depth;
}
bool Connection::attachedToSegment() const {
return (m_segment_number > 0);
return (segment_number > 0);
}
bool Connection::operator==( const Connection& rhs ) const {
return this->m_i == rhs.m_i
&& this->m_j == rhs.m_j
&& this->m_k == rhs.m_k
&& this->m_complnum == rhs.m_complnum
return this->ijk == rhs.ijk
&& this->complnum == rhs.complnum
&& this->m_diameter == rhs.m_diameter
&& this->m_connectionTransmissibilityFactor
== rhs.m_connectionTransmissibilityFactor
&& this->m_wellPi == rhs.m_wellPi
&& this->m_connectionTransmissibilityFactor == rhs.m_connectionTransmissibilityFactor
&& this->wellPi == rhs.wellPi
&& this->m_skinFactor == rhs.m_skinFactor
&& this->m_satTableId == rhs.m_satTableId
&& this->m_state == rhs.m_state
&& this->m_direction == rhs.m_direction
&& this->m_segment_number == rhs.m_segment_number
&& this->m_center_depth == rhs.m_center_depth;
&& this->sat_tableId == rhs.sat_tableId
&& this->state == rhs.state
&& this->dir == rhs.dir
&& this->segment_number == rhs.segment_number
&& this->center_depth == rhs.center_depth;
}
bool Connection::operator!=( const Connection& rhs ) const {

View File

@ -41,8 +41,8 @@ namespace Opm {
m_distance_start(distance_start_in),
m_distance_end(distance_end_in),
m_dir(dir_in),
m_center_depth(center_depth_in),
m_segment_number(segment_number_in)
center_depth(center_depth_in),
segment_number(segment_number_in)
{
}
@ -141,7 +141,7 @@ namespace Opm {
for( auto& compseg : compsegs ) {
// need to determine the related segment number first
if (compseg.m_segment_number != 0) continue;
if (compseg.segment_number != 0) continue;
const double center_distance = (compseg.m_distance_start + compseg.m_distance_end) / 2.0;
const int branch_number = compseg.m_branch_number;
@ -164,15 +164,15 @@ namespace Opm {
throw std::runtime_error("The perforation failed in finding a related segment \n");
}
if (compseg.m_center_depth < 0.) {
if (compseg.center_depth < 0.) {
throw std::runtime_error("Obtaining perforation depth from COMPDAT data is not supported yet");
}
compseg.m_segment_number = segment_number;
compseg.segment_number = segment_number;
// when depth is default or zero, we obtain the depth of the connection based on the information
// of the related segments
if (compseg.m_center_depth == 0.) {
if (compseg.center_depth == 0.) {
compseg.calculateCenterDepthWithSegments(segment_set);
}
}
@ -181,13 +181,13 @@ namespace Opm {
void Compsegs::calculateCenterDepthWithSegments(const WellSegments& segment_set) {
// the depth and distance of the segment to the well head
const Segment& segment = segment_set.getFromSegmentNumber(m_segment_number);
const Segment& segment = segment_set.getFromSegmentNumber(segment_number);
const double segment_depth = segment.depth();
const double segment_distance = segment.totalLength();
// for top segment, no interpolation is needed
if (m_segment_number == 1) {
m_center_depth = segment_depth;
if (segment_number == 1) {
center_depth = segment_depth;
return;
}
@ -211,7 +211,7 @@ namespace Opm {
if (interpolation_segment_number == 0) {
throw std::runtime_error("Failed in finding a segment to do the interpolation with segment "
+ std::to_string(m_segment_number));
+ std::to_string(segment_number));
}
// performing the interpolation
@ -224,10 +224,10 @@ namespace Opm {
if (segment_length == 0.) {
throw std::runtime_error("Zero segment length is botained when doing interpolation between segment "
+ std::to_string(m_segment_number) + " and segment " + std::to_string(interpolation_segment_number) );
+ std::to_string(segment_number) + " and segment " + std::to_string(interpolation_segment_number) );
}
m_center_depth = segment_depth + (center_distance - segment_distance) / segment_length * depth_change_segment;
center_depth = segment_depth + (center_distance - segment_distance) / segment_length * depth_change_segment;
}
void Compsegs::updateConnectionsWithSegment(const std::vector< Compsegs >& compsegs,
@ -238,8 +238,9 @@ namespace Opm {
const int j = compseg.m_j;
const int k = compseg.m_k;
const Connection& connection = connection_set.getFromIJK( i, j, k );
connection_set.add(Connection(connection, compseg.m_segment_number, compseg.m_center_depth) );
Connection& connection = connection_set.getFromIJK( i, j, k );
connection.segment_number = compseg.segment_number;
connection.center_depth = compseg.center_depth;
}
for (size_t ic = 0; ic < connection_set.size(); ++ic) {

View File

@ -44,10 +44,10 @@ namespace Opm {
double m_distance_end;
WellCompletion::DirectionEnum m_dir;
double m_center_depth;
double center_depth;
// we do not handle thermal length for the moment
// double m_thermal_length;
int m_segment_number;
int segment_number;
Compsegs(int i_in, int j_in, int k_in, int branch_number_in, double distance_start_in, double distance_end_in,
WellCompletion::DirectionEnum dir_in, double center_depth_in, int segment_number_in);

View File

@ -22,7 +22,7 @@
namespace Opm {
Segment::Segment()
: m_segment_number(-1),
: segment_number(-1),
m_branch(-1),
m_outlet_segment(-1),
m_total_length(invalid_value),
@ -39,7 +39,7 @@ namespace Opm {
Segment::Segment(int segment_number_in, int branch_in, int outlet_segment_in, double length_in, double depth_in,
double internal_diameter_in, double roughness_in, double cross_area_in,
double volume_in, bool data_ready_in)
: m_segment_number(segment_number_in),
: segment_number(segment_number_in),
m_branch(branch_in),
m_outlet_segment(outlet_segment_in),
m_total_length(length_in),
@ -53,7 +53,7 @@ namespace Opm {
}
int Segment::segmentNumber() const {
return m_segment_number;
return segment_number;
}
@ -122,7 +122,7 @@ namespace Opm {
}
bool Segment::operator==( const Segment& rhs ) const {
return this->m_segment_number == rhs.m_segment_number
return this->segment_number == rhs.segment_number
&& this->m_branch == rhs.m_branch
&& this->m_outlet_segment == rhs.m_outlet_segment
&& this->m_total_length == rhs.m_total_length
@ -135,7 +135,7 @@ namespace Opm {
}
bool Segment::operator!=( const Segment& rhs ) const {
return this->m_segment_number == rhs.m_segment_number
return this->segment_number == rhs.segment_number
&& this->m_branch == rhs.m_branch
&& this->m_outlet_segment == rhs.m_outlet_segment
&& this->m_total_length == rhs.m_total_length

View File

@ -76,8 +76,8 @@ namespace Opm {
}
int WellSegments::segmentNumberToIndex(const int segment_number) const {
const auto it = m_segment_number_to_index.find(segment_number);
if (it != m_segment_number_to_index.end()) {
const auto it = segment_number_to_index.find(segment_number);
if (it != segment_number_to_index.end()) {
return it->second;
} else {
return -1;
@ -91,14 +91,14 @@ namespace Opm {
const int segment_index = segmentNumberToIndex(segment_number);
if (segment_index < 0) { // it is a new segment
m_segment_number_to_index[segment_number] = size();
segment_number_to_index[segment_number] = size();
m_segments.push_back(new_segment);
} else { // the segment already exists
m_segments[segment_index] = new_segment;
}
}
void WellSegments::segmentsFromWELSEGSKeyword( const DeckKeyword& welsegsKeyword ) {
void WellSegments::loadWELSEGS( const DeckKeyword& welsegsKeyword ) {
// for the first record, which provides the information for the top segment
// and information for the whole segment set
@ -203,7 +203,7 @@ namespace Opm {
if (index >= 0) { // found in the existing m_segments already
throw std::logic_error("Segments with same segment number are found!\n");
}
m_segment_number_to_index[segment_number] = i_segment;
segment_number_to_index[segment_number] = i_segment;
}
for (size_t i_segment = 0; i_segment < m_segments.size(); ++i_segment) {
@ -212,7 +212,7 @@ namespace Opm {
if (outlet_segment <= 0) { // no outlet segment
continue;
}
const int outlet_segment_index = m_segment_number_to_index[outlet_segment];
const int outlet_segment_index = segment_number_to_index[outlet_segment];
m_segments[outlet_segment_index].addInletSegment(segment_number);
}
@ -350,9 +350,9 @@ namespace Opm {
int current_index= 1;
// clear the mapping from segment number to store index
m_segment_number_to_index.clear();
segment_number_to_index.clear();
// for the top segment
m_segment_number_to_index[1] = 0;
segment_number_to_index[1] = 0;
while (current_index< size()) {
// the branch number of the last segment that is done re-ordering
@ -390,7 +390,7 @@ namespace Opm {
std::swap(m_segments[current_index], m_segments[target_segment_index]);
}
const int segment_number = m_segments[current_index].segmentNumber();
m_segment_number_to_index[segment_number] = current_index;
segment_number_to_index[segment_number] = current_index;
current_index++;
}
}
@ -405,13 +405,13 @@ namespace Opm {
&& this->m_comp_pressure_drop == rhs.m_comp_pressure_drop
&& this->m_multiphase_model == rhs.m_multiphase_model
&& this->m_segments.size() == rhs.m_segments.size()
&& this->m_segment_number_to_index.size() == rhs.m_segment_number_to_index.size()
&& this->segment_number_to_index.size() == rhs.segment_number_to_index.size()
&& std::equal( this->m_segments.begin(),
this->m_segments.end(),
rhs.m_segments.begin() )
&& std::equal( this->m_segment_number_to_index.begin(),
this->m_segment_number_to_index.end(),
rhs.m_segment_number_to_index.begin() );
&& std::equal( this->segment_number_to_index.begin(),
this->segment_number_to_index.end(),
rhs.segment_number_to_index.begin() );
}
bool WellSegments::operator!=( const WellSegments& rhs ) const {

View File

@ -22,16 +22,15 @@
namespace Opm {
WellConnections updatingConnectionsWithSegments(const DeckKeyword& compsegs,
const WellConnections& input_connections,
const WellSegments& segment_set)
WellConnections * newConnectionsWithSegments(const DeckKeyword& compsegs,
const WellConnections& input_connections,
const WellSegments& segment_set)
{
WellConnections new_connection_set(input_connections);
WellConnections * new_connection_set = new WellConnections(input_connections);
std::vector<Compsegs> compsegs_vector = Compsegs::compsegsFromCOMPSEGSKeyword( compsegs );
Compsegs::processCOMPSEGS(compsegs_vector, segment_set);
Compsegs::updateConnectionsWithSegment(compsegs_vector, new_connection_set);
Compsegs::updateConnectionsWithSegment(compsegs_vector, *new_connection_set);
return new_connection_set;
}
}

View File

@ -552,69 +552,18 @@ namespace Opm {
return data;
}
void Schedule::handleWPIMULT( const DeckKeyword& keyword, size_t currentStep) {
for( const auto& record : keyword ) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
double wellPi = record.getItem("WELLPI").get< double >(0);
for( auto* well : getWells( wellNamePattern ) ) {
const auto& currentWellConnections = well->getConnections(currentStep);
WellConnections newWellConnections;
Opm::Value<int> I = getValueItem(record.getItem("I"));
Opm::Value<int> J = getValueItem(record.getItem("J"));
Opm::Value<int> K = getValueItem(record.getItem("K"));
Opm::Value<int> FIRST = getValueItem(record.getItem("FIRST"));
Opm::Value<int> LAST = getValueItem(record.getItem("LAST"));
size_t completionSize = currentWellConnections.size();
for(size_t i = 0; i < completionSize;i++) {
const auto& currentConnection = currentWellConnections.get(i);
if (FIRST.hasValue()) {
if (i < (size_t) FIRST.getValue()) {
newWellConnections.add(currentConnection);
continue;
}
}
if (LAST.hasValue()) {
if (i > (size_t) LAST.getValue()) {
newWellConnections.add(currentConnection);
continue;
}
}
int ci = currentConnection.getI();
int cj = currentConnection.getJ();
int ck = currentConnection.getK();
if (I.hasValue() && (!(I.getValue() == ci) )) {
newWellConnections.add(currentConnection);
continue;
}
if (J.hasValue() && (!(J.getValue() == cj) )) {
newWellConnections.add(currentConnection);
continue;
}
if (K.hasValue() && (!(K.getValue() == ck) )) {
newWellConnections.add(currentConnection);
continue;
}
newWellConnections.add( Connection{ currentConnection, wellPi } );
}
well->addWellConnections(currentStep, newWellConnections);
}
for( auto* well : getWells( wellNamePattern ) )
well->handleWPIMULT(record, currentStep);
}
}
void Schedule::handleWCONINJE( const SCHEDULESection& section, const DeckKeyword& keyword, size_t currentStep, const ParseContext& parseContext) {
for( const auto& record : keyword ) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
@ -920,37 +869,14 @@ namespace Opm {
}
}
void Schedule::handleCOMPLUMP( const DeckKeyword& keyword,
size_t timestep ) {
for( const auto& record : keyword ) {
const int N = maybe( record, "N" ) + 1;
if( N < 1 ) throw std::invalid_argument(
"Completion number in COMPLUMP can not be defaulted."
);
const auto& wellname = record.getItem( "WELL" ).getTrimmedString(0);
const int I = maybe( record, "I" );
const int J = maybe( record, "J" );
const int K1 = maybe( record, "K1" );
const int K2 = maybe( record, "K2" );
auto new_completion = [=]( const Connection& c ) -> Connection {
if( !defaulted( I ) && c.getI() != I ) return c;
if( !defaulted( J ) && c.getJ() != J ) return c;
if( !defaulted( K1 ) && c.getK() < K1 ) return c;
if( !defaulted( K2 ) && c.getK() > K2 ) return c;
return { c, N };
};
for( auto& well : this->getWells( wellname ) ) {
WellConnections new_completions;
for( const auto& completion : well->getConnections( timestep ) )
new_completions.add( new_completion( completion ) );
well->addWellConnections( timestep, new_completions );
}
const std::string& well_name = record.getItem("WELL").getTrimmedString(0);
auto& well = this->m_wells.get(well_name);
well.handleCOMPLUMP(record, timestep);
}
}
@ -979,10 +905,9 @@ namespace Opm {
* well status is updated
*/
if( all_defaulted( record ) ) {
const auto status = WellCommon::StatusFromString( status_str );
const auto well_status = WellCommon::StatusFromString( status_str );
for( auto* well : wells ) {
if( status == open && !well->canOpen(currentStep) ) {
if( well_status == open && !well->canOpen(currentStep) ) {
auto days = m_timeMap.getTimePassedUntil( currentStep ) / (60 * 60 * 24);
std::string msg = "Well " + well->name()
+ " where crossflow is banned has zero total rate."
@ -990,53 +915,16 @@ namespace Opm {
+ std::to_string( days ) + " days";
OpmLog::note(msg);
} else {
this->updateWellStatus( *well, currentStep, status );
this->updateWellStatus( *well, currentStep, well_status );
}
}
continue;
}
const int I = maybe( record, "I" );
const int J = maybe( record, "J" );
const int K = maybe( record, "K" );
const int C1 = maybe( record, "C1" );
const int C2 = maybe( record, "C2" );
const auto status = WellCompletion::StateEnumFromString( status_str );
/*
* Construct the updated completion with the possible status change
* applied. Status is changed when a completion matches all the IJK
* criteria *and* the completion number. A defaulted field always
* matches the property in question.
*/
auto new_completion = [=]( const Connection& completion ) -> Connection {
if( !defaulted( I ) && completion.getI() != I ) return completion;
if( !defaulted( J ) && completion.getJ() != J ) return completion;
if( !defaulted( K ) && completion.getK() != K ) return completion;
// assuming CM can be defaulted, even in the presence of
// CN, e.g. it's a match for c >= C1 when C2 is defaulted
// and vice versa.
// complnum starts at 1, but we temp. adjust it for zero to
// generalise the negative default value
const auto complnum = completion.complnum() - 1;
if( !defaulted( C1 ) && complnum < C1 ) return completion;
if( !defaulted( C2 ) && complnum > C2 ) return completion;
if( !defaulted( C1 ) && !defaulted( C2 )
&& ( C1 > complnum || complnum > C2 ) ) return completion;
// completion matched - update it's status
return { completion, status };
};
for( auto* well : wells ) {
WellConnections new_completions;
for( const auto& c : well->getConnections( currentStep ) )
new_completions.add( new_completion( c ) );
well->addWellConnections( currentStep, new_completions );
const auto comp_status = WellCompletion::StateEnumFromString( status_str );
well->handleWELOPEN(record, currentStep, comp_status);
m_events.addEvent( ScheduleEvents::COMPLETION_CHANGE, currentStep );
}
}
@ -1415,46 +1303,42 @@ namespace Opm {
}
void Schedule::handleCOMPDAT( const DeckKeyword& keyword, size_t currentStep, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties, const ParseContext& parseContext) {
const auto wells = this->getWells( currentStep );
auto completions = Connection::fromCOMPDAT( grid, eclipseProperties, keyword, wells, parseContext, *this );
for (const auto& record : keyword) {
const std::string& wellNamePattern = record.getItem("WELL").getTrimmedString(0);
auto wells = getWells(wellNamePattern);
if (wells.empty())
invalidNamePattern(wellNamePattern, parseContext, keyword);
for( const auto pair : completions ) {
auto& well = this->m_wells.get( pair.first );
well.addConnections( currentStep, pair.second );
if (well.getConnections( currentStep ).allConnectionsShut()) {
std::string msg =
"All completions in well " + well.name() + " is shut at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days. \n" +
for (auto* well : wells) {
well->handleCOMPDAT(currentStep, record, grid, eclipseProperties);
if (well->getConnections( currentStep ).allConnectionsShut()) {
std::string msg =
"All completions in well " + well->name() + " is shut at " + std::to_string ( m_timeMap.getTimePassedUntil(currentStep) / (60*60*24) ) + " days. \n" +
"The well is therefore also shut.";
OpmLog::note(msg);
updateWellStatus( well, currentStep, WellCommon::StatusEnum::SHUT);
OpmLog::note(msg);
updateWellStatus( *well, currentStep, WellCommon::StatusEnum::SHUT);
}
}
}
m_events.addEvent(ScheduleEvents::COMPLETION_CHANGE, currentStep);
}
void Schedule::handleWELSEGS( const DeckKeyword& keyword, size_t currentStep) {
WellSegments newSegmentset;
newSegmentset.segmentsFromWELSEGSKeyword(keyword);
const std::string& well_name = newSegmentset.wellName();
auto& well = this->m_wells.get( well_name );
// update multi-segment related information for the well
well.addWellSegments(currentStep, newSegmentset);
const auto& record1 = keyword.getRecord(0);
auto& well = this->m_wells.get(record1.getItem("WELL").getTrimmedString(0));
well.handleWELSEGS(keyword, currentStep);WellSegments newSegmentset;
}
void Schedule::handleCOMPSEGS( const DeckKeyword& keyword, size_t currentStep) {
const auto& record1 = keyword.getRecord(0);
const std::string& well_name = record1.getItem("WELL").getTrimmedString(0);
auto& well = this->m_wells.get( well_name );
const auto& segment_set = well.getWellSegments(currentStep);
const auto& completion_set = well.getConnections( currentStep );
const WellConnections new_completion_set = updatingConnectionsWithSegments(keyword, completion_set, segment_set);
well.addWellConnections(currentStep, new_completion_set);
well.handleCOMPSEGS(keyword, currentStep);
}
void Schedule::handleWGRUPCON( const DeckKeyword& keyword, size_t currentStep) {

View File

@ -26,6 +26,7 @@
#include <opm/parser/eclipse/EclipseState/Schedule/WellConnections.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/DynamicState.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/WellSegments.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/updatingConnectionsWithSegments.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/TimeMap.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Well.hpp>
@ -48,7 +49,7 @@ namespace Opm {
m_guideRateScalingFactor( timeMap, 1.0 ),
m_efficiencyFactors (timeMap, 1.0 ),
m_isProducer( timeMap, true ) ,
m_completions( timeMap, WellConnections{} ),
m_completions( timeMap, std::make_shared<WellConnections>(headI, headJ) ),
m_productionProperties( timeMap, WellProductionProperties() ),
m_injectionProperties( timeMap, WellInjectionProperties() ),
m_polymerProperties( timeMap, WellPolymerProperties() ),
@ -336,7 +337,7 @@ namespace Opm {
+ ". Can not infer reference depth" );
}
return completions.get( 0 ).getCenterDepth();
return completions.get( 0 ).center_depth;
}
void Well::setRefDepth( size_t timestep, double depth ) {
@ -348,53 +349,33 @@ namespace Opm {
}
const WellConnections& Well::getConnections(size_t timeStep) const {
return m_completions.get( timeStep );
return *m_completions.get( timeStep );
}
std::map<int, std::vector<Connection>> Well::getCompletions(size_t time_step) const {
std::map<int, std::vector<Connection>> completions;
const auto& connections = this->getConnections(time_step);
for (const auto& conn : connections) {
auto pair = completions.find( conn.complnum );
if (pair == completions.end())
completions[conn.complnum] = {};
pair = completions.find(conn.complnum);
pair->second.push_back(conn);
}
return completions;
}
WellConnections Well::getActiveConnections(size_t timeStep, const EclipseGrid& grid) const {
return WellConnections(this->getConnections(timeStep), grid);
}
const WellConnections& Well::getConnections() const {
return m_completions.back();
}
void Well::addConnections(size_t time_step, const std::vector< Connection >& newConnections ) {
auto new_set = this->getConnections( time_step );
int complnum_shift = new_set.size();
const auto headI = this->m_headI[ time_step ];
const auto headJ = this->m_headJ[ time_step ];
auto prev_size = new_set.size();
for( auto completion : newConnections ) {
completion.fixDefaultIJ( headI , headJ );
completion.shift_complnum( complnum_shift );
new_set.add( completion );
const auto new_size = new_set.size();
/* Connections can be "re-added", i.e. same coordinates but with a
* different set of properties. In this case they also inherit the
* completion number (which must otherwise be shifted because
* every COMPDAT keyword thinks it's the only one.
*/
if( new_size == prev_size ) --complnum_shift;
else ++prev_size;
}
this->addWellConnections( time_step, new_set );
}
void Well::addWellConnections(size_t time_step, WellConnections new_set ){
if( getWellConnectionOrdering() == WellCompletion::TRACK) {
const auto headI = this->m_headI[ time_step ];
const auto headJ = this->m_headJ[ time_step ];
new_set.orderConnections( headI, headJ );
}
m_completions.update( time_step, std::move( new_set ) );
addEvent( ScheduleEvents::COMPLETION_CHANGE , time_step );
return *m_completions.back();
}
const std::string Well::getGroupName(size_t time_step) const {
@ -567,7 +548,20 @@ namespace Opm {
m_segmentset.update(time_step, new_segmentset);
}
WellConnections * Well::newWellConnections(size_t time_step) {
return new WellConnections( this->m_headI[time_step], this->m_headJ[time_step]);
}
void Well::updateWellConnections(size_t time_step, WellConnections * new_set ){
if( getWellConnectionOrdering() == WellCompletion::TRACK) {
const auto headI = this->m_headI[ time_step ];
const auto headJ = this->m_headJ[ time_step ];
new_set->orderConnections( headI, headJ );
}
m_completions.update( time_step, std::shared_ptr<WellConnections>( new_set ));
addEvent( ScheduleEvents::COMPLETION_CHANGE , time_step );
}
void Well::addEvent(ScheduleEvents::Events event, size_t reportStep) {
@ -586,6 +580,148 @@ namespace Opm {
instance, hence this for loop is over all timesteps.
*/
for (auto& completions : m_completions)
completions.filter(grid);
completions->filter(grid);
}
namespace {
bool defaulted(const DeckRecord& rec, const std::string& s) {
const auto& item = rec.getItem( s );
if (item.defaultApplied(0))
return true;
if (item.get<int>(0) == 0)
return true;
return false;
}
int limit(const DeckRecord& rec, const std::string&s , int shift) {
const auto& item = rec.getItem( s );
return shift + item.get<int>(0);
}
bool match_le(int value, const DeckRecord& rec, const std::string& s, int shift = 0) {
if (defaulted(rec,s))
return true;
return (value <= limit(rec,s,shift));
}
bool match_ge(int value, const DeckRecord& rec, const std::string& s, int shift = 0) {
if (defaulted(rec,s))
return true;
return (value >= limit(rec,s,shift));
}
bool match_eq(int value, const DeckRecord& rec, const std::string& s, int shift = 0) {
if (defaulted(rec,s))
return true;
return (limit(rec,s,shift) == value);
}}
void Well::handleCOMPLUMP(const DeckRecord& record, size_t time_step) {
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, "K1", -1)) return false;
if (!match_le(c.getK(), record, "K2", -1)) return false;
return true;
};
WellConnections * new_connections = this->newWellConnections(time_step);
const int complnum = record.getItem("N").get<int>(0);
if (complnum <= 0)
throw std::invalid_argument("Completion number must be >= 1. COMPLNUM=" + std::to_string(complnum) + "is invalid");
for (auto c : this->getConnections(time_step)) {
if (match(c))
c.complnum = complnum;
new_connections->add(c);
}
this->updateWellConnections(time_step, new_connections);
}
void Well::handleWELOPEN(const DeckRecord& record, size_t time_step, WellCompletion::StateEnum status) {
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_eq(c.getK(), record, "K", -1)) return false;
if (!match_ge(c.complnum, record, "C1")) return false;
if (!match_le(c.complnum, record, "C2")) return false;
return true;
};
WellConnections * new_connections = this->newWellConnections(time_step);
for (auto c : this->getConnections(time_step)) {
if (match(c))
c.state = status;
new_connections->add(c);
}
this->updateWellConnections(time_step, new_connections);
}
void Well::handleCOMPDAT(size_t time_step, const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties) {
WellConnections * connections = new WellConnections(this->getConnections(time_step));
connections->loadCOMPDAT(record, grid, eclipseProperties);
this->updateWellConnections(time_step, connections);
}
void Well::handleCOMPSEGS(const DeckKeyword& keyword, size_t time_step) {
const auto& segment_set = this->getWellSegments(time_step);
const auto& completion_set = this->getConnections( time_step );
WellConnections * new_connection_set = newConnectionsWithSegments(keyword, completion_set, segment_set);
this->updateWellConnections(time_step, new_connection_set);
}
void Well::handleWPIMULT(const DeckRecord& record, size_t time_step) {
auto match = [=]( const Connection &c) -> bool {
if (!match_ge(c.complnum, record, "FIRST")) return false;
if (!match_le(c.complnum, record, "LAST")) return false;
if (!match_eq(c.getI() , record, "I", -1)) return false;
if (!match_eq(c.getJ() , record, "J", -1)) return false;
if (!match_eq(c.getK() , record, "K", -1)) return false;
return true;
};
WellConnections * new_connections = this->newWellConnections(time_step);
double wellPi = record.getItem("WELLPI").get< double >(0);
for (auto c : this->getConnections(time_step)) {
if (match(c))
c.wellPi *= wellPi;
new_connections->add(c);
}
this->updateWellConnections(time_step, new_connections);
}
void Well::handleWELSEGS(const DeckKeyword& keyword, size_t time_step) {
WellSegments newSegmentset;
newSegmentset.loadWELSEGS(keyword);
// update multi-segment related information for the well
this->addWellSegments(time_step, newSegmentset);
}
}

View File

@ -22,17 +22,21 @@
#include <limits>
#include <opm/parser/eclipse/EclipseState/Grid/EclipseGrid.hpp>
#include <opm/parser/eclipse/EclipseState/Eclipse3DProperties.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/ScheduleEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/Connection.hpp>
#include <opm/parser/eclipse/EclipseState/Schedule/WellConnections.hpp>
namespace Opm {
WellConnections::WellConnections( std::initializer_list< Connection > cs ) {
for( auto&& c : cs ) this->add( c );
WellConnections::WellConnections(int headI, int headJ) :
headI(headI),
headJ(headJ)
{
}
WellConnections::WellConnections(const WellConnections& src, const EclipseGrid& grid) {
for (const auto& c : src) {
if (grid.cellActive(c.getI(), c.getJ(), c.getK()))
@ -40,6 +44,130 @@ namespace Opm {
}
}
void WellConnections::addConnection(int i, int j , int k ,
int complnum,
double depth,
WellCompletion::StateEnum state ,
const Value<double>& connectionTransmissibilityFactor,
const Value<double>& diameter,
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction)
{
int conn_i = (i < 0) ? this->headI : i;
int conn_j = (j < 0) ? this->headJ : j;
Connection conn(conn_i, conn_j, k, complnum, depth, state, connectionTransmissibilityFactor, diameter, skinFactor, satTableId, direction);
this->add(conn);
}
void WellConnections::addConnection(int i, int j , int k ,
double depth,
WellCompletion::StateEnum state ,
const Value<double>& connectionTransmissibilityFactor,
const Value<double>& diameter,
const Value<double>& skinFactor,
const int satTableId,
const WellCompletion::DirectionEnum direction)
{
int complnum = -(this->m_connections.size() + 1);
this->addConnection(i,
j,
k,
complnum,
depth,
state,
connectionTransmissibilityFactor,
diameter,
skinFactor,
satTableId,
direction);
}
void WellConnections::loadCOMPDAT(const DeckRecord& record, const EclipseGrid& grid, const Eclipse3DProperties& eclipseProperties) {
const auto& itemI = record.getItem( "I" );
const auto defaulted_I = itemI.defaultApplied( 0 ) || itemI.get< int >( 0 ) == 0;
const int I = !defaulted_I ? itemI.get< int >( 0 ) - 1 : this->headI;
const auto& itemJ = record.getItem( "J" );
const auto defaulted_J = itemJ.defaultApplied( 0 ) || itemJ.get< int >( 0 ) == 0;
const int J = !defaulted_J ? itemJ.get< int >( 0 ) - 1 : this->headJ;
int K1 = record.getItem("K1").get< int >(0) - 1;
int K2 = record.getItem("K2").get< int >(0) - 1;
WellCompletion::StateEnum state = WellCompletion::StateEnumFromString( record.getItem("STATE").getTrimmedString(0) );
Value<double> connectionTransmissibilityFactor("CompletionTransmissibilityFactor");
Value<double> diameter("Diameter");
Value<double> skinFactor("SkinFactor");
const auto& satnum = eclipseProperties.getIntGridProperty("SATNUM");
int satTableId = -1;
bool defaultSatTable = true;
{
const auto& connectionTransmissibilityFactorItem = record.getItem("CONNECTION_TRANSMISSIBILITY_FACTOR");
const auto& diameterItem = record.getItem("DIAMETER");
const auto& skinFactorItem = record.getItem("SKIN");
const auto& satTableIdItem = record.getItem("SAT_TABLE");
if (connectionTransmissibilityFactorItem.hasValue(0) && connectionTransmissibilityFactorItem.getSIDouble(0) > 0)
connectionTransmissibilityFactor.setValue(connectionTransmissibilityFactorItem.getSIDouble(0));
if (diameterItem.hasValue(0))
diameter.setValue( diameterItem.getSIDouble(0));
if (skinFactorItem.hasValue(0))
skinFactor.setValue( skinFactorItem.get< double >(0));
if (satTableIdItem.hasValue(0) && satTableIdItem.get < int > (0) > 0)
{
satTableId = satTableIdItem.get< int >(0);
defaultSatTable = false;
}
}
const WellCompletion::DirectionEnum direction = WellCompletion::DirectionEnumFromString(record.getItem("DIR").getTrimmedString(0));
for (int k = K1; k <= K2; k++) {
if (defaultSatTable)
satTableId = satnum.iget(grid.getGlobalIndex(I,J,k));
auto same_ijk = [&]( const Connection& c ) {
return c.sameCoordinate( I,J,k );
};
auto prev = std::find_if( this->m_connections.begin(),
this->m_connections.end(),
same_ijk );
if (prev == this->m_connections.end()) {
this->addConnection(I,J,k,
grid.getCellDepth( I,J,k ),
state,
connectionTransmissibilityFactor,
diameter,
skinFactor,
satTableId,
direction );
} else {
// The complnum value carries over; the rest of the state is fully specified by
// the current COMPDAT keyword.
int complnum = prev->complnum;
*prev = Connection(I,J,k,
complnum,
grid.getCellDepth(I,J,k),
state,
connectionTransmissibilityFactor,
diameter,
skinFactor,
satTableId,
direction );
}
}
}
size_t WellConnections::size() const {
return m_connections.size();
}
@ -58,27 +186,23 @@ namespace Opm {
}
void WellConnections::add( Connection connection ) {
auto same = [&]( const Connection& c ) {
return c.sameCoordinate( connection );
};
auto prev = std::find_if( this->m_connections.begin(),
this->m_connections.end(),
same );
if( prev != this->m_connections.end() ) {
// update the completion, but preserve it's number
*prev = Connection( connection, prev->complnum() );
return;
Connection& WellConnections::getFromIJK(const int i, const int j, const int k) {
for (size_t ic = 0; ic < size(); ++ic) {
if (get(ic).sameCoordinate(i, j, k)) {
return this->m_connections[ic];
}
}
throw std::runtime_error(" the connection is not found! \n ");
}
void WellConnections::add( Connection connection ) {
m_connections.emplace_back( connection );
}
bool WellConnections::allConnectionsShut( ) const {
auto shut = []( const Connection& c ) {
return c.getState() == WellCompletion::StateEnum::SHUT;
return c.state == WellCompletion::StateEnum::SHUT;
};
return std::all_of( this->m_connections.begin(),
@ -109,7 +233,7 @@ namespace Opm {
for (size_t pos = 1; pos < m_connections.size() - 1; ++pos) {
const auto& prev = m_connections[pos - 1];
const double prevz = prev.getCenterDepth();
const double prevz = prev.center_depth;
size_t next_index = findClosestConnection(prev.getI(), prev.getJ(), prevz, pos);
std::swap(m_connections[next_index], m_connections[pos]);
}
@ -125,7 +249,7 @@ namespace Opm {
for (size_t pos = start_pos; pos < m_connections.size(); ++pos) {
const auto& connection = m_connections[ pos ];
const double depth = connection.getCenterDepth();
const double depth = connection.center_depth;
const int ci = connection.getI();
const int cj = connection.getJ();
// Using square of distance to avoid non-integer arithmetics.

View File

@ -85,29 +85,29 @@ namespace Opm {
void WellTestState::addClosedCompletion(const std::string& well_name, size_t completionIdx, double sim_time) {
if (this->hasCompletion(well_name, completionIdx))
void WellTestState::addClosedCompletion(const std::string& well_name, int complnum, double sim_time) {
if (this->hasCompletion(well_name, complnum))
return;
this->completions.push_back({well_name, completionIdx, sim_time, 0});
this->completions.push_back( {well_name, complnum, sim_time, 0} );
}
void WellTestState::dropCompletion(const std::string& well_name, size_t completionIdx) {
void WellTestState::dropCompletion(const std::string& well_name, int complnum) {
completions.erase(std::remove_if(completions.begin(),
completions.end(),
[&well_name, completionIdx](const ClosedCompletion& completion) { return (completion.wellName == well_name && completion.completion == completionIdx); }),
completions.end());
completions.end(),
[&well_name, complnum](const ClosedCompletion& completion) { return (completion.wellName == well_name && completion.complnum == complnum); }),
completions.end());
}
bool WellTestState::hasCompletion(const std::string& well_name, const size_t completionIdx) const {
bool WellTestState::hasCompletion(const std::string& well_name, const int complnum) const {
const auto completion_iter = std::find_if(completions.begin(),
completions.end(),
[&well_name, &completionIdx](const ClosedCompletion& completion)
{
return (completionIdx == completion.completion && completion.wellName == well_name);
});
completions.end(),
[&well_name, &complnum](const ClosedCompletion& completion)
{
return (complnum == completion.complnum && completion.wellName == well_name);
});
return (completion_iter != completions.end());
}
@ -115,8 +115,8 @@ namespace Opm {
return this->completions.size();
}
std::vector<std::pair<std::string, size_t>> WellTestState::updateCompletion(const WellTestConfig& config, double sim_time) {
std::vector<std::pair<std::string, size_t>> output;
std::vector<std::pair<std::string, int>> WellTestState::updateCompletion(const WellTestConfig& config, double sim_time) {
std::vector<std::pair<std::string, int>> output;
for (auto& closed_completion : this->completions) {
if (config.has(closed_completion.wellName, WellTestConfig::Reason::COMPLETION)) {
const auto& well_config = config.get(closed_completion.wellName, WellTestConfig::Reason::COMPLETION);
@ -126,7 +126,7 @@ namespace Opm {
if (well_config.num_test == 0 || (closed_completion.num_attempt < well_config.num_test)) {
closed_completion.last_test = sim_time;
closed_completion.num_attempt += 1;
output.push_back(std::make_pair(closed_completion.wellName, closed_completion.completion));
output.push_back(std::make_pair(closed_completion.wellName, closed_completion.complnum));
}
}
}

View File

@ -53,37 +53,22 @@ inline std::ostream& operator<<( std::ostream& stream, const WellConnections& cs
BOOST_AUTO_TEST_CASE(CreateCompletionOK) {
Opm::Connection completion(10,10,10, 1, 0.0,Opm::WellCompletion::OPEN,Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
}
BOOST_AUTO_TEST_CASE(testGetFunctions) {
Opm::Connection completion(10,11,12, 1, 0.0, Opm::WellCompletion::OPEN,Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::Connection completion(10,11,12, 1, 0.0, Opm::WellCompletion::OPEN,Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
BOOST_CHECK_EQUAL( 10 , completion.getI() );
BOOST_CHECK_EQUAL( 11 , completion.getJ() );
BOOST_CHECK_EQUAL( 12 , completion.getK() );
BOOST_CHECK_EQUAL( Opm::WellCompletion::OPEN , completion.getState());
BOOST_CHECK_EQUAL( Opm::WellCompletion::OPEN , completion.state);
BOOST_CHECK_EQUAL( 99.88 , completion.getConnectionTransmissibilityFactor());
BOOST_CHECK_EQUAL( 22.33 , completion.getDiameter());
BOOST_CHECK_EQUAL( 33.22 , completion.getSkinFactor());
BOOST_CHECK_EQUAL( 0 , completion.getSatTableId());
BOOST_CHECK_EQUAL( 0 , completion.sat_tableId);
}
BOOST_AUTO_TEST_CASE(CompletionTestssameCoordinate) {
Opm::Connection completion1(10,10,10, 1, 0.0, Opm::WellCompletion::OPEN, Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2(10,10,10, 1, 0.0, Opm::WellCompletion::OPEN, Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion3(11,10,10, 1, 0.0, Opm::WellCompletion::OPEN, Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion4(10,11,10, 1, 0.0, Opm::WellCompletion::OPEN, Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion5(10,10,11, 1, 0.0, Opm::WellCompletion::OPEN, Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
BOOST_CHECK( completion1.sameCoordinate( completion2 ));
BOOST_CHECK_EQUAL( false , completion1.sameCoordinate( completion3 ));
BOOST_CHECK_EQUAL( false , completion1.sameCoordinate( completion4 ));
BOOST_CHECK_EQUAL( false , completion1.sameCoordinate( completion5 ));
}
BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
Opm::WellConnections completionSet;
@ -93,9 +78,10 @@ BOOST_AUTO_TEST_CASE(CreateWellConnectionsOK) {
BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::WellConnections completionSet;
Opm::Connection completion1( 10,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2( 11,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion1( 10,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion2( 11,10,10, 1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
completionSet.add( completion1 );
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
@ -107,9 +93,10 @@ BOOST_AUTO_TEST_CASE(AddCompletionSizeCorrect) {
BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows) {
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::WellConnections completionSet;
Opm::Connection completion1( 10,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2( 11,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion1( 10,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion2( 11,10,10,1, 0.0,Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
completionSet.add( completion1 );
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
@ -122,27 +109,14 @@ BOOST_AUTO_TEST_CASE(WellConnectionsGetOutOfRangeThrows) {
BOOST_AUTO_TEST_CASE(AddCompletionSameCellUpdates) {
Opm::WellConnections completionSet;
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2( 10,10,10, 1, 0.0,Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
completionSet.add( completion1 );
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
completionSet.add( completion2 );
BOOST_CHECK_EQUAL( 1U , completionSet.size() );
}
BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
Opm::WellConnections completionSet;
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion3( 10,10,12, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion1( 10,10,10, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion2( 10,10,11, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion3( 10,10,12, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
completionSet.add( completion1 );
completionSet.add( completion2 );
@ -160,10 +134,11 @@ BOOST_AUTO_TEST_CASE(AddCompletionCopy) {
BOOST_AUTO_TEST_CASE(ActiveCompletions) {
Opm::EclipseGrid grid(10,10,10);
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::WellConnections completions;
Opm::Connection completion1( 0,0,0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion2( 0,0,1, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion3( 0,0,2, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection completion1( 0,0,0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion2( 0,0,1, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
Opm::Connection completion3( 0,0,2, 1, 0.0, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0, dir);
completions.add( completion1 );
completions.add( completion2 );

View File

@ -42,10 +42,12 @@
#include <opm/parser/eclipse/EclipseState/Schedule/MSW/updatingConnectionsWithSegments.hpp>
BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
Opm::WellConnections connection_set;
connection_set.add(Opm::Connection( 19, 0, 0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), 0) );
connection_set.add(Opm::Connection( 19, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), 0) );
connection_set.add(Opm::Connection( 19, 0, 2, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), 0) );
Opm::WellCompletion::DirectionEnum dir = Opm::WellCompletion::DirectionEnum::Z;
Opm::WellConnections connection_set;
connection_set.add(Opm::Connection( 19, 0, 0, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), 0, dir) );
connection_set.add(Opm::Connection( 19, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.5), Opm::Value<double>("SKIN", 0.), 0, dir) );
connection_set.add(Opm::Connection( 19, 0, 2, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), 0, dir) );
connection_set.add(Opm::Connection( 18, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), 0, Opm::WellCompletion::DirectionEnum::X) );
connection_set.add(Opm::Connection( 17, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), 0, Opm::WellCompletion::DirectionEnum::X) );
connection_set.add(Opm::Connection( 16, 0, 1, 1, 0.0, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor", 200.), Opm::Value<double>("D", 0.4), Opm::Value<double>("SKIN", 0.), 0, Opm::WellCompletion::DirectionEnum::X) );
@ -82,41 +84,41 @@ BOOST_AUTO_TEST_CASE(MultisegmentWellTest) {
Opm::WellSegments segment_set;
const Opm::DeckKeyword welsegs = deck.getKeyword("WELSEGS");
segment_set.segmentsFromWELSEGSKeyword(welsegs);
segment_set.loadWELSEGS(welsegs);
BOOST_CHECK_EQUAL(6U, segment_set.size());
const Opm::WellConnections new_connection_set = Opm::updatingConnectionsWithSegments(compsegs, connection_set, segment_set);
const Opm::WellConnections * new_connection_set = Opm::newConnectionsWithSegments(compsegs, connection_set, segment_set);
BOOST_CHECK_EQUAL(7U, new_connection_set.size());
BOOST_CHECK_EQUAL(7U, new_connection_set->size());
const Opm::Connection& connection1 = new_connection_set.get(0);
const int segment_number_connection1 = connection1.getSegmentNumber();
const double center_depth_connection1 = connection1.getCenterDepth();
const Opm::Connection& connection1 = new_connection_set->get(0);
const int segment_number_connection1 = connection1.segment_number;
const double center_depth_connection1 = connection1.center_depth;
BOOST_CHECK_EQUAL(segment_number_connection1, 1);
BOOST_CHECK_EQUAL(center_depth_connection1, 2512.5);
const Opm::Connection& connection3 = new_connection_set.get(2);
const int segment_number_connection3 = connection3.getSegmentNumber();
const double center_depth_connection3 = connection3.getCenterDepth();
const Opm::Connection& connection3 = new_connection_set->get(2);
const int segment_number_connection3 = connection3.segment_number;
const double center_depth_connection3 = connection3.center_depth;
BOOST_CHECK_EQUAL(segment_number_connection3, 3);
BOOST_CHECK_EQUAL(center_depth_connection3, 2562.5);
const Opm::Connection& connection5 = new_connection_set.get(4);
const int segment_number_connection5 = connection5.getSegmentNumber();
const double center_depth_connection5 = connection5.getCenterDepth();
const Opm::Connection& connection5 = new_connection_set->get(4);
const int segment_number_connection5 = connection5.segment_number;
const double center_depth_connection5 = connection5.center_depth;
BOOST_CHECK_EQUAL(segment_number_connection5, 6);
BOOST_CHECK_CLOSE(center_depth_connection5, 2538.83, 0.001);
const Opm::Connection& connection6 = new_connection_set.get(5);
const int segment_number_connection6 = connection6.getSegmentNumber();
const double center_depth_connection6 = connection6.getCenterDepth();
const Opm::Connection& connection6 = new_connection_set->get(5);
const int segment_number_connection6 = connection6.segment_number;
const double center_depth_connection6 = connection6.center_depth;
BOOST_CHECK_EQUAL(segment_number_connection6, 6);
BOOST_CHECK_CLOSE(center_depth_connection6, 2537.83, 0.001);
const Opm::Connection& connection7 = new_connection_set.get(6);
const int segment_number_connection7 = connection7.getSegmentNumber();
const double center_depth_connection7 = connection7.getCenterDepth();
const Opm::Connection& connection7 = new_connection_set->get(6);
const int segment_number_connection7 = connection7.segment_number;
const double center_depth_connection7 = connection7.center_depth;
BOOST_CHECK_EQUAL(segment_number_connection7, 7);
BOOST_CHECK_EQUAL(center_depth_connection7, 2534.5);
}

View File

@ -605,16 +605,6 @@ static Deck createDeckWithWellsAndConnectionDataWithWELOPEN() {
" 'OP_2' 8 7 3 6 'OPEN' 1* 6.242 0.311 576.458 1* 1* 'Y' 21.915 / \n"
" 'OP_3' 7 7 1 1 'OPEN' 1* 27.412 0.311 2445.337 1* 1* 'Y' 18.521 / \n"
" 'OP_3' 7 7 2 2 'OPEN' 1* 55.195 0.311 4923.842 1* 1* 'Y' 18.524 / \n"
/*
* Completions for OP_2:
* 1 - 8 8 1
* 2 - 8 8 2
* 3 - 8 8 3
* 4 - 8 7 3
* 5 - 8 7 4
* 6 - 8 7 5
* 7 - 8 7 6
*/
"/\n"
"DATES -- 2,3\n"
" 10 JUL 2007 / \n"
@ -664,25 +654,25 @@ BOOST_AUTO_TEST_CASE(CreateScheduleDeckWellsAndConnectionDataWithWELOPEN) {
constexpr auto open = WellCompletion::StateEnum::OPEN;
BOOST_CHECK_EQUAL( 7U, cs.size() );
BOOST_CHECK_EQUAL(shut, cs.getFromIJK( 7, 6, 2 ).getState());
BOOST_CHECK_EQUAL(shut, cs.getFromIJK( 7, 6, 3 ).getState());
BOOST_CHECK_EQUAL(shut, cs.getFromIJK( 7, 6, 4 ).getState());
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 7, 2 ).getState());
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 2 ).state);
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 3 ).state);
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 6, 4 ).state);
BOOST_CHECK_EQUAL(open, cs.getFromIJK( 7, 7, 2 ).state);
const auto& cs2 = well->getConnections( 4 );
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 2 ).getState());
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 3 ).getState());
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 4 ).getState());
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 7, 2 ).getState());
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 2 ).state);
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 3 ).state);
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 6, 4 ).state);
BOOST_CHECK_EQUAL(open, cs2.getFromIJK( 7, 7, 2 ).state);
well = schedule.getWell("OP_3");
const auto& cs3 = well->getConnections( 3 );
BOOST_CHECK_EQUAL(shut, cs3.get( 0 ).getState());
BOOST_CHECK_EQUAL(shut, cs3.get( 0 ).state);
const auto& cs4 = well->getConnections( 4 );
BOOST_CHECK_EQUAL(open, cs4.get( 0 ).getState());
BOOST_CHECK_EQUAL(open, cs4.get( 0 ).state);
well = schedule.getWell("OP_1");
BOOST_CHECK_EQUAL(WellCommon::StatusEnum::SHUT, well->getStatus( 3 ));
@ -1082,17 +1072,17 @@ BOOST_AUTO_TEST_CASE(createDeckWithWPIMULT) {
const auto& cs2 = well->getConnections( 2 );
for(size_t i = 0; i < cs2.size(); i++) {
BOOST_CHECK_EQUAL(cs2.get( i ).getWellPi(), 1.3);
BOOST_CHECK_EQUAL(cs2.get( i ).wellPi, 1.3);
}
const auto& cs3 = well->getConnections( 3 );
for(size_t i = 0; i < cs3.size(); i++ ) {
BOOST_CHECK_EQUAL(cs3.get( i ).getWellPi(), (1.3*1.3));
BOOST_CHECK_EQUAL(cs3.get( i ).wellPi, (1.3*1.3));
}
const auto& cs4 = well->getConnections( 4 );
for(size_t i = 0; i < cs4.size(); i++ ) {
BOOST_CHECK_EQUAL(cs4.get( i ).getWellPi(), 1.0);
BOOST_CHECK_EQUAL(cs4.get( i ).wellPi, 1.0);
}
}
@ -1683,16 +1673,16 @@ BOOST_AUTO_TEST_CASE( COMPDAT_sets_automatic_complnum ) {
Schedule schedule( deck, grid, eclipseProperties, Phases( true, true, true ) ,ctx);
const auto& cs1 = schedule.getWell( "W1" )->getConnections( 1 );
BOOST_CHECK_EQUAL( 1, cs1.get( 0 ).complnum() );
BOOST_CHECK_EQUAL( 2, cs1.get( 1 ).complnum() );
BOOST_CHECK_EQUAL( 3, cs1.get( 2 ).complnum() );
BOOST_CHECK_EQUAL( 4, cs1.get( 3 ).complnum() );
BOOST_CHECK_EQUAL( -1, cs1.get( 0 ).complnum );
BOOST_CHECK_EQUAL( -2, cs1.get( 1 ).complnum );
BOOST_CHECK_EQUAL( -3, cs1.get( 2 ).complnum );
BOOST_CHECK_EQUAL( -4, cs1.get( 3 ).complnum );
const auto& cs2 = schedule.getWell( "W1" )->getConnections( 2 );
BOOST_CHECK_EQUAL( 1, cs2.get( 0 ).complnum() );
BOOST_CHECK_EQUAL( 2, cs2.get( 1 ).complnum() );
BOOST_CHECK_EQUAL( 3, cs2.get( 2 ).complnum() );
BOOST_CHECK_EQUAL( 4, cs2.get( 3 ).complnum() );
BOOST_CHECK_EQUAL( -1, cs2.get( 0 ).complnum );
BOOST_CHECK_EQUAL( -2, cs2.get( 1 ).complnum );
BOOST_CHECK_EQUAL( -3, cs2.get( 2 ).complnum );
BOOST_CHECK_EQUAL( -4, cs2.get( 3 ).complnum );
}
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
@ -1727,20 +1717,20 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_wells ) {
Schedule schedule( deck, grid, eclipseProperties, Phases( true, true, true ) ,ctx);
const auto& w1cs = schedule.getWell( "W1" )->getConnections();
BOOST_CHECK_EQUAL( 1, w1cs.get( 0 ).complnum() );
BOOST_CHECK_EQUAL( 2, w1cs.get( 1 ).complnum() );
BOOST_CHECK_EQUAL( 3, w1cs.get( 2 ).complnum() );
BOOST_CHECK_EQUAL( 4, w1cs.get( 3 ).complnum() );
BOOST_CHECK_EQUAL( 5, w1cs.get( 4 ).complnum() );
BOOST_CHECK_EQUAL( -1, w1cs.get( 0 ).complnum );
BOOST_CHECK_EQUAL( -2, w1cs.get( 1 ).complnum );
BOOST_CHECK_EQUAL( -3, w1cs.get( 2 ).complnum );
BOOST_CHECK_EQUAL( -4, w1cs.get( 3 ).complnum );
BOOST_CHECK_EQUAL( -5, w1cs.get( 4 ).complnum );
const auto& w2cs = schedule.getWell( "W2" )->getConnections();
BOOST_CHECK_EQUAL( 1, w2cs.getFromIJK( 4, 4, 2 ).complnum() );
BOOST_CHECK_EQUAL( 2, w2cs.getFromIJK( 4, 4, 0 ).complnum() );
BOOST_CHECK_EQUAL( 3, w2cs.getFromIJK( 4, 4, 1 ).complnum() );
BOOST_CHECK_EQUAL( 4, w2cs.getFromIJK( 4, 4, 3 ).complnum() );
BOOST_CHECK_EQUAL( 5, w2cs.getFromIJK( 4, 4, 4 ).complnum() );
BOOST_CHECK_EQUAL( -1, w2cs.getFromIJK( 4, 4, 2 ).complnum );
BOOST_CHECK_EQUAL( -2, w2cs.getFromIJK( 4, 4, 0 ).complnum );
BOOST_CHECK_EQUAL( -3, w2cs.getFromIJK( 4, 4, 1 ).complnum );
BOOST_CHECK_EQUAL( -4, w2cs.getFromIJK( 4, 4, 3 ).complnum );
BOOST_CHECK_EQUAL( -5, w2cs.getFromIJK( 4, 4, 4 ).complnum );
BOOST_CHECK_THROW( w2cs.get( 5 ).complnum(), std::out_of_range );
BOOST_CHECK_THROW( w2cs.get( 5 ).complnum, std::out_of_range );
}
BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
@ -1772,9 +1762,9 @@ BOOST_AUTO_TEST_CASE( COMPDAT_multiple_records_same_completion ) {
const auto& cs = schedule.getWell( "W1" )->getConnections();
BOOST_CHECK_EQUAL( 3U, cs.size() );
BOOST_CHECK_EQUAL( 1, cs.get( 0 ).complnum() );
BOOST_CHECK_EQUAL( 2, cs.get( 1 ).complnum() );
BOOST_CHECK_EQUAL( 3, cs.get( 2 ).complnum() );
BOOST_CHECK_EQUAL( -1, cs.get( 0 ).complnum );
BOOST_CHECK_EQUAL( -2, cs.get( 1 ).complnum );
BOOST_CHECK_EQUAL( -3, cs.get( 2 ).complnum );
}
BOOST_AUTO_TEST_CASE( complump_less_than_1 ) {
@ -1853,22 +1843,37 @@ BOOST_AUTO_TEST_CASE( complump ) {
const auto& sc0 = well.getConnections( 0 );
/* complnum should be modified by COMPLNUM */
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 0 ).complnum() );
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 1 ).complnum() );
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 2 ).complnum() );
BOOST_CHECK_EQUAL( 4, sc0.getFromIJK( 2, 2, 3 ).complnum() );
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 0 ).complnum );
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 1 ).complnum );
BOOST_CHECK_EQUAL( 1, sc0.getFromIJK( 2, 2, 2 ).complnum );
BOOST_CHECK( sc0.getFromIJK( 2, 2, 3 ).complnum < 0);
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 0 ).getState() );
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 1 ).getState() );
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 2 ).getState() );
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 0 ).state );
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 1 ).state );
BOOST_CHECK_EQUAL( shut, sc0.getFromIJK( 2, 2, 2 ).state );
const auto& sc1 = well.getConnections( 1 );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 0 ).getState() );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 1 ).getState() );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 2 ).getState() );
BOOST_CHECK_EQUAL( shut, sc1.getFromIJK( 2, 2, 3 ).getState() );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 0 ).state );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 1 ).state );
BOOST_CHECK_EQUAL( open, sc1.getFromIJK( 2, 2, 2 ).state );
BOOST_CHECK_EQUAL( shut, sc1.getFromIJK( 2, 2, 3 ).state );
const auto completions = well.getCompletions(1);
BOOST_CHECK_EQUAL(completions.size(), 4);
const auto& c1 = completions.at(1);
BOOST_CHECK_EQUAL(c1.size(), 3);
for (const auto& pair : completions) {
if (pair.first > 0)
BOOST_CHECK(pair.second.size() > 1);
else
BOOST_CHECK_EQUAL(pair.second.size(), 1);
}
}
BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
std::string input = R"(
START -- 0
@ -1892,9 +1897,6 @@ BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
10 OKT 2008 /
/
WELOPEN -- open completion 1, rest are still shut
'W1' OPEN 1 1 0 1 1 /
/
DATES -- 2
15 OKT 2008 /
@ -1928,25 +1930,23 @@ BOOST_AUTO_TEST_CASE( COMPLUMP_specific_coordinates ) {
const auto& cs2 = well.getConnections( 2 );
BOOST_CHECK_EQUAL( 9U, cs1.size() );
BOOST_CHECK_EQUAL( open, cs1.getFromIJK( 0, 0, 0 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 0, 0, 1 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 0 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 1 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 2 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 0 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 3 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 4 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 5 ).getState() );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 0, 0, 1 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 0 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 1 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 2, 2, 2 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 0 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 3 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 4 ).state );
BOOST_CHECK_EQUAL( shut, cs1.getFromIJK( 1, 1, 5 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 0, 0, 0 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 0, 0, 1 ).getState() );
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 2, 2, 0 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 1 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 2 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 0 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 3 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 4 ).getState() );
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 1, 1, 5 ).getState() );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 0, 0, 1 ).state );
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 2, 2, 0 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 1 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 2, 2, 2 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 0 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 3 ).state );
BOOST_CHECK_EQUAL( open, cs2.getFromIJK( 1, 1, 4 ).state );
BOOST_CHECK_EQUAL( shut, cs2.getFromIJK( 1, 1, 5 ).state );
}
BOOST_AUTO_TEST_CASE(TestCompletionStateEnum2String) {

View File

@ -337,41 +337,6 @@ BOOST_AUTO_TEST_CASE(NewWellZeroCompletions) {
BOOST_CHECK_EQUAL( 0U , well.getConnections( 0 ).size() );
}
BOOST_AUTO_TEST_CASE(UpdateCompletions) {
auto timeMap = createXDaysTimeMap(10);
Opm::Well well("WELL1" , 0, 0, 0.0, Opm::Phase::OIL, timeMap , 0);
const auto& completions = well.getConnections( 0 );
BOOST_CHECK_EQUAL( 0U , completions.size());
Opm::Connection comp1( 10 , 10 , 10 , 1, 10, Opm::WellCompletion::AUTO , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection comp2( 10 , 10 , 11 , 1, 11, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection comp3( 10 , 10 , 12 , 1, 12, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection comp4( 10 , 10 , 12 , 1, 12, Opm::WellCompletion::SHUT , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
Opm::Connection comp5( 10 , 10 , 13 , 1, 13, Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
//std::vector<Opm::CompletionConstPtr> newCompletions2{ comp4 , comp5}; Newer c++
std::vector< Opm::Connection > newCompletions, newCompletions2;
newCompletions.push_back( comp1 );
newCompletions.push_back( comp2 );
newCompletions.push_back( comp3 );
newCompletions2.push_back( comp4 );
newCompletions2.push_back( comp5 );
BOOST_CHECK_EQUAL( 3U , newCompletions.size());
well.addConnections( 5 , newCompletions );
BOOST_CHECK_EQUAL( 3U , well.getConnections( 5 ).size());
BOOST_CHECK_EQUAL( comp3 , well.getConnections( 5 ).get(2));
well.addConnections( 6 , newCompletions2 );
BOOST_CHECK_EQUAL( 4U , well.getConnections( 6 ).size());
BOOST_CHECK_EQUAL( comp4 , well.getConnections( 6 ).get(2));
}
// Helper function for CompletionOrder test.
inline Opm::Connection connection( int i, int j, int k, int complnum = 1 ) {
return Opm::Connection { i, j, k,
@ -386,71 +351,6 @@ inline Opm::Connection connection( int i, int j, int k, int complnum = 1 ) {
}
BOOST_AUTO_TEST_CASE(CompletionOrder) {
auto timeMap = createXDaysTimeMap(10);
{
// Vertical well.
Opm::Well well("WELL1" , 5, 5, 0.0, Opm::Phase::OIL, timeMap , 0);
auto c1 = connection(5, 5, 8);
auto c2 = connection(5, 5, 9);
auto c3 = connection(5, 5, 1);
auto c4 = connection(5, 5, 0);
Opm::WellConnections cv1 = { c1, c2 };
well.addWellConnections(1, cv1);
BOOST_CHECK_EQUAL(well.getConnections(1).get(0), c1);
Opm::WellConnections cv2 = { c3, c4 };
well.addWellConnections(2, cv2);
BOOST_CHECK_EQUAL(well.getConnections(1).get(0), c1);
BOOST_CHECK_EQUAL(well.getConnections(2).get(0), c4);
}
{
// Horizontal well.
Opm::Well well("WELL1" , 5, 5, 0.0, Opm::Phase::OIL, timeMap , 0);
auto c1 = connection(6, 5, 8, 1);
auto c2 = connection(5, 6, 7, 2);
auto c3 = connection(7, 5, 8, 1);
auto c4 = connection(9, 5, 8, 2);
auto c5 = connection(8, 5, 9, 3);
auto c6 = connection(5, 5, 4, 1);
std::vector< Opm::Connection > cv1 = { c1, c2 };
well.addConnections(1, cv1);
BOOST_CHECK_EQUAL(well.getConnections(1).get(0), c2);
/*
* adding completions in batches like this will under the hood modify
* completion numbers to match expectations, so we ensure that we're
* comparing to the right value by forcing the right-hand-side of the
* comparison to use the expected completion number
*/
std::vector< Opm::Connection > cv2 = { c3, c4, c5 };
well.addConnections(2, cv2);
BOOST_CHECK_EQUAL(well.getConnections(1).get(0), Connection( c2, 2 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(0), Connection( c2, 2 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(1), Connection( c1, 1 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(2), Connection( c3, 3 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(3), Connection( c5, 5 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(4), Connection( c4, 4 ) );
std::vector< Opm::Connection > cv3 = { c6 };
well.addConnections(3, cv3);
BOOST_CHECK_EQUAL(well.getConnections(1).get(0), Connection( c2, 2 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(0), Connection( c2, 2 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(1), Connection( c1, 1 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(2), Connection( c3, 3 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(3), Connection( c5, 5 ) );
BOOST_CHECK_EQUAL(well.getConnections(2).get(4), Connection( c4, 4 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(0), Connection( c6, 6 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(1), Connection( c2, 2 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(2), Connection( c1, 1 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(3), Connection( c3, 3 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(4), Connection( c5, 5 ) );
BOOST_CHECK_EQUAL(well.getConnections(3).get(5), Connection( c4, 4 ) );
}
}
BOOST_AUTO_TEST_CASE(setGasRate_RateSetCorrect) {
auto timeMap = createXDaysTimeMap(10);
@ -632,23 +532,6 @@ BOOST_AUTO_TEST_CASE(InjectorType) {
BOOST_AUTO_TEST_CASE(WellStatus) {
auto timeMap = createXDaysTimeMap(10);
Opm::Well well("WELL1" , 0, 0, 0.0, Opm::Phase::OIL, timeMap , 0);
std::vector<Opm::Connection> newCompletions;
Opm::Connection comp1(10 , 10 , 10 , 1, 0.25 , Opm::WellCompletion::OPEN , Opm::Value<double>("ConnectionTransmissibilityFactor",99.88), Opm::Value<double>("D",22.33), Opm::Value<double>("SKIN",33.22), 0);
newCompletions.push_back( comp1 );
well.addConnections( 2 , newCompletions );
well.setStatus( 3 , Opm::WellCommon::OPEN );
BOOST_CHECK_EQUAL( Opm::WellCommon::OPEN , well.getStatus( 5 ));
}
/*****************************************************************/

View File

@ -443,13 +443,8 @@ BOOST_AUTO_TEST_CASE( MULTREGT_ECLIPSE_STATE ) {
BOOST_AUTO_TEST_CASE( MULTISEGMENT_ABS ) {
const Parser parser;
const std::string deckFile(pathprefix() + "SCHEDULE/SCHEDULE_MULTISEGMENT_WELL");
const auto deck = parser.parseFile(deckFile, ParseContext());
const ParseContext parseContext;
const EclipseState state(deck, parseContext);
const auto& grid = state.getInputGrid();
const TableManager table ( deck );
const Eclipse3DProperties eclipseProperties ( deck , table, grid);
const Schedule sched(deck, grid, eclipseProperties, Phases(true, true, true), parseContext );
const auto deck = parser.parseFile(deckFile, parseContext);
// for WELSEGS keyword
const auto& kw = deck.getKeyword("WELSEGS");
@ -568,6 +563,11 @@ BOOST_AUTO_TEST_CASE( MULTISEGMENT_ABS ) {
BOOST_CHECK_EQUAL( 3237.5, distance_end );
}
const EclipseState state(deck, parseContext);
const auto& grid = state.getInputGrid();
const TableManager table ( deck );
const Eclipse3DProperties eclipseProperties ( deck , table, grid);
const Schedule sched(deck, grid, eclipseProperties, Phases(true, true, true), parseContext );
// checking the relation between segments and completions
// and also the depth of completions
{
@ -577,26 +577,26 @@ BOOST_AUTO_TEST_CASE( MULTISEGMENT_ABS ) {
BOOST_CHECK_EQUAL(7U, connections.size());
const Connection& connection5 = connections.get(4);
const int seg_number_connection5 = connection5.getSegmentNumber();
const double connection5_depth = connection5.getCenterDepth();
const int seg_number_connection5 = connection5.segment_number;
const double connection5_depth = connection5.center_depth;
BOOST_CHECK_EQUAL(seg_number_connection5, 6);
BOOST_CHECK_CLOSE(connection5_depth, 2538.83, 0.001);
const Connection& connection6 = connections.get(5);
const int seg_number_connection6 = connection6.getSegmentNumber();
const double connection6_depth = connection6.getCenterDepth();
const int seg_number_connection6 = connection6.segment_number;
const double connection6_depth = connection6.center_depth;
BOOST_CHECK_EQUAL(seg_number_connection6, 6);
BOOST_CHECK_CLOSE(connection6_depth, 2537.83, 0.001);
const Connection& connection1 = connections.get(0);
const int seg_number_connection1 = connection1.getSegmentNumber();
const double connection1_depth = connection1.getCenterDepth();
const int seg_number_connection1 = connection1.segment_number;
const double connection1_depth = connection1.center_depth;
BOOST_CHECK_EQUAL(seg_number_connection1, 1);
BOOST_CHECK_EQUAL(connection1_depth, 2512.5);
const Connection& connection3 = connections.get(2);
const int seg_number_connection3 = connection3.getSegmentNumber();
const double connection3_depth = connection3.getCenterDepth();
const int seg_number_connection3 = connection3.segment_number;
const double connection3_depth = connection3.center_depth;
BOOST_CHECK_EQUAL(seg_number_connection3, 3);
BOOST_CHECK_EQUAL(connection3_depth, 2562.5);
}

View File

@ -349,13 +349,13 @@ BOOST_AUTO_TEST_CASE(WellTestCOMPDAT) {
const auto& connections = well1->getConnections(3);
BOOST_CHECK_EQUAL(4U, connections.size());
BOOST_CHECK_EQUAL(WellCompletion::OPEN, connections.get(3).getState());
BOOST_CHECK_EQUAL(WellCompletion::OPEN, connections.get(3).state);
BOOST_CHECK_EQUAL(2.2836805555555556e-12 , connections.get(3).getConnectionTransmissibilityFactor());
BOOST_CHECK_EQUAL(0.311/Metric::Length, connections.get(3).getDiameter());
BOOST_CHECK_EQUAL(3.3, connections.get(3).getSkinFactor());
BOOST_CHECK_EQUAL(4U, well1->getConnections( 7 ).size() );
BOOST_CHECK_EQUAL(WellCompletion::SHUT, well1->getConnections( 7 ).get( 3 ).getState() );
BOOST_CHECK_EQUAL(WellCompletion::SHUT, well1->getConnections( 7 ).get( 3 ).state );
}
}

View File

@ -56,7 +56,7 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
const size_t offset = w_offset + c_offset;
BOOST_CHECK_EQUAL(icondata[offset + ICON_IC_INDEX],
c.complnum());
c.complnum);
BOOST_CHECK_EQUAL(icondata[offset + ICON_I_INDEX],
c.getI() + 1);
BOOST_CHECK_EQUAL(icondata[offset + ICON_J_INDEX],
@ -64,9 +64,9 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
BOOST_CHECK_EQUAL(icondata[offset + ICON_K_INDEX],
c.getK() + 1);
BOOST_CHECK_EQUAL(icondata[offset + ICON_DIRECTION_INDEX],
c.getDirection());
c.dir);
if (c.getState() == Opm::WellCompletion::StateEnum::OPEN)
if (c.state == Opm::WellCompletion::StateEnum::OPEN)
BOOST_CHECK_EQUAL(icondata[offset + ICON_STATUS_INDEX],
1);
else
@ -75,7 +75,7 @@ BOOST_AUTO_TEST_CASE( serialize_icon_test )
if (c.attachedToSegment())
BOOST_CHECK_EQUAL(icondata[offset + ICON_SEGMENT_INDEX],
c.getSegmentNumber());
c.segment_number);
else
BOOST_CHECK_EQUAL(icondata[offset + ICON_SEGMENT_INDEX],
0);