mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
Use commit 0e1e780fd6f18ce93119061e36a4fca9711bc020 Excluded multibuild folder, as this caused git issues
359 lines
10 KiB
C++
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;
|
|
}
|