Files
ResInsight/ThirdParty/Ert/lib/ecl/well_conn.cpp
Magne Sjaastad 04091ad77d #4266 Update libecl
Use commit 0e1e780fd6f18ce93119061e36a4fca9711bc020

Excluded multibuild folder, as this caused git issues
2019-05-09 08:40:32 +02:00

359 lines
10 KiB
C++

/*
Copyright (C) 2011 Equinor ASA, Norway.
The file 'well_conn.c' is part of ERT - Ensemble based Reservoir Tool.
ERT is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
ERT is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License at <http://www.gnu.org/licenses/gpl.html>
for more details.
*/
#include <stdbool.h>
#include <string.h>
#include <ert/util/util.h>
#include <ert/util/type_macros.hpp>
#include <ert/ecl/ecl_kw.hpp>
#include <ert/ecl/ecl_rsthead.hpp>
#include <ert/ecl_well/well_const.hpp>
#include <ert/ecl_well/well_conn.hpp>
#define WELL_CONN_NORMAL_WELL_SEGMENT_ID -999
//#define ECLIPSE_NORMAL_WELL_SEGMENT_ID -1
/*
Observe that when the (ijk) values are initialized they are
shifted to zero offset values, to be aligned with the rest of the
ert libraries.
*/
#define WELL_CONN_TYPE_ID 702052013
struct well_conn_struct {
UTIL_TYPE_ID_DECLARATION;
int i;
int j;
int k;
well_conn_dir_enum dir;
bool open;
int segment_id; // -1: Ordinary well
bool matrix_connection; // k >= nz => fracture (and k -= nz )
double connection_factor;
double oil_rate;
double gas_rate;
double water_rate;
double volume_rate;
};
bool well_conn_equal( const well_conn_type *conn1 , const well_conn_type * conn2) {
if (memcmp(conn1 , conn2 , sizeof * conn1) == 0)
return true;
else
return false;
}
double well_conn_get_connection_factor( const well_conn_type * conn ) {
return conn->connection_factor;
}
bool well_conn_MSW( const well_conn_type * conn ) {
if (conn->segment_id == WELL_CONN_NORMAL_WELL_SEGMENT_ID)
return false;
else
return true;
}
static bool well_conn_assert_direction( well_conn_dir_enum dir, bool matrix_connection) {
if ((dir == well_conn_fracX || dir == well_conn_fracY) && matrix_connection)
return false;
else
return true;
}
UTIL_IS_INSTANCE_FUNCTION( well_conn , WELL_CONN_TYPE_ID)
UTIL_SAFE_CAST_FUNCTION( well_conn , WELL_CONN_TYPE_ID)
static well_conn_type * well_conn_alloc__( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open, int segment_id, bool matrix_connection) {
if (well_conn_assert_direction( dir , matrix_connection)) {
well_conn_type * conn = new well_conn_type();
UTIL_TYPE_ID_INIT( conn , WELL_CONN_TYPE_ID );
conn->i = i;
conn->j = j;
conn->k = k;
conn->open = open;
conn->dir = dir;
conn->connection_factor = connection_factor;
conn->matrix_connection = matrix_connection;
if (segment_id == CONN_NORMAL_WELL_SEGMENT_VALUE)
conn->segment_id = WELL_CONN_NORMAL_WELL_SEGMENT_ID;
else
conn->segment_id = segment_id;
conn->water_rate = 0;
conn->gas_rate = 0;
conn->oil_rate = 0;
conn->volume_rate = 0;
return conn;
} else {
printf("assert-direction failed. dir:%d matrix_connection:%d \n",dir , matrix_connection);
return NULL;
}
}
well_conn_type * well_conn_alloc( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open) {
return well_conn_alloc__(i , j , k , connection_factor , dir , open , WELL_CONN_NORMAL_WELL_SEGMENT_ID , true );
}
well_conn_type * well_conn_alloc_MSW( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open, int segment_id) {
return well_conn_alloc__(i , j , k , connection_factor , dir , open , segment_id , true );
}
well_conn_type * well_conn_alloc_fracture( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open) {
return well_conn_alloc__(i , j , k , connection_factor , dir , open , WELL_CONN_NORMAL_WELL_SEGMENT_ID , false);
}
well_conn_type * well_conn_alloc_fracture_MSW( int i , int j , int k , double connection_factor , well_conn_dir_enum dir , bool open, int segment_id) {
return well_conn_alloc__(i , j , k , connection_factor , dir , open , segment_id , false);
}
/*
Observe that the (ijk) and branch values are shifted to zero offset to be
aligned with the rest of the ert libraries.
*/
well_conn_type * well_conn_alloc_from_kw( const ecl_kw_type * icon_kw ,
const ecl_kw_type * scon_kw ,
const ecl_kw_type * xcon_kw ,
const ecl_rsthead_type * header ,
int well_nr ,
int conn_nr ) {
const int icon_offset = header->niconz * ( header->ncwmax * well_nr + conn_nr );
int IC =ecl_kw_iget_int( icon_kw , icon_offset + ICON_IC_INDEX );
if (IC <= 0)
return NULL; /* IC < 0: Connection not in current LGR. */
/*
Out in the wild we have encountered files where the integer value used to
indicate direction has had an invalid value for some connections. In this
case we just return NULL and forget about the connection - it seems to work.
*/
int int_direction = ecl_kw_iget_int( icon_kw , icon_offset + ICON_DIRECTION_INDEX );
if ((int_direction < 0) || (int_direction > ICON_FRACY)) {
fprintf(stderr,"Invalid direction value:%d encountered for well - connection ignored\n",int_direction);
return NULL;
}
int i = ecl_kw_iget_int( icon_kw , icon_offset + ICON_I_INDEX ) - 1;
int j = ecl_kw_iget_int( icon_kw , icon_offset + ICON_J_INDEX ) - 1;
int k = ecl_kw_iget_int( icon_kw , icon_offset + ICON_K_INDEX ) - 1;
double connection_factor = -1;
bool matrix_connection = true;
bool is_open = (ecl_kw_iget_int(icon_kw, icon_offset + ICON_STATUS_INDEX) > 0);
well_conn_dir_enum dir = well_conn_fracX;
/* Set the K value and fracture flag. */
{
if (header->dualp) {
int geometric_nz = header->nz / 2;
if (k >= geometric_nz) {
k -= geometric_nz;
matrix_connection = false;
}
}
}
/* Set the direction flag */
if (int_direction == ICON_DEFAULT_DIR_VALUE)
int_direction = ICON_DEFAULT_DIR_TARGET;
switch (int_direction) {
case(ICON_DIRX):
dir = well_conn_dirX;
break;
case(ICON_DIRY):
dir = well_conn_dirY;
break;
case(ICON_DIRZ):
dir = well_conn_dirZ;
break;
case(ICON_FRACX):
dir = well_conn_fracX;
break;
case(ICON_FRACY):
dir = well_conn_fracY;
break;
}
if (scon_kw) {
const int scon_offset = header->nsconz * ( header->ncwmax * well_nr + conn_nr );
connection_factor = ecl_kw_iget_as_double(scon_kw , scon_offset + SCON_CF_INDEX);
}
{
int segment_id = ecl_kw_iget_int( icon_kw , icon_offset + ICON_SEGMENT_INDEX ) - ECLIPSE_WELL_SEGMENT_OFFSET + WELL_SEGMENT_OFFSET;
well_conn_type * conn = well_conn_alloc__(i,j,k,connection_factor,dir,is_open,segment_id,matrix_connection);
if (xcon_kw) {
const int xcon_offset = header->nxconz * (header->ncwmax * well_nr + conn_nr);
conn->water_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_WRAT_INDEX);
conn->gas_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_GRAT_INDEX);
conn->oil_rate = ecl_kw_iget_as_double(xcon_kw, xcon_offset + XCON_ORAT_INDEX);
conn->volume_rate = ecl_kw_iget_double(xcon_kw, xcon_offset + XCON_QR_INDEX);
}
/**
For multisegmented wells ONLY the global part of the restart
file has segment information, i.e. the ?SEG
keywords. Consequently iseg_kw will be NULL for the part of a
MSW + LGR well.
*/
return conn;
}
}
void well_conn_free( well_conn_type * conn) {
delete conn;
}
void well_conn_free__( void * arg ) {
well_conn_type * conn = well_conn_safe_cast( arg );
well_conn_free( conn );
}
well_conn_type * well_conn_alloc_wellhead( const ecl_kw_type * iwel_kw , const ecl_rsthead_type * header , int well_nr) {
const int iwel_offset = header->niwelz * well_nr;
int conn_i = ecl_kw_iget_int( iwel_kw , iwel_offset + IWEL_HEADI_INDEX ) - 1;
if (conn_i >= 0) {
//well_conn_type * conn = util_malloc( sizeof * conn );
int conn_j = ecl_kw_iget_int( iwel_kw , iwel_offset + IWEL_HEADJ_INDEX ) - 1;
int conn_k = ecl_kw_iget_int( iwel_kw , iwel_offset + IWEL_HEADK_INDEX ) - 1;
bool matrix_connection = true;
bool open = true;
double connection_factor = -1;
if (header->dualp) {
int geometric_nz = header->nz / 2;
if (conn_k >= geometric_nz) {
conn_k -= geometric_nz;
matrix_connection = false;
}
}
if (matrix_connection)
return well_conn_alloc( conn_i , conn_j , conn_k , connection_factor , (well_conn_dir_enum)open , well_conn_dirZ );
else
return well_conn_alloc_fracture( conn_i , conn_j , conn_k , connection_factor , (well_conn_dir_enum)open , well_conn_dirZ );
} else
// The well is completed in this LGR - however the wellhead is in another LGR.
return NULL;
}
/*****************************************************************/
int well_conn_get_i(const well_conn_type * conn) {
return conn->i;
}
int well_conn_get_j(const well_conn_type * conn) {
return conn->j;
}
int well_conn_get_k(const well_conn_type * conn) {
return conn->k;
}
well_conn_dir_enum well_conn_get_dir(const well_conn_type * conn) {
return conn->dir;
}
bool well_conn_open( const well_conn_type * conn ) {
return conn->open;
}
int well_conn_get_segment_id( const well_conn_type * conn ) {
return conn->segment_id;
}
bool well_conn_fracture_connection( const well_conn_type * conn) {
return !conn->matrix_connection;
}
bool well_conn_matrix_connection( const well_conn_type * conn) {
return conn->matrix_connection;
}
double well_conn_get_oil_rate(const well_conn_type *conn) {
return conn->oil_rate;
}
double well_conn_get_gas_rate(const well_conn_type *conn) {
return conn->gas_rate;
}
double well_conn_get_water_rate(const well_conn_type *conn) {
return conn->water_rate;
}
double well_conn_get_volume_rate(const well_conn_type *conn) {
return conn->volume_rate;
}
double well_conn_get_oil_rate_si(const well_conn_type *conn) {
return conn->oil_rate;
}
double well_conn_get_gas_rate_si(const well_conn_type *conn) {
return conn->gas_rate;
}
double well_conn_get_water_rate_si(const well_conn_type *conn) {
return conn->water_rate;
}
double well_conn_get_volume_rate_si(const well_conn_type *conn) {
return conn->volume_rate;
}