mirror of
https://github.com/OPM/ResInsight.git
synced 2025-02-25 18:55:39 -06:00
835 lines
29 KiB
C++
835 lines
29 KiB
C++
/*
|
|
Copyright (C) 2016 Statoil ASA, Norway.
|
|
|
|
The file 'ecl_file_view.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 <ert/util/vector.hpp>
|
|
#include <ert/util/hash.hpp>
|
|
#include <ert/util/stringlist.hpp>
|
|
|
|
#include <ert/ecl/fortio.h>
|
|
#include <ert/ecl/ecl_kw.hpp>
|
|
#include <ert/ecl/ecl_kw_magic.hpp>
|
|
#include <ert/ecl/ecl_file_kw.hpp>
|
|
#include <ert/ecl/ecl_file_view.hpp>
|
|
#include <ert/ecl/ecl_rsthead.hpp>
|
|
#include <ert/ecl/ecl_type.hpp>
|
|
|
|
|
|
struct ecl_file_view_struct {
|
|
vector_type * kw_list; /* This is a vector of ecl_file_kw instances corresponding to the content of the file. */
|
|
hash_type * kw_index; /* A hash table with integer vectors of indices - see comment below. */
|
|
stringlist_type * distinct_kw; /* A stringlist of the keywords occuring in the file - each string occurs ONLY ONCE. */
|
|
fortio_type * fortio; /* The same fortio instance pointer as in the ecl_file styructure. */
|
|
bool owner; /* Is this map the owner of the ecl_file_kw instances; only true for the global_map. */
|
|
inv_map_type * inv_map; /* Shared reference owned by the ecl_file structure. */
|
|
vector_type * child_list;
|
|
int * flags;
|
|
};
|
|
|
|
struct ecl_file_transaction_struct {
|
|
const ecl_file_view_type * file_view;
|
|
int * ref_count;
|
|
};
|
|
|
|
|
|
/*****************************************************************/
|
|
/* Here comes the functions related to the index ecl_file_view. These
|
|
functions are all of them static.
|
|
*/
|
|
|
|
bool ecl_file_view_check_flags( int state_flags , int query_flags) {
|
|
if ((state_flags & query_flags) == query_flags)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
bool ecl_file_view_flags_set( const ecl_file_view_type * file_view , int query_flags) {
|
|
return ecl_file_view_check_flags( *file_view->flags , query_flags );
|
|
}
|
|
|
|
|
|
const char * ecl_file_view_get_src_file( const ecl_file_view_type * file_view ) {
|
|
return fortio_filename_ref( file_view->fortio );
|
|
}
|
|
|
|
|
|
ecl_file_view_type * ecl_file_view_alloc( fortio_type * fortio , int * flags , inv_map_type * inv_map , bool owner ) {
|
|
ecl_file_view_type * ecl_file_view = (ecl_file_view_type*)util_malloc( sizeof * ecl_file_view );
|
|
ecl_file_view->kw_list = vector_alloc_new();
|
|
ecl_file_view->kw_index = hash_alloc();
|
|
ecl_file_view->distinct_kw = stringlist_alloc_new();
|
|
ecl_file_view->child_list = vector_alloc_new();
|
|
ecl_file_view->owner = owner;
|
|
ecl_file_view->fortio = fortio;
|
|
ecl_file_view->inv_map = inv_map;
|
|
ecl_file_view->flags = flags;
|
|
return ecl_file_view;
|
|
}
|
|
|
|
int ecl_file_view_get_global_index( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) {
|
|
const int_vector_type * index_vector = (const int_vector_type*)hash_get(ecl_file_view->kw_index , kw);
|
|
int global_index = int_vector_iget( index_vector , ith);
|
|
return global_index;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
This function iterates over the kw_list vector and builds the
|
|
internal index fields 'kw_index' and 'distinct_kw'. This function
|
|
must be called every time the content of the kw_list vector is
|
|
modified (otherwise the ecl_file instance will be in an
|
|
inconsistent state).
|
|
*/
|
|
|
|
|
|
void ecl_file_view_make_index( ecl_file_view_type * ecl_file_view ) {
|
|
stringlist_clear( ecl_file_view->distinct_kw );
|
|
hash_clear( ecl_file_view->kw_index );
|
|
{
|
|
int i;
|
|
for (i=0; i < vector_get_size( ecl_file_view->kw_list ); i++) {
|
|
const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , i);
|
|
const char * header = ecl_file_kw_get_header( file_kw );
|
|
if ( !hash_has_key( ecl_file_view->kw_index , header )) {
|
|
int_vector_type * index_vector = int_vector_alloc( 0 , -1 );
|
|
hash_insert_hash_owned_ref( ecl_file_view->kw_index , header , index_vector , int_vector_free__);
|
|
stringlist_append_copy( ecl_file_view->distinct_kw , header);
|
|
}
|
|
|
|
{
|
|
int_vector_type * index_vector = (int_vector_type*)hash_get( ecl_file_view->kw_index , header);
|
|
int_vector_append( index_vector , i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool ecl_file_view_has_kw( const ecl_file_view_type * ecl_file_view, const char * kw) {
|
|
return hash_has_key( ecl_file_view->kw_index , kw );
|
|
}
|
|
|
|
|
|
ecl_file_kw_type * ecl_file_view_iget_file_kw( const ecl_file_view_type * ecl_file_view , int global_index) {
|
|
ecl_file_kw_type * file_kw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , global_index);
|
|
return file_kw;
|
|
}
|
|
|
|
ecl_file_kw_type * ecl_file_view_iget_named_file_kw( const ecl_file_view_type * ecl_file_view , const char * kw, int ith) {
|
|
int global_index = ecl_file_view_get_global_index( ecl_file_view , kw , ith);
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , global_index );
|
|
return file_kw;
|
|
}
|
|
|
|
bool ecl_file_view_drop_flag( ecl_file_view_type * file_view , int flag) {
|
|
bool flag_set = ecl_file_view_flags_set( file_view , flag );
|
|
if (flag_set)
|
|
*file_view->flags -= flag;
|
|
|
|
return flag_set;
|
|
}
|
|
|
|
void ecl_file_view_add_flag( ecl_file_view_type * file_view , int flag) {
|
|
*file_view->flags |= flag;
|
|
}
|
|
|
|
static ecl_kw_type * ecl_file_view_get_kw(const ecl_file_view_type * ecl_file_view, ecl_file_kw_type * file_kw) {
|
|
ecl_kw_type * ecl_kw = ecl_file_kw_get_kw_ptr( file_kw );
|
|
if (!ecl_kw) {
|
|
if (fortio_assert_stream_open( ecl_file_view->fortio )) {
|
|
|
|
ecl_kw = ecl_file_kw_get_kw( file_kw , ecl_file_view->fortio , ecl_file_view->inv_map);
|
|
|
|
if (ecl_file_view_flags_set( ecl_file_view , ECL_FILE_CLOSE_STREAM))
|
|
fortio_fclose_stream( ecl_file_view->fortio );
|
|
}
|
|
}
|
|
return ecl_kw;
|
|
}
|
|
|
|
ecl_kw_type * ecl_file_view_iget_kw( const ecl_file_view_type * ecl_file_view , int index) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , index );
|
|
return ecl_file_view_get_kw(ecl_file_view, file_kw);
|
|
}
|
|
|
|
void ecl_file_view_index_fload_kw(const ecl_file_view_type * ecl_file_view, const char* kw, int index, const int_vector_type * index_map, char* io_buffer) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_named_file_kw( ecl_file_view , kw , index);
|
|
|
|
if (fortio_assert_stream_open( ecl_file_view->fortio )) {
|
|
offset_type offset = ecl_file_kw_get_offset(file_kw);
|
|
ecl_data_type data_type = ecl_file_kw_get_data_type(file_kw);
|
|
int element_count = ecl_file_kw_get_size(file_kw);
|
|
|
|
ecl_kw_fread_indexed_data(ecl_file_view->fortio, offset + ECL_KW_HEADER_FORTIO_SIZE, data_type, element_count, index_map, io_buffer);
|
|
}
|
|
}
|
|
|
|
|
|
int ecl_file_view_find_kw_value( const ecl_file_view_type * ecl_file_view , const char * kw , const void * value) {
|
|
int global_index = -1;
|
|
if ( ecl_file_view_has_kw( ecl_file_view , kw)) {
|
|
const int_vector_type * index_list = (const int_vector_type*)hash_get( ecl_file_view->kw_index , kw );
|
|
int index = 0;
|
|
while (index < int_vector_size( index_list )) {
|
|
const ecl_kw_type * ecl_kw = ecl_file_view_iget_kw( ecl_file_view , int_vector_iget( index_list , index ));
|
|
if (ecl_kw_data_equal( ecl_kw , value )) {
|
|
global_index = int_vector_iget( index_list , index );
|
|
break;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
return global_index;
|
|
}
|
|
|
|
const char * ecl_file_view_iget_distinct_kw( const ecl_file_view_type * ecl_file_view , int index) {
|
|
return stringlist_iget( ecl_file_view->distinct_kw , index);
|
|
}
|
|
|
|
int ecl_file_view_get_num_distinct_kw( const ecl_file_view_type * ecl_file_view ) {
|
|
return stringlist_get_size( ecl_file_view->distinct_kw );
|
|
}
|
|
|
|
int ecl_file_view_get_size( const ecl_file_view_type * ecl_file_view ) {
|
|
return vector_get_size( ecl_file_view->kw_list );
|
|
}
|
|
|
|
|
|
ecl_data_type ecl_file_view_iget_data_type( const ecl_file_view_type * ecl_file_view , int index) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , index );
|
|
return ecl_file_kw_get_data_type( file_kw );
|
|
}
|
|
|
|
int ecl_file_view_iget_size( const ecl_file_view_type * ecl_file_view , int index) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , index );
|
|
return ecl_file_kw_get_size( file_kw );
|
|
}
|
|
|
|
const char * ecl_file_view_iget_header( const ecl_file_view_type * ecl_file_view , int index) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw( ecl_file_view , index );
|
|
return ecl_file_kw_get_header( file_kw );
|
|
}
|
|
|
|
|
|
ecl_kw_type * ecl_file_view_iget_named_kw( const ecl_file_view_type * ecl_file_view , const char * kw, int ith) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_named_file_kw( ecl_file_view , kw , ith);
|
|
return ecl_file_view_get_kw(ecl_file_view, file_kw);
|
|
}
|
|
|
|
ecl_data_type ecl_file_view_iget_named_data_type( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_named_file_kw( ecl_file_view , kw, ith);
|
|
return ecl_file_kw_get_data_type( file_kw );
|
|
}
|
|
|
|
int ecl_file_view_iget_named_size( const ecl_file_view_type * ecl_file_view , const char * kw , int ith) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_named_file_kw( ecl_file_view , kw , ith );
|
|
return ecl_file_kw_get_size( file_kw );
|
|
}
|
|
|
|
|
|
void ecl_file_view_replace_kw( ecl_file_view_type * ecl_file_view , ecl_kw_type * old_kw , ecl_kw_type * new_kw , bool insert_copy) {
|
|
int index = 0;
|
|
while (index < vector_get_size( ecl_file_view->kw_list )) {
|
|
ecl_file_kw_type * ikw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , index );
|
|
if (ecl_file_kw_ptr_eq( ikw , old_kw)) {
|
|
/*
|
|
Found it; observe that the vector_iset() function will
|
|
automatically invoke the destructor on the old_kw.
|
|
*/
|
|
ecl_kw_type * insert_kw = new_kw;
|
|
|
|
if (insert_copy)
|
|
insert_kw = ecl_kw_alloc_copy( new_kw );
|
|
ecl_file_kw_replace_kw( ikw , ecl_file_view->fortio , insert_kw );
|
|
|
|
ecl_file_view_make_index( ecl_file_view );
|
|
return;
|
|
}
|
|
index++;
|
|
}
|
|
util_abort("%s: could not find ecl_kw ptr: %p \n",__func__ , old_kw);
|
|
}
|
|
|
|
|
|
bool ecl_file_view_load_all( ecl_file_view_type * ecl_file_view ) {
|
|
bool loadOK = false;
|
|
|
|
if (fortio_assert_stream_open( ecl_file_view->fortio )) {
|
|
int index;
|
|
for (index = 0; index < vector_get_size( ecl_file_view->kw_list); index++) {
|
|
ecl_file_kw_type * ikw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , index );
|
|
ecl_file_kw_get_kw( ikw , ecl_file_view->fortio , ecl_file_view->inv_map);
|
|
}
|
|
loadOK = true;
|
|
}
|
|
|
|
if (ecl_file_view_flags_set( ecl_file_view , ECL_FILE_CLOSE_STREAM))
|
|
fortio_fclose_stream( ecl_file_view->fortio );
|
|
|
|
return loadOK;
|
|
}
|
|
|
|
|
|
/*****************************************************************/
|
|
|
|
|
|
|
|
void ecl_file_view_add_kw( ecl_file_view_type * ecl_file_view , ecl_file_kw_type * file_kw) {
|
|
if (ecl_file_view->owner)
|
|
vector_append_owned_ref( ecl_file_view->kw_list , file_kw , ecl_file_kw_free__ );
|
|
else
|
|
vector_append_ref( ecl_file_view->kw_list , file_kw);
|
|
}
|
|
|
|
void ecl_file_view_free( ecl_file_view_type * ecl_file_view ) {
|
|
vector_free( ecl_file_view->child_list );
|
|
hash_free( ecl_file_view->kw_index );
|
|
stringlist_free( ecl_file_view->distinct_kw );
|
|
vector_free( ecl_file_view->kw_list );
|
|
free( ecl_file_view );
|
|
}
|
|
|
|
void ecl_file_view_free__( void * arg ) {
|
|
ecl_file_view_type * ecl_file_view = ( ecl_file_view_type * ) arg;
|
|
ecl_file_view_free( ecl_file_view );
|
|
}
|
|
|
|
|
|
int ecl_file_view_get_num_named_kw(const ecl_file_view_type * ecl_file_view , const char * kw) {
|
|
if (hash_has_key(ecl_file_view->kw_index , kw)) {
|
|
const int_vector_type * index_vector = (const int_vector_type*)hash_get(ecl_file_view->kw_index , kw);
|
|
return int_vector_size( index_vector );
|
|
} else
|
|
return 0;
|
|
}
|
|
|
|
void ecl_file_view_fwrite( const ecl_file_view_type * ecl_file_view , fortio_type * target , int offset) {
|
|
int index;
|
|
for (index = offset; index < vector_get_size( ecl_file_view->kw_list ); index++) {
|
|
ecl_kw_type * ecl_kw = ecl_file_view_iget_kw( ecl_file_view , index );
|
|
ecl_kw_fwrite( ecl_kw , target );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
int ecl_file_view_iget_occurence( const ecl_file_view_type * ecl_file_view , int global_index) {
|
|
const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , global_index);
|
|
const char * header = ecl_file_kw_get_header( file_kw );
|
|
const int_vector_type * index_vector = (const int_vector_type*)hash_get( ecl_file_view->kw_index , header );
|
|
const int * index_data = int_vector_get_const_ptr( index_vector );
|
|
|
|
int occurence = -1;
|
|
{
|
|
/* Manual reverse lookup. */
|
|
int i;
|
|
for (i=0; i < int_vector_size( index_vector ); i++)
|
|
if (index_data[i] == global_index)
|
|
occurence = i;
|
|
}
|
|
if (occurence < 0)
|
|
util_abort("%s: internal error ... \n" , __func__);
|
|
|
|
return occurence;
|
|
}
|
|
|
|
void ecl_file_view_fprintf_kw_list(const ecl_file_view_type * ecl_file_view , FILE * stream) {
|
|
int i;
|
|
for (i=0; i < vector_get_size( ecl_file_view->kw_list ); i++) {
|
|
const ecl_file_kw_type * file_kw = (const ecl_file_kw_type*)vector_iget_const( ecl_file_view->kw_list , i );
|
|
char * type_name = ecl_type_alloc_name(ecl_file_kw_get_data_type(file_kw));
|
|
fprintf(stream , "%-8s %7d:%s\n",
|
|
ecl_file_kw_get_header( file_kw ) ,
|
|
ecl_file_kw_get_size( file_kw ) ,
|
|
type_name);
|
|
free(type_name);
|
|
}
|
|
}
|
|
|
|
|
|
ecl_file_view_type * ecl_file_view_alloc_blockview2(const ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence) {
|
|
if ((start_kw != NULL) && ecl_file_view_get_num_named_kw( ecl_file_view , start_kw ) <= occurence)
|
|
return NULL;
|
|
|
|
|
|
ecl_file_view_type * block_map = ecl_file_view_alloc( ecl_file_view->fortio , ecl_file_view->flags , ecl_file_view->inv_map , false);
|
|
int kw_index = 0;
|
|
if (start_kw)
|
|
kw_index = ecl_file_view_get_global_index( ecl_file_view , start_kw , occurence );
|
|
|
|
{
|
|
ecl_file_kw_type * file_kw = (ecl_file_kw_type*)vector_iget( ecl_file_view->kw_list , kw_index );
|
|
while (true) {
|
|
ecl_file_view_add_kw( block_map , file_kw );
|
|
|
|
kw_index++;
|
|
if (kw_index == vector_get_size( ecl_file_view->kw_list ))
|
|
break;
|
|
else {
|
|
if (end_kw) {
|
|
file_kw = (ecl_file_kw_type*)vector_iget(ecl_file_view->kw_list , kw_index);
|
|
if (strcmp( end_kw , ecl_file_kw_get_header( file_kw )) == 0)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
ecl_file_view_make_index( block_map );
|
|
return block_map;
|
|
}
|
|
|
|
/**
|
|
Will return NULL if the block which is asked for is not present.
|
|
*/
|
|
ecl_file_view_type * ecl_file_view_alloc_blockview(const ecl_file_view_type * ecl_file_view , const char * header, int occurence) {
|
|
return ecl_file_view_alloc_blockview2( ecl_file_view , header , header , occurence );
|
|
}
|
|
|
|
|
|
ecl_file_view_type * ecl_file_view_add_blockview(const ecl_file_view_type * file_view , const char * header, int occurence) {
|
|
ecl_file_view_type * child = ecl_file_view_alloc_blockview2(file_view, header, header, occurence);
|
|
|
|
if (child)
|
|
vector_append_owned_ref( file_view->child_list , child , ecl_file_view_free__ );
|
|
|
|
return child;
|
|
}
|
|
|
|
|
|
ecl_file_view_type * ecl_file_view_add_blockview2(const ecl_file_view_type * ecl_file_view , const char * start_kw, const char * end_kw, int occurence) {
|
|
ecl_file_view_type * child = ecl_file_view_alloc_blockview2(ecl_file_view, start_kw , end_kw , occurence);
|
|
|
|
if (child)
|
|
vector_append_owned_ref( ecl_file_view->child_list , child , ecl_file_view_free__ );
|
|
|
|
return child;
|
|
}
|
|
|
|
|
|
|
|
/*****************************************************************/
|
|
/* R E S T A R T F I L E S */
|
|
/*****************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
There is no special datastructure for working with restart files,
|
|
they are 100% stock ecl_file instances with the following limited
|
|
structure:
|
|
|
|
* They are organized in blocks; where each block starts with a
|
|
SEQNUM keyword, which contains the report step.
|
|
|
|
* Each block contains an INTEHEAD keyword, immediately after the
|
|
SEQNUM keyword, which contains the true simulation date of of the
|
|
block, and also some other data. Observe that also INIT files and
|
|
GRID files contain an INTEHEAD keyword; and that for files with
|
|
LGRs there is one INTEHEAD keyword for each LGR. This creates an
|
|
extra level of mess.
|
|
|
|
The natural time ordering when working with the file data is just
|
|
the running index in the file; however from a user perspective the
|
|
natural way to indicate time coordinate is through the report step
|
|
or the true simulation time (i.e. 22.th of October 2009). This file
|
|
is all about converting the natural input unit time and report_step
|
|
to the internal indexing. This is achieved by consulting the value
|
|
of the INTEHEAD and SEQNUM keywords respectively.
|
|
*/
|
|
|
|
/*
|
|
About the time-direction
|
|
========================
|
|
|
|
For the following discussion we will focus on the following simplified
|
|
unified restart file. The leading number is the global index of the
|
|
keyword, the value in [] corresponds to the relevant part of the
|
|
content of the keyword on the line, the labels A,B,C,D,E are used for
|
|
references in the text below.
|
|
|
|
0 | SEQNUM [0] \ A
|
|
1 | INTEHEAD [01.01.2005] |
|
|
2 | PRESSURE [... ] |
|
|
3 | SWAT [...] |
|
|
| -----------------------+
|
|
4 | SEQNUM [5] | B
|
|
5 | INTEHEAD [01.06.2005] |
|
|
6 | PRESSURE [... ] |
|
|
7 | SWAT [...] |
|
|
|------------------------+
|
|
8 | SEQNUM [10] | C
|
|
9 | INTEHEAD [01.12.2006] |
|
|
10 | PRESSURE [...] |
|
|
11 | SWAT [...] |
|
|
|------------------------+
|
|
12 | SEQNUM [20] | D
|
|
13 | INTEHEAD [01.12.2007] |
|
|
14 | PRESSURE [...] |
|
|
15 | SWAT [...] |
|
|
16 | OIL_DEN [...] |
|
|
|------------------------+
|
|
17 | SEQNUM [40] | E
|
|
18 | INTEHEAD [01.12.2009] |
|
|
19 | PRESSURE [...] |
|
|
20 | SWAT [...] /
|
|
|
|
|
|
This restart file has the following features:
|
|
|
|
o It contains in total 16 keywords.
|
|
|
|
o It contains 5 blocks of collected keywords corresponding to one
|
|
time instant, each of these blocks is called a report_step,
|
|
typcially coming from one DATES keyword in the ECLIPSE
|
|
datafile. Observe that the file does not have the block structure
|
|
visualized on this figure, the only thing separating the blocks in
|
|
the file is the occurence of a SEQNUM keyword.
|
|
|
|
o Only a few of the report steps are present, namely 0, 5, 10, 20 and
|
|
40.
|
|
|
|
o The different blocks are not equally long, the fourth block has an
|
|
extra keyword OIL_DEN.
|
|
|
|
To adress these keywords and blocks using different time coordinates
|
|
we have introduced the following concepts:
|
|
|
|
report_step: This corresponds to the value of the SEQNUM keword,
|
|
i.e. to do queries based on the report_step we must load the
|
|
seqnum kewyord and read the value.
|
|
|
|
ecl_file_get_unrstmap_report_step( ecl_file , 0 ) => A
|
|
ecl_file_get_unrstmap_report_step( ecl_file , 1 ) => NULL
|
|
|
|
ecl_file_has_report_step( ecl_file , 5 ) => True
|
|
ecl_file_has_report_step( ecl_file , 2 ) => False
|
|
|
|
sim_time: This correpsonds to the true simulation time of the report
|
|
step, the simulation time is stored as integers DAY, MONTH, YEAR
|
|
in the INTEHEAD keyword; the function INTEHEAD_date() will extract
|
|
the DAY, MONTH and YEAR values from an INTEHEAD keyword instance
|
|
and convert to a time_t instance. The functions:
|
|
|
|
ecl_file_get_unrstmap_sim_time() and ecl_file_has_has_sim_time()
|
|
|
|
can be used to query for simulation times and get the
|
|
corresponding block maps.
|
|
|
|
index/global_index : This is typically the global running index of
|
|
the keyword in the file; this is the unique address of the keyword
|
|
which is used for the final lookup.
|
|
|
|
occurence: The nth' time a particular keyword has occured in the
|
|
file, i.e. the SEQNUM keyword in block C is the third occurence of
|
|
SEQNUM. Instead of occurence xxxx_index is also used to indicate
|
|
the occurence of keyword xxxx. The occurence number is the integer
|
|
argument to the xxx_iget_named_kw() function, and also the final
|
|
call to create blockmaps.
|
|
|
|
*/
|
|
|
|
|
|
bool ecl_file_view_has_report_step( const ecl_file_view_type * ecl_file_view , int report_step) {
|
|
int global_index = ecl_file_view_find_kw_value( ecl_file_view , SEQNUM_KW , &report_step );
|
|
if (global_index >= 0)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
|
|
time_t ecl_file_view_iget_restart_sim_date(const ecl_file_view_type * ecl_file_view , int seqnum_index) {
|
|
time_t sim_time = -1;
|
|
ecl_file_view_type * seqnum_map = ecl_file_view_alloc_blockview( ecl_file_view , SEQNUM_KW , seqnum_index);
|
|
|
|
if (seqnum_map != NULL) {
|
|
ecl_kw_type * intehead_kw = ecl_file_view_iget_named_kw( seqnum_map , INTEHEAD_KW , 0);
|
|
sim_time = ecl_rsthead_date( intehead_kw );
|
|
ecl_file_view_free( seqnum_map );
|
|
}
|
|
|
|
return sim_time;
|
|
}
|
|
|
|
|
|
double ecl_file_view_iget_restart_sim_days(const ecl_file_view_type * ecl_file_view , int seqnum_index) {
|
|
double sim_days = 0;
|
|
ecl_file_view_type * seqnum_map = ecl_file_view_alloc_blockview( ecl_file_view , SEQNUM_KW , seqnum_index);
|
|
|
|
if (seqnum_map != NULL) {
|
|
ecl_kw_type * doubhead_kw = ecl_file_view_iget_named_kw( seqnum_map , DOUBHEAD_KW , 0);
|
|
sim_days = ecl_kw_iget_double( doubhead_kw , DOUBHEAD_DAYS_INDEX);
|
|
ecl_file_view_free( seqnum_map );
|
|
}
|
|
|
|
return sim_days;
|
|
}
|
|
|
|
|
|
|
|
|
|
int ecl_file_view_find_sim_time(const ecl_file_view_type * ecl_file_view , time_t sim_time) {
|
|
int seqnum_index = -1;
|
|
if ( ecl_file_view_has_kw( ecl_file_view , INTEHEAD_KW)) {
|
|
const int_vector_type * intehead_index_list = (const int_vector_type *)hash_get( ecl_file_view->kw_index , INTEHEAD_KW );
|
|
int index = 0;
|
|
while (index < int_vector_size( intehead_index_list )) {
|
|
const ecl_kw_type * intehead_kw = ecl_file_view_iget_kw( ecl_file_view , int_vector_iget( intehead_index_list , index ));
|
|
if (ecl_rsthead_date( intehead_kw ) == sim_time) {
|
|
seqnum_index = index;
|
|
break;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
return seqnum_index;
|
|
}
|
|
|
|
|
|
/**
|
|
This function will scan through the ecl_file looking for INTEHEAD
|
|
headers corresponding to sim_time. If sim_time is found the
|
|
function will return the INTEHEAD occurence number, i.e. for a
|
|
unified restart file like:
|
|
|
|
INTEHEAD / 01.01.2000
|
|
...
|
|
PRESSURE
|
|
SWAT
|
|
...
|
|
INTEHEAD / 01.03.2000
|
|
...
|
|
PRESSURE
|
|
SWAT
|
|
...
|
|
INTEHEAD / 01.05.2000
|
|
...
|
|
PRESSURE
|
|
SWAT
|
|
....
|
|
|
|
The function call:
|
|
|
|
ecl_file_get_restart_index( restart_file , (time_t) "01.03.2000")
|
|
|
|
will return 1. Observe that this will in general NOT agree with the
|
|
DATES step number.
|
|
|
|
If the sim_time can not be found the function will return -1, that
|
|
includes the case when the file in question is not a restart file
|
|
at all, and no INTEHEAD headers can be found.
|
|
|
|
Observe that the function requires on-the-second-equality; which is
|
|
of course quite strict.
|
|
|
|
Each report step only has one occurence of SEQNUM, but one INTEHEAD
|
|
for each LGR; i.e. one should call iselect_rstblock() prior to
|
|
calling this function.
|
|
*/
|
|
|
|
|
|
bool ecl_file_view_has_sim_time( const ecl_file_view_type * ecl_file_view , time_t sim_time) {
|
|
int num_INTEHEAD = ecl_file_view_get_num_named_kw( ecl_file_view , INTEHEAD_KW );
|
|
if (num_INTEHEAD == 0)
|
|
return false; /* We have no INTEHEAD headers - probably not a restart file at all. */
|
|
else {
|
|
int intehead_index = 0;
|
|
while (true) {
|
|
time_t itime = ecl_file_view_iget_restart_sim_date( ecl_file_view , intehead_index );
|
|
|
|
if (itime == sim_time) /* Perfect hit. */
|
|
return true;
|
|
|
|
if (itime > sim_time) /* We have gone past the target_time - i.e. we do not have it. */
|
|
return false;
|
|
|
|
intehead_index++;
|
|
if (intehead_index == num_INTEHEAD) /* We have iterated through the whole thing without finding sim_time. */
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool ecl_file_view_has_sim_days( const ecl_file_view_type * ecl_file_view , double sim_days) {
|
|
int num_DOUBHEAD = ecl_file_view_get_num_named_kw( ecl_file_view , DOUBHEAD_KW );
|
|
if (num_DOUBHEAD == 0)
|
|
return false; /* We have no DOUBHEAD headers - probably not a restart file at all. */
|
|
else {
|
|
int doubhead_index = 0;
|
|
while (true) {
|
|
double file_sim_days = ecl_file_view_iget_restart_sim_days( ecl_file_view , doubhead_index );
|
|
|
|
if (util_double_approx_equal(sim_days, file_sim_days)) /* Perfect hit. */
|
|
return true;
|
|
|
|
if (file_sim_days > sim_days) /* We have gone past the target_time - i.e. we do not have it. */
|
|
return false;
|
|
|
|
doubhead_index++;
|
|
if (doubhead_index == num_DOUBHEAD) /* We have iterated through the whole thing without finding sim_time. */
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
int ecl_file_view_seqnum_index_from_sim_time( ecl_file_view_type * parent_map , time_t sim_time) {
|
|
int num_seqnum = ecl_file_view_get_num_named_kw( parent_map , SEQNUM_KW );
|
|
ecl_file_view_type * seqnum_map;
|
|
|
|
for (int s_idx = 0; s_idx < num_seqnum; s_idx++) {
|
|
seqnum_map = ecl_file_view_alloc_blockview( parent_map , SEQNUM_KW , s_idx );
|
|
|
|
if (!seqnum_map)
|
|
continue;
|
|
|
|
bool sim = ecl_file_view_has_sim_time( seqnum_map , sim_time);
|
|
ecl_file_view_free( seqnum_map );
|
|
if (sim)
|
|
return s_idx;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
|
|
int ecl_file_view_seqnum_index_from_sim_days( ecl_file_view_type * file_view , double sim_days) {
|
|
int num_seqnum = ecl_file_view_get_num_named_kw( file_view , SEQNUM_KW );
|
|
int seqnum_index = 0;
|
|
ecl_file_view_type * seqnum_map;
|
|
|
|
while (true) {
|
|
seqnum_map = ecl_file_view_alloc_blockview( file_view , SEQNUM_KW , seqnum_index);
|
|
|
|
if (seqnum_map != NULL) {
|
|
if (ecl_file_view_has_sim_days( seqnum_map , sim_days)) {
|
|
ecl_file_view_free( seqnum_map );
|
|
return seqnum_index;
|
|
} else {
|
|
ecl_file_view_free( seqnum_map );
|
|
seqnum_index++;
|
|
}
|
|
}
|
|
|
|
if (num_seqnum == seqnum_index)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Will mulitplex on the four input arguments.
|
|
*/
|
|
ecl_file_view_type * ecl_file_view_add_restart_view( ecl_file_view_type * file_view , int input_index, int report_step , time_t sim_time, double sim_days) {
|
|
ecl_file_view_type * child = NULL;
|
|
int seqnum_index = -1;
|
|
|
|
if (input_index >= 0)
|
|
seqnum_index = input_index;
|
|
else if (report_step >= 0) {
|
|
int global_index = ecl_file_view_find_kw_value( file_view , SEQNUM_KW , &report_step);
|
|
if ( global_index >= 0)
|
|
seqnum_index = ecl_file_view_iget_occurence( file_view , global_index );
|
|
} else if (sim_time != -1)
|
|
seqnum_index = ecl_file_view_seqnum_index_from_sim_time( file_view , sim_time );
|
|
else if (sim_days >= 0)
|
|
seqnum_index = ecl_file_view_seqnum_index_from_sim_days( file_view , sim_days );
|
|
|
|
|
|
if (seqnum_index >= 0)
|
|
child = ecl_file_view_add_blockview( file_view , SEQNUM_KW , seqnum_index );
|
|
|
|
return child;
|
|
}
|
|
|
|
|
|
|
|
ecl_file_view_type * ecl_file_view_add_summary_view( ecl_file_view_type * file_view , int report_step ) {
|
|
ecl_file_view_type * child = ecl_file_view_add_blockview( file_view , SEQHDR_KW , report_step );
|
|
return child;
|
|
}
|
|
|
|
|
|
void ecl_file_view_fclose_stream( ecl_file_view_type * file_view ) {
|
|
fortio_fclose_stream( file_view->fortio );
|
|
}
|
|
|
|
void ecl_file_view_write_index(const ecl_file_view_type * file_view, FILE * ostream) {
|
|
int size = ecl_file_view_get_size(file_view);
|
|
util_fwrite_int( size , ostream);
|
|
|
|
ecl_file_kw_type * file_kw;
|
|
for (int i = 0; i < size; i++) {
|
|
file_kw = ecl_file_view_iget_file_kw( file_view, i );
|
|
ecl_file_kw_fwrite( file_kw , ostream );
|
|
}
|
|
}
|
|
|
|
ecl_file_view_type * ecl_file_view_fread_alloc( fortio_type * fortio , int * flags , inv_map_type * inv_map, FILE * istream ) {
|
|
|
|
int index_size = util_fread_int(istream);
|
|
ecl_file_kw_type ** file_kw_list = ecl_file_kw_fread_alloc_multiple( istream, index_size);
|
|
if (file_kw_list) {
|
|
ecl_file_view_type * file_view = ecl_file_view_alloc( fortio , flags , inv_map , true );
|
|
for (int i=0; i < index_size; i++)
|
|
ecl_file_view_add_kw(file_view , file_kw_list[i]);
|
|
|
|
free(file_kw_list);
|
|
ecl_file_view_make_index( file_view );
|
|
return file_view;
|
|
}
|
|
else {
|
|
fprintf(stderr, "%s: error reading ecl_file_type index file.\n", __func__);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
ecl_file_transaction_type * ecl_file_view_start_transaction(ecl_file_view_type * file_view) {
|
|
ecl_file_transaction_type * t = (ecl_file_transaction_type *)util_malloc(sizeof * t);
|
|
int size = ecl_file_view_get_size(file_view);
|
|
t->file_view = file_view;
|
|
t->ref_count = (int*)util_malloc( size * sizeof * t->ref_count );
|
|
for (int i = 0; i < size; i++) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw(file_view, i);
|
|
ecl_file_kw_start_transaction(file_kw, &t->ref_count[i]);
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
void ecl_file_view_end_transaction( ecl_file_view_type * file_view, ecl_file_transaction_type * transaction) {
|
|
if (transaction->file_view != file_view)
|
|
util_abort("%s: internal error - file_view / transaction mismatch\n",__func__);
|
|
|
|
const int * ref_count = transaction->ref_count;
|
|
for (int i = 0; i < ecl_file_view_get_size(file_view); i++) {
|
|
ecl_file_kw_type * file_kw = ecl_file_view_iget_file_kw(file_view, i);
|
|
ecl_file_kw_end_transaction(file_kw, ref_count[i]);
|
|
}
|
|
}
|
|
|
|
|
|
|