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

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;
}