diff --git a/lib/ecl/ecl_smspec.c b/lib/ecl/ecl_smspec.c index 69fffe905f..c725d5d2f2 100644 --- a/lib/ecl/ecl_smspec.c +++ b/lib/ecl/ecl_smspec.c @@ -142,6 +142,7 @@ struct ecl_smspec_struct { char * restart_case; ert_ecl_unit_enum unit_system; + int restart_step; }; @@ -282,6 +283,7 @@ ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join ecl_smspec->index_map = int_vector_alloc(0,0); ecl_smspec->restart_case = NULL; + ecl_smspec->restart_step = -1; ecl_smspec->params_default = float_vector_alloc(0 , PARAMS_GLOBAL_DEFAULT); ecl_smspec->write_mode = write_mode; ecl_smspec->need_nums = false; @@ -392,7 +394,6 @@ static void ecl_smspec_fwrite_RESTART(const ecl_smspec_type * smspec, fortio_typ offset += ECL_STRING8_LENGTH; } } - ecl_kw_fwrite( restart_kw , fortio ); ecl_kw_free( restart_kw ); } @@ -406,10 +407,8 @@ static void ecl_smspec_fwrite_DIMENS(const ecl_smspec_type * smspec, fortio_type ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NX_INDEX , smspec->grid_dims[0] ); ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NY_INDEX , smspec->grid_dims[1] ); ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_NZ_INDEX , smspec->grid_dims[2] ); - - /* Do not know what these two last items are for. */ - ecl_kw_iset_int( dimens_kw , 4 , 0 ); - ecl_kw_iset_int( dimens_kw , 5 , -1 ); + ecl_kw_iset_int( dimens_kw , 4 , 0 ); // Do not know what this is for. + ecl_kw_iset_int( dimens_kw , DIMENS_SMSPEC_RESTART_STEP_INDEX , smspec->restart_step ); ecl_kw_fwrite( dimens_kw , fortio ); ecl_kw_free( dimens_kw ); @@ -515,16 +514,19 @@ void ecl_smspec_fwrite( const ecl_smspec_type * smspec , const char * ecl_case , free( filename ); } -ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const char * restart_case, time_t sim_start , bool time_in_days , int nx , int ny , int nz) { - ecl_smspec_type * ecl_smspec = ecl_smspec_alloc_empty( true , key_join_string ); + +static ecl_smspec_type * ecl_smspec_alloc_writer__( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz) { + ecl_smspec_type * ecl_smspec = ecl_smspec_alloc_empty( true , key_join_string ); /* Only a total of 9 * 8 characters is set aside for the restart keyword, if the supplied restart case is longer than that we silently ignore it. */ if (restart_case) { - if (strlen(restart_case) <= (SUMMARY_RESTART_SIZE * ECL_STRING8_LENGTH)) + if (strlen(restart_case) <= (SUMMARY_RESTART_SIZE * ECL_STRING8_LENGTH)) { ecl_smspec->restart_case = util_alloc_string_copy( restart_case ); + ecl_smspec->restart_step = restart_step; + } } ecl_smspec->grid_dims[0] = nx; ecl_smspec->grid_dims[1] = ny; @@ -563,6 +565,14 @@ ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const return ecl_smspec; } +ecl_smspec_type * ecl_smspec_alloc_restart_writer( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz) { + return ecl_smspec_alloc_writer__(key_join_string, restart_case, restart_step, sim_start, time_in_days, nx, ny, nz); +} + +ecl_smspec_type * ecl_smspec_alloc_writer(const char * key_join_string, time_t sim_start, bool time_in_days, int nx, int ny , int nz) { + return ecl_smspec_alloc_writer__(key_join_string, NULL, 0, sim_start, time_in_days, nx, ny, nz); +} + UTIL_SAFE_CAST_FUNCTION( ecl_smspec , ECL_SMSPEC_ID ) @@ -1196,6 +1206,7 @@ static bool ecl_smspec_fread_header(ecl_smspec_type * ecl_smspec, const char * h ecl_smspec->grid_dims[0] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NX_INDEX ); ecl_smspec->grid_dims[1] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NY_INDEX ); ecl_smspec->grid_dims[2] = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_NZ_INDEX ); + ecl_smspec->restart_step = ecl_kw_iget_int(dimens , DIMENS_SMSPEC_RESTART_STEP_INDEX); ecl_smspec_set_params_size( ecl_smspec , ecl_kw_get_size(keywords)); ecl_util_get_file_type( header_file , &ecl_smspec->formatted , NULL ); @@ -1670,6 +1681,10 @@ const char * ecl_smspec_get_header_file( const ecl_smspec_type * ecl_smspec ) { } +int ecl_smspec_get_restart_step(const ecl_smspec_type * ecl_smspec) { + return ecl_smspec->restart_step; +} + const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec) { return ecl_smspec->restart_case; diff --git a/lib/ecl/ecl_sum.c b/lib/ecl/ecl_sum.c index 235afb16d3..57692fe185 100644 --- a/lib/ecl/ecl_sum.c +++ b/lib/ecl/ecl_sum.c @@ -317,22 +317,46 @@ ecl_sum_tstep_type * ecl_sum_add_tstep( ecl_sum_type * ecl_sum , int report_step return ecl_sum_data_add_new_tstep( ecl_sum->data , report_step , sim_seconds ); } - -ecl_sum_type * ecl_sum_alloc_restart_writer( const char * ecl_case , const char * restart_case , bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { +static ecl_sum_type * ecl_sum_alloc_writer__( const char * ecl_case , const char * restart_case , int restart_step, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { ecl_sum_type * ecl_sum = ecl_sum_alloc__( ecl_case , key_join_string ); if (ecl_sum) { ecl_sum_set_unified( ecl_sum , unified ); ecl_sum_set_fmt_case( ecl_sum , fmt_output ); - ecl_sum->smspec = ecl_smspec_alloc_writer( key_join_string , restart_case, sim_start , time_in_days , nx , ny , nz ); + if (restart_case) + ecl_sum->smspec = ecl_smspec_alloc_restart_writer( key_join_string , restart_case, restart_step, sim_start , time_in_days , nx , ny , nz ); + else + ecl_sum->smspec = ecl_smspec_alloc_writer( key_join_string, sim_start, time_in_days, nx, ny, nz); + ecl_sum->data = ecl_sum_data_alloc_writer( ecl_sum->smspec ); } return ecl_sum; } + +ecl_sum_type * ecl_sum_alloc_restart_writer2( const char * ecl_case , const char * restart_case , int restart_step, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { + return ecl_sum_alloc_writer__(ecl_case, restart_case, restart_step, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz); +} + + +/* + This does not take in the restart_step argument is depcrecated. You should use the + ecl_sum_alloc_restart_writer2() function. +*/ + +ecl_sum_type * ecl_sum_alloc_restart_writer( const char * ecl_case , const char * restart_case, bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { + int restart_step = 0; + return ecl_sum_alloc_writer__(ecl_case, restart_case, restart_step, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz); +} + + + + + + ecl_sum_type * ecl_sum_alloc_writer( const char * ecl_case , bool fmt_output , bool unified , const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz) { - return ecl_sum_alloc_restart_writer(ecl_case, NULL, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz); + return ecl_sum_alloc_writer__(ecl_case, NULL, 0, fmt_output, unified, key_join_string, sim_start, time_in_days, nx, ny, nz); } @@ -1144,6 +1168,10 @@ const ecl_sum_type * ecl_sum_get_restart_case(const ecl_sum_type * ecl_sum) { return ecl_sum->restart_case; } +int ecl_sum_get_restart_step(const ecl_sum_type * ecl_sum) { + return ecl_smspec_get_restart_step(ecl_sum->smspec); +} + const char * ecl_sum_get_case(const ecl_sum_type * ecl_sum) { return ecl_sum->ecl_case; diff --git a/lib/ecl/ecl_sum_data.c b/lib/ecl/ecl_sum_data.c index 001632b290..73d29f763f 100644 --- a/lib/ecl/ecl_sum_data.c +++ b/lib/ecl/ecl_sum_data.c @@ -928,9 +928,15 @@ void ecl_sum_data_add_case(ecl_sum_data_type * self, const ecl_sum_data_type * o ecl_sum_tstep_type * other_tstep = ecl_sum_data_iget_ministep( other , tstep_nr ); /* - The dataset 'self' is the authorative in the timeinterval where - it has data, so if 'other' also has data in the same time interval - that is discarded. + The dataset 'self' is the authorative in the timeinterval where it has + data, so if 'other' also has data in the same time interval that is + discarded. In most cases 'other' will represent a history case, and 'self' + is a prediction which has been restarted. + + After implementing the time_interval_contains() based check it turned out + that the smspec structure also contains a restart_step integer value in + the DIMENS vector which could probably be used to achieve the same thing. + That field is currently not used. */ if (!time_interval_contains( self->sim_time , ecl_sum_tstep_get_sim_time( other_tstep ))) { diff --git a/lib/ecl/tests/ecl_sum_writer.c b/lib/ecl/tests/ecl_sum_writer.c index 396353e69b..f1691a943d 100644 --- a/lib/ecl/tests/ecl_sum_writer.c +++ b/lib/ecl/tests/ecl_sum_writer.c @@ -184,8 +184,9 @@ void test_long_restart_names() { const char * name = "THE_CASE"; test_work_area_type * work_area = test_work_area_alloc("sum_write_restart_long_name"); { + int restart_step = 77; time_t start_time = util_make_date_utc( 1,1,2010 ); - ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer( name , restart_case , false , true , ":" , start_time , true , 3, 3, 3); + ecl_sum_type * ecl_sum = ecl_sum_alloc_restart_writer2( name , restart_case , restart_step, false , true , ":" , start_time , true , 3, 3, 3); ecl_sum_fwrite( ecl_sum ); ecl_sum_free(ecl_sum); @@ -199,8 +200,9 @@ void test_long_restart_names() { char s[9]; sprintf(s, "WWWWGGG%d", n); test_assert_string_equal(s, ecl_kw_iget_char_ptr(restart_kw, n) ); } + ecl_file_close( smspec_file); { - ecl_smspec_type * smspec = ecl_smspec_alloc_writer( ":" , "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ", start_time, true, 3, 3 ,3); + ecl_smspec_type * smspec = ecl_smspec_alloc_restart_writer( ":" , "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ", 10, start_time, true, 3, 3 ,3); /* Restart case is too long - it is ignored. */ diff --git a/lib/include/ert/ecl/ecl_kw_magic.h b/lib/include/ert/ecl/ecl_kw_magic.h index 20c7036909..8c0f50db65 100644 --- a/lib/include/ert/ecl/ecl_kw_magic.h +++ b/lib/include/ert/ecl/ecl_kw_magic.h @@ -453,15 +453,17 @@ values (2e20) are denoted with '*'. keyword in the SMSPEC files. Observe that these magic indices differ from the magic indices used to look up grid dimensions from the DIMENS keyword in GRID files. */ -#define DIMENS_SMSPEC_SIZE_INDEX 0 -#define DIMENS_SMSPEC_NX_INDEX 1 -#define DIMENS_SMSPEC_NY_INDEX 2 -#define DIMENS_SMSPEC_NZ_INDEX 3 -#define DIMENS_SIZE 6 // Do not know what the two last items are? - -#define INTEHEAD_SMSPEC_IPROG_INDEX 0 -#define INTEHEAD_SMSPEC_UNIT_INDEX 1 +#define DIMENS_SMSPEC_SIZE_INDEX 0 +#define DIMENS_SMSPEC_NX_INDEX 1 +#define DIMENS_SMSPEC_NY_INDEX 2 +#define DIMENS_SMSPEC_NZ_INDEX 3 +#define DIMENS_SMSPEC_RESTART_STEP_INDEX 5 +#define DIMENS_SIZE 6 + #define INTEHEAD_SMSPEC_SIZE 2 +#define INTEHEAD_SMSPEC_UNIT_INDEX 0 +#define INTEHEAD_SMSPEC_IPROG_INDEX 1 + /* Summary data files: */ #define SEQHDR_KW "SEQHDR" // Contains a single 'magic' integer - not used in libecl. diff --git a/lib/include/ert/ecl/ecl_smspec.h b/lib/include/ert/ecl/ecl_smspec.h index 53033877c8..f42e5c338b 100644 --- a/lib/include/ert/ecl/ecl_smspec.h +++ b/lib/include/ert/ecl/ecl_smspec.h @@ -56,7 +56,10 @@ typedef struct ecl_smspec_struct ecl_smspec_type; const char * ecl_smspec_get_var_type_name( ecl_smspec_var_type var_type ); ecl_smspec_var_type ecl_smspec_identify_var_type(const char * var); ecl_smspec_type * ecl_smspec_alloc_empty(bool write_mode , const char * key_join_string); - ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , const char * restart_case, time_t sim_start , bool time_in_days , int nx , int ny , int nz); + + ecl_smspec_type * ecl_smspec_alloc_restart_writer( const char * key_join_string , const char * restart_case, int restart_step, time_t sim_start , bool time_in_days , int nx , int ny , int nz); + + ecl_smspec_type * ecl_smspec_alloc_writer( const char * key_join_string , time_t sim_start , bool time_in_days , int nx , int ny , int nz); void ecl_smspec_fwrite( const ecl_smspec_type * smspec , const char * ecl_case , bool fmt_file ); ecl_smspec_type * ecl_smspec_fread_alloc(const char *header_file, const char * key_join_string , bool include_restart); @@ -130,6 +133,7 @@ typedef struct ecl_smspec_struct ecl_smspec_type; stringlist_type * ecl_smspec_alloc_group_list( const ecl_smspec_type * smspec , const char * pattern); stringlist_type * ecl_smspec_alloc_well_var_list( const ecl_smspec_type * smspec ); const char * ecl_smspec_get_simulation_path(const ecl_smspec_type * ecl_smspec); + int ecl_smspec_get_restart_step(const ecl_smspec_type * ecl_smspec); const char * ecl_smspec_get_restart_case( const ecl_smspec_type * ecl_smspec); const char * ecl_smspec_get_join_string( const ecl_smspec_type * smspec); const float_vector_type * ecl_smspec_get_params_default( const ecl_smspec_type * ecl_smspec ); diff --git a/lib/include/ert/ecl/ecl_sum.h b/lib/include/ert/ecl/ecl_sum.h index b4cc20ff89..5c2f8fdc96 100644 --- a/lib/include/ert/ecl/ecl_sum.h +++ b/lib/include/ert/ecl/ecl_sum.h @@ -202,7 +202,18 @@ typedef struct ecl_sum_struct ecl_sum_type; int ecl_sum_iget_report_end( const ecl_sum_type * ecl_sum , int report_step ); int ecl_sum_iget_report_start( const ecl_sum_type * ecl_sum , int report_step ); - + ecl_sum_type * ecl_sum_alloc_restart_writer2( const char * ecl_case, + const char * restart_case, + int restart_step, + bool fmt_output, + bool unified, + const char * key_join_string, + time_t sim_start, + bool time_in_days, + int nx, + int ny, + int nz); + ecl_sum_type * ecl_sum_alloc_restart_writer(const char * ecl_case , const char * restart_case , bool fmt_output , diff --git a/python/ecl/summary/ecl_sum.py b/python/ecl/summary/ecl_sum.py index 5aee17a057..8225a04414 100644 --- a/python/ecl/summary/ecl_sum.py +++ b/python/ecl/summary/ecl_sum.py @@ -88,7 +88,8 @@ class EclSum(BaseCClass): TYPE_NAME = "ecl_sum" _fread_alloc_case = EclPrototype("void* ecl_sum_fread_alloc_case__(char*, char*, bool)", bind=False) _fread_alloc = EclPrototype("void* ecl_sum_fread_alloc(char*, stringlist, char*, bool)", bind=False) - _create_restart_writer = EclPrototype("ecl_sum_obj ecl_sum_alloc_restart_writer(char*, char*, bool, bool, char*, time_t, bool, int, int, int)", bind = False) + _create_restart_writer = EclPrototype("ecl_sum_obj ecl_sum_alloc_restart_writer2(char*, char*, int, bool, bool, char*, time_t, bool, int, int, int)", bind = False) + _create_writer = EclPrototype("ecl_sum_obj ecl_sum_alloc_writer(char*, bool, bool, char*, time_t, bool, int, int, int)", bind = False) _resample = EclPrototype("ecl_sum_obj ecl_sum_alloc_resample( ecl_sum, char*, time_t_vector)") _iiget = EclPrototype("double ecl_sum_iget(ecl_sum, int, int)") _free = EclPrototype("void ecl_sum_free(ecl_sum)") @@ -121,6 +122,7 @@ class EclSum(BaseCClass): _get_data_start = EclPrototype("time_t ecl_sum_get_data_start(ecl_sum)") _get_unit = EclPrototype("char* ecl_sum_get_unit(ecl_sum, char*)") _get_restart_case = EclPrototype("ecl_sum_ref ecl_sum_get_restart_case(ecl_sum)") + _get_restart_step = EclPrototype("int ecl_sum_get_restart_step(ecl_sum)") _get_simcase = EclPrototype("char* ecl_sum_get_case(ecl_sum)") _get_unit_system = EclPrototype("ecl_unit_enum ecl_sum_get_unit_system(ecl_sum)") _get_base = EclPrototype("char* ecl_sum_get_base(ecl_sum)") @@ -217,15 +219,15 @@ def writer(case, start_time, nx,ny,nz, fmt_output=False, unified=True, time_in_d The writer is not generally usable. @rtype: EclSum """ - return EclSum._create_restart_writer(case, None, fmt_output, unified, key_join_string, CTime(start_time), time_in_days, nx, ny, nz) + return EclSum._create_writer(case, fmt_output, unified, key_join_string, CTime(start_time), time_in_days, nx, ny, nz) @staticmethod - def restart_writer(case, restart_case, start_time, nx,ny,nz, fmt_output=False, unified=True, time_in_days=True, key_join_string=":"): + def restart_writer(case, restart_case, restart_step, start_time, nx,ny,nz, fmt_output=False, unified=True, time_in_days=True, key_join_string=":"): """ The writer is not generally usable. @rtype: EclSum """ - return EclSum._create_restart_writer(case, restart_case, fmt_output, unified, key_join_string, CTime(start_time), time_in_days, nx, ny, nz) + return EclSum._create_restart_writer(case, restart_case, restart_step, fmt_output, unified, key_join_string, CTime(start_time), time_in_days, nx, ny, nz) def add_variable(self, variable, wgname=None, num=0, unit="None", default_value=0): return self._add_variable(variable, wgname, num, unit, default_value).setParent(parent=self) @@ -776,6 +778,14 @@ def case(self): return self._get_simcase() + @property + def restart_step(self): + """ + Will return the report step this case has been restarted from, or -1. + """ + return self._get_restart_step() + + @property def restart_case(self): restart_case = self._get_restart_case() diff --git a/python/ecl/util/test/ecl_mock/ecl_sum_mock.py b/python/ecl/util/test/ecl_mock/ecl_sum_mock.py index 07e5b3bc2d..a2f1e210f2 100644 --- a/python/ecl/util/test/ecl_mock/ecl_sum_mock.py +++ b/python/ecl/util/test/ecl_mock/ecl_sum_mock.py @@ -15,9 +15,10 @@ def createEclSum( case, num_mini_step = 10, dims = (20,10,5) , func_table = {}, - restart_case = None): + restart_case = None, + restart_step = -1): - ecl_sum = EclSum.restart_writer(case , restart_case, sim_start , dims[0] , dims[1] , dims[2]) + ecl_sum = EclSum.restart_writer(case , restart_case, restart_step, sim_start , dims[0] , dims[1] , dims[2]) var_list = [] for (kw,wgname,num) in keys: var_list.append( ecl_sum.addVariable( kw , wgname = wgname , num = num) ) diff --git a/python/tests/ecl_tests/test_sum.py b/python/tests/ecl_tests/test_sum.py index 69d241a5a1..811e7ec6db 100644 --- a/python/tests/ecl_tests/test_sum.py +++ b/python/tests/ecl_tests/test_sum.py @@ -47,8 +47,9 @@ def pushd(path): def create_prediction(history, pred_path): restart_case = os.path.join( os.getcwd(), history.base) + restart_step = history.last_report with pushd(pred_path): - prediction = create_case( case = "PREDICTION", restart_case = restart_case, data_start = history.end_date) + prediction = create_case( case = "PREDICTION", restart_case = restart_case, restart_step = restart_step, data_start = history.end_date) prediction.fwrite() @@ -64,7 +65,7 @@ def fgpt(days): else: return 100 - days -def create_case(case = "CSV", restart_case = None, data_start = None): +def create_case(case = "CSV", restart_case = None, restart_step = -1, data_start = None): length = 100 return createEclSum(case , [("FOPT", None , 0) , ("FOPR" , None , 0), ("FGPT" , None , 0)], sim_length_days = length, @@ -74,7 +75,8 @@ def create_case(case = "CSV", restart_case = None, data_start = None): func_table = {"FOPT" : fopt, "FOPR" : fopr , "FGPT" : fgpt }, - restart_case = restart_case) + restart_case = restart_case, + restart_step = restart_step) class SumTest(EclTest): @@ -401,7 +403,7 @@ def test_resample(self): def test_restart_abs_path(self): with TestAreaContext("restart_test"): - history = create_case(case = "HISTORY") + history = create_case(case = "HISTORY") history.fwrite() pred_path = "prediction" @@ -414,6 +416,7 @@ def test_restart_abs_path(self): if pred.restart_case: self.assertTrue(isinstance(pred.restart_case, EclSum)) self.assertEqual(pred.restart_case.case, os.path.join(os.getcwd(), history.case)) + self.assertEqual(pred.restart_step, history.last_report) length = pred.sim_length pred_times = pred.alloc_time_vector(False) @@ -472,7 +475,7 @@ def test_units(self): f = EclFile("UNITS.SMSPEC") for kw in f: if kw.name == "INTEHEAD": - kw[1] = 3 + kw[0] = 3 kw_list.append(kw.copy()) f.close()