mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
348 lines
13 KiB
C++
348 lines
13 KiB
C++
/*
|
|
Copyright (C) 2012 Statoil ASA, Norway.
|
|
|
|
The file 'ecl_sum_tstep.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 <time.h>
|
|
#include <math.h>
|
|
|
|
#include <ert/util/util.h>
|
|
#include <ert/util/type_macros.hpp>
|
|
|
|
#include <ert/ecl/ecl_sum_tstep.hpp>
|
|
#include <ert/ecl/ecl_kw.hpp>
|
|
#include <ert/ecl/ecl_smspec.hpp>
|
|
#include <ert/ecl/ecl_kw_magic.hpp>
|
|
#include <ert/ecl/ecl_type.hpp>
|
|
|
|
#define ECL_SUM_TSTEP_ID 88631
|
|
|
|
|
|
/*
|
|
This file implements the ecl_sum_tstep datatype which contains the
|
|
summary information for all summary vectors at one instant in
|
|
time. If we view the summary data as this:
|
|
|
|
|
|
Header direction: ecl_smspec DAYS WWCT:OP_3 FOPT BPR:15,10,25
|
|
--------------------------------------------
|
|
/|\ 0.00 0.00 0.00 256.00 <-- One timestep ecl_sum_tstep
|
|
| 10.00 0.56 10.00 255.00
|
|
Time direction: ecl_sum_data 20.00 0.61 18.70 253.00
|
|
| 30.00 0.63 21.20 251.00
|
|
| ...
|
|
\|/ 90.00 0.80 39.70 244.00
|
|
--------------------------------------------
|
|
|
|
The ecl_sum_tstep structure corresponds to one 'horizontal line' in
|
|
the summary data.
|
|
|
|
These timesteps correspond exactly to the simulators timesteps,
|
|
i.e. when convergence is poor they are closely spaced. In the
|
|
ECLIPSE summary files these time steps are called "MINISTEPS" - and
|
|
that term is also used some places in the ecl_sum_xxx codebase.
|
|
*/
|
|
|
|
|
|
struct ecl_sum_tstep_struct {
|
|
UTIL_TYPE_ID_DECLARATION;
|
|
float * data; /* A memcpy copy of the PARAMS vector in ecl_kw instance - the raw data. */
|
|
time_t sim_time; /* The true time (i.e. 20.th of october 2010) of corresponding to this timestep. */
|
|
int ministep; /* The ECLIPSE internal time-step number; one ministep per numerical timestep. */
|
|
int report_step; /* The report step this time-step is part of - in general there can be many timestep for each report step. */
|
|
double sim_seconds; /* Accumulated simulation time up to this ministep. */
|
|
int data_size; /* Number of elements in data - only used for checking indices. */
|
|
int internal_index; /* Used for lookups of the next / previous ministep based on an existing ministep. */
|
|
const ecl_smspec_type * smspec; /* The smespec header information for this tstep - must be compatible. */
|
|
};
|
|
|
|
|
|
ecl_sum_tstep_type * ecl_sum_tstep_alloc_remap_copy( const ecl_sum_tstep_type * src , const ecl_smspec_type * new_smspec, float default_value , const int * params_map) {
|
|
int params_size = ecl_smspec_get_params_size( new_smspec );
|
|
ecl_sum_tstep_type * target = (ecl_sum_tstep_type*)util_alloc_copy(src , sizeof * src );
|
|
|
|
target->smspec = new_smspec;
|
|
target->data = (float*)util_malloc( params_size * sizeof * target->data );
|
|
target->data_size = params_size;
|
|
for (int i=0; i < params_size; i++) {
|
|
|
|
if (params_map[i] >= 0)
|
|
target->data[i] = src->data[ params_map[i] ];
|
|
else
|
|
target->data[i] = default_value;
|
|
|
|
}
|
|
return target;
|
|
}
|
|
|
|
ecl_sum_tstep_type * ecl_sum_tstep_alloc_copy( const ecl_sum_tstep_type * src ) {
|
|
ecl_sum_tstep_type * target = (ecl_sum_tstep_type*)util_alloc_copy(src , sizeof * src );
|
|
target->data = (float*)util_alloc_copy( src->data , src->data_size * sizeof * src->data );
|
|
return target;
|
|
}
|
|
|
|
|
|
static ecl_sum_tstep_type * ecl_sum_tstep_alloc( int report_step , int ministep_nr , const ecl_smspec_type * smspec) {
|
|
ecl_sum_tstep_type * tstep = (ecl_sum_tstep_type*)util_malloc( sizeof * tstep );
|
|
UTIL_TYPE_ID_INIT( tstep , ECL_SUM_TSTEP_ID);
|
|
tstep->smspec = smspec;
|
|
tstep->report_step = report_step;
|
|
tstep->ministep = ministep_nr;
|
|
tstep->data_size = ecl_smspec_get_params_size( smspec );
|
|
tstep->data = (float*)util_calloc( tstep->data_size , sizeof * tstep->data );
|
|
return tstep;
|
|
}
|
|
|
|
|
|
UTIL_SAFE_CAST_FUNCTION( ecl_sum_tstep , ECL_SUM_TSTEP_ID)
|
|
UTIL_SAFE_CAST_FUNCTION_CONST( ecl_sum_tstep , ECL_SUM_TSTEP_ID)
|
|
|
|
|
|
void ecl_sum_tstep_free( ecl_sum_tstep_type * ministep ) {
|
|
free( ministep->data );
|
|
free( ministep );
|
|
}
|
|
|
|
|
|
|
|
void ecl_sum_tstep_free__( void * __ministep) {
|
|
ecl_sum_tstep_type * ministep = ecl_sum_tstep_safe_cast( __ministep );
|
|
ecl_sum_tstep_free( ministep );
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
This function sets the internal time representation in the
|
|
ecl_sum_tstep. The treatment of time is a bit weird; on the one
|
|
hand the time elements in the summary data are just like any other
|
|
element like e.g. the FOPT or GGPR:NAME - on the other hand the
|
|
time information is strictly required and the summary file will
|
|
fall to pieces if it is missing.
|
|
|
|
The time can be provided in using (at least) two different
|
|
keywords:
|
|
|
|
DAYS/HOURS: The data vector will contain the number of
|
|
days/hours since the simulation start (hours in the case
|
|
of lab units).
|
|
|
|
DAY,MONTH,YEAR: The data vector will contain the true date of
|
|
the tstep.
|
|
|
|
The ecl_sum_tstep class can utilize both types of information, but
|
|
will select the DAYS variety if both are present.
|
|
*/
|
|
|
|
static void ecl_sum_tstep_set_time_info_from_seconds( ecl_sum_tstep_type * tstep , time_t sim_start , double sim_seconds) {
|
|
tstep->sim_seconds = sim_seconds;
|
|
tstep->sim_time = sim_start;
|
|
util_inplace_forward_seconds_utc( &tstep->sim_time , tstep->sim_seconds);
|
|
}
|
|
|
|
|
|
static void ecl_sum_tstep_set_time_info_from_date( ecl_sum_tstep_type * tstep , time_t sim_start , time_t sim_time) {
|
|
tstep->sim_time = sim_time;
|
|
tstep->sim_seconds = util_difftime_seconds( sim_start , tstep->sim_time);
|
|
}
|
|
|
|
|
|
static void ecl_sum_tstep_set_time_info( ecl_sum_tstep_type * tstep , const ecl_smspec_type * smspec ) {
|
|
int date_day_index = ecl_smspec_get_date_day_index( smspec );
|
|
int date_month_index = ecl_smspec_get_date_month_index( smspec );
|
|
int date_year_index = ecl_smspec_get_date_year_index( smspec );
|
|
int sim_time_index = ecl_smspec_get_time_index( smspec );
|
|
time_t sim_start = ecl_smspec_get_start_time( smspec );
|
|
|
|
if (sim_time_index >= 0) {
|
|
float sim_time = tstep->data[ sim_time_index ];
|
|
double sim_seconds = sim_time * ecl_smspec_get_time_seconds( smspec );
|
|
ecl_sum_tstep_set_time_info_from_seconds( tstep , sim_start , sim_seconds );
|
|
} else if ( date_day_index >= 0) {
|
|
int day = util_roundf(tstep->data[date_day_index]);
|
|
int month = util_roundf(tstep->data[date_month_index]);
|
|
int year = util_roundf(tstep->data[date_year_index]);
|
|
|
|
time_t sim_time = ecl_util_make_date(day , month , year);
|
|
ecl_sum_tstep_set_time_info_from_date( tstep , sim_start , sim_time );
|
|
} else
|
|
util_abort("%s: Hmmm - could not extract date/time information from SMSPEC header file? \n",__func__);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
If the ecl_kw instance is in some way invalid (i.e. wrong size);
|
|
the function will return NULL:
|
|
*/
|
|
|
|
|
|
ecl_sum_tstep_type * ecl_sum_tstep_alloc_from_file( int report_step ,
|
|
int ministep_nr ,
|
|
const ecl_kw_type * params_kw ,
|
|
const char * src_file ,
|
|
const ecl_smspec_type * smspec) {
|
|
|
|
int data_size = ecl_kw_get_size( params_kw );
|
|
|
|
if (data_size == ecl_smspec_get_params_size( smspec )) {
|
|
ecl_sum_tstep_type * ministep = ecl_sum_tstep_alloc( report_step , ministep_nr , smspec);
|
|
ecl_kw_get_memcpy_data( params_kw , ministep->data );
|
|
ecl_sum_tstep_set_time_info( ministep , smspec );
|
|
return ministep;
|
|
} else {
|
|
/*
|
|
This is actually a fatal error / bug; the difference in smspec
|
|
header structure should have been detected already in the
|
|
ecl_smspec_load_restart() function and the restart case
|
|
discarded.
|
|
*/
|
|
fprintf(stderr , "** Warning size mismatch between timestep loaded from:%s and header:%s - timestep discarded.\n" , src_file , ecl_smspec_get_header_file( smspec ));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
Should be called in write mode.
|
|
*/
|
|
|
|
ecl_sum_tstep_type * ecl_sum_tstep_alloc_new( int report_step , int ministep , float sim_seconds , const ecl_smspec_type * smspec ) {
|
|
ecl_sum_tstep_type * tstep = ecl_sum_tstep_alloc( report_step , ministep , smspec );
|
|
const float_vector_type * default_data = ecl_smspec_get_params_default( smspec );
|
|
float_vector_memcpy_data( tstep->data , default_data );
|
|
|
|
ecl_sum_tstep_set_time_info_from_seconds( tstep , ecl_smspec_get_start_time( smspec ) , sim_seconds );
|
|
ecl_sum_tstep_iset( tstep , ecl_smspec_get_time_index( smspec ) , sim_seconds / ecl_smspec_get_time_seconds( smspec ) );
|
|
return tstep;
|
|
}
|
|
|
|
|
|
|
|
|
|
double ecl_sum_tstep_iget(const ecl_sum_tstep_type * ministep , int index) {
|
|
if ((index >= 0) && (index < ministep->data_size))
|
|
return ministep->data[index];
|
|
else {
|
|
util_abort("%s: param index:%d invalid: Valid range: [0,%d) \n",__func__ , index , ministep->data_size);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
time_t ecl_sum_tstep_get_sim_time(const ecl_sum_tstep_type * ministep) {
|
|
return ministep->sim_time;
|
|
}
|
|
|
|
|
|
double ecl_sum_tstep_get_sim_days(const ecl_sum_tstep_type * ministep) {
|
|
return ministep->sim_seconds / (24 * 3600);
|
|
}
|
|
|
|
double ecl_sum_tstep_get_sim_seconds(const ecl_sum_tstep_type * ministep) {
|
|
return ministep->sim_seconds;
|
|
}
|
|
|
|
int ecl_sum_tstep_get_report(const ecl_sum_tstep_type * ministep) {
|
|
return ministep->report_step;
|
|
}
|
|
|
|
|
|
int ecl_sum_tstep_get_ministep(const ecl_sum_tstep_type * ministep) {
|
|
return ministep->ministep;
|
|
}
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
void ecl_sum_tstep_fwrite( const ecl_sum_tstep_type * ministep , const int_vector_type * index_map , fortio_type * fortio) {
|
|
{
|
|
ecl_kw_type * ministep_kw = ecl_kw_alloc( MINISTEP_KW , 1 , ECL_INT );
|
|
ecl_kw_iset_int( ministep_kw , 0 , ministep->ministep );
|
|
ecl_kw_fwrite( ministep_kw , fortio );
|
|
ecl_kw_free( ministep_kw );
|
|
}
|
|
|
|
{
|
|
int compact_size = int_vector_size( index_map );
|
|
ecl_kw_type * params_kw = ecl_kw_alloc( PARAMS_KW , compact_size , ECL_FLOAT );
|
|
|
|
const int * index = int_vector_get_ptr( index_map );
|
|
float * data = (float*)ecl_kw_get_ptr( params_kw );
|
|
|
|
{
|
|
int i;
|
|
for (i=0; i < compact_size; i++)
|
|
data[i] = ministep->data[ index[i] ];
|
|
}
|
|
ecl_kw_fwrite( params_kw , fortio );
|
|
ecl_kw_free( params_kw );
|
|
}
|
|
}
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
void ecl_sum_tstep_iset( ecl_sum_tstep_type * tstep , int index , float value) {
|
|
if ((index < tstep->data_size) && (index >= 0))
|
|
tstep->data[index] = value;
|
|
else
|
|
util_abort("%s: index:%d invalid. Valid range: [0,%d) \n",__func__ ,index , tstep->data_size);
|
|
}
|
|
|
|
void ecl_sum_tstep_iscale(ecl_sum_tstep_type * tstep, int index, float scalar) {
|
|
ecl_sum_tstep_iset(tstep, index, ecl_sum_tstep_iget(tstep, index) * scalar);
|
|
}
|
|
|
|
void ecl_sum_tstep_ishift(ecl_sum_tstep_type * tstep, int index, float addend) {
|
|
ecl_sum_tstep_iset(tstep, index, ecl_sum_tstep_iget(tstep, index) + addend);
|
|
}
|
|
|
|
void ecl_sum_tstep_set_from_node( ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node , float value) {
|
|
int data_index = smspec_node_get_params_index( smspec_node );
|
|
ecl_sum_tstep_iset( tstep , data_index , value);
|
|
}
|
|
|
|
double ecl_sum_tstep_get_from_node( const ecl_sum_tstep_type * tstep , const smspec_node_type * smspec_node) {
|
|
int data_index = smspec_node_get_params_index( smspec_node );
|
|
return ecl_sum_tstep_iget( tstep , data_index);
|
|
}
|
|
|
|
|
|
void ecl_sum_tstep_set_from_key( ecl_sum_tstep_type * tstep , const char * gen_key , float value) {
|
|
const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key );
|
|
ecl_sum_tstep_set_from_node( tstep , smspec_node , value);
|
|
}
|
|
|
|
double ecl_sum_tstep_get_from_key(const ecl_sum_tstep_type * tstep , const char * gen_key) {
|
|
const smspec_node_type * smspec_node = ecl_smspec_get_general_var_node( tstep->smspec , gen_key );
|
|
return ecl_sum_tstep_get_from_node(tstep , smspec_node );
|
|
}
|
|
|
|
bool ecl_sum_tstep_has_key(const ecl_sum_tstep_type * tstep , const char * gen_key) {
|
|
return ecl_smspec_has_general_var(tstep->smspec, gen_key);
|
|
}
|
|
|
|
|
|
bool ecl_sum_tstep_sim_time_equal( const ecl_sum_tstep_type * tstep1 , const ecl_sum_tstep_type * tstep2 ) {
|
|
if (tstep1->sim_time == tstep2->sim_time)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|