Skip to content

Commit

Permalink
Ecl sum keyword vector (#237)
Browse files Browse the repository at this point in the history
EclSumKeywordVector: can handle missing values.
  • Loading branch information
joakim-hove committed Nov 16, 2017
1 parent f7ac7f2 commit 2fff098
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 28 deletions.
43 changes: 33 additions & 10 deletions lib/ecl/ecl_sum_data.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/

#include <string.h>
#include <math.h>

#include <ert/util/util.h>
#include <ert/util/vector.h>
Expand Down Expand Up @@ -1180,12 +1181,10 @@ double ecl_sum_data_interp_get(const ecl_sum_data_type * data , int time_index1
}


static double ecl_sum_data_vector_iget(const ecl_sum_data_type * data, time_t sim_time, const ecl_sum_vector_type * keylist, int key_index,
static double ecl_sum_data_vector_iget(const ecl_sum_data_type * data, time_t sim_time, int params_index, bool is_rate,
int time_index1 , int time_index2 , double weight1 , double weight2 ) {

int params_index = ecl_sum_vector_iget_param_index(keylist, key_index);
double value = 0.0;
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, key_index);
if (is_rate) {
int time_index = ecl_sum_data_get_index_from_sim_time(data, sim_time);
// uses step function since it is a rate
Expand All @@ -1205,15 +1204,35 @@ void ecl_sum_data_fwrite_interp_csv_line(const ecl_sum_data_type * data, time_t
ecl_sum_data_init_interp_from_sim_time(data, sim_time, &time_index1, &time_index2, &weight1, &weight2);

for (int i = 0; i < num_keywords; i++) {
double value = ecl_sum_data_vector_iget( data, sim_time, keylist , i , time_index1, time_index2, weight1, weight2);
if (ecl_sum_vector_iget_valid(keylist, i)) {
int params_index = ecl_sum_vector_iget_param_index(keylist, i);
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, i);
double value = ecl_sum_data_vector_iget( data, sim_time, params_index , is_rate, time_index1, time_index2, weight1, weight2);

if (i == 0)
fprintf(fp, "%f", value);
else
fprintf(fp, ",%f", value);
if (i == 0)
fprintf(fp, "%f", value);
else
fprintf(fp, ",%f", value);
} else {
if (i == 0)
fputs("", fp);
else
fputs(",", fp);
}
}
}


/*
If the keylist contains invalid indices the corresponding element in the
results vector will *not* be updated; i.e. it is smart to initialize the
results vector with an invalid-value marker before calling this function:
double_vector_type * results = double_vector_alloc( ecl_sum_vector_get_size(keys), NAN);
ecl_sum_data_get_interp_vector( data, sim_time, keys, results);
*/

void ecl_sum_data_get_interp_vector( const ecl_sum_data_type * data , time_t sim_time, const ecl_sum_vector_type * keylist, double_vector_type * results){
int num_keywords = ecl_sum_vector_get_size(keylist);
double weight1, weight2;
Expand All @@ -1222,8 +1241,12 @@ void ecl_sum_data_get_interp_vector( const ecl_sum_data_type * data , time_t sim
ecl_sum_data_init_interp_from_sim_time(data, sim_time, &time_index1, &time_index2, &weight1, &weight2);
double_vector_reset( results );
for (int i = 0; i < num_keywords; i++) {
double value = ecl_sum_data_vector_iget( data, sim_time, keylist , i , time_index1, time_index2, weight1, weight2);
double_vector_iset( results, i , value );
if (ecl_sum_vector_iget_valid(keylist, i)) {
int params_index = ecl_sum_vector_iget_param_index(keylist, i);
bool is_rate = ecl_sum_vector_iget_is_rate(keylist, i);
double value = ecl_sum_data_vector_iget( data, sim_time, params_index, is_rate, time_index1, time_index2, weight1, weight2);
double_vector_iset( results, i , value );
}
}
}

Expand Down
39 changes: 37 additions & 2 deletions lib/ecl/ecl_sum_vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,39 @@ ecl_sum_vector_type * ecl_sum_vector_alloc(const ecl_sum_type * ecl_sum){
return ecl_sum_vector;
}

static void ecl_sum_vector_add_invalid_key(ecl_sum_vector_type * vector, const char * key) {
int_vector_append(vector->node_index_list, -1);
bool_vector_append(vector->is_rate_list, false);
stringlist_append_copy(vector->key_list, key);
}


/*
This function will allocate a keyword vector for the keys in the @ecl_sum
argument passed in, it will contain all the same keys as in the input argument
@src_vector. If the @src_vector contains keys which are not present in
@ecl_sum an entry marked as *invalid* will be added. The whole point about
this function is to ensure that calls to:
ecl_sum_fwrite_interp_csv_line( )
will result in nicely aligned output even if the different summary cases do
not have the exact same keys.
*/

ecl_sum_vector_type * ecl_sum_vector_alloc_layout_copy(const ecl_sum_vector_type * src_vector, const ecl_sum_type * ecl_sum) {
ecl_sum_vector_type * new_vector = ecl_sum_vector_alloc(ecl_sum);
for (int i=0; i < stringlist_get_size(src_vector->key_list); i++) {
const char * key = stringlist_iget(src_vector->key_list, i);
if (ecl_sum_has_general_var(ecl_sum, key))
ecl_sum_vector_add_key(new_vector, key);
else
ecl_sum_vector_add_invalid_key(new_vector, key);
}
return new_vector;
}



bool ecl_sum_vector_add_key( ecl_sum_vector_type * ecl_sum_vector, const char * key){
if (ecl_sum_has_general_var( ecl_sum_vector->ecl_sum , key)) {
Expand All @@ -73,8 +106,6 @@ bool ecl_sum_vector_add_key( ecl_sum_vector_type * ecl_sum_vector, const char *
return false;
}



void ecl_sum_vector_add_keys( ecl_sum_vector_type * ecl_sum_vector, const char * pattern){
stringlist_type * keylist = ecl_sum_alloc_matching_general_var_list(ecl_sum_vector->ecl_sum , pattern);

Expand All @@ -101,6 +132,10 @@ bool ecl_sum_vector_iget_is_rate(const ecl_sum_vector_type * ecl_sum_vector, int
return bool_vector_iget(ecl_sum_vector->is_rate_list, index);
}

bool ecl_sum_vector_iget_valid(const ecl_sum_vector_type * ecl_sum_vector, int index) {
return (int_vector_iget(ecl_sum_vector->node_index_list, index) >= 0);
}

int ecl_sum_vector_iget_param_index(const ecl_sum_vector_type * ecl_sum_vector, int index){
return int_vector_iget(ecl_sum_vector->node_index_list, index);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/include/ert/ecl/ecl_sum_vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ typedef struct ecl_sum_vector_struct ecl_sum_vector_type;
bool ecl_sum_vector_iget_is_rate(const ecl_sum_vector_type * ecl_sum_vector, int index);
int ecl_sum_vector_iget_param_index(const ecl_sum_vector_type * ecl_sum_vector, int index);
int ecl_sum_vector_get_size(const ecl_sum_vector_type * ecl_sum_vector);
bool ecl_sum_vector_iget_valid(const ecl_sum_vector_type * ecl_sum_vector, int index);


UTIL_IS_INSTANCE_HEADER( ecl_sum_vector);

Expand Down
4 changes: 2 additions & 2 deletions python/python/ecl/ecl/ecl_sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,9 +538,9 @@ def get_interp(self, key, days=None, date=None):
raise ValueError("Must supply either days or date")


def get_interp_row(self, key_list, sim_time):
def get_interp_row(self, key_list, sim_time, invalid_value = -1):
ctime = CTime(sim_time)
data = DoubleVector( initial_size = len(key_list) )
data = DoubleVector( initial_size = len(key_list) , default_value = invalid_value)
EclSum._get_interp_vector(self, ctime, key_list, data)
return data

Expand Down
5 changes: 5 additions & 0 deletions python/python/ecl/ecl/ecl_sum_keyword_vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
class EclSumKeyWordVector(BaseCClass):
TYPE_NAME = "ecl_sum_vector"
_alloc = EclPrototype("void* ecl_sum_vector_alloc(ecl_sum)", bind=False)
_alloc_copy = EclPrototype("ecl_sum_vector_obj ecl_sum_vector_alloc_layout_copy(ecl_sum_vector, ecl_sum)")
_free = EclPrototype("void ecl_sum_vector_free(ecl_sum_vector)")
_add = EclPrototype("bool ecl_sum_vector_add_key(ecl_sum_vector, char*)")
_add_multiple = EclPrototype("void ecl_sum_vector_add_keys(ecl_sum_vector, char*)")
Expand Down Expand Up @@ -68,5 +69,9 @@ def add_keywords(self, keyword_pattern):
def __repr__(self):
return self._create_repr('len=%d' % len(self))

def copy(self, ecl_sum):
return self._alloc_copy(ecl_sum)


monkey_the_camel(EclSumKeyWordVector, 'addKeyword', EclSumKeyWordVector.add_keyword)
monkey_the_camel(EclSumKeyWordVector, 'addKeywords', EclSumKeyWordVector.add_keywords)
65 changes: 51 additions & 14 deletions python/tests/ecl/test_sum.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
# for more details.

import os
import inspect
import datetime
import csv
import shutil
Expand Down Expand Up @@ -287,23 +288,32 @@ def test_invalid(self):


def test_kw_vector(self):
case = createEclSum("CSV" , [("FOPT", None , 0) , ("FOPR" , None , 0), ("FGPT" , None , 0)],
sim_length_days = 100,
num_report_step = 10,
num_mini_step = 10,
func_table = {"FOPT" : fopt,
"FOPR" : fopr ,
"FGPT" : fgpt })
kw_list = EclSumKeyWordVector( case )
case1 = createEclSum("CSV" , [("FOPT", None , 0) , ("FOPR" , None , 0), ("FGPT" , None , 0)],
sim_length_days = 100,
num_report_step = 10,
num_mini_step = 10,
func_table = {"FOPT" : fopt,
"FOPR" : fopr ,
"FGPT" : fgpt })

case2 = createEclSum("CSV" , [("FOPR", None , 0) , ("FOPT" , None , 0), ("FWPT" , None , 0)],
sim_length_days = 100,
num_report_step = 10,
num_mini_step = 10,
func_table = {"FOPT" : fopt,
"FOPR" : fopr ,
"FWPT" : fgpt })

kw_list = EclSumKeyWordVector( case1 )
kw_list.add_keyword("FOPT")
kw_list.add_keyword("FOPR")
kw_list.add_keyword("FGPT")
kw_list.add_keyword("FOPR")

t = case.getDataStartTime( ) + datetime.timedelta( days = 43 );
data = case.get_interp_row( kw_list , t )
for d1,d2 in zip(data, [ case.get_interp("FOPT", date = t),
case.get_interp("FOPT", date = t),
case.get_interp("FOPT", date = t) ]):
t = case1.getDataStartTime( ) + datetime.timedelta( days = 43 );
data = case1.get_interp_row( kw_list , t )
for d1,d2 in zip(data, [ case1.get_interp("FOPT", date = t),
case1.get_interp("FOPT", date = t),
case1.get_interp("FOPT", date = t) ]):

self.assertFloatEqual(d1,d2)

Expand All @@ -313,3 +323,30 @@ def test_kw_vector(self):

for (k1,k2) in zip(kw_list,tmp):
self.assertEqual(k1,k2)

kw_list2 = kw_list.copy(case2)
self.assertIn("FOPT", kw_list2)
self.assertIn("FOPR", kw_list2)
self.assertIn("FGPT", kw_list2)
data2 = case2.get_interp_row( kw_list2 , t )

self.assertEqual(len(data2), 3)
self.assertEqual(data[0], data2[0])
self.assertEqual(data[2], data2[2])

with TestAreaContext("sum_vector"):
with open("f1.txt","w") as f:
case1.dumpCSVLine(t, kw_list, f)

with open("f2.txt", "w") as f:
case2.dumpCSVLine(t,kw_list2,f)

with open("f1.txt") as f:
d1 = f.readline().split(",")

with open("f2.txt") as f:
d2 = f.readline().split(",")

self.assertEqual(d1[0],d2[0])
self.assertEqual(d1[2],d2[2])
self.assertEqual(d2[1],"")

0 comments on commit 2fff098

Please sign in to comment.