Files
ResInsight/ThirdParty/Ert/lib/ecl/ecl_grav_common.cpp

165 lines
5.9 KiB
C++

/*
Copyright (C) 2011 Statoil ASA, Norway.
The file 'ecl_grav_common.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 <stdlib.h>
#include <stdbool.h>
#include <math.h>
#include <ert/util/util.h>
#include <ert/ecl/ecl_kw.hpp>
#include <ert/ecl/ecl_file.hpp>
#include <ert/ecl/ecl_region.hpp>
#include <ert/ecl/ecl_grid_cache.hpp>
#include <ert/ecl/ecl_kw_magic.hpp>
#include <ert/ecl/ecl_grav_common.hpp>
/*
This file contains code which is common to both the ecl_grav
implementation for gravity changes, and the ecl_subsidence
implementation for changes in subsidence.
*/
bool * ecl_grav_common_alloc_aquifer_cell( const ecl_grid_cache_type * grid_cache , const ecl_file_type * init_file) {
bool * aquifer_cell = (bool*)util_calloc( ecl_grid_cache_get_size( grid_cache ) , sizeof * aquifer_cell );
for (int active_index = 0; active_index < ecl_grid_cache_get_size( grid_cache ); active_index++)
aquifer_cell[ active_index ] = false;
if (ecl_file_has_kw( init_file , AQUIFER_KW)) {
ecl_kw_type * aquifer_kw = ecl_file_iget_named_kw( init_file , AQUIFER_KW , 0);
const int * aquifer_data = ecl_kw_get_int_ptr( aquifer_kw );
for (int active_index = 0; active_index < ecl_grid_cache_get_size( grid_cache ); active_index++) {
if (aquifer_data[ active_index ] < 0)
aquifer_cell[ active_index ] = true;
}
}
return aquifer_cell;
}
double ecl_grav_common_eval_biot_savart( const ecl_grid_cache_type * grid_cache , ecl_region_type * region , const bool * aquifer , const double * weight , double utm_x , double utm_y , double depth) {
const double * xpos = ecl_grid_cache_get_xpos( grid_cache );
const double * ypos = ecl_grid_cache_get_ypos( grid_cache );
const double * zpos = ecl_grid_cache_get_zpos( grid_cache );
double sum = 0;
if (region == NULL) {
const int size = ecl_grid_cache_get_size( grid_cache );
int index;
for ( index = 0; index < size; index++) {
if (!aquifer[index]) {
double dist_x = (xpos[index] - utm_x );
double dist_y = (ypos[index] - utm_y );
double dist_z = (zpos[index] - depth );
double dist = sqrt( dist_x*dist_x + dist_y*dist_y + dist_z*dist_z );
/**
For numerical precision it might be benficial to use the
util_kahan_sum() function to do a Kahan summation.
*/
sum += weight[index] * dist_z/(dist * dist * dist );
}
}
} else {
const int_vector_type * index_vector = ecl_region_get_active_list( region );
const int size = int_vector_size( index_vector );
const int * index_list = int_vector_get_const_ptr( index_vector );
int i, index;
for (i = 0; i < size; i++) {
index = index_list[i];
if (!aquifer[index]) {
double dist_x = (xpos[index] - utm_x );
double dist_y = (ypos[index] - utm_y );
double dist_z = (zpos[index] - depth );
double dist = sqrt( dist_x*dist_x + dist_y*dist_y + dist_z*dist_z );
sum += weight[index] * dist_z/(dist * dist * dist );
}
}
}
return sum;
}
static inline double ecl_grav_common_eval_geertsma_kernel(int index, const double * xpos, const double * ypos, const double * zpos , double utm_x , double utm_y , double depth, double poisson_ratio, double seabed) {
double z = zpos[index];
z -= seabed;
double dist_x = xpos[index] - utm_x;
double dist_y = ypos[index] - utm_y;
double dist_z1 = z - depth;
double dist_z2 = dist_z1 - 2*z;
double dist1 = sqrt( dist_x*dist_x + dist_y*dist_y + dist_z1*dist_z1 );
double dist2 = sqrt( dist_x*dist_x + dist_y*dist_y + dist_z2*dist_z2 );
double cube_dist1 = dist1*dist1*dist1;
double cube_dist2 = dist2*dist2*dist2;
double displacement =
dist_z1 / cube_dist1 +
(3 - 4*poisson_ratio)*dist_z2 / cube_dist2 -
6*depth * (z + depth) * dist_z2 / (dist2*dist2*cube_dist2) +
2*((3 - 4*poisson_ratio)*(z + depth) - depth)/cube_dist2 ;
return displacement;
}
double ecl_grav_common_eval_geertsma( const ecl_grid_cache_type * grid_cache , ecl_region_type * region , const bool * aquifer , const double * weight , double utm_x , double utm_y , double depth, double poisson_ratio, double seabed) {
const double * xpos = ecl_grid_cache_get_xpos( grid_cache );
const double * ypos = ecl_grid_cache_get_ypos( grid_cache );
const double * zpos = ecl_grid_cache_get_zpos( grid_cache );
double sum = 0;
if (region == NULL) {
const int size = ecl_grid_cache_get_size( grid_cache );
int index;
for ( index = 0; index < size; index++) {
if (!aquifer[index]) {
double displacement = ecl_grav_common_eval_geertsma_kernel( index, xpos , ypos , zpos, utm_x, utm_y , depth, poisson_ratio, seabed);
/**
For numerical precision it might be benficial to use the
util_kahan_sum() function to do a Kahan summation.
*/
sum += weight[index] * displacement;
}
}
} else {
const int_vector_type * index_vector = ecl_region_get_active_list( region );
const int size = int_vector_size( index_vector );
const int * index_list = int_vector_get_const_ptr( index_vector );
int i, index;
for (i = 0; i < size; i++) {
index = index_list[i];
if (!aquifer[index]) {
double displacement = ecl_grav_common_eval_geertsma_kernel( index, xpos , ypos , zpos, utm_x, utm_y , depth , poisson_ratio, seabed);
sum += weight[index] * displacement;
}
}
}
return sum;
}