From 496aee1015fb674a997216a242060fc044a1e6f0 Mon Sep 17 00:00:00 2001 From: "Oddvar Lia (ST MSU GEO)" Date: Fri, 20 Oct 2023 09:39:09 +0200 Subject: [PATCH] Add test case for non-adaptive localisation Add option to specify alternative settings for the test case using a yml file Replaced gaussianfft as python module for simulation of gaussian fields with gstools. write scaling factor in same file format as input fields Add config file for test example Add example case with ROFF and GRDECL file Add cases with RMS grid index origin Add case with actnum --- .../localisation/local_script_lib.py | 84 +- test_requirements.txt | 1 + tests/jobs/localisation/example_case/README | 43 + .../example_case/example_test_config_A.yml | 53 + .../example_test_config_A_with_actnum.yml | 54 + .../example_case/example_test_config_B.yml | 53 + .../example_case/example_test_config_C.yml | 53 + .../example_case/example_test_config_D.yml | 53 + .../example_case/init_files/README | 7 + .../localisation/example_case/localisation.wf | 1 + .../example_case/modify_variogram.yml | 5 + .../example_case/scripts/FM_SIM_FIELD | 6 + .../localisation/example_case/scripts/README | 13 + .../example_case/scripts/__init__.py | 0 .../example_case/scripts/common_functions.py | 924 ++++++++++++++++++ .../scripts/import_field_parameters.py | 22 + .../scripts/import_field_parameters_local.py | 29 + .../scripts/import_fields_to_rms.py | 121 +++ .../import_upscaled_field_parameters.py | 21 + .../import_upscaled_field_parameters_local.py | 21 + .../example_case/scripts/init_test_case.py | 304 ++++++ .../example_case/scripts/sim_fields.py | 112 +++ .../localisation/example_case/sim_field.ert | 58 ++ .../example_case/sim_field_case_A.ert | 58 ++ .../sim_field_case_A_with_actnum.ert | 58 ++ .../example_case/sim_field_case_B.ert | 57 ++ .../example_case/sim_field_case_C.ert | 58 ++ .../example_case/sim_field_case_D.ert | 57 ++ .../example_case/sim_field_local.ert | 57 ++ .../example_case/sim_field_local_case_A.ert | 57 ++ .../sim_field_local_case_A_with_actnum.ert | 57 ++ .../example_case/sim_field_local_case_B.ert | 57 ++ .../example_case/sim_field_local_case_C.ert | 57 ++ .../example_case/sim_field_local_case_D.ert | 57 ++ .../localisation/example_case/time_map.txt | 1 + 35 files changed, 2643 insertions(+), 26 deletions(-) create mode 100644 tests/jobs/localisation/example_case/README create mode 100644 tests/jobs/localisation/example_case/example_test_config_A.yml create mode 100644 tests/jobs/localisation/example_case/example_test_config_A_with_actnum.yml create mode 100644 tests/jobs/localisation/example_case/example_test_config_B.yml create mode 100644 tests/jobs/localisation/example_case/example_test_config_C.yml create mode 100644 tests/jobs/localisation/example_case/example_test_config_D.yml create mode 100644 tests/jobs/localisation/example_case/init_files/README create mode 100644 tests/jobs/localisation/example_case/localisation.wf create mode 100644 tests/jobs/localisation/example_case/modify_variogram.yml create mode 100644 tests/jobs/localisation/example_case/scripts/FM_SIM_FIELD create mode 100644 tests/jobs/localisation/example_case/scripts/README create mode 100644 tests/jobs/localisation/example_case/scripts/__init__.py create mode 100644 tests/jobs/localisation/example_case/scripts/common_functions.py create mode 100644 tests/jobs/localisation/example_case/scripts/import_field_parameters.py create mode 100644 tests/jobs/localisation/example_case/scripts/import_field_parameters_local.py create mode 100644 tests/jobs/localisation/example_case/scripts/import_fields_to_rms.py create mode 100644 tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters.py create mode 100644 tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters_local.py create mode 100755 tests/jobs/localisation/example_case/scripts/init_test_case.py create mode 100755 tests/jobs/localisation/example_case/scripts/sim_fields.py create mode 100644 tests/jobs/localisation/example_case/sim_field.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_case_A.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_case_A_with_actnum.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_case_B.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_case_C.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_case_D.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local_case_A.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local_case_A_with_actnum.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local_case_B.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local_case_C.ert create mode 100644 tests/jobs/localisation/example_case/sim_field_local_case_D.ert create mode 100644 tests/jobs/localisation/example_case/time_map.txt diff --git a/semeio/workflows/localisation/local_script_lib.py b/semeio/workflows/localisation/local_script_lib.py index 4e560ef0..938cd5ca 100644 --- a/semeio/workflows/localisation/local_script_lib.py +++ b/semeio/workflows/localisation/local_script_lib.py @@ -17,6 +17,8 @@ from ecl.util.geometry import Surface from ert.analysis.row_scaling import RowScaling from ert.config import Field, GenDataConfig, GenKwConfig, SurfaceConfig +from ert.field_utils import save_field +from ert.field_utils.field_file_format import FieldFileFormat from numpy import ma from semeio.workflows.localisation.localisation_debug_settings import ( @@ -632,7 +634,9 @@ def add_ministeps( tapering_range = ( corr_spec.field_scale.normalised_tapering_range ) - check_if_ref_point_in_grid(ref_pos, grid_for_field) + check_if_ref_point_in_grid( + ref_pos, grid_for_field, log_level=user_config.log_level + ) param_for_field = apply_decay( corr_spec.field_scale.method, row_scaling, @@ -695,6 +699,7 @@ def add_ministeps( grid_for_field, param_for_field, user_config.log_level, + node.file_format, ) update_step["row_scaling_parameters"].append( [node_name, row_scaling] @@ -810,15 +815,21 @@ def add_ministeps( return update_steps -def check_if_ref_point_in_grid(ref_point, grid): +def check_if_ref_point_in_grid(ref_point, grid, log_level): try: - grid.find_cell_xy(ref_point[0], ref_point[1], 0) + (i_indx, j_indx) = grid.find_cell_xy(ref_point[0], ref_point[1], 0) except ValueError as err: raise ValueError( f"Reference point {ref_point} corresponds to undefined grid cell " f"or is outside the area defined by the grid {grid.get_name()}\n" - "Check specification of reference point." + "Check specification of reference point ", + "and grid index origin of grid with field parameters.", ) from err + debug_print( + f"Reference point {ref_point} has grid indices: ({i_indx}, {j_indx})", + LogLevel.LEVEL3, + log_level, + ) @dataclass @@ -947,35 +958,56 @@ def write_qc_parameter( grid, param_for_field, log_level=LogLevel.OFF, + file_format=FieldFileFormat.GRDECL, ): # pylint: disable=too-many-arguments + if param_for_field is None or field_scale is None: return - scaling_values = np.reshape( - param_for_field, (grid.getNX(), grid.getNY(), grid.getNZ()), "F" + # Write scaling parameter once per corr_name + if corr_name == cls.corr_name: + return + + cls.corr_name = corr_name + + # Need a parameter name <= 8 character long for GRDECL format + scaling_kw_name = "S_" + str(cls.scaling_param_number) + file_name_without_suffix = ( + cls.corr_name + "_" + node_name + "_" + scaling_kw_name ) - # Write scaling parameter once per corr_name - if corr_name != cls.corr_name: - cls.corr_name = corr_name - # Need a parameter name <= 8 character long - scaling_kw_name = "S_" + str(cls.scaling_param_number) - scaling_kw = grid.create_kw(scaling_values, scaling_kw_name, False) - filename = ( - cls.corr_name + "_" + node_name + "_" + scaling_kw_name + ".GRDECL" - ) - print( - "Write calculated scaling factor with name: " - f"{scaling_kw_name} to file: {filename}" - ) - debug_print( - f"Write calculated scaling factor with name: " - f"{scaling_kw_name} to file: {filename}", - LogLevel.LEVEL3, - log_level, + if file_format == FieldFileFormat.GRDECL: + scaling_values = np.reshape( + param_for_field, (grid.getNX(), grid.getNY(), grid.getNZ()), "F" ) + + scaling_kw = grid.create_kw(scaling_values, scaling_kw_name, False) + filename = file_name_without_suffix + ".GRDECL" + with cwrap.open(filename, "w") as file: grid.write_grdecl(scaling_kw, file) - # Increase parameter number to define unique parameter name - cls.scaling_param_number = cls.scaling_param_number + 1 + # For testing + name = scaling_kw_name + "_use_save_field" + save_field(scaling_values, name, filename, FieldFileFormat.GRDECL) + + elif file_format == FieldFileFormat.ROFF: + scaling_values = np.reshape( + param_for_field, (grid.getNX(), grid.getNY(), grid.getNZ()), "C" + ) + filename = file_name_without_suffix + ".roff" + save_field(scaling_values, scaling_kw_name, filename, FieldFileFormat.ROFF) + + print( + "Write calculated scaling factor with name: " + f"{scaling_kw_name} to file: {filename}" + ) + debug_print( + f"Write calculated scaling factor with name: " + f"{scaling_kw_name} to file: {filename}", + LogLevel.LEVEL3, + log_level, + ) + + # Increase parameter number to define unique parameter name + cls.scaling_param_number = cls.scaling_param_number + 1 diff --git a/test_requirements.txt b/test_requirements.txt index 8bfdb402..0a58e14e 100644 --- a/test_requirements.txt +++ b/test_requirements.txt @@ -8,3 +8,4 @@ pytest-httpserver pytest-snapshot rstcheck-core<=1.0.3 xlwt +gstools diff --git a/tests/jobs/localisation/example_case/README b/tests/jobs/localisation/example_case/README new file mode 100644 index 00000000..bdfba08e --- /dev/null +++ b/tests/jobs/localisation/example_case/README @@ -0,0 +1,43 @@ +## Directory for Test Case for Non-Adaptive Localisation (`LOCALISATION_JOB`) +​ +### Main Components: +​ +- **ERT config file:** `sim_field.ert` +​ + The ERT model depends on: + - `scripts/sim_fields.py` + - `scripts/common_functions.py` +​ +​ +- **ERT Keyword Input:** + - **GRID:** Input grid is made by `scripts/init_test_case.py` + - **OBS_CONFIG:** Observations are extracted from an upscaled realization made by `scripts/init_test_case.py` + - **GEN_DATA:** Prediction of observables made by forward model `SIM_FIELD` which runs `scripts/sim_fields.py` + - **FIELD:** Prior realizations of field made by forward model `SIM_FIELD` which runs `scripts/sim_fields.py` +​ +- **Other ERT Input Files:** + - `time_map.txt` + - `localisation.wf` +​ +- **Other Files:** + - `randomseeds.txt`: Not used by ERT, but by `sim_fields.py`. This file can be generated by `scripts/init_test_case.py` + - `UpscaledGrid.EGRID`: Not used by ERT, but by `sim_fields.py`. This file can be generated by `scripts/init_test_case.py` +​ +### Typical Workflow: +​ +1. **Preparation:** Prepare ERT config input by running `scripts/init_test_case.py`. +2. Directories for observations are created automatically according to the default settings. +3. Activate or deactivate localisation in ERT config file (`HOOK_WORKFLOW LOAD_WORKFLOW` for localisation). +4. Now ready to run ERT. +​ +### What the Script `sim_fields.py` Does: +​ +1. Get iteration and realisation number from ERT using ERT environment variables `_ERT_ITERATION_NUMBER` and `_ERT_REALIZATION_NUMBER`. If running with an old Komodo version, the script will require iteration and realisation_number as command line input. +2. If iteration = 0, then: + - Simulate field and export to file to be used in `FIELD` keyword in ERT config file. + - Upscale field and optionally export to file for QC purpose. + Else: + - Import updated field from ERT. + - Upscale field and optionally export file for QC purpose. +3. Extract predicted values of observables from upscaled field (values for selected grid cells related to the upscaled grid) and write `GEN_DATA` files. +4. Optionally write some files for QC purpose.Directory for test case for non-adaptive localisation (LOCALISATION_JOB) diff --git a/tests/jobs/localisation/example_case/example_test_config_A.yml b/tests/jobs/localisation/example_case/example_test_config_A.yml new file mode 100644 index 00000000..8ba59633 --- /dev/null +++ b/tests/jobs/localisation/example_case/example_test_config_A.yml @@ -0,0 +1,53 @@ +# ROFF format standard Eclipse origo +settings: + grid_size: + xsize: 7500.0 + ysize: 12500.0 + zsize: 50.0 + use_eclipse_grid_index_origo: True + + field: + name: "FIELDPAR" + algorithm: "gstools" + file_format: "ROFF" + initial_file_name: "init_files/FieldParam" + updated_file_name: "FieldParam" + seed_file: "randomseeds.txt" + variogram: "gaussian" + correlation_range: [3000.0, 2000.0, 2.0] + correlation_azimuth: 45.0 + correlation_dip: 0.0 + correlation_exponent: 1.9 + trend_use: False + trend_params: [ 1.0, -1.0 ] + trend_relstd: 0.15 + grid_dimension: [150, 250, 1] + grid_file_name: "GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID" + + response: + name: "UPSCALED" + grid_dimension: [15, 25, 1] + upscaled_file_name: "Upscaled" + grid_file_name: "UpscaleGrid.EGRID" + file_format: "ROFF" + write_upscaled_field: True + response_function: "average" + gen_data_file_name: "UpscaledField_0.txt" + + observation: + directory: "observations" + file_name: "observations.obs" + data_dir: "obs_data" + reference_param_file: "init_files/ObsField" + reference_field_name: "ObsField" + rel_error: 0.10 + min_abs_error: 0.01 +# selected_grid_cells: +# - [5, 10, 1] +# - [10, 5, 1] + + localisation: + method: "gaussian" + + optional: + write_obs_pred_diff_field_file: True diff --git a/tests/jobs/localisation/example_case/example_test_config_A_with_actnum.yml b/tests/jobs/localisation/example_case/example_test_config_A_with_actnum.yml new file mode 100644 index 00000000..daec97eb --- /dev/null +++ b/tests/jobs/localisation/example_case/example_test_config_A_with_actnum.yml @@ -0,0 +1,54 @@ +# ROFF format standard Eclipse origo +settings: + grid_size: + xsize: 7500.0 + ysize: 12500.0 + zsize: 50.0 + use_eclipse_grid_index_origo: True + polygon_file: "Polygons.txt" + + field: + name: "FIELDPAR" + algorithm: "gstools" + file_format: "ROFF" + initial_file_name: "init_files/FieldParam" + updated_file_name: "FieldParam" + seed_file: "randomseeds.txt" + variogram: "gaussian" + correlation_range: [3000.0, 2000.0, 2.0] + correlation_azimuth: 45.0 + correlation_dip: 0.0 + correlation_exponent: 1.9 + trend_use: False + trend_params: [ 1.0, -1.0 ] + trend_relstd: 0.15 + grid_dimension: [150, 250, 1] + grid_file_name: "GRID_WITH_ACTNUM.EGRID" + + response: + name: "UPSCALED" + grid_dimension: [15, 25, 1] + upscaled_file_name: "Upscaled" + grid_file_name: "UpscaleGrid.EGRID" + file_format: "ROFF" + write_upscaled_field: True + response_function: "average" + gen_data_file_name: "UpscaledField_0.txt" + + observation: + directory: "observations" + file_name: "observations.obs" + data_dir: "obs_data" + reference_param_file: "init_files/ObsField" + reference_field_name: "ObsField" + rel_error: 0.10 + min_abs_error: 0.01 +# selected_grid_cells: +# - [5, 10, 1] +# - [10, 5, 1] + + localisation: + method: "gaussian" + + optional: + write_obs_pred_diff_field_file: True diff --git a/tests/jobs/localisation/example_case/example_test_config_B.yml b/tests/jobs/localisation/example_case/example_test_config_B.yml new file mode 100644 index 00000000..ffa21549 --- /dev/null +++ b/tests/jobs/localisation/example_case/example_test_config_B.yml @@ -0,0 +1,53 @@ +# GRDECL format standard Eclipse origo +settings: + grid_size: + xsize: 7500.0 + ysize: 12500.0 + zsize: 50.0 + use_eclipse_grid_index_origo: True + + field: + name: "FIELDPAR" + algorithm: "gstools" + file_format: "GRDECL" + initial_file_name: "init_files/FieldParam" + updated_file_name: "FieldParam" + seed_file: "randomseeds.txt" + variogram: "gaussian" + correlation_range: [3000.0, 2000.0, 2.0] + correlation_azimuth: 45.0 + correlation_dip: 0.0 + correlation_exponent: 1.9 + trend_use: False + trend_params: [ 1.0, -1.0 ] + trend_relstd: 0.15 + grid_dimension: [150, 250, 1] + grid_file_name: "GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID" + + response: + name: "UPSCALED" + grid_dimension: [15, 25, 1] + upscaled_file_name: "Upscaled" + grid_file_name: "UpscaleGrid.EGRID" + file_format: "GRDECL" + write_upscaled_field: True + response_function: "average" + gen_data_file_name: "UpscaledField_0.txt" + + observation: + directory: "observations" + file_name: "observations.obs" + data_dir: "obs_data" + reference_param_file: "init_files/ObsField" + reference_field_name: "ObsField" + rel_error: 0.10 + min_abs_error: 0.01 +# selected_grid_cells: +# - [5, 10, 1] +# - [10, 5, 1] + + localisation: + method: "gaussian" + + optional: + write_obs_pred_diff_field_file: True diff --git a/tests/jobs/localisation/example_case/example_test_config_C.yml b/tests/jobs/localisation/example_case/example_test_config_C.yml new file mode 100644 index 00000000..87c6a827 --- /dev/null +++ b/tests/jobs/localisation/example_case/example_test_config_C.yml @@ -0,0 +1,53 @@ +# ROFF format standard RMS origo +settings: + grid_size: + xsize: 7500.0 + ysize: 12500.0 + zsize: 50.0 + use_eclipse_grid_index_origo: False + + field: + name: "FIELDPAR" + algorithm: "gstools" + file_format: "ROFF" + initial_file_name: "init_files/FieldParam" + updated_file_name: "FieldParam" + seed_file: "randomseeds.txt" + variogram: "gaussian" + correlation_range: [3000.0, 2000.0, 2.0] + correlation_azimuth: 45.0 + correlation_dip: 0.0 + correlation_exponent: 1.9 + trend_use: False + trend_params: [ 1.0, -1.0 ] + trend_relstd: 0.15 + grid_dimension: [150, 250, 1] + grid_file_name: "GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID" + + response: + name: "UPSCALED" + grid_dimension: [15, 25, 1] + upscaled_file_name: "Upscaled" + grid_file_name: "UpscaleGrid.EGRID" + file_format: "ROFF" + write_upscaled_field: True + response_function: "average" + gen_data_file_name: "UpscaledField_0.txt" + + observation: + directory: "observations" + file_name: "observations.obs" + data_dir: "obs_data" + reference_param_file: "init_files/ObsField" + reference_field_name: "ObsField" + rel_error: 0.10 + min_abs_error: 0.01 +# selected_grid_cells: +# - [5, 10, 1] +# - [10, 5, 1] + + localisation: + method: "gaussian" + + optional: + write_obs_pred_diff_field_file: True diff --git a/tests/jobs/localisation/example_case/example_test_config_D.yml b/tests/jobs/localisation/example_case/example_test_config_D.yml new file mode 100644 index 00000000..2fa36cd1 --- /dev/null +++ b/tests/jobs/localisation/example_case/example_test_config_D.yml @@ -0,0 +1,53 @@ +# GRDECL format standard RMS origo +settings: + grid_size: + xsize: 7500.0 + ysize: 12500.0 + zsize: 50.0 + use_eclipse_grid_index_origo: False + + field: + name: "FIELDPAR" + algorithm: "gstools" + file_format: "GRDECL" + initial_file_name: "init_files/FieldParam" + updated_file_name: "FieldParam" + seed_file: "randomseeds.txt" + variogram: "gaussian" + correlation_range: [3000.0, 2000.0, 2.0] + correlation_azimuth: 45.0 + correlation_dip: 0.0 + correlation_exponent: 1.9 + trend_use: False + trend_params: [ 1.0, -1.0 ] + trend_relstd: 0.15 + grid_dimension: [150, 250, 1] + grid_file_name: "GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID" + + response: + name: "UPSCALED" + grid_dimension: [15, 25, 1] + upscaled_file_name: "Upscaled" + grid_file_name: "UpscaleGrid.EGRID" + file_format: "GRDECL" + write_upscaled_field: True + response_function: "average" + gen_data_file_name: "UpscaledField_0.txt" + + observation: + directory: "observations" + file_name: "observations.obs" + data_dir: "obs_data" + reference_param_file: "init_files/ObsField" + reference_field_name: "ObsField" + rel_error: 0.10 + min_abs_error: 0.01 +# selected_grid_cells: +# - [5, 10, 1] +# - [10, 5, 1] + + localisation: + method: "gaussian" + + optional: + write_obs_pred_diff_field_file: True diff --git a/tests/jobs/localisation/example_case/init_files/README b/tests/jobs/localisation/example_case/init_files/README new file mode 100644 index 00000000..2abda6e8 --- /dev/null +++ b/tests/jobs/localisation/example_case/init_files/README @@ -0,0 +1,7 @@ +Directory where initial ensemble realisation is saved: +FieldParam.roff - The field parameter +Upscaled.roff - The upscaled field parameter (for QC purpose) +UpscaledObsField.roff - The upscaled field parameter used when + extracting observations (selected grid cells to be used as observables) +UpscaledConditionedCells.roff - A coarse grid parameter with all cells except the cells defined as observable + with a dummy value and the observable grid cells with the values used as observations. diff --git a/tests/jobs/localisation/example_case/localisation.wf b/tests/jobs/localisation/example_case/localisation.wf new file mode 100644 index 00000000..c6477f3d --- /dev/null +++ b/tests/jobs/localisation/example_case/localisation.wf @@ -0,0 +1 @@ +LOCALISATION_JOB local_config.yml diff --git a/tests/jobs/localisation/example_case/modify_variogram.yml b/tests/jobs/localisation/example_case/modify_variogram.yml new file mode 100644 index 00000000..144f3652 --- /dev/null +++ b/tests/jobs/localisation/example_case/modify_variogram.yml @@ -0,0 +1,5 @@ +settings: + + field: + variogram: "spherical" + correlation_range: [4000.0, 4000.0, 2.0] diff --git a/tests/jobs/localisation/example_case/scripts/FM_SIM_FIELD b/tests/jobs/localisation/example_case/scripts/FM_SIM_FIELD new file mode 100644 index 00000000..b78850cb --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/FM_SIM_FIELD @@ -0,0 +1,6 @@ +EXECUTABLE ./sim_fields.py + +ARGLIST + +STDERR sim_fields.stderr +STDOUT sim_fields.stdout diff --git a/tests/jobs/localisation/example_case/scripts/README b/tests/jobs/localisation/example_case/scripts/README new file mode 100644 index 00000000..9c2c35e6 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/README @@ -0,0 +1,13 @@ +Source code scripts: +common_functions.py - Functions used by the two scripts init_test_case.py and sim_fields.py +init_test_case.py - Create grid files, random seed file localisation config file and observation files for the test case +sim_fields.py - This script is run from ERT config file as a FORWARD model. +FM_SIM_FIELD - ERT configuration of forward model SIM_FIELD + using sim_fields.py. + +Scripts used in RMS project to load and visualize the realizations. +These are not needed to run the test and alternatives for visualizing the realizations exists (coviz, webviz?): +import_field_parameters.py +import_field_parameters_local.py +import_upscaled_field_parameters_local.py +import_upscaled_field_parameters.py diff --git a/tests/jobs/localisation/example_case/scripts/__init__.py b/tests/jobs/localisation/example_case/scripts/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/jobs/localisation/example_case/scripts/common_functions.py b/tests/jobs/localisation/example_case/scripts/common_functions.py new file mode 100644 index 00000000..61581722 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/common_functions.py @@ -0,0 +1,924 @@ +""" +Common functions used by the scripts: init_test_case.py and sim_field.py +""" +import math +import os +from dataclasses import dataclass +from typing import Tuple + +import gstools as gs +import numpy as np +import xtgeo +import yaml + +# pylint: disable=missing-function-docstring, too-many-locals, invalid-name +# pylint: disable=raise-missing-from +# pylint: disable=too-many-nested-blocks + + +# Settings for the test case in the following dataclasses +@dataclass +class GridSize: + """ + Length, width, thickness of a box containing the field + Same size is used for both fine scale grid with + the simulated field and the coarse scale grid + containing upscaled values of the simulated field. + """ + + xsize: float = 7500.0 + ysize: float = 12500.0 + # xsize: float = 7500.0 + # ysize: float = 7500.0 + zsize: float = 50.0 + polygon_file: str = None + use_eclipse_grid_index_origo: bool = True + + +@dataclass +class Field: + """ + Define the dimension (number of grid cells) for fine scale grid, + name of output files and specification of model parameters for + simulation of gaussian field with option to use linear trend. + Relative standard deviation specify standard deviation of + gaussian residual field relative to the trends span of value + (max trend value - min trend value) + """ + + # pylint: disable=too-many-instance-attributes + name: str = "FIELDPAR" + algorithm: str = "gstools" + file_format: str = "ROFF" + initial_file_name: str = "init_files/FieldParam" + updated_file_name: str = "FieldParam" + seed_file: str = "randomseeds.txt" + variogram: str = "exponential" + correlation_range: Tuple[float] = (3000.0, 1000.0, 2.0) + correlation_azimuth: float = 45.0 + correlation_dip: float = 0.0 + correlation_exponent: float = 1.9 + trend_use: bool = False + trend_params: Tuple[float] = (1.0, -1.0) + trend_relstd: float = 0.05 + grid_dimension: Tuple[int] = (150, 250, 1) + grid_file_name: str = "GRID.EGRID" + + +@dataclass +class Response: + """ + Specify the coarse grid dimensions, name of file and type + of average operation to calculated upscaled values that + are predictions of observations of the same grid cells. + Which cell indices are observed are specified in + observation settings. + """ + + # pylint: disable=too-many-instance-attributes + name: str = "UPSCALED" + grid_dimension: Tuple[int] = (15, 25, 1) + upscaled_file_name: str = "Upscaled" + grid_file_name: str = "UpscaleGrid.EGRID" + file_format: str = "ROFF" + write_upscaled_field: bool = True + response_function: str = "average" + gen_data_file_name: str = "UpscaledField_0.txt" + + +# pylint: disable=too-many-instance-attributes +@dataclass +class Observation: + """ + Specify name of files for generated observations + and also which grid cells from coarse grid is used + as observables. (Cells that have values that are used as observations) + """ + + directory: str = "observations" + file_name: str = "observations.obs" + data_dir: str = "obs_data" + reference_param_file: str = "init_files/ObsField" + reference_field_name: str = "ObsField" + rel_error: float = 0.10 + min_abs_error: float = 0.01 + # selected_grid_cells: Tuple[Tuple[int]] = ((5, 10, 1), (10, 5, 1)) + selected_grid_cells: Tuple[Tuple[int]] = (8, 12, 1) + + +@dataclass +class Localisation: + """ + Specify settings for the localisation config file. + """ + + method: str = "gaussian" + # method: str = "constant" + + +@dataclass +class Optional: + """ + Specify if some optional files should be + written or not (for QC purpose). + """ + + write_obs_pred_diff_field_file: bool = True + + +@dataclass +class Settings: + """ + Settings for the test case + """ + + grid_size: GridSize = GridSize() + field: Field = Field() + response: Response = Response() + observation: Observation = Observation() + localisation: Localisation = Localisation() + optional: Optional = Optional() + + +settings = Settings() + + +def read_config_file(config_file_name=None): + # Modify default settings if config_file exists + if config_file_name: + if os.path.exists(config_file_name): + with open(config_file_name, "r", encoding="utf-8") as yml_file: + settings_yml = yaml.safe_load(yml_file) + + update_settings(settings_yml) + + +def update_key(key, default_value, settings_dict, parent_key=None): + value = settings_dict.get(key, default_value) + if value != default_value: + if parent_key: + print(f"Changed settings parameter for {key} under {parent_key} : {value} ") + else: + print(f"Changed settings parameter for {key} : {value} ") + return value + + +def update_settings(config_dict: dict): + # pylint: disable=too-many-branches, too-many-statements + settings_dict = config_dict["settings"] + + valid_keys = [ + "grid_size", + "field", + "response", + "observation", + "localisation", + "optional", + ] + for key in settings_dict: + if key not in valid_keys: + raise KeyError(f"Unknown keyword {key} in 'settings' ") + + key = "grid_size" + grid_size_dict = settings_dict[key] if key in settings_dict else None + valid_keys = [ + "xsize", + "ysize", + "zsize", + "polygon_file", + "use_eclipse_grid_index_origo", + ] + if grid_size_dict: + err_msg = [] + for sub_key in grid_size_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + grid_size_object = settings.grid_size + grid_size_object.xsize = update_key( + "xsize", grid_size_object.xsize, grid_size_dict, key + ) + grid_size_object.ysize = update_key( + "ysize", grid_size_object.ysize, grid_size_dict, key + ) + grid_size_object.zsize = update_key( + "zsize", grid_size_object.zsize, grid_size_dict, key + ) + grid_size_object.polygon_file = update_key( + "polygon_file", grid_size_object.polygon_file, grid_size_dict, key + ) + grid_size_object.use_eclipse_grid_index_origo = update_key( + "use_eclipse_grid_index_origo", + grid_size_object.use_eclipse_grid_index_origo, + grid_size_dict, + key, + ) + + key = "field" + field_dict = settings_dict[key] if key in settings_dict else None + valid_keys = [ + "name", + "algorithm", + "file_format", + "initial_file_name", + "updated_file_name", + "seed_file", + "variogram", + "correlation_range", + "correlation_azimuth", + "correlation_dip", + "correlation_exponent", + "trend_use", + "trend_params", + "trend_relstd", + "grid_dimension", + "grid_file_name", + ] + if field_dict: + err_msg = [] + for sub_key in field_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + field = settings.field + field.name = update_key("name", field.name, field_dict, key) + field.algorithm = update_key("algorithm", field.algorithm, field_dict, key) + field.file_format = update_key( + "file_format", field.file_format, field_dict, key + ) + field.initial_file_name = update_key( + "initial_file_name", field.initial_file_name, field_dict, key + ) + field.updated_file_name = update_key( + "updated_file_name", field.updated_file_name, field_dict, key + ) + field.seed_file = update_key("seed_file", field.seed_file, field_dict, key) + field.variogram = update_key("variogram", field.variogram, field_dict, key) + field.correlation_range = update_key( + "correlation_range", field.correlation_range, field_dict, key + ) + field.correlation_azimuth = update_key( + "correlation_azimuth", field.correlation_azimuth, field_dict, key + ) + field.correlation_dip = update_key( + "correlation_dip", field.correlation_dip, field_dict, key + ) + field.correlation_exponent = update_key( + "correlation_exponent", field.correlation_exponent, field_dict, key + ) + field.trend_use = update_key("trend_use", field.trend_use, field_dict, key) + field.trend_params = update_key( + "trend_params", field.trend_params, field_dict, key + ) + field.grid_dimension = update_key( + "grid_dimension", field.grid_dimension, field_dict, key + ) + field.grid_file_name = update_key( + "grid_file_name", field.grid_file_name, field_dict, key + ) + + key = "response" + response_dict = settings_dict[key] if key in settings_dict else None + valid_keys = [ + "name", + "grid_dimension", + "upscaled_file_name", + "grid_file_name", + "file_format", + "write_upscaled_field", + "response_function", + "gen_data_file_name", + ] + if response_dict: + err_msg = [] + for sub_key in response_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + response = settings.response + response.name = update_key("name", response.name, response_dict, key) + response.grid_dimension = update_key( + "grid_dimension", response.grid_dimension, response_dict, key + ) + response.upscaled_file_name = update_key( + "upscaled_file_name", response.upscaled_file_name, response_dict, key + ) + response.grid_file_name = update_key( + "grid_file_name", response.grid_file_name, response_dict, key + ) + response.file_format = update_key( + "file_format", response.file_format, response_dict, key + ) + response.write_upscaled_field = update_key( + "write_upscaled_field", response.write_upscaled_field, response_dict, key + ) + response.response_function = update_key( + "response_function", response.response_function, response_dict, key + ) + response.gen_data_file_name = update_key( + "gen_data_file_name", response.gen_data_file_name, response_dict, key + ) + + key = "observation" + obs_dict = settings_dict[key] if key in settings_dict else None + valid_keys = [ + "directory", + "file_name", + "data_dir", + "reference_param_file", + "reference_field_name", + "rel_error", + "min_abs_error", + "selected_grid_cells", + ] + + if obs_dict: + err_msg = [] + for sub_key in obs_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + observation = settings.observation + observation.directory = update_key( + "directory", observation.directory, obs_dict, key + ) + observation.file_name = update_key( + "file_name", observation.file_name, obs_dict, key + ) + observation.data_dir = update_key( + "data_dir", observation.data_dir, obs_dict, key + ) + observation.reference_param_file = update_key( + "reference_param_file", observation.reference_param_file, obs_dict, key + ) + observation.reference_field_name = update_key( + "reference_field_name", observation.reference_field_name, obs_dict, key + ) + observation.rel_error = update_key( + "rel_error", observation.rel_error, obs_dict, key + ) + observation.min_abs_error = update_key( + "min_abs_error", observation.min_abs_error, obs_dict, key + ) + observation.selected_grid_cells = update_key( + "selected_grid_cells", observation.selected_grid_cells, obs_dict, key + ) + + key = "localisation" + local_dict = settings_dict[key] if key in settings_dict else None + valid_keys = ["method"] + + if local_dict: + err_msg = [] + for sub_key in local_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + localisation = settings.localisation + localisation.method = update_key("method", localisation.method, local_dict, key) + + key = "optional" + optional_dict = settings_dict[key] if key in settings_dict else None + valid_keys = ["write_obs_pred_diff_field_file"] + + if optional_dict: + err_msg = [] + for sub_key in optional_dict: + if sub_key not in valid_keys: + err_msg.append(f" {sub_key}") + if len(err_msg) > 0: + print(f"Unknown keywords in config file under keyword {key}: ") + for text in err_msg: + print(text) + raise KeyError("Unknown keywords") + + optional = settings.optional + optional.write_obs_pred_diff_field_file = update_key( + "write_obs_pred_diff_field_file", + optional.write_obs_pred_diff_field_file, + optional_dict, + key, + ) + + +def generate_field_and_upscale(real_number): + seed_file_name = settings.field.seed_file + relative_std = settings.field.trend_relstd + use_trend = settings.field.trend_use + algorithm_method = settings.field.algorithm + start_seed = get_seed(seed_file_name, real_number) + if algorithm_method == "gstools": + print(f"Use algorithm: {algorithm_method}") + residual_field = simulate_field_using_gstools(start_seed) + else: + print("Use algorithm: gaussianfft") + residual_field = simulate_field(start_seed) + if use_trend == 1: + trend_field = trend() + field3D = trend_field + relative_std * residual_field + + else: + field3D = residual_field + + # Write field parameter for fine scale grid + field_object = export_field(field3D) + field_values = field_object.values + + # Calculate upscaled values for selected coarse grid cells + upscaled_values = upscaling( + field_values, + iteration=0, + ) + return upscaled_values + + +def get_seed(seed_file_name, r_number): + with open(seed_file_name, "r", encoding="utf8") as file: + lines = file.readlines() + try: + seed_value = int(lines[r_number - 1]) + except IndexError as exc: + raise IOError("Seed value not found for realization {r_number} ") from exc + except ValueError as exc: + raise IOError( + "Invalid seed value in file for realization{r_number}" + ) from exc + return seed_value + + +def upscaling(field_values, iteration=0): + """ + Calculate upscaled values and optionally write upscaled values to file. + Return upscaled values + """ + response_function_name = settings.response.response_function + file_format = settings.response.file_format + upscaled_field_name = settings.response.name + write_upscaled_field = settings.response.write_upscaled_field + NX, NY, NZ = settings.response.grid_dimension + upscaled_values = np.zeros((NX, NY, NZ), dtype=np.float32, order="F") + upscaled_values[:, :, :] = -999 + + if response_function_name == "average": + upscaled_values = upscale_average( + field_values, + upscaled_values, + ) + + if write_upscaled_field: + upscaled_file_name = settings.response.upscaled_file_name + if iteration == 0: + upscaled_file_name = "init_files/" + upscaled_file_name + + write_upscaled_field_to_file( + upscaled_values, + upscaled_file_name, + upscaled_field_name, + file_format=file_format, + ) + + return upscaled_values + + +# pylint: disable=too-many-arguments +def write_upscaled_field_to_file( + upscaled_values, + upscaled_file_name, + upscaled_field_name, + selected_cell_index_list=None, + file_format="ROFF", +): + nx, ny, nz = upscaled_values.shape + + field_object = xtgeo.grid3d.GridProperty( + ncol=nx, + nrow=ny, + nlay=nz, + values=upscaled_values, + discrete=False, + name=upscaled_field_name, + ) + + if file_format.upper() == "ROFF": + fullfilename = upscaled_file_name + ".roff" + field_object.to_file(fullfilename, fformat="roff") + elif file_format.upper() == "GRDECL": + fullfilename = upscaled_file_name + ".GRDECL" + field_object.to_file(fullfilename, fformat="grdecl") + else: + raise ValueError(f"Unknown file format: {file_format} ") + print(f"Write upscaled field file: {fullfilename} ") + + if selected_cell_index_list is not None: + # Grid index order to xtgeo must be c-order masked array + selected_upscaled_values = np.ma.zeros((nx, ny, nz), dtype=np.float32) + selected_upscaled_values[:, :, :] = -1 + nobs = get_nobs() + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices( + obs_number, nobs, selected_cell_index_list + ) + selected_upscaled_values[Iindx, Jindx, Kindx] = upscaled_values[ + Iindx, Jindx, Kindx + ] + + field_name_selected = upscaled_field_name + "_conditioned_cells" + file_name_selected = "init_files/" + field_name_selected + ".roff" + cond_field_object = xtgeo.grid3d.GridProperty( + ncol=nx, + nrow=ny, + nlay=nz, + values=selected_upscaled_values, + discrete=False, + name=field_name_selected, + ) + print(f"Write conditioned cell values as field: {file_name_selected}") + cond_field_object.to_file(file_name_selected, fformat="roff") + + return field_object + + +def upscale_average(field_values, upscaled_values): + """ + Input: field_values (numpy 3D) + coarse_cell_index_list (list of tuples (I,J,K)) + Output: upscaled_values (numpy 3D) initialized outside + but filled in specified (I,J,K) cells. + """ + nx, ny, nz = field_values.shape + NX, NY, NZ = upscaled_values.shape + + print(f"Number of fine scale grid cells: (nx,ny,nz): ({nx},{ny},{nz})") + print(f"Number of coarse scale grid cells: (NX,NY,NZ): ({NX},{NY},{NZ}) ") + mx = int(nx / NX) + my = int(ny / NY) + mz = int(nz / NZ) + print( + "Number of fine scale grid cells per coarse grid cell: " + f"(mx,my,mz): ({mx},{my},{mz}) " + ) + + print("Calculate upscaled values for all grid cells") + for Kindx in range(NZ): + for Jindx in range(NY): + for Iindx in range(NX): + istart = mx * Iindx + iend = istart + mx + jstart = my * Jindx + jend = jstart + my + kstart = mz * Kindx + kend = kstart + mz + sum_val = 0.0 + for k in range(kstart, kend): + for j in range(jstart, jend): + for i in range(istart, iend): + sum_val += field_values[i, j, k] + upscaled_values[Iindx, Jindx, Kindx] = sum_val / (mx * my * mz) + return upscaled_values + + +def trend(): + """ + Return 3D numpy array with values following a linear trend + scaled to take values between 0 and 1. + """ + nx, ny, nz = settings.field.grid_dimension + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + a, b = settings.field.trend_params + + x0 = 0.0 + y0 = 0.0 + dx = xsize / nx + dy = ysize / ny + + maxsize = ysize + if xsize > ysize: + maxsize = xsize + + val = np.zeros((nx, ny, nz), dtype=np.float32, order="F") + for i in range(nx): + x = x0 + i * dx + for j in range(ny): + y = y0 + j * dy + for k in range(nz): + val[i, j, k] = a * (x - x0) / maxsize + b * (y - y0) / maxsize + + minval = np.min(val) + maxval = np.max(val) + val_normalized = (val - minval) / (maxval - minval) + return val_normalized + + +def simulate_field(start_seed): + # pylint: disable=no-member,import-outside-toplevel + # This function will not be available untill gaussianfft is available on python 3.10 + # import gaussianfft as sim # isort: skip + # dummy code to avoid pylint complaining in github actions + sim = None + + variogram_name = settings.field.variogram + corr_ranges = settings.field.correlation_range + azimuth = settings.field.correlation_azimuth + dip = settings.field.correlation_dip + alpha = settings.field.correlation_exponent + nx, ny, nz = settings.field.grid_dimension + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + zsize = settings.grid_size.zsize + + xrange = corr_ranges[0] + yrange = corr_ranges[1] + zrange = corr_ranges[2] + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + print(f"Start seed: {start_seed}") + sim.seed(start_seed) + + variogram = sim.variogram( + variogram_name, + xrange, + perp_range=yrange, + depth_range=zrange, + azimuth=azimuth - 90, + dip=dip, + power=alpha, + ) + + print(f"Simulate field with size: nx={nx},ny={ny} ") + # gaussianfft.simulate will save the values in F-order + field1D = sim.simulate(variogram, nx, dx, ny, dy, nz, dz) + field_sim = field1D.reshape((nx, ny, nz), order="F") + if settings.grid_size.use_eclipse_grid_index_origo: + field_c_order = np.ma.zeros((nx, ny, nz), dtype=np.float32) + j_indices = -np.arange(ny) + ny - 1 + # Flip j index and use c-order + field_c_order[:, j_indices, :] = field_sim[:, :, :] + return field_c_order + # Change to C-order + field_c_order = np.ma.zeros((nx, ny, nz), dtype=np.float32) + field_c_order[:, :, :] = field_sim[:, :, :] + return field_c_order + + +def simulate_field_using_gstools(start_seed): + # pylint: disable=no-member, + + variogram_name = settings.field.variogram + corr_ranges = settings.field.correlation_range + azimuth = settings.field.correlation_azimuth + xrange = corr_ranges[0] + yrange = corr_ranges[1] + zrange = corr_ranges[2] + + nx, ny, nz = settings.field.grid_dimension + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + zsize = settings.grid_size.zsize + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + x = np.arange(0.5 * dx, xsize, dx) + y = np.arange(0.5 * dy, ysize, dy) + z = np.arange(0.5 * dz, zsize, dz) + # Rescale factor is set to: + # sqrt(3.0) for gaussian correlation functions, + # 3.0 for exponetial correlation function, + # pow(3.0, 1/alpha) for general exponential correlation function + # with exponent alpha + # to ensure the correlation function have the same definition of correlation + # lenght as is used in RMS and gaussianfft algorithm. + print(f"Variogram name: {variogram_name}") + if variogram_name.upper() == "GAUSSIAN": + model = gs.Gaussian( + dim=3, + var=1.0, + len_scale=[xrange, yrange, zrange], + angles=np.pi * (0.5 - azimuth / 180.0), + rescale=math.sqrt(3), + ) + elif variogram_name.upper() == "EXPONENTIAL": + model = gs.Exponential( + dim=3, + var=1.0, + len_scale=[xrange, yrange, zrange], + angles=np.pi * (0.5 - azimuth / 180.0), + rescale=3, + ) + else: + raise ValueError(f"Unknown variogram type: {variogram_name} ") + + print(f"Start seed: {start_seed}") + print(f"Simulate field with size: nx={nx},ny={ny} nz={nz} ") + srf = gs.SRF(model, seed=start_seed) + field_srf = srf.structured([x, y, z], store="Field") + # print(f"Field: {srf.field_names} ") + # print(f"Field shape: {srf.field_shape} ") + # print(f"Field type name: {srf.name} ") + # print(f"Field nugget: {srf.nugget} ") + # print(f"Field opt arg: {srf.opt_arg}") + field = field_srf.reshape((nx, ny, nz)) + if settings.grid_size.use_eclipse_grid_index_origo: + field_flip_j_index = np.ma.zeros((nx, ny, nz), dtype=np.float32) + j_indices = -np.arange(ny) + ny - 1 + field_flip_j_index[:, j_indices, :] = field[:, :, :] + return field_flip_j_index + + return field + + +def export_field(field3D): + """ + Export initial realization of field to roff format + Input field3D should be C-index order since xtgeo requires that + """ + + # nx, ny, nz = settings.field.grid_dimension + field_name = settings.field.name + field_file_name = settings.field.initial_file_name + file_format = settings.field.file_format + nx, ny, nz = settings.field.grid_dimension + field_object = xtgeo.grid3d.GridProperty( + ncol=nx, nrow=ny, nlay=nz, values=field3D, discrete=False, name=field_name + ) + + if file_format.upper() == "GRDECL": + fullfilename = field_file_name + ".GRDECL" + field_object.to_file(fullfilename, fformat="grdecl", dtype="float32") + elif file_format.upper() == "ROFF": + fullfilename = field_file_name + ".roff" + field_object.to_file(fullfilename, fformat="roff") + else: + raise IOError(f"Unknown file format for fields: {file_format} ") + print(f"Write field file: {fullfilename} ") + return field_object + + +def read_field_from_file(): + """ + Read field from roff formatted file and return xtgeo property object + """ + + input_file_name = settings.field.updated_file_name + name = settings.field.name + file_format = settings.field.file_format + if file_format.upper() == "GRDECL": + grid = xtgeo.grid_from_file(settings.field.grid_file_name, fformat="egrid") + fullfilename = input_file_name + ".GRDECL" + field_object = xtgeo.grid3d.GridProperty( + fullfilename, fformat="grdecl", grid=grid, name=name + ) + elif file_format.upper() == "ROFF": + fullfilename = input_file_name + ".roff" + field_object = xtgeo.gridproperty_from_file( + fullfilename, fformat="roff", name=name + ) + else: + raise IOError(f"Unknown file format for fields: {file_format} ") + return field_object + + +def read_obs_field_from_file(): + """ + Read field parameter containing parameter with observed values + for selected grid cells + """ + + file_format = settings.response.file_format + pred_obs_file_name = settings.observation.reference_param_file + if file_format.upper() == "ROFF": + fullfilename = pred_obs_file_name + ".roff" + obs_field_object = xtgeo.gridproperty_from_file(fullfilename, fformat="roff") + elif file_format.upper() == "GRDECL": + grid = xtgeo.grid_from_file(settings.response.grid_file_name, fformat="egrid") + fullfilename = pred_obs_file_name + ".GRDECL" + obs_field_object = xtgeo.gridproperty_from_file( + fullfilename, + fformat="grdecl", + grid=grid, + name=settings.observation.reference_field_name, + ) + else: + raise IOError(f"Unknown file format:{file_format} ") + return obs_field_object + + +def read_upscaled_field_from_file(iteration): + """ + Read upscaled field parameter either from initial ensemble or updated ensemble. + Return xtgeo property object + """ + + input_file_name = settings.response.upscaled_file_name + file_format = settings.response.file_format + upscaled_field_name = settings.response.name + if iteration == 0: + filename = "init_files/" + input_file_name + else: + filename = input_file_name + if file_format.upper() == "ROFF": + fullfilename = filename + ".roff" + field_object = xtgeo.gridproperty_from_file(fullfilename, fformat="roff") + elif file_format.upper() == "GRDECL": + grid = xtgeo.grid_from_file(settings.response.grid_file_name, fformat="egrid") + fullfilename = filename + ".GRDECL" + field_object = xtgeo.gridproperty_from_file( + fullfilename, fformat="grdecl", grid=grid, name=upscaled_field_name + ) + else: + raise IOError(f"Unknown file format:{file_format} ") + return field_object + + +def write_obs_pred_diff_field(upscaled_field_object, observation_field_object): + """ + Get xtgeo property objects for predicted values for observables + and observation values. + Write file with difference as roff formatted file. + """ + nx, ny, nz = upscaled_field_object.dimensions + values_diff = upscaled_field_object.values - observation_field_object.values + file_format = settings.response.file_format + + diff_object = xtgeo.grid3d.GridProperty( + ncol=nx, + nrow=ny, + nlay=nz, + values=values_diff, + discrete=False, + name="DiffObsPred", + ) + + filename = "DiffObsPred" + if file_format.upper() == "ROFF": + fullfilename = filename + ".roff" + diff_object.to_file(fullfilename, fformat="roff") + elif file_format.upper() == "GRDECL": + fullfilename = filename + ".GRDECL" + diff_object.to_file(fullfilename, fformat="grdecl") + else: + raise IOError(f"Unknown file format: {file_format} ") + print( + "Write field with difference between upscaled reference " + "field from which observations are extracted and " + f"and prediction from current realization: {fullfilename} " + ) + + +def get_cell_indices(obs_number, nobs, cell_indx_list): + if nobs == 1: + Iindx = cell_indx_list[0] - 1 + Jindx = cell_indx_list[1] - 1 + Kindx = cell_indx_list[2] - 1 + else: + Iindx = cell_indx_list[obs_number][0] - 1 + Jindx = cell_indx_list[obs_number][1] - 1 + Kindx = cell_indx_list[obs_number][2] - 1 + + return (Iindx, Jindx, Kindx) + + +def get_nobs(): + """ + Check if cell_indx_list is a single tuple (i,j,k) or + a list of tuples of type (i,j,k). + Return number of cell indices found in list + """ + cell_indx_list = settings.observation.selected_grid_cells + is_list_of_ints = all(isinstance(indx, int) for indx in cell_indx_list) + if is_list_of_ints: + nobs = 1 + else: + # list of tuples (i,j,k) + nobs = len(cell_indx_list) + return nobs diff --git a/tests/jobs/localisation/example_case/scripts/import_field_parameters.py b/tests/jobs/localisation/example_case/scripts/import_field_parameters.py new file mode 100644 index 00000000..bc3d8a76 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/import_field_parameters.py @@ -0,0 +1,22 @@ +""" +Import field parameters into RMS (Must be included as python job +in RMS workflow and edited to fit your scratch directory). +Variable project is defined when running within RMS, +but not outside since it refers to Roxar API +""" +# pylint: disable=import-error, undefined-variable +from import_fields_to_rms import import_from_scratch_directory + +SCRATCH = "/scratch/fmu/olia/sim_field/" +CASE_NAME = "original" +PRJ = project # noqa: 821 +GRID_MODEL_NAME = "GRID" +FIELD_NAMES = [ + "FieldParam", +] +FILE_FORMAT = "ROFF" +ITERATION = 3 + +import_from_scratch_directory( + PRJ, GRID_MODEL_NAME, FIELD_NAMES, CASE_NAME, SCRATCH, FILE_FORMAT, ITERATION +) diff --git a/tests/jobs/localisation/example_case/scripts/import_field_parameters_local.py b/tests/jobs/localisation/example_case/scripts/import_field_parameters_local.py new file mode 100644 index 00000000..8f84d78d --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/import_field_parameters_local.py @@ -0,0 +1,29 @@ +""" +Import field parameters into RMS (Must be included as python job +in RMS workflow and edited to fit your scratch directory) +Variable project is defined when running within RMS, +but not outside since it refers to Roxar API. +""" + +# pylint: disable=import-error, undefined-variable +from import_fields_to_rms import import_from_scratch_directory + +PRJ = project # noqa: 821 +GRID_MODEL_NAME = "GRID" +FIELD_NAMES = [ + "FieldParam", +] +FILE_FORMAT = "ROFF" +ITERATION = 3 + +# The different cases +CASE_NAME = "original" +SCRATCH = "/scratch/fmu/olia/sim_field/" +import_from_scratch_directory( + PRJ, GRID_MODEL_NAME, FIELD_NAMES, CASE_NAME, SCRATCH, FILE_FORMAT, ITERATION +) +CASE_NAME = "local" +SCRATCH = "/scratch/fmu/olia/sim_field_local/" +import_from_scratch_directory( + PRJ, GRID_MODEL_NAME, FIELD_NAMES, CASE_NAME, SCRATCH, FILE_FORMAT, ITERATION +) diff --git a/tests/jobs/localisation/example_case/scripts/import_fields_to_rms.py b/tests/jobs/localisation/example_case/scripts/import_fields_to_rms.py new file mode 100644 index 00000000..02a04433 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/import_fields_to_rms.py @@ -0,0 +1,121 @@ +""" +Import field parameters into RMS (Must be included as python job +in RMS workflow and edited to fit your scratch directory) +Variable project is defined when running within RMS, +but not outside since it refers to Roxar API. +""" + +from pathlib import Path + +import xtgeo + + +# pylint: disable=bare-except, too-many-arguments, too-many-branches +# pylint: disable=too-many-locals, too-many-statements +def import_from_scratch_directory( + project, + grid_model_name, + field_names, + case_name, + scratch_dir, + file_format, + max_iteration, +): + """ + Import files with initial ensemble and updated fields into RMS project + """ + grid = xtgeo.grid_from_roxar(project, grid_model_name, project.current_realisation) + + path = Path(scratch_dir) + if not path.exists(): + raise IOError(f"File path: {scratch_dir} does not exist. ") + + real = project.current_realisation + print("\n") + print(f"Realization: {real} ") + for name in field_names: + for iteration in [0, max_iteration]: + print(f"Iteration: {iteration}") + if iteration == 0: + name_with_iter = name + "_" + case_name + "_" + str(iteration) + path = ( + scratch_dir + + "realization-" + + str(real) + + "/iter-" + + str(iteration) + + "/init_files/" + ) + if file_format == "ROFF": + file_name = path + name + ".roff" + elif file_format == "GRDECL": + file_name = path + name + ".GRDECL" + else: + raise IOError(f"Unknown file format: {file_format} ") + print(f"File name: {file_name} ") + + try: + if file_format == "ROFF": + # print(f"Import ROFF file: {file_name} ") + property0 = xtgeo.gridproperty_from_file( + file_name, fformat="roff" + ) + else: + # print(f"Import GRDECL file: {file_name} ") + property0 = xtgeo.gridproperty_from_file( + file_name, fformat="grdecl", name="FIELDPAR", grid=grid + ) + print( + f"Import property {property0.name} for iteration {iteration} " + f"into {name_with_iter} " + ) + property0.to_roxar( + project, grid_model_name, name_with_iter, realisation=real + ) + except: # noqa: E722 + print(f"Skip realization: {real} for iteration: {iteration} ") + elif iteration == max_iteration: + name_with_iter = name + "_" + case_name + "_" + str(iteration) + path = ( + scratch_dir + + "realization-" + + str(real) + + "/iter-" + + str(iteration) + + "/" + ) + if file_format == "ROFF": + file_name = path + name + ".roff" + elif file_format == "GRDECL": + file_name = path + name + ".GRDECL" + print(f"File name: {file_name} ") + + try: + if file_format == "ROFF": + property3 = xtgeo.gridproperty_from_file(file_name, "roff") + else: + property3 = xtgeo.gridproperty_from_file( + file_name, fformat="grdecl", name="FIELDPAR", grid=grid + ) + print( + f"Import property {property3.name} for iteration {iteration} " + f"into {name_with_iter} " + ) + property3.to_roxar( + project, grid_model_name, name_with_iter, realisation=real + ) + except: # noqa: E722 + print(f"Skip realization: {real} for iteration: {iteration} ") + try: + diff_property = property0 + diff_property.values = property3.values - property0.values + name_diff = name + "_" + case_name + "_diff" + print( + f"Calculate difference between iteration {max_iteration} " + f" and 0: {name_diff}" + ) + diff_property.to_roxar( + project, grid_model_name, name_diff, realisation=real + ) + except: # noqa: E722 + print(f"Skip difference for realisation: {real} ") diff --git a/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters.py b/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters.py new file mode 100644 index 00000000..433ef180 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters.py @@ -0,0 +1,21 @@ +""" +Import upscaled field parameters into RMS (Must be included as python job +in RMS workflow and edited to fit your scratch directory) +Variable project is defined when running within RMS, +but not outside since it refers to Roxar API +""" +# pylint: disable=import-error, undefined-variable +from import_fields_to_rms import import_from_scratch_directory + +SCRATCH = "/scratch/fmu/olia/sim_field/" +CASE_NAME = "original" + +PRJ = project # noqa: 821 +GRID_MODEL_NAME = "UpscaleGrid" +FIELD_NAMES = [ + "Upscaled", +] +ITERATION = 3 +import_from_scratch_directory( + PRJ, GRID_MODEL_NAME, FIELD_NAMES, CASE_NAME, SCRATCH, ITERATION +) diff --git a/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters_local.py b/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters_local.py new file mode 100644 index 00000000..ce4f6072 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/import_upscaled_field_parameters_local.py @@ -0,0 +1,21 @@ +""" +Import field parameters into RMS (Must be included as python job +in RMS workflow and edited to fit your scratch directory) +Variable project is defined when running within RMS, +but not outside since it refers to Roxar API +""" +# pylint: disable=import-error, undefined-variable +from import_fields_to_rms import import_from_scratch_directory + +SCRATCH = "/scratch/fmu/olia/sim_field_local/" +CASE_NAME = "local" + +PRJ = project # noqa: 821 +GRID_MODEL_NAME = "UpscaleGrid" +FIELD_NAMES = [ + "Upscaled", +] +ITERATION = 3 +import_from_scratch_directory( + PRJ, GRID_MODEL_NAME, FIELD_NAMES, CASE_NAME, SCRATCH, ITERATION +) diff --git a/tests/jobs/localisation/example_case/scripts/init_test_case.py b/tests/jobs/localisation/example_case/scripts/init_test_case.py new file mode 100755 index 00000000..409818be --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/init_test_case.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python +""" +Script initialize the test case by creating the grid files, observation files etc +""" + +import math +import os +import random +import sys + +# pylint: disable=import-error +import xtgeo +from common_functions import ( + generate_field_and_upscale, + get_cell_indices, + get_nobs, + read_config_file, + settings, + write_upscaled_field_to_file, +) + +# pylint: disable=too-many-arguments,invalid-name,missing-function-docstring +# pylint: disable=too-many-locals,redefined-outer-name + + +def generate_seed_file( + start_seed: int = 9828862224, + number_of_seeds: int = 1000, +): + # pylint: disable=unused-variable + + seed_file_name = settings.field.seed_file + print(f"Generate random seed file: {seed_file_name}") + random.seed(start_seed) + with open(seed_file_name, "w", encoding="utf8") as file: + for i in range(number_of_seeds): + file.write(f"{random.randint(1, 999999999)}\n") + + +def obs_positions(): + NX, NY, _ = settings.response.grid_dimension + use_eclipse_origo = settings.grid_size.use_eclipse_grid_index_origo + + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + dx = xsize / NX + dy = ysize / NY + cell_indx_list = settings.observation.selected_grid_cells + if use_eclipse_origo: + print("Grid index origin: Eclipse standard") + else: + print("Grid index origin: RMS standard") + print( + "Observation reference point coordinates is always " + "from origin at lower left corner" + ) + + pos_list = [] + nobs = get_nobs() + for obs_number in range(nobs): + (Iindx, Jindx, _) = get_cell_indices(obs_number, nobs, cell_indx_list) + x = (Iindx + 0.5) * dx + if use_eclipse_origo: + y = ysize - (Jindx + 0.5) * dy + else: + y = (Jindx + 0.5) * dy + + pos_list.append((x, y)) + + return pos_list + + +def write_localisation_config( + config_file_name="local_config.yml", + write_scaling=True, + localisation_method="gaussian", +): + obs_index_list = settings.observation.selected_grid_cells + field_name = settings.field.name + corr_ranges = settings.field.correlation_range + azimuth = settings.field.correlation_azimuth + space = " " * 2 + space2 = " " * 4 + space3 = " " * 6 + positions = obs_positions() + print(f"Write localisation config file: {config_file_name}") + with open(config_file_name, "w", encoding="utf8") as file: + file.write("log_level: 3\n") + file.write(f"write_scaling_factors: {write_scaling}\n") + file.write("correlations:\n") + nobs = get_nobs() + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, nobs, obs_index_list) + obs_name = f"OBS_{Iindx+1}_{Jindx+1}_{Kindx+1}" + pos = positions[obs_number] + file.write(f"{space}- name: CORR_{obs_number}\n") + file.write(f"{space2}obs_group:\n") + file.write(f'{space3}add: ["{obs_name}"]\n') + file.write(f"{space2}param_group:\n") + file.write(f'{space3}add: ["{field_name}"]\n') + file.write(f"{space2}field_scale:\n") + if localisation_method == "gaussian": + file.write(f"{space3}method: gaussian_decay\n") + file.write(f"{space3}main_range: {corr_ranges[0]}\n") + file.write(f"{space3}perp_range: {corr_ranges[1]}\n") + file.write(f"{space3}azimuth: {azimuth}\n") + file.write(f"{space3}ref_point: [ {pos[0]}, {pos[1]} ]\n") + elif localisation_method == "constant": + file.write(f"{space3}method: constant\n") + file.write(f"{space3}value: 1.0\n") + + +def write_gen_obs(upscaled_values): + observation_dir = settings.observation.directory + obs_file_name = settings.observation.file_name + obs_data_dir = settings.observation.data_dir + cell_indx_list = settings.observation.selected_grid_cells + rel_err = settings.observation.rel_error + min_err = settings.observation.min_abs_error + if not os.path.exists(observation_dir): + print(f"Create directory: {observation_dir} ") + os.makedirs(observation_dir) + data_dir = observation_dir + "/" + obs_data_dir + if not os.path.exists(data_dir): + print(f"Create directory: {data_dir} ") + os.makedirs(data_dir) + + print(f"Write observation file: {obs_file_name} ") + filename = observation_dir + "/" + obs_file_name + with open(filename, "w", encoding="utf8") as obs_file: + # Check if cell_indx_list is a single tuple (i,j,k) + # or a list of tuples of type (i,j,k) + nobs = get_nobs() + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, nobs, cell_indx_list) + value = upscaled_values[Iindx, Jindx, Kindx] + value_err = math.fabs(value) * rel_err + value_err = max(value_err, min_err) + + obs_data_relative_file_name = ( + obs_data_dir + + "/obs_" + + str(Iindx + 1) + + "_" + + str(Jindx + 1) + + "_" + + str(Kindx + 1) + + ".txt" + ) + + obs_file.write(f"GENERAL_OBSERVATION OBS_{Iindx+1}_{Jindx+1}_{Kindx+1} ") + obs_file.write("{ ") + obs_file.write( + f"DATA = RESULT_UPSCALED_FIELD ; INDEX_LIST = {obs_number} ; " + ) + obs_file.write("RESTART = 0; ") + obs_file.write(f"OBS_FILE = ./{obs_data_relative_file_name} ; ") + obs_file.write(" };\n") + + data_file_name = observation_dir + "/" + obs_data_relative_file_name + print(f"Write file: {data_file_name} ") + with open(data_file_name, "w", encoding="utf8") as data_file: + data_file.write(f"{value} {value_err}\n") + + +def create_grid(): + grid_file_name = settings.field.grid_file_name + nx, ny, nz = settings.field.grid_dimension + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + zsize = settings.grid_size.zsize + if settings.grid_size.use_eclipse_grid_index_origo: + flip = -1 + x0 = 0.0 + y0 = ysize + z0 = 0.0 + else: + flip = 1 + x0 = 0.0 + y0 = 0.0 + z0 = 0.0 + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + grid_object = xtgeo.create_box_grid( + dimension=(nx, ny, nz), + origin=(x0, y0, z0), + increment=(dx, dy, dz), + rotation=0.0, + flip=flip, + ) + + polygon_file_name = settings.grid_size.polygon_file + if polygon_file_name is not None and os.path.exists(polygon_file_name): + print(f"Use polygon file {polygon_file_name} to create actnum ") + polygon = xtgeo.polygons_from_file(polygon_file_name, fformat="xyz") + grid_object.inactivate_outside(polygon) + + print(f"Write grid file: {grid_file_name} ") + grid_object.to_file(grid_file_name, fformat="egrid") + return grid_object + + +def create_upscaled_grid(): + grid_file_name = settings.response.grid_file_name + nx, ny, nz = settings.response.grid_dimension + xsize = settings.grid_size.xsize + ysize = settings.grid_size.ysize + zsize = settings.grid_size.zsize + if settings.grid_size.use_eclipse_grid_index_origo: + flip = -1 + x0 = 0.0 + y0 = ysize + z0 = 0.0 + else: + flip = 1 + x0 = 0.0 + y0 = 0.0 + z0 = 0.0 + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + grid_object = xtgeo.create_box_grid( + dimension=(nx, ny, nz), + origin=(x0, y0, z0), + increment=(dx, dy, dz), + rotation=0.0, + flip=flip, + ) + + print(f"Write grid file: {grid_file_name} ") + grid_object.to_file(grid_file_name, fformat="egrid") + return grid_object + + +def main(config_file_name=None): + """ + Initialize seed file, grid files, observation files and localisation config file + """ + + read_config_file(config_file_name) + + # Create seed file + generate_seed_file() + + # Create grid for the field parameter + create_grid() + + # Create coarse grid to be used in QC of upscaled field parameter + create_upscaled_grid() + + print("Generate field parameter and upscale this.") + print( + f"The upscaled field {settings.observation.reference_param_file} " + "is used when extracting observations." + ) + + # Simulate field (with trend) + real_number = 0 + upscaled_values = generate_field_and_upscale(real_number) + + # Create observations by extracting from existing upscaled field + write_gen_obs(upscaled_values) + + # Write upscaled field used as reference + # since obs are extracted from this field + write_upscaled_field_to_file( + upscaled_values, + settings.observation.reference_param_file, + selected_cell_index_list=settings.observation.selected_grid_cells, + file_format=settings.field.file_format, + upscaled_field_name=settings.observation.reference_field_name, + ) + + # Write file for non-adaptive localisation using distance based localisation + write_localisation_config( + config_file_name="local_config_gaussian_decay.yml", + write_scaling=True, + localisation_method="gaussian", + ) + write_localisation_config( + config_file_name="local_config_constant.yml", + write_scaling=True, + localisation_method="constant", + ) + write_localisation_config( + config_file_name="local_config.yml", + write_scaling=True, + localisation_method=settings.localisation.method, + ) + + +if __name__ == "__main__": + if len(sys.argv) < 2: + raise IOError( + f"The script {sys.argv[0]} requires one input with test config yml file" + ) + + config_file_name = sys.argv[1] + main(config_file_name) diff --git a/tests/jobs/localisation/example_case/scripts/sim_fields.py b/tests/jobs/localisation/example_case/scripts/sim_fields.py new file mode 100755 index 00000000..d11f2660 --- /dev/null +++ b/tests/jobs/localisation/example_case/scripts/sim_fields.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +""" +Script used as forward model in ERT to test localisation. +""" +import sys + +# pylint: disable=import-error, redefined-outer-name +# pylint: disable=missing-function-docstring,invalid-name +from common_functions import ( + generate_field_and_upscale, + get_cell_indices, + get_nobs, + read_config_file, + read_field_from_file, + read_obs_field_from_file, + read_upscaled_field_from_file, + settings, + upscaling, + write_obs_pred_diff_field, +) + + +def write_prediction_gen_data(upscaled_values): + """ + Write GEN_DATA file with predicted values of observables (selected upscaled values) + """ + cell_indx_list = settings.observation.selected_grid_cells + response_file_name = settings.response.gen_data_file_name + print(f"Write GEN_DATA file with prediction of observations: {response_file_name}") + with open(response_file_name, "w", encoding="utf8") as file: + # NOTE: The sequence of values must be the same as for the observations + nobs = get_nobs() + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, nobs, cell_indx_list) + value = upscaled_values[Iindx, Jindx, Kindx] + print(f"Prediction of obs for {Iindx+1},{Jindx+1},{Kindx+1}: {value}") + file.write(f"{value}\n") + + +def get_iteration_real_number_config_file(argv): + if len(argv) < 4: + raise IOError( + "Missing command line arguments " + ) + arg1 = argv[1] + if arg1 is None: + raise IOError( + "Missing iteration number (argv[1]) when running this script manually" + ) + iteration = int(arg1) + print(f"ERT iteration: {iteration}") + + arg2 = argv[2] + if arg2 is None: + raise IOError("Missing real_number (argv[2]) when running this script manually") + real_number = int(arg2) + print(f"ERT realization: {real_number}") + + config_file_name = argv[3] + return iteration, real_number, config_file_name + + +def main(args): + """ + For iteration = 0: + - simulate field, export to file as initial ensemble realization + - upscale and extract predicted values for observables + (selected coarse grid cell values) + For iteration > 0: + - Import updated field from ERT. + - upscale and extract predicted values for observables + (selected coarse grid cell values) + """ + + # NOTE: Both the fine scale grid with simulated field values + # and the coarse grid with upscaled values must have Eclipse grid index origin + + # Read config_file if it exists. Use default settings for everything not specified. + iteration, real_number, config_file_name = get_iteration_real_number_config_file( + args + ) + read_config_file(config_file_name) + + if iteration == 0: + print(f"Generate new field parameter realization:{real_number} ") + # Simulate field (with trend) + upscaled_values = generate_field_and_upscale(real_number) + + else: + print(f"Import updated field parameter realization: {real_number} ") + field_object = read_field_from_file() + field_values = field_object.values + + # Calculate upscaled values for selected coarse grid cells + upscaled_values = upscaling( + field_values, + iteration=iteration, + ) + # Write GEN_DATA file + write_prediction_gen_data(upscaled_values) + + # Optional output calculate difference between upscaled field and + # and reference upscaled field + if settings.optional.write_obs_pred_diff_field_file: + obs_field_object = read_obs_field_from_file() + upscaled_field_object = read_upscaled_field_from_file(iteration) + write_obs_pred_diff_field(upscaled_field_object, obs_field_object) + + +if __name__ == "__main__": + # Command line arguments are iteration real_number test_case_config_file + main(sys.argv) diff --git a/tests/jobs/localisation/example_case/sim_field.ert b/tests/jobs/localisation/example_case/sim_field.ert new file mode 100644 index 00000000..98648ab9 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field.ert @@ -0,0 +1,58 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_A +DEFINE randomseeds.txt +DEFINE /example_test_config_A.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID.EGRID, =/GRID.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_case_A.ert b/tests/jobs/localisation/example_case/sim_field_case_A.ert new file mode 100644 index 00000000..c96cabc2 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_case_A.ert @@ -0,0 +1,58 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_A +DEFINE randomseeds.txt +DEFINE /example_test_config_A.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_case_A_with_actnum.ert b/tests/jobs/localisation/example_case/sim_field_case_A_with_actnum.ert new file mode 100644 index 00000000..da1765cc --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_case_A_with_actnum.ert @@ -0,0 +1,58 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_A_with_actnum +DEFINE randomseeds.txt +DEFINE /example_test_config_A_with_actnum.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_WITH_ACTNUM.EGRID, =/GRID_WITH_ACTNUM.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID_WITH_ACTNUM.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_case_B.ert b/tests/jobs/localisation/example_case/sim_field_case_B.ert new file mode 100644 index 00000000..5c8fabee --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_case_B.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_B +DEFINE randomseeds.txt +DEFINE /example_test_config_B.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.GRDECL, =/init_files/ObsField.GRDECL) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.GRDECL INIT_FILES:init_files/FieldParam.GRDECL MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_case_C.ert b/tests/jobs/localisation/example_case/sim_field_case_C.ert new file mode 100644 index 00000000..4816dae1 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_case_C.ert @@ -0,0 +1,58 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_C +DEFINE randomseeds.txt +DEFINE /example_test_config_C.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_case_D.ert b/tests/jobs/localisation/example_case/sim_field_case_D.ert new file mode 100644 index 00000000..4e9e52cc --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_case_D.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_D +DEFINE randomseeds.txt +DEFINE /example_test_config_D.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +-- LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +-- HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.GRDECL, =/init_files/ObsField.GRDECL) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + + +GRID /GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.GRDECL INIT_FILES:init_files/FieldParam.GRDECL MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local.ert b/tests/jobs/localisation/example_case/sim_field_local.ert new file mode 100644 index 00000000..e0e24346 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_A +DEFINE randomseeds.txt +DEFINE /example_test_config_A.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID.EGRID, =/GRID.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local_case_A.ert b/tests/jobs/localisation/example_case/sim_field_local_case_A.ert new file mode 100644 index 00000000..51f6d80b --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local_case_A.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_A +DEFINE randomseeds.txt +DEFINE /example_test_config_A.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local_case_A_with_actnum.ert b/tests/jobs/localisation/example_case/sim_field_local_case_A_with_actnum.ert new file mode 100644 index 00000000..2a5c8b04 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local_case_A_with_actnum.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_A_with_actnum +DEFINE randomseeds.txt +DEFINE /example_test_config_A_with_actnum.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_WITH_ACTNUM.EGRID, =/GRID_WITH_ACTNUM.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID_WITH_ACTNUM.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local_case_B.ert b/tests/jobs/localisation/example_case/sim_field_local_case_B.ert new file mode 100644 index 00000000..99f5517a --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local_case_B.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_B +DEFINE randomseeds.txt +DEFINE /example_test_config_B.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.GRDECL, =/init_files/ObsField.GRDECL) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID_ECLIPSE_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.GRDECL INIT_FILES:init_files/FieldParam.GRDECL MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local_case_C.ert b/tests/jobs/localisation/example_case/sim_field_local_case_C.ert new file mode 100644 index 00000000..cde89a12 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local_case_C.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_C +DEFINE randomseeds.txt +DEFINE /example_test_config_C.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.roff, =/init_files/ObsField.roff) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.roff INIT_FILES:init_files/FieldParam.roff MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/sim_field_local_case_D.ert b/tests/jobs/localisation/example_case/sim_field_local_case_D.ert new file mode 100644 index 00000000..5b3630d2 --- /dev/null +++ b/tests/jobs/localisation/example_case/sim_field_local_case_D.ert @@ -0,0 +1,57 @@ +DEFINE $USER +DEFINE /scratch/fmu +DEFINE sim_field_local_D +DEFINE randomseeds.txt +DEFINE /example_test_config_D.yml +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG +TIME_MAP time_map.txt + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS 10 -- Set number of realizations to run +MAX_RUNTIME 18000 -- Set the maximum allowed run time (in seconds) +MIN_REALIZATIONS 1 -- Success criteria +MAX_SUBMIT 1 -- How many times should the queue system retry a simulation. +QUEUE_OPTION LSF MAX_RUNNING 100 -- Choke the number of simultaneous run +QUEUE_OPTION LSF LSF_QUEUE mr -- Assign LSF cluster queue to use + +RUNPATH ///realization-/iter- +RANDOM_SEED 123456 -- ERT seed value + +ENSPATH output//storage -- Storage of internal ert data +UPDATE_LOG_PATH output//update_log -- Info of active and inactive data points +RUNPATH_FILE output//runpath_file -- List of runpaths + +LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW +HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:UpscaledField_%d.txt REPORT_STEPS:0 INPUT_FORMAT:ASCII OUTPUT_FORMAT:ASCII + +----------------------------------------------------- +-- Forward models +----------------------------------------------------- +--Simulate Gaussian field with trend and calculate upscaled values. Observables are upscaled values of selected grid cells. +FORWARD_MODEL MAKE_DIRECTORY(=init_files) +-- Is used to identify iteration number (only relevant for old komodo versions) +FORWARD_MODEL MAKE_DIRECTORY(=) +-- The common seed file +FORWARD_MODEL COPY_FILE(=/, =/) +-- For QC purpose only +FORWARD_MODEL COPY_FILE(=/init_files/ObsField.GRDECL, =/init_files/ObsField.GRDECL) +FORWARD_MODEL MAKE_SYMLINK(=/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID, =/GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID) +FORWARD_MODEL MAKE_SYMLINK(=/UpscaleGrid.EGRID, =/UpscaleGrid.EGRID) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =) + +GRID /GRID_RMS_STANDARD_GRID_INDEX_ORIGO.EGRID -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER FieldParam.GRDECL INIT_FILES:init_files/FieldParam.GRDECL MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/jobs/localisation/example_case/time_map.txt b/tests/jobs/localisation/example_case/time_map.txt new file mode 100644 index 00000000..9c6b8b80 --- /dev/null +++ b/tests/jobs/localisation/example_case/time_map.txt @@ -0,0 +1 @@ +2000-01-01