From fe0d1c0184d363f135b0b9c46a6df27cfec24ba4 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 fix_grid_index_order in non-adaptive localisation Update tests for localisation due to c-index order Fixed a bug when field_scale keyword is missing Added script to convert from roff to grdecl ascii format Added test case with constant scaling factor Added an new test case with regions in localisation Added test case using scaling field from file Removed unnecessary files Add test using scaling from file using RMS grid index origo local_script_lib typing Create ert config files. New script to generate reference cases. Remove unused files Type annotation in local_script_lib.py Updated doc-string for test_full.py Type def for local_script_lib.py moved test files to new directory Updated test_full.py due to changes in how ert storage deliver field parameters --- pyproject.toml | 1 + .../localisation/local_script_lib.py | 9 - .../localisation/example_case/README | 55 + .../FieldParam_real5_iter0_A2_local.grdecl | 35 + .../FieldParam_real5_iter0_A_local.grdecl | 35 + .../FieldParam_real5_iter0_B_local.grdecl | 35 + .../FieldParam_real5_iter0_C_local.grdecl | 35 + .../FieldParam_real5_iter0_D.grdecl | 35 + .../FieldParam_real5_iter0_E_local.grdecl | 35 + .../FieldParam_real5_iter0_F_local.grdecl | 35 + .../FieldParam_real5_iter0_G_local.grdecl | 35 + .../FieldParam_real5_iter1_A2_local.grdecl | 35 + .../FieldParam_real5_iter1_A_local.grdecl | 35 + .../FieldParam_real5_iter1_B_local.grdecl | 35 + .../FieldParam_real5_iter1_C_local.grdecl | 35 + .../FieldParam_real5_iter1_D.grdecl | 35 + .../FieldParam_real5_iter1_E_local.grdecl | 35 + .../FieldParam_real5_iter1_F_local.grdecl | 35 + .../FieldParam_real5_iter1_G_local.grdecl | 35 + .../example_case/init_files/README | 18 + .../example_case/init_files/polygons.txt | 17 + .../init_files/region_polygons.txt | 153 ++ .../init_files/scaling_factor.grdecl | 63 + .../scaling_factor_rms_origo.grdecl | 63 + .../init_files/sim_field_template.ert | 56 + .../localisation/example_case/localisation.wf | 1 + .../example_case/scripts/FM_SIM_FIELD | 6 + .../localisation/example_case/scripts/README | 11 + .../example_case/scripts/__init__.py | 0 .../example_case/scripts/common_functions.py | 1880 +++++++++++++++++ .../scripts/make_reference_data.py | 138 ++ .../example_case/scripts/roff_to_grdecl.py | 53 + .../example_case/scripts/sim_fields.py | 209 ++ .../localisation/example_case/test_full.py | 267 +++ 34 files changed, 3551 insertions(+), 9 deletions(-) create mode 100644 tests/workflows/localisation/example_case/README create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A2_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_B_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_C_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_D.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_E_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_F_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_G_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A2_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_B_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_C_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_D.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_E_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_F_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_G_local.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/README create mode 100644 tests/workflows/localisation/example_case/init_files/polygons.txt create mode 100644 tests/workflows/localisation/example_case/init_files/region_polygons.txt create mode 100644 tests/workflows/localisation/example_case/init_files/scaling_factor.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/scaling_factor_rms_origo.grdecl create mode 100644 tests/workflows/localisation/example_case/init_files/sim_field_template.ert create mode 100644 tests/workflows/localisation/example_case/localisation.wf create mode 100644 tests/workflows/localisation/example_case/scripts/FM_SIM_FIELD create mode 100644 tests/workflows/localisation/example_case/scripts/README create mode 100644 tests/workflows/localisation/example_case/scripts/__init__.py create mode 100644 tests/workflows/localisation/example_case/scripts/common_functions.py create mode 100755 tests/workflows/localisation/example_case/scripts/make_reference_data.py create mode 100755 tests/workflows/localisation/example_case/scripts/roff_to_grdecl.py create mode 100755 tests/workflows/localisation/example_case/scripts/sim_fields.py create mode 100644 tests/workflows/localisation/example_case/test_full.py diff --git a/pyproject.toml b/pyproject.toml index 567e1bf1f..6acb3c64f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -79,6 +79,7 @@ test = [ "pandas-stubs", "types-setuptools", "types-PyYAML", +"gstools", ] [tool.black] diff --git a/semeio/workflows/localisation/local_script_lib.py b/semeio/workflows/localisation/local_script_lib.py index a3084c065..a6da7373d 100644 --- a/semeio/workflows/localisation/local_script_lib.py +++ b/semeio/workflows/localisation/local_script_lib.py @@ -1078,15 +1078,6 @@ def add_ministeps( param_for_field, user_config.log_level, ) - - # write_qc_parameter_field( - # node_name, - # corr_spec.name, - # corr_spec.field_scale, - # grid_for_field, - # param_for_field, - # user_config.log_level, - # ) update_step["row_scaling_parameters"].append( [node_name, row_scaling] ) diff --git a/tests/workflows/localisation/example_case/README b/tests/workflows/localisation/example_case/README new file mode 100644 index 000000000..9fba569d5 --- /dev/null +++ b/tests/workflows/localisation/example_case/README @@ -0,0 +1,55 @@ +## 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/make_reference_data.py` + - **OBS_CONFIG:** Observations are extracted from an upscaled realization made by `scripts/make_reference_data.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:** + - `localisation.wf` +​ +- **Other Files:** + - `randomseeds.txt`: Not used by ERT, but by `sim_fields.py`. This file can be generated by `scripts/make_reference_data.py` + - `UpscaledGrid.EGRID`: Not used by ERT, but by `sim_fields.py`. This file can be generated by `scripts/make_reference_data.py` +​ +### Typical Workflow: +​ +- **Preparation to create reference data:** + - Prepare ERT config input by running `scripts/make_reference_data.py`. + - The preparation step is **only necessary** if the reference data need to be updated. + - QC manually the created reference data (GRDECL files to appear in the init_files directory). + - The created reference data should be checked into git if they are modified. + - The reference data is used to check the results from running pytest on test_full.py + +​- **Run the pytest on test_full.py** + - The test script will run through a number of cases and compare a selected realization with the reference. + +- **How to modify the test:** + - To modify the test, edit the template file for the ERT configuration file + - Edit the alternative parameter settings in the file common_function.py + - Run the script scripts/make_reference_data.py + - QC manually the created reference data files + - Add the new reference files to git + +### What the Script `sim_fields.py` Does: +1. It must be installed as a FORWARD model in ERT. This is done in the ERT config template file. +​1. Requires 4 input arguments: iteration number, realization_number, config file , config path +1. Get iteration and realisation number from ERT. +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/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A2_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A2_local.grdecl new file mode 100644 index 000000000..718a55f64 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A2_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.003016 -0.494571 + -1.028435 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 -0.829884 + -1.867067 -2.117355 -1.216993 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 -1.915480 -2.726342 -3.124574 + -2.504564 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 -0.876790 -0.636449 -0.371928 -0.186803 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 999999999999999945575230987042816.000000 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 999999999999999945575230987042816.000000 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 999999999999999945575230987042816.000000 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 999999999999999945575230987042816.000000 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A_local.grdecl new file mode 100644 index 000000000..13da8ea21 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_A_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_B_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_B_local.grdecl new file mode 100644 index 000000000..13da8ea21 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_B_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_C_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_C_local.grdecl new file mode 100644 index 000000000..cdf227831 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_C_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.662012 0.092502 -1.249170 -2.481425 -2.643038 -2.015550 + -1.732791 -2.259825 -3.021738 -3.374325 2.535338 2.215707 + 0.622777 -1.049959 -1.704248 -1.537606 -1.549673 -2.107112 + -2.676758 -2.857547 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 0.545837 -0.318973 -0.824143 -0.816984 -0.678996 -0.777436 + -0.967488 -0.856602 -0.316280 0.517896 -0.841584 -1.226023 + -1.207091 -0.902073 -0.387598 0.025259 -0.029104 -0.373039 + -0.433728 0.006049 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.995523 -1.374976 -0.900708 0.206069 1.040176 1.223922 + 1.279978 1.478402 1.243197 0.178017 0.235147 0.157758 + 0.172461 0.312229 0.509417 0.808807 1.215309 1.370256 + 0.795799 -0.342228 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + -0.049208 0.944598 1.588994 1.513464 1.166571 1.047943 + 1.075387 0.881568 0.389300 -0.185701 -0.035406 1.009202 + 1.709299 1.983187 1.760534 0.946370 0.064703 -0.146747 + 0.213693 0.432429 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + 1.324994 0.901444 0.074174 -0.849109 -1.649805 -1.964304 + -1.696768 -1.163499 -0.598027 -0.028493 1.430932 1.254107 + 0.654710 -0.078125 -0.653691 -0.862671 -0.729918 -0.454728 + -0.200309 -0.092174 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + -0.057085 -0.287224 -0.724738 -0.876790 -0.636449 -0.371928 + -0.186803 0.130124 0.381840 0.089729 0.439765 -0.143754 + -1.070861 -1.915480 -2.726342 -3.124574 -2.504564 -1.177302 + -0.224223 -0.178808 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.526481 0.509107 0.391517 -0.025932 -0.279426 -0.127581 + 0.017761 -0.193278 -0.633775 -1.029683 0.648341 0.376487 + 0.306689 0.234835 0.003016 -0.494571 -1.028435 -1.095739 + -0.725329 -0.679467 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_D.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_D.grdecl new file mode 100644 index 000000000..13da8ea21 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_D.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_E_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_E_local.grdecl new file mode 100644 index 000000000..13da8ea21 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_E_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_F_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_F_local.grdecl new file mode 100644 index 000000000..13da8ea21 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_F_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_G_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_G_local.grdecl new file mode 100644 index 000000000..cdf227831 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter0_G_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.662012 0.092502 -1.249170 -2.481425 -2.643038 -2.015550 + -1.732791 -2.259825 -3.021738 -3.374325 2.535338 2.215707 + 0.622777 -1.049959 -1.704248 -1.537606 -1.549673 -2.107112 + -2.676758 -2.857547 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 0.545837 -0.318973 -0.824143 -0.816984 -0.678996 -0.777436 + -0.967488 -0.856602 -0.316280 0.517896 -0.841584 -1.226023 + -1.207091 -0.902073 -0.387598 0.025259 -0.029104 -0.373039 + -0.433728 0.006049 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.995523 -1.374976 -0.900708 0.206069 1.040176 1.223922 + 1.279978 1.478402 1.243197 0.178017 0.235147 0.157758 + 0.172461 0.312229 0.509417 0.808807 1.215309 1.370256 + 0.795799 -0.342228 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + -0.049208 0.944598 1.588994 1.513464 1.166571 1.047943 + 1.075387 0.881568 0.389300 -0.185701 -0.035406 1.009202 + 1.709299 1.983187 1.760534 0.946370 0.064703 -0.146747 + 0.213693 0.432429 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + 1.324994 0.901444 0.074174 -0.849109 -1.649805 -1.964304 + -1.696768 -1.163499 -0.598027 -0.028493 1.430932 1.254107 + 0.654710 -0.078125 -0.653691 -0.862671 -0.729918 -0.454728 + -0.200309 -0.092174 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + -0.057085 -0.287224 -0.724738 -0.876790 -0.636449 -0.371928 + -0.186803 0.130124 0.381840 0.089729 0.439765 -0.143754 + -1.070861 -1.915480 -2.726342 -3.124574 -2.504564 -1.177302 + -0.224223 -0.178808 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.526481 0.509107 0.391517 -0.025932 -0.279426 -0.127581 + 0.017761 -0.193278 -0.633775 -1.029683 0.648341 0.376487 + 0.306689 0.234835 0.003016 -0.494571 -1.028435 -1.095739 + -0.725329 -0.679467 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A2_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A2_local.grdecl new file mode 100644 index 000000000..826f39f47 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A2_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 -0.025439 -0.499686 + -1.025187 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 -0.227774 -0.402043 -0.176976 0.012591 -0.188477 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 -1.104130 + -2.056793 -2.207476 -1.245579 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 -2.149746 -2.849843 -3.153856 + -2.503523 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 -0.908881 -0.656306 -0.381115 -0.188604 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.538834 0.159408 + 0.151831 0.260319 0.256477 0.275927 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 999999999999999945575230987042816.000000 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 999999999999999945575230987042816.000000 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 999999999999999945575230987042816.000000 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 999999999999999945575230987042816.000000 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 999999999999999945575230987042816.000000 + 999999999999999945575230987042816.000000 999999999999999945575230987042816.000000 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A_local.grdecl new file mode 100644 index 000000000..4bd40f618 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_A_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.677030 -1.916461 -1.234550 0.036298 + 1.080500 1.341265 0.997033 0.657986 0.617346 0.557741 + -0.785418 -1.138156 -1.132628 -0.879481 -0.405060 0.006809 + -0.035418 -0.373511 -0.433511 0.006049 0.769581 0.062903 + -0.452333 -0.645152 -0.663255 -0.772958 -0.955062 -0.851693 + -0.314759 0.518246 1.967144 1.617958 0.749545 -0.002046 + -0.417782 -0.717122 -1.107298 -1.288744 -0.874998 -0.019301 + 2.806293 2.787779 1.551428 -0.208671 -1.304757 -1.426859 + -1.513472 -2.089342 -2.670547 -2.856769 0.728909 0.219844 + -1.055842 -2.294567 -2.544213 -1.989089 -1.728381 -2.258027 + -3.021247 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_B_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_B_local.grdecl new file mode 100644 index 000000000..0005ac71e --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_B_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.629633 0.334735 0.244305 0.178606 -0.025440 -0.499686 + -1.025187 -1.093356 -0.725006 -0.679467 0.424872 0.316520 + 0.147939 -0.227774 -0.402043 -0.176976 0.012591 -0.188477 + -0.631527 -1.029457 0.721032 0.377646 -0.197684 -1.104130 + -2.056793 -2.207476 -1.245579 -0.115779 0.089260 -0.479708 + 0.304551 -0.341557 -1.325423 -2.149746 -2.849843 -3.153856 + -2.503523 -1.175000 -0.223699 -0.178820 -0.080649 -0.322371 + -0.764448 -0.908881 -0.656306 -0.381115 -0.188604 0.130685 + 0.382037 0.089729 1.203098 0.997691 0.538834 0.159407 + 0.151831 0.260320 0.256477 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + 0.389300 -0.185701 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + 0.235147 0.157758 0.172461 0.312229 0.509417 0.808807 + 1.215309 1.370256 0.795799 -0.342228 -0.995523 -1.374976 + -0.900708 0.206069 1.040176 1.223922 1.279978 1.478402 + 1.243197 0.178017 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.841584 -1.226023 -1.207091 -0.902073 -0.387598 0.025259 + -0.029104 -0.373039 -0.433728 0.006049 0.545837 -0.318973 + -0.824143 -0.816984 -0.678996 -0.777436 -0.967488 -0.856602 + -0.316280 0.517896 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 2.535338 2.215707 0.622777 -1.049959 -1.704248 -1.537606 + -1.549673 -2.107112 -2.676758 -2.857547 0.662012 0.092502 + -1.249170 -2.481425 -2.643038 -2.015550 -1.732791 -2.259825 + -3.021738 -3.374325 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_C_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_C_local.grdecl new file mode 100644 index 000000000..f77f41d45 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_C_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.662012 0.092502 -1.249170 -2.481425 -2.643038 -2.015550 + -1.732791 -2.259825 -3.021738 -3.374325 2.535338 2.215707 + 0.622777 -1.049959 -1.704248 -1.537606 -1.549673 -2.107112 + -2.676758 -2.857547 1.752741 1.156656 0.156627 -0.349148 + -0.425633 -0.648444 -1.098076 -1.299050 -0.878778 -0.019675 + 0.545837 -0.318973 -0.824143 -0.816984 -0.678996 -0.777436 + -0.967488 -0.856602 -0.316280 0.517896 -0.841584 -1.226023 + -1.207091 -0.902073 -0.387598 0.025259 -0.029104 -0.373039 + -0.433728 0.006049 -1.679243 -1.919407 -1.234238 0.040584 + 1.085511 1.344037 0.997618 0.657986 0.617346 0.557741 + -0.995523 -1.374976 -0.900708 0.206069 1.040176 1.223922 + 1.279978 1.478402 1.243197 0.178017 0.235147 0.157758 + 0.172461 0.312229 0.509417 0.808807 1.215309 1.370256 + 0.795799 -0.342228 0.296088 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.562969 1.421198 0.483566 -0.607791 + -0.049208 0.944598 1.588994 1.513464 1.166571 1.047943 + 1.075387 0.881568 0.389300 -0.185701 -0.035406 1.009202 + 1.709299 1.983187 1.760534 0.946370 0.064703 -0.146747 + 0.213693 0.432429 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + 1.324994 0.901444 0.074174 -0.849109 -1.649805 -1.964304 + -1.696768 -1.163499 -0.598027 -0.028493 1.430932 1.254107 + 0.654710 -0.078125 -0.653691 -0.862671 -0.729918 -0.454728 + -0.200309 -0.092174 1.203098 0.997692 0.538834 0.159408 + 0.151831 0.260319 0.256477 0.275927 0.215435 -0.279581 + -0.080649 -0.322371 -0.764447 -0.908881 -0.656306 -0.381115 + -0.188604 0.130684 0.382037 0.089729 0.304551 -0.341557 + -1.325423 -2.149746 -2.849843 -3.153856 -2.503523 -1.175001 + -0.223698 -0.178820 0.721032 0.377647 -0.197684 -1.104130 + -2.056793 -2.207476 -1.245579 -0.115779 0.089260 -0.479708 + 0.424872 0.316521 0.147938 -0.227774 -0.402043 -0.176976 + 0.012591 -0.188477 -0.631527 -1.029457 0.629634 0.334735 + 0.244304 0.178606 -0.025439 -0.499686 -1.025187 -1.093356 + -0.725006 -0.679467 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_D.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_D.grdecl new file mode 100644 index 000000000..b03341305 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_D.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.058295 0.248749 0.388570 0.249038 0.000283 -0.176982 + -0.328420 -0.484198 -0.589901 -0.695144 -0.315096 -0.277978 + -0.276790 -0.312213 -0.269854 -0.147767 -0.122723 -0.248172 + -0.371110 -0.465613 -1.020727 -1.177666 -1.161339 -1.148812 + -1.337923 -1.390415 -0.852292 -0.042150 0.261905 -0.077604 + -1.009536 -0.847495 -0.697763 -0.750847 -0.950620 -0.969765 + -0.615036 -0.067567 0.305606 0.250316 -0.420416 -0.792555 + -1.180631 -0.999140 -0.325773 0.295402 0.577985 0.641194 + 0.622060 0.494645 0.381958 -0.273400 -0.644773 -0.434449 + 0.077097 0.389331 0.406498 0.389883 0.425638 0.373432 + 0.557541 0.432428 0.527930 0.494641 0.224039 -0.120332 + -0.398642 -0.423386 -0.010316 0.589501 0.588478 0.124527 + -0.270139 -0.533729 -0.830287 -1.131914 -1.236447 -1.091899 + -0.751424 -0.229210 -0.052205 -0.067141 0.066797 0.101213 + -0.231870 -0.866168 -1.454288 -1.735008 -1.712798 -1.465199 + -0.786013 -0.120096 0.854054 1.528835 1.507371 0.874103 + 0.091204 -0.371360 -0.431444 -0.426733 -0.142205 0.318141 + 0.967773 1.505608 1.583705 1.187642 0.723000 0.451266 + 0.193373 -0.228383 0.476335 0.524315 0.668647 0.547055 + 0.134166 -0.294362 -0.565245 -0.648533 -0.553100 -0.392055 + -0.297262 -0.426719 -0.352796 -0.284941 -0.492572 -1.019570 + -1.572755 -1.718771 -1.257758 -0.442012 -1.062786 -1.278902 + -0.813618 0.065464 0.569216 0.263687 -0.355284 -0.607314 + -0.467468 -0.241040 -1.265793 -0.853971 0.033670 0.687807 + 0.818975 0.593910 0.193730 -0.225818 -0.475444 -0.519302 + -0.775314 -0.416251 0.034658 0.207452 0.195375 0.163425 + 0.029731 -0.312759 -0.703724 -0.835337 -0.314654 -0.500735 + -0.469920 -0.304734 -0.207327 -0.322978 -0.506223 -0.528140 + -0.396959 -0.198479 0.043096 -0.169129 -0.345117 -0.418549 + -0.510572 -0.733959 -1.007160 -1.025567 -0.579104 0.056893 + 0.457937 0.108470 -0.548896 -0.979114 -1.024414 -1.005246 + -1.128199 -1.241025 -1.160557 -0.918426 -0.041656 -0.567358 + -1.017082 -1.132163 -0.793021 -0.343733 -0.297997 -0.729932 + -1.226567 -1.377502 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_E_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_E_local.grdecl new file mode 100644 index 000000000..164372e94 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_E_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391517 -0.025932 -0.279426 -0.127581 0.017761 -0.193278 + -0.633775 -1.029683 0.859417 0.607622 0.091949 -0.829884 + -1.867067 -2.117355 -1.216993 -0.109772 0.090068 -0.479618 + 0.439765 -0.143754 -1.070861 -1.915480 -2.726342 -3.124574 + -2.504564 -1.177302 -0.224223 -0.178808 -0.057085 -0.287224 + -0.724738 -0.876790 -0.636449 -0.371928 -0.186803 0.130124 + 0.381840 0.089729 1.202264 0.996304 0.536597 0.157487 + 0.151960 0.261694 0.257023 0.275927 0.215435 -0.279581 + 1.430932 1.254107 0.654710 -0.078125 -0.653691 -0.862671 + -0.729918 -0.454728 -0.200309 -0.092174 1.324994 0.901444 + 0.074174 -0.849109 -1.649805 -1.964304 -1.696768 -1.163499 + -0.598027 -0.028493 0.899565 0.992203 0.749731 0.404224 + -0.167782 -1.022487 -1.668451 -1.600215 -1.044804 -0.566005 + -0.035406 1.009202 1.709299 1.983187 1.760534 0.946370 + 0.064703 -0.146747 0.213693 0.432429 -0.049208 0.944598 + 1.588994 1.513464 1.166571 1.047943 1.075387 0.881568 + -0.238143 -0.109934 0.390472 0.753952 1.023120 0.847401 + 0.682307 1.046445 1.725379 1.567073 0.702032 -0.382223 + -0.262876 0.157758 0.172461 0.312229 0.509417 0.808807 + 2.048589 2.678183 2.160811 0.606263 -1.286302 -1.515503 + -0.900708 0.206069 1.040176 1.223922 1.428210 1.932714 + 1.873495 0.937052 -1.368768 -1.618878 -1.261231 0.040584 + 1.085511 0.566150 0.340310 0.322680 0.728392 1.134462 + -0.141165 -0.467429 -0.634675 -0.902073 -0.387598 -0.397320 + -0.366566 -0.448727 -0.189603 0.574898 1.203215 0.463139 + -0.148902 -0.465059 -0.632746 -0.753503 -0.812524 -0.672923 + -0.102951 0.910524 2.142118 1.741012 0.822085 0.090545 + -0.411376 -0.875820 -1.168968 -1.063000 -0.552467 0.190168 + 3.331424 3.387353 2.309292 0.673060 -0.530516 -0.945719 + -1.098227 -1.442308 -1.805538 -1.984318 1.496248 1.191897 + 0.236994 -0.868205 -1.410640 -1.409458 -1.497087 -1.971519 + -2.470902 -2.588709 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_F_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_F_local.grdecl new file mode 100644 index 000000000..e3850c811 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_F_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.648341 0.376487 0.306689 0.234835 0.003016 -0.494571 + -1.028435 -1.095739 -0.725329 -0.679467 0.526481 0.509107 + 0.391374 -0.023878 -0.273295 -0.122468 0.016831 -0.198939 + -0.636846 -1.026473 0.854990 0.587617 0.076319 -0.826784 + -1.845253 -2.088240 -1.196803 -0.100361 0.101494 -0.460296 + 0.416105 -0.149265 -1.036649 -1.856664 -2.652755 -3.043142 + -2.427564 -1.126902 -0.197833 -0.150158 -0.055808 -0.292010 + -0.727036 -0.863188 -0.599546 -0.323781 -0.146615 0.151039 + 0.377920 0.099002 1.159265 0.913927 0.442901 0.083079 + 0.146301 0.328343 0.314699 0.315541 0.254183 -0.217592 + 1.382339 1.182361 0.606164 -0.074510 -0.512851 -0.599575 + -0.556185 -0.402004 -0.171722 -0.034386 1.299749 0.856614 + 0.039093 -0.813428 -1.370089 -1.451543 -1.283660 -0.999643 + -0.564703 -0.015819 0.869501 0.934594 0.686416 0.334369 + -0.201242 -0.828715 -1.268825 -1.403175 -1.056628 -0.581179 + -0.082381 0.883116 1.544651 1.770907 1.501780 0.848208 + 0.235476 -0.092404 0.065977 0.333041 -0.086845 0.850050 + 1.454510 1.348493 1.025901 0.843455 0.743175 0.669055 + 0.304108 -0.241397 0.283275 0.710515 0.965203 0.711999 + 0.281040 -0.008500 -0.258105 -0.155182 0.076932 -0.525380 + 0.218085 0.120154 0.144979 0.266826 0.274259 -0.063610 + -0.706025 -0.859636 -0.201938 -0.423356 -0.984475 -1.346387 + -0.885522 0.207641 0.991150 0.874515 0.277199 0.084113 + 0.436803 0.028687 -1.642724 -1.771777 -1.099965 0.083042 + 1.075412 1.225557 0.752793 0.391639 0.446377 0.474999 + -0.832171 -1.124079 -1.055536 -0.790068 -0.338841 0.032714 + -0.033998 -0.381813 -0.458102 -0.083964 0.478834 -0.389831 + -0.818266 -0.749837 -0.595607 -0.706766 -0.914550 -0.820072 + -0.313926 0.432227 1.639994 0.966942 0.034676 -0.378038 + -0.398683 -0.584507 -1.007885 -1.202743 -0.801227 0.002337 + 2.448313 2.022981 0.450787 -1.105491 -1.668478 -1.479002 + -1.479979 -1.990964 -2.507444 -2.668368 0.655684 0.058050 + -1.259949 -2.426922 -2.541627 -1.906752 -1.623146 -2.131591 + -2.867963 -3.213965 / diff --git a/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_G_local.grdecl b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_G_local.grdecl new file mode 100644 index 000000000..0aea1419c --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/FieldParam_real5_iter1_G_local.grdecl @@ -0,0 +1,35 @@ +FIELDPAR + 0.655684 0.058050 -1.259949 -2.426922 -2.541627 -1.906752 + -1.623146 -2.131591 -2.867963 -3.213965 2.448313 2.022981 + 0.450787 -1.105491 -1.668478 -1.479002 -1.479979 -1.990964 + -2.507444 -2.668368 1.639994 0.966942 0.034676 -0.378038 + -0.398683 -0.584507 -1.007885 -1.202743 -0.801227 0.002337 + 0.478834 -0.389831 -0.818266 -0.749837 -0.595607 -0.706766 + -0.914550 -0.820072 -0.313926 0.432227 -0.832171 -1.124079 + -1.055536 -0.790068 -0.338841 0.032714 -0.033998 -0.381813 + -0.458102 -0.083964 -1.642724 -1.771777 -1.099965 0.083042 + 1.075412 1.225557 0.752793 0.391639 0.446377 0.474999 + -0.984475 -1.346387 -0.885522 0.207641 0.991150 0.874515 + 0.277199 0.084113 0.436803 0.028687 0.218085 0.120154 + 0.144979 0.266826 0.274259 -0.063610 -0.706025 -0.859636 + -0.201938 -0.423356 0.283275 0.710515 0.965203 0.711999 + 0.281040 -0.008500 -0.258105 -0.155182 0.076932 -0.525380 + -0.086845 0.850050 1.454510 1.348493 1.025901 0.843455 + 0.743175 0.669055 0.304108 -0.241397 -0.082381 0.883116 + 1.544651 1.770907 1.501780 0.848208 0.235476 -0.092404 + 0.065977 0.333041 0.869501 0.934594 0.686416 0.334369 + -0.201242 -0.828715 -1.268825 -1.403175 -1.056628 -0.581179 + 1.299749 0.856614 0.039093 -0.813428 -1.370089 -1.451543 + -1.283660 -0.999643 -0.564703 -0.015819 1.382339 1.182361 + 0.606164 -0.074510 -0.512851 -0.599575 -0.556185 -0.402004 + -0.171722 -0.034386 1.159265 0.913927 0.442901 0.083079 + 0.146301 0.328343 0.314699 0.315541 0.254183 -0.217592 + -0.055808 -0.292010 -0.727036 -0.863188 -0.599546 -0.323781 + -0.146615 0.151039 0.377920 0.099002 0.416105 -0.149265 + -1.036649 -1.856664 -2.652755 -3.043142 -2.427564 -1.126902 + -0.197833 -0.150158 0.854990 0.587617 0.076319 -0.826784 + -1.845253 -2.088240 -1.196803 -0.100361 0.101494 -0.460296 + 0.526481 0.509107 0.391374 -0.023878 -0.273295 -0.122468 + 0.016831 -0.198939 -0.636846 -1.026473 0.648341 0.376487 + 0.306689 0.234835 0.003016 -0.494571 -1.028435 -1.095739 + -0.725329 -0.679467 / diff --git a/tests/workflows/localisation/example_case/init_files/README b/tests/workflows/localisation/example_case/init_files/README new file mode 100644 index 000000000..6a8c65626 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/README @@ -0,0 +1,18 @@ +### Directory with reference data and input files + +- **Input files:** + - `sim_field_template.ert` + - `polygons.txt` + - `region_polygons.txt` + - `scaling_factor.grdecl` + - `scaling_factor_rms_orgo.grdecl` + +- **Reference files:** + - `FieldParam_real5_iter0_X_local.grdecl` + - `FieldParam_real5_iter3_X_local.grdecl` + - `X is case name (A, B, C, ...)` + +- **Temporary files:** + - Initial ensemble files are stored here when running scripts/make_reference_data.py: + - `FieldParam.roff`: The field parameter + - `Upscaled.roff`: The upscaled field parameter (for QC purpose) diff --git a/tests/workflows/localisation/example_case/init_files/polygons.txt b/tests/workflows/localisation/example_case/init_files/polygons.txt new file mode 100644 index 000000000..4a45ad4e8 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/polygons.txt @@ -0,0 +1,17 @@ +499.666718 2093.778320 25.000000 +341.397217 1917.105408 0.000000 +216.253906 1324.514893 0.000000 +-18.913147 1133.715820 0.000000 +106.429382 890.193115 0.000000 +130.630096 479.416870 0.000000 +-64.992249 440.292480 0.000000 +204.256226 -47.930542 0.000000 +561.117737 -119.302979 0.000000 +714.058411 38.735840 0.000000 +1087.448486 541.147339 0.000000 +879.294128 1025.106445 0.000000 +738.789978 1514.269440 0.000000 +754.401611 1878.539673 0.000000 +582.674133 2123.121155 0.000000 +499.666718 2093.778320 25.000000 +999.000000 999.000000 999.000000 diff --git a/tests/workflows/localisation/example_case/init_files/region_polygons.txt b/tests/workflows/localisation/example_case/init_files/region_polygons.txt new file mode 100644 index 000000000..0c5a68db4 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/region_polygons.txt @@ -0,0 +1,153 @@ +424.509949 2079.387421 20.833294 +349.525574 2077.578644 23.765421 +260.721008 2077.669594 24.845678 +169.519867 2077.044716 25.000004 +86.164909 2070.750626 25.000002 +16.176638 2044.482727 25.000000 +-36.105103 1981.598633 25.000004 +-67.602112 1871.688156 25.000002 +-80.282654 1729.270020 25.000000 +-77.376656 1575.095093 25.000004 +-61.402237 1427.718933 24.845680 +-32.030331 1296.914978 23.765432 +11.779886 1190.261230 20.833336 +70.523544 1115.098511 15.586418 +142.512741 1077.817566 9.413568 +225.513870 1084.571716 4.166626 +316.264160 1136.641357 1.234479 +407.384247 1215.814209 0.154193 +490.465576 1299.004700 -0.000122 +559.404480 1367.602234 -0.000051 +617.315918 1420.894714 0.000038 +669.619995 1462.644531 0.000081 +720.154053 1495.998566 0.000036 +766.425232 1521.639862 -0.000063 +804.358276 1539.635681 -0.000163 +832.164429 1550.605621 -0.000220 +857.200378 1557.378571 -0.000241 +889.109863 1563.335663 -0.000244 +934.286072 1574.346130 -0.000244 +986.121887 1606.231659 -0.000244 +1034.759888 1677.301727 -0.000244 +1068.650513 1796.007446 -0.000244 +1069.475220 1931.365677 -0.000244 +1017.223267 2042.534809 -0.000244 +902.403015 2099.124138 0.154078 +757.601257 2112.546516 1.234336 +625.923889 2104.665764 4.166463 +538.766174 2093.921379 9.413428 +480.680878 2085.055855 15.586329 +424.509949 2079.387421 20.833294 +999.000000 999.000000 999.000000 +1175.375488 1016.951172 -0.000163 +1127.616089 1031.741028 -0.000216 +1066.552368 1035.509888 -0.000205 +995.064148 1029.995544 -0.000122 +916.582642 1016.936829 0.000030 +836.747009 998.074219 0.000200 +761.747864 975.148926 0.000326 +696.421936 947.580444 0.000360 +640.188721 905.502197 0.000332 +591.113647 836.726074 0.000285 +547.842468 735.448120 0.000256 +511.342438 621.401733 0.000246 +483.161316 520.704346 0.000244 +463.492584 453.733765 0.000243 +447.112701 417.910889 0.000232 +427.443970 404.916626 0.000203 +400.120544 407.141479 0.000152 +369.624359 419.813477 0.000092 +342.649261 438.869873 0.000041 +324.282745 461.092529 0.000014 +313.187164 486.642090 0.000014 +306.418579 516.523315 0.000041 +301.349274 551.017334 0.000092 +296.616669 587.508423 0.000152 +291.174377 622.656738 0.000203 +283.304962 654.361938 0.000232 +268.606812 685.481689 0.000243 +242.006943 720.113525 0.000244 +200.838959 760.598633 0.000244 +152.061737 802.254272 0.000244 +105.040504 838.642090 0.000244 +66.897408 864.863159 0.000244 +35.782269 882.177368 0.000244 +7.601859 893.384766 0.000244 +-20.563051 899.712036 0.000244 +-46.935501 896.092651 0.000244 +-68.564507 875.886963 0.000244 +-84.266357 831.946533 0.000244 +-99.926460 755.086914 0.000244 +-123.197540 635.614624 0.000244 +-156.755280 471.414795 0.000244 +-183.367401 290.685303 0.000244 +-180.824615 129.202026 0.000244 +-130.081009 14.246216 0.000244 +-24.744156 -60.882324 0.000244 +138.414948 -111.378418 0.000244 +355.891235 -149.908936 0.000244 +597.242981 -179.027344 0.000244 +825.294128 -198.758301 0.000244 +1009.999023 -207.018066 0.000244 +1149.831543 -193.288574 0.000244 +1250.396118 -144.943359 0.000244 +1316.705811 -52.310303 0.000244 +1351.408203 82.465698 0.000244 +1356.560181 254.284424 0.000244 +1336.038330 453.482178 0.000241 +1300.999146 652.138062 0.000220 +1264.419189 817.766602 0.000163 +1235.577637 926.227905 0.000060 +1208.965210 986.761230 -0.000060 +1175.375488 1016.951172 -0.000163 +999.000000 999.000000 999.000000 +1100.404907 1563.663239 -0.000244 +1093.085693 1580.043121 -0.000241 +1080.155762 1597.196869 -0.000220 +1049.040649 1608.933655 -0.000163 +990.550293 1609.417297 -0.000062 +909.037842 1594.230499 0.000048 +812.241943 1559.310425 0.000122 +707.159241 1502.077637 0.000128 +597.820374 1425.885376 0.000089 +487.514221 1335.570435 0.000041 +380.109985 1238.548706 0.000012 +281.798523 1152.554382 0.000002 +199.351074 1097.901123 0.000000 +137.217148 1087.896362 0.000000 +90.559929 1107.823669 0.000000 +52.220978 1135.960205 0.000000 +17.030819 1153.067566 0.000000 +-12.224041 1149.843445 0.000000 +-30.768122 1119.469666 0.000000 +-33.904774 1058.583801 0.000000 +-17.252659 977.645142 0.000000 +23.490715 890.568726 0.000000 +88.479721 808.518433 0.000000 +161.276154 731.652832 0.000000 +221.293686 657.379761 0.000000 +254.415771 584.146362 0.000000 +272.405029 514.559692 0.000000 +293.493774 452.265869 0.000000 +331.234711 402.557861 -0.000002 +380.462097 377.315674 -0.000012 +431.330383 390.064941 -0.000041 +475.952148 448.652710 -0.000090 +514.272339 538.209106 -0.000140 +548.194092 638.184570 -0.000163 +580.220703 730.961548 -0.000142 +615.257507 810.648438 -0.000102 +658.809998 874.285400 -0.000081 +715.118774 920.285522 -0.000104 +783.363953 952.553223 -0.000154 +861.460938 976.365906 -0.000203 +945.597290 999.150879 -0.000232 +1025.049927 1036.934814 -0.000243 +1087.368286 1107.894287 -0.000244 +1123.369019 1221.228210 -0.000244 +1136.937866 1350.224487 -0.000244 +1135.228271 1459.193237 -0.000244 +1125.039185 1521.875244 -0.000244 +1111.754639 1549.733948 -0.000244 +1100.404907 1563.663239 -0.000244 +999.000000 999.000000 999.000000 diff --git a/tests/workflows/localisation/example_case/init_files/scaling_factor.grdecl b/tests/workflows/localisation/example_case/init_files/scaling_factor.grdecl new file mode 100644 index 000000000..4d6f606f5 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/scaling_factor.grdecl @@ -0,0 +1,63 @@ + +SCALING + 0 0 0 0 0 + 0 0 0 0 0 + + 0 0 0.0024178524 0.00884367712 0.0132498778 + 0.0161081199 0.0182318985 0.0201500896 0.0203383286 0.0155032165 + + 0.003006696 0.0156889092 0.0205063 0.0220940653 0.0239405781 + 0.0273311734 0.0326220095 0.0396278054 0.0452148803 0.0438990891 + + 0.0279479939 0.0363404155 0.03613998 0.0340526439 0.0340892971 + 0.0368285999 0.0430386923 0.0538446382 0.0647787303 0.0673846528 + + 0.0432741642 0.0517198518 0.0529378206 0.0574502349 0.0607241429 + 0.0538347289 0.0475190282 0.0564772375 0.0722196251 0.0810511559 + + 0.0468719564 0.0599104799 0.0680627897 0.0913911909 0.117351525 + 0.108548783 0.0624484308 0.0494863279 0.0646237284 0.0794273764 + + 0.0423487797 0.0586890392 0.0715542361 0.120984368 0.216681033 + 0.261977315 0.183652744 0.0777159408 0.0435763821 0.0589708723 + + 0.0365328901 0.0551960096 0.0803627595 0.175753772 0.354921192 + 0.496848464 0.433681875 0.222422212 0.0679221153 0.036710728 + + 0.0362647735 0.0638489351 0.109380685 0.24080199 0.456255645 + 0.638256907 0.630086362 0.419066995 0.165060177 0.0379007943 + + 0.0416177697 0.0837309957 0.136203006 0.264866084 0.480560392 + 0.683874905 0.733731925 0.542562187 0.313413531 0.103217475 + + 0.0437682532 0.0769556612 0.112662002 0.229829431 0.461149663 + 0.723126411 0.871051311 0.711820066 0.450462759 0.227276623 + + 0.0451645106 0.063203834 0.066589959 0.159034893 0.425005674 + 0.744041264 0.956496 0.911683619 0.516521394 0.283591837 + + 0.0492031202 0.0741543695 0.0527167879 0.0891754478 0.352179855 + 0.695928216 0.895608008 0.852726817 0.517417789 0.260448962 + + 0.0523970835 0.0939117745 0.0628247038 0.0399134271 0.198853135 + 0.46667394 0.65412581 0.635288835 0.387747556 0.149869889 + + 0.0571080595 0.113578357 0.0907923728 0.0506353714 0.069845207 + 0.152088627 0.252010256 0.238708615 0.124544971 0.055357337 + + 0.0635695606 0.127395019 0.125238523 0.0950208232 0.0677052438 + 0.0437932834 0.0376545079 0.0385723859 0.0507421643 0.0839931592 + + 0.0676470697 0.128882632 0.141776979 0.128613114 0.107911579 + 0.0893575996 0.0812080279 0.0852842182 0.10028512 0.122700267 + + 0.0620717965 0.114647269 0.134200275 0.135575622 0.131714463 + 0.128724501 0.129031375 0.13239418 0.137205586 0.140333056 + + 0.0413737856 0.0846893489 0.106586784 0.114918746 0.118551478 + 0.120768428 0.12276534 0.125401542 0.126825631 0.122835122 + + 0.00877429079 0.0441762544 0.0665985122 0.0785425529 0.0850359648 + 0.0885261223 0.0905158073 0.0923460945 0.0924721509 0.0868233591 + + / diff --git a/tests/workflows/localisation/example_case/init_files/scaling_factor_rms_origo.grdecl b/tests/workflows/localisation/example_case/init_files/scaling_factor_rms_origo.grdecl new file mode 100644 index 000000000..b0f6f9926 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/scaling_factor_rms_origo.grdecl @@ -0,0 +1,63 @@ + +SCALING + 0.00877429079 0.0441762544 0.0665985122 0.0785425529 0.0850359648 + 0.0885261223 0.0905158073 0.0923460945 0.0924721509 0.0868233591 + + 0.0413737856 0.0846893489 0.106586784 0.114918746 0.118551478 + 0.120768428 0.12276534 0.125401542 0.126825631 0.122835122 + + 0.0620717965 0.114647269 0.134200275 0.135575622 0.131714463 + 0.128724501 0.129031375 0.13239418 0.137205586 0.140333056 + + 0.0676470697 0.128882632 0.141776979 0.128613114 0.107911579 + 0.0893575996 0.0812080279 0.0852842182 0.10028512 0.122700267 + + 0.0635695606 0.127395019 0.125238523 0.0950208232 0.0677052438 + 0.0437932834 0.0376545079 0.0385723859 0.0507421643 0.0839931592 + + 0.0571080595 0.113578357 0.0907923728 0.0506353714 0.069845207 + 0.152088627 0.252010256 0.238708615 0.124544971 0.055357337 + + 0.0523970835 0.0939117745 0.0628247038 0.0399134271 0.198853135 + 0.46667394 0.65412581 0.635288835 0.387747556 0.149869889 + + 0.0492031202 0.0741543695 0.0527167879 0.0891754478 0.352179855 + 0.695928216 0.895608008 0.852726817 0.517417789 0.260448962 + + 0.0451645106 0.063203834 0.066589959 0.159034893 0.425005674 + 0.744041264 0.956496 0.911683619 0.516521394 0.283591837 + + 0.0437682532 0.0769556612 0.112662002 0.229829431 0.461149663 + 0.723126411 0.871051311 0.711820066 0.450462759 0.227276623 + + 0.0416177697 0.0837309957 0.136203006 0.264866084 0.480560392 + 0.683874905 0.733731925 0.542562187 0.313413531 0.103217475 + + 0.0362647735 0.0638489351 0.109380685 0.24080199 0.456255645 + 0.638256907 0.630086362 0.419066995 0.165060177 0.0379007943 + + 0.0365328901 0.0551960096 0.0803627595 0.175753772 0.354921192 + 0.496848464 0.433681875 0.222422212 0.0679221153 0.036710728 + + 0.0423487797 0.0586890392 0.0715542361 0.120984368 0.216681033 + 0.261977315 0.183652744 0.0777159408 0.0435763821 0.0589708723 + + 0.0468719564 0.0599104799 0.0680627897 0.0913911909 0.117351525 + 0.108548783 0.0624484308 0.0494863279 0.0646237284 0.0794273764 + + 0.0432741642 0.0517198518 0.0529378206 0.0574502349 0.0607241429 + 0.0538347289 0.0475190282 0.0564772375 0.0722196251 0.0810511559 + + 0.0279479939 0.0363404155 0.03613998 0.0340526439 0.0340892971 + 0.0368285999 0.0430386923 0.0538446382 0.0647787303 0.0673846528 + + 0.003006696 0.0156889092 0.0205063 0.0220940653 0.0239405781 + 0.0273311734 0.0326220095 0.0396278054 0.0452148803 0.0438990891 + + 0 0 0.0024178524 0.00884367712 0.0132498778 + 0.0161081199 0.0182318985 0.0201500896 0.0203383286 0.0155032165 + + 0 0 0 0 0 + 0 0 0 0 0 + + / diff --git a/tests/workflows/localisation/example_case/init_files/sim_field_template.ert b/tests/workflows/localisation/example_case/init_files/sim_field_template.ert new file mode 100644 index 000000000..806bbf7c7 --- /dev/null +++ b/tests/workflows/localisation/example_case/init_files/sim_field_template.ert @@ -0,0 +1,56 @@ +DEFINE $$USER +DEFINE ${CASE_NAME} +DEFINE ${ENSEMBLE_SEED_FILE} +DEFINE /example_config.yml + +INSTALL_JOB SIM_FIELD scripts/FM_SIM_FIELD +----------------------------------------------------- +-- Observations +----------------------------------------------------- + +DEFINE /observations/observations.obs +OBS_CONFIG + +JOBNAME sim_fields_ + + +NUM_REALIZATIONS ${NREAL} -- 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_SYSTEM LOCAL +QUEUE_OPTION LOCAL MAX_RUNNING 10 +RANDOM_SEED ${ERT_START_SEED} -- ERT seed value + +RUNPATH simulations//realization-/iter- +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 + +-- Activate localisation setup +${LOAD_LOCALISATION_WORKFLOW} +${HOOK_LOCALISATION_WORKFLOW} + +--Result data from forward model-- +GEN_DATA RESULT_UPSCALED_FIELD RESULT_FILE:${RESPONSE_FILE_PREFIX}_%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(=/, =/) + +FORWARD_MODEL MAKE_SYMLINK(=/${GRID_FILE_NAME}, =/${GRID_FILE_NAME}) +FORWARD_MODEL MAKE_SYMLINK(=/${GRID_FILE_NAME_UPSCALED}, =/${GRID_FILE_NAME_UPSCALED}) + +-- The main forward model simulating gaussian field with trend, and upscale +FORWARD_MODEL SIM_FIELD(=, =, =, =) + +GRID /${GRID_FILE_NAME} -- Necessary for AHM using field parameters + +FIELD FIELDPAR PARAMETER ${UPDATED_FIELDPARAM_FILE_NAME} INIT_FILES:${INITIAL_FIELDPARAM_FILE_NAME} MIN:-5.0 MAX:5.0 FORWARD_INIT:True diff --git a/tests/workflows/localisation/example_case/localisation.wf b/tests/workflows/localisation/example_case/localisation.wf new file mode 100644 index 000000000..c6477f3d7 --- /dev/null +++ b/tests/workflows/localisation/example_case/localisation.wf @@ -0,0 +1 @@ +LOCALISATION_JOB local_config.yml diff --git a/tests/workflows/localisation/example_case/scripts/FM_SIM_FIELD b/tests/workflows/localisation/example_case/scripts/FM_SIM_FIELD new file mode 100644 index 000000000..53ae455ca --- /dev/null +++ b/tests/workflows/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/workflows/localisation/example_case/scripts/README b/tests/workflows/localisation/example_case/scripts/README new file mode 100644 index 000000000..b8670faa1 --- /dev/null +++ b/tests/workflows/localisation/example_case/scripts/README @@ -0,0 +1,11 @@ +### Source code scripts + +- `common_functions.py`: Functions used by the two scripts make_reference_data.py and sim_fields.py +- `make_reference_data.py`: + - Create grid files, random seed file localisation config file and observation files for the test cases + - Create reference data (assuming the ERT and localistion code is correct and updated) +- `sim_fields.py`: + - Used as forward model in ERT + - Simulate the GRF field, upscale it, extract responses (predictions) of observations. + +- `FM_SIM_FIELD`: ERT configuration of forward model SIM_FIELD using sim_fields.py. diff --git a/tests/workflows/localisation/example_case/scripts/__init__.py b/tests/workflows/localisation/example_case/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/tests/workflows/localisation/example_case/scripts/common_functions.py b/tests/workflows/localisation/example_case/scripts/common_functions.py new file mode 100644 index 000000000..f11b3e1dc --- /dev/null +++ b/tests/workflows/localisation/example_case/scripts/common_functions.py @@ -0,0 +1,1880 @@ +""" +Common functions used by the scripts: init_test_case.py and sim_field.py +""" +import copy +import dataclasses +import math +import os +import random +import shutil +from dataclasses import asdict, dataclass +from pathlib import Path +from string import Template +from typing import Any, Dict, Tuple + +import gstools as gs +import numpy as np +import xtgeo +import yaml + +# pylint: disable=too-many-lines +# 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 ModelSize: + """ + 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. + """ + + size: Tuple[float] = (1000.0, 2000.0, 50.0) + polygon_file: str = None + use_eclipse_grid_index_origo: bool = True + + def reset_to_default(self): + self.size = (1000.0, 2000.0, 50.0) + self.polygon_file = None + self.use_eclipse_grid_index_origo = 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_prefix: str = "init_files/FieldParam" + updated_file_name_prefix: str = "FieldParam" + seed_file: str = "randomseeds.txt" + variogram: str = "gaussian" + correlation_range: Tuple[float] = (250.0, 500.0, 2.0) + correlation_azimuth: float = 0.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.15 + grid_dimension: Tuple[int] = (10, 20, 1) + grid_file_name: str = "GRID_STANDARD.EGRID" + + def reset_to_default(self): + self.name = "FIELDPAR" + self.algorithm = "gstools" + self.file_format = "ROFF" + self.initial_file_name_prefix = "init_files/FieldParam" + self.updated_file_name_prefix = "FieldParam" + self.seed_file = "randomseeds.txt" + self.variogram = "gaussian" + self.correlation_range = (250.0, 500.0, 2.0) + self.correlation_azimuth = 0.0 + self.correlation_dip = 0.0 + self.correlation_exponent = 1.9 + self.trend_use = False + self.trend_params = (1.0, -1.0) + self.trend_relstd = 0.15 + self.grid_dimension = (10, 20, 1) + self.grid_file_name = "GRID_STANDARD.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] = (2, 4, 1) + upscaled_file_name: str = "Upscaled" + grid_file_name: str = "GRID_STANDARD_UPSCALED.EGRID" + file_format: str = "ROFF" + write_upscaled_field: bool = True + response_function: str = "average" + gen_data_file_prefix: str = "UpscaledField" + ert_config_template_file: str = "init_files/sim_field_template.ert" + ert_config_file: str = "sim_field.ert" + + def reset_to_default(self): + self.name = "UPSCALED" + self.grid_dimension = (2, 4, 1) + self.upscaled_file_name = "Upscaled" + self.grid_file_name = "GRID_STANDARD_UPSCALED.EGRID" + self.file_format = "ROFF" + self.write_upscaled_field = True + self.response_function = "average" + self.gen_data_file_prefix = "UpscaledField" + self.ert_config_template_file = "init_files/sim_field_template.ert" + self.ert_config_file = "sim_field.ert" + + +# pylint: disable=too-many-instance-attributes +@dataclass +class Observation: + """ + Specify name of files for generated observations + and also position of observations. Grid cell indices for grid cells + with observations are calculated from position of 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]] = None + obs_positions: Tuple[Tuple[float]] = None + obs_values: Tuple[float] = None + + def reset_to_default(self): + self.directory = "observations" + self.file_name = "observations.obs" + self.data_dir = "obs_data" + self.reference_param_file = "init_files/ObsField" + self.reference_field_name = "ObsField" + self.rel_error = 0.10 + self.min_abs_error = 0.01 + self.selected_grid_cells = None + self.obs_positions = None + self.obs_values = None + + +@dataclass +class Localisation: + """ + Specify settings for the localisation config file. + """ + + method: str = "gaussian" + region_polygons: str = None + region_file: str = None + scaling_file: str = None + use_localisation: bool = True + + def reset_to_default(self): + self.method = "gaussian" + self.region_polygons = None + self.region_file = None + self.scaling_file = None + self.use_localisation = True + + +@dataclass +class Optional: + """ + Specify if some optional files should be + written or not (for QC purpose). + """ + + write_obs_pred_diff_field_file: bool = False + + def reset_to_default(self): + self.write_obs_pred_diff_field_file = False + + +@dataclass +class Settings: + """ + Settings for the test case + """ + + case_name: str = None + model_size: ModelSize = None + field: Field = None + response: Response = None + observation: Observation = None + localisation: Localisation = None + optional: Optional = None + + def update(self, updates): + for key, value in updates.items(): + if hasattr(self, key): + attr = getattr(self, key) + if dataclasses.is_dataclass(attr): + for attr_key, attr_value in value.items(): + if hasattr(attr, attr_key): + setattr(attr, attr_key, attr_value) + else: + setattr(self, key, value) + self.set_observed_cell_indices() + + def to_dict(self): + main_dict = {"settings": {}} + for key, value in asdict(self).items(): + if dataclasses.is_dataclass(key): + sub_dict = {} + for key2, value2 in asdict(key): + sub_dict[key2] = value2 + main_dict["settings"][key] = sub_dict + else: + main_dict["settings"][key] = value + return main_dict + + def reset_to_default(self): + self.model_size = ModelSize() + self.model_size.reset_to_default() + self.field = Field() + self.field.reset_to_default() + self.response = Response() + self.response.reset_to_default() + self.localisation = Localisation() + self.localisation.reset_to_default() + self.observation = Observation() + self.observation.reset_to_default() + self.optional = Optional() + self.optional.reset_to_default() + self.case_name = "A" + + def set_observed_cell_indices(self): + self.observation.selected_grid_cells = cell_index_list_from_obs_positions( + self.response.grid_dimension, + self.model_size.size, + self.observation.obs_positions, + self.model_size.use_eclipse_grid_index_origo, + ) + + +def read_config_file(config_file_name: Path) -> Dict[str, Any]: + with open(config_file_name, "r", encoding="utf-8") as f: + settings = yaml.safe_load(f) + case_name = settings["settings"]["case_name"] + model_size = ModelSize(**settings["settings"]["model_size"]) + field = Field(**settings["settings"]["field"]) + response = Response(**settings["settings"]["response"]) + observation = Observation(**settings["settings"]["observation"]) + localisation = Localisation(**settings["settings"]["localisation"]) + optional = Optional(**settings["settings"]["optional"]) + settings = Settings( + case_name=case_name, + model_size=model_size, + field=field, + response=response, + observation=observation, + localisation=localisation, + optional=optional, + ) + settings.set_observed_cell_indices() + return settings + + +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(settings_original: Settings, config_dict: dict): + # pylint: disable=too-many-branches, too-many-statements + settings_dict = config_dict["settings"] + settings = copy.deepcopy(settings_original) + valid_keys = [ + "case_name", + "model_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 = "case_name" + if key in settings_dict: + settings[key] = settings_dict[key] + + key = "model_size" + model_size_dict = settings_dict[key] if key in settings_dict else None + valid_keys = [ + "size", + "polygon_file", + "use_eclipse_grid_index_origo", + ] + if model_size_dict: + err_msg = [] + for sub_key in model_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") + + model_size_object = settings.model_size + model_size_object.size = update_key( + "size", model_size_object.size, model_size_dict, key + ) + model_size_object.polygon_file = update_key( + "polygon_file", model_size_object.polygon_file, model_size_dict, key + ) + model_size_object.use_eclipse_grid_index_origo = update_key( + "use_eclipse_grid_index_origo", + model_size_object.use_eclipse_grid_index_origo, + model_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_prefix", + "updated_file_name_prefix", + "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_prefix = update_key( + "initial_file_name_prefix", field.initial_file_name_prefix, field_dict, key + ) + field.updated_file_name_prefix = update_key( + "updated_file_name_prefix", field.updated_file_name_prefix, 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_prefix", + "ert_config_template_file", + "ert_config_file", + ] + 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_prefix = update_key( + "gen_data_file_prefix", response.gen_data_file_prefix, response_dict, key + ) + response.ert_config_template_file = update_key( + "ert_config_template_file", + response.ert_config_template_file, + response_dict, + key, + ) + response.ert_config_file = update_key( + "ert_config_file", + response.ert_config_file, + 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", + "obs_positions", + ] + + 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.obs_positions = update_key( + "obs_positions", observation.obs_positions, obs_dict, key + ) + + key = "localisation" + local_dict = settings_dict[key] if key in settings_dict else None + valid_keys = ["method", "use_localisation"] + + 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) + localisation.use_localisation = update_key( + "use_localisation", localisation.use_localisation, 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, + ) + settings.set_observed_cell_indices() + return settings + + +def generate_field_and_upscale( + # pylint: disable=too-many-arguments + real_number: int, + iteration: int, + seed_file_name: str, + algorithm_method: str, + field_name: str, + field_file_name: str, + file_format: str, + grid_dimension: tuple, + model_size: tuple, + variogram_name: str, + corr_ranges: tuple, + azimuth: float, + dip: float, + alpha: float, + use_trend: bool, + trend_params: tuple, + relative_std: float, + upscale_name: str, + response_function: str, + upscaled_file_name: str, + grid_dimension_upscaled: tuple, + write_upscaled_field: bool, + use_standard_grid_index_origo: bool, +): + start_seed = get_seed(seed_file_name, real_number) + if algorithm_method == "gstools": + print(f"Use algorithm: {algorithm_method} with version: {gs.__version__} ") + residual_field = simulate_field_using_gstools( + start_seed, + variogram_name, + corr_ranges, + azimuth, + grid_dimension, + model_size, + use_standard_grid_index_origo, + ) + else: + print("Use algorithm: gaussianfft") + residual_field = simulate_field( + start_seed, + variogram_name, + corr_ranges, + azimuth, + dip, + alpha, + grid_dimension, + model_size, + use_standard_grid_index_origo, + ) + if use_trend: + trend_field = trend(grid_dimension, model_size, trend_params) + field3D = trend_field + relative_std * residual_field + else: + field3D = residual_field + + # Write field parameter for fine scale grid + field_object = export_field( + field3D, field_name, field_file_name, file_format, grid_dimension + ) + + field_values = field_object.values + + # Calculate upscaled values for selected coarse grid cells + upscaled_values = upscaling( + field_values, + response_function, + file_format, + upscale_name, + write_upscaled_field, + upscaled_file_name, + grid_dimension_upscaled, + iteration, + ) + 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]) + 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( + # pylint: disable=too-many-arguments + field_values, + response_function_name: str, + file_format: str, + upscaled_field_name: str, + write_upscaled_field: bool, + upscaled_file_name: str, + dimension: tuple, + iteration: int = 0, +): + """ + Calculate upscaled values and optionally write upscaled values to file. + Return upscaled values + """ + NX, NY, NZ = 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: + 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_from_cell_index_list(selected_cell_index_list) + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices( + obs_number, 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): + i_slice = slice(Iindx * mx, (Iindx + 1) * mx) + j_slice = slice(Jindx * my, (Jindx + 1) * my) + k_slice = slice(Kindx * mz, (Kindx + 1) * mz) + upscaled_values[Iindx, Jindx, Kindx] = np.mean( + field_values[i_slice, j_slice, k_slice] + ) + return upscaled_values + + +def trend(grid_dimension: tuple, model_size: tuple, trend_params: tuple): + """ + Return 3D numpy array with values following a linear trend + scaled to take values between 0 and 1. + """ + nx, ny, nz = grid_dimension + xsize, ysize, _ = model_size + a, b = 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: int, + variogram_name: str, + corr_ranges: tuple, + azimuth: float, + dip: float, + alpha: float, + grid_dimension: tuple, + model_size: tuple, + use_standard_grid_index_origo: bool, +): + # pylint: disable=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 + nx, ny, nz = grid_dimension + xrange, yrange, zrange = corr_ranges + xsize, ysize, zsize = model_size + + 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 use_standard_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: int, + variogram_name: str, + corr_ranges: tuple, + azimuth: float, + grid_dimension: tuple, + model_size: tuple, + use_standard_grid_index_origo: bool, +): + # pylint: disable=no-member, + xrange, yrange, zrange = corr_ranges + xsize, ysize, zsize = model_size + nx, ny, nz = grid_dimension + + 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, + # 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") + field = field_srf.reshape((nx, ny, nz)) + if use_standard_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, + field_name: str, + field_file_name: str, + file_format: str, + grid_dimension: tuple, +): + """ + Export initial realization of field to roff format + Input field3D should be C-index order since xtgeo requires that + """ + nx, ny, nz = 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", fmt="%20.6f" + ) + 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( + input_file_name: str, name: str, file_format: str, grid_file_name: str +): + """ + Read field from roff formatted file and return xtgeo property object + """ + if file_format.upper() == "GRDECL": + grid = xtgeo.grid_from_file(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( + file_format: str, pred_obs_file_name: str, grid_file_name: str, field_name: str +): + """ + Read field parameter containing parameter with observed values + for selected grid cells + """ + 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(grid_file_name, fformat="egrid") + fullfilename = pred_obs_file_name + ".grdecl" + obs_field_object = xtgeo.gridproperty_from_file( + fullfilename, fformat="grdecl", grid=grid, name=field_name + ) + else: + raise IOError(f"Unknown file format:{file_format} ") + return obs_field_object + + +def read_upscaled_field_from_file( + iteration: int, + input_file_name: str, + file_format: str, + upscaled_field_name: str, + grid_file_name: str, +): + """ + Read upscaled field parameter either from initial ensemble or updated ensemble. + Return xtgeo property object + """ + + 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(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, file_format: str +): + """ + 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 + + 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, cell_indx_list): + if cell_indx_list is None: + return None + if len(cell_indx_list) == 0: + return None + try: + Iindx = cell_indx_list[obs_number][0] + Jindx = cell_indx_list[obs_number][1] + Kindx = cell_indx_list[obs_number][2] + except IndexError: + try: + Iindx = cell_indx_list[0] + Jindx = cell_indx_list[1] + Kindx = cell_indx_list[2] + except IndexError: + raise ValueError(f"Index error for cell indices in: {cell_indx_list}") + + return (Iindx, Jindx, Kindx) + + +def get_obs_pos(obs_number, obs_pos_list): + x = obs_pos_list[obs_number][0] + y = obs_pos_list[obs_number][1] + z = obs_pos_list[obs_number][2] + + return (x, y, z) + + +def get_nobs_from_cell_index_list(cell_index_list: list): + """ + Check if cell_index_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 + """ + is_list_of_ints = all(isinstance(indx, int) for indx in cell_index_list) + if is_list_of_ints: + nobs = 1 + else: + # list of tuples (x,y,z) + nobs = len(cell_index_list) + return nobs + + +def get_nobs_from_position_list(obs_positions: list): + """ + Check if obs_positions is a single tuple (x,y,z) or + a list of tuples of type (x,y,z). + Return number of positions found in list + """ + if not obs_positions: + return 0 + is_list_of_floats = all( + isinstance(coordinate, float) for coordinate in obs_positions + ) + if is_list_of_floats: + nobs = 1 + else: + # list of tuples (x,y,z) + nobs = len(obs_positions) + return nobs + + +def obs_positions_from_cell_index( + grid_dimension_upscaled: tuple, + model_size: tuple, + cell_indx_list: list, + use_eclipse_origo: bool, +): + nx, ny, nz = grid_dimension_upscaled + xsize, ysize, zsize = model_size + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + 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_from_cell_index_list(cell_indx_list) + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, cell_indx_list) + x = (Iindx + 0.5) * dx + z = (Kindx + 0.5) * dz + if use_eclipse_origo: + y = ysize - (Jindx + 0.5) * dy + else: + y = (Jindx + 0.5) * dy + + pos_list.append((x, y, z)) + + return pos_list + + +def cell_index_list_from_obs_positions( + grid_dimension_upscaled: tuple, + model_size: tuple, + obs_positions: list, + use_eclipse_origo: bool, +): + nx, ny, nz = grid_dimension_upscaled + xsize, ysize, zsize = model_size + + dx = xsize / nx + dy = ysize / ny + dz = zsize / nz + + 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" + ) + + cell_index_list = [] + nobs = get_nobs_from_position_list(obs_positions) + for obs_number in range(nobs): + obs_pos = get_obs_pos(obs_number, obs_positions) + Iindx = int(obs_pos[0] / dx) + Jindx = int(obs_pos[1] / dy) + Kindx = int(obs_pos[2] / dz) + if use_eclipse_origo: + Jindx = ny - Jindx - 1 + cell_index_list.append((Iindx, Jindx, Kindx)) + + return cell_index_list + + +def read_observations( + config_path: str, + observation_dir: str, + obs_data_dir: str, + cell_index_list: list, +): + values = [] + for index in cell_index_list: + Iindx = index[0] + Jindx = index[1] + Kindx = index[2] + filename = ( + config_path + + "/" + + observation_dir + + "/" + + obs_data_dir + + "/" + + "obs_" + + str(Iindx + 1) + + "_" + + str(Jindx + 1) + + "_" + + str(Kindx + 1) + + ".txt" + ) + print(f"Read observations from: {filename}") + with open(filename, "r", encoding="utf-8") as file: + lines = file.readlines() + for line in lines: + words = line.split() + if len(words) == 2: + values.append(float(words[0])) + return values + + +def write_gen_obs( + upscaled_values, + observation_dir: str, + obs_file_name: str, + obs_data_dir: str, + cell_index_list: list, + rel_err: float, + min_err: float, +): + if os.path.exists(observation_dir): + shutil.rmtree(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 + observation_value_list = [] + with open(filename, "w", encoding="utf8") as obs_file: + # Check if obs_position list is a single tuple (i,j,k) + # or a list of tuples of type (i,j,k) + nobs = get_nobs_from_cell_index_list(cell_index_list) + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, cell_index_list) + value = upscaled_values[Iindx, Jindx, Kindx] + observation_value_list.append(value) + 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, + dimensions, + size, + standard_grid_index_origo, + polygon_file_name=None, +): + xsize, ysize, zsize = size + nx, ny, nz = dimensions + if standard_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, + ) + + 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 + + +# pylint: disable=too-many-statements,too-many-branches +def write_localisation_config( + obs_positions: list, + obs_index_list: list, + field_name: str, + corr_ranges: tuple, + azimuth: float, + config_file_name: str = "local_config.yml", + write_scaling: bool = True, + localisation_method: str = "gaussian", + segment_file_name: str = None, + scaling_param_file_name: str = None, +): + space = " " * 2 + space2 = " " * 4 + space3 = " " * 6 + 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_from_position_list(obs_positions) + if nobs != get_nobs_from_cell_index_list(obs_index_list): + raise ValueError( + "Inconsistency between observation list and cell-index_list" + ) + local_method = localisation_method.lower() + if local_method in ["gaussian", "exponential"]: + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, obs_index_list) + obs_name = f"OBS_{Iindx+1}_{Jindx+1}_{Kindx+1}" + pos = obs_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 local_method == "gaussian": + file.write(f"{space3}method: gaussian_decay\n") + else: + file.write(f"{space3}method: exponential_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") + + if local_method == "constant": + # Constant scaling factor, use only one correlation group + file.write(f"{space}- name: CORR\n") + file.write(f"{space2}obs_group:\n") + file.write(f"{space3}add: [ ") + obs_list = "" + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, obs_index_list) + obs_name = f' "OBS_{Iindx+1}_{Jindx+1}_{Kindx+1}" ' + obs_list += obs_name + if obs_number < (nobs - 1): + obs_list += ", " + else: + obs_list += " ]" + file.write(obs_list) + file.write("\n") + pos = obs_positions[0] + file.write(f"{space2}param_group:\n") + file.write(f'{space3}add: ["{field_name}"]\n') + file.write(f"{space2}field_scale:\n") + file.write(f"{space3}method: constant\n") + file.write(f"{space3}value: 1.0\n") + + if local_method == "region": + # Use region parameter with one obs per region + if segment_file_name is None or len(segment_file_name) == 0: + raise ValueError("Missing segment file name when using region") + + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, obs_index_list) + obs_name = f"OBS_{Iindx+1}_{Jindx+1}_{Kindx+1}" + pos = obs_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") + file.write(f"{space3}method: segment\n") + file.write(f'{space3}segment_filename: "{segment_file_name}"\n') + file.write(f'{space3}param_name: "Region"\n') + file.write(f"{space3}active_segments: [ {obs_number + 1} ]\n") + file.write(f"{space3}scalingfactors: [ 1.0 ]\n") + file.write(f"{space3}smooth_ranges: [ 1, 1 ]\n") + + if local_method == "scaling_file": + # Use a scaling factor from file + file.write(f"{space}- name: CORR\n") + file.write(f"{space2}obs_group:\n") + file.write(f"{space3}add: [ ") + obs_list = "" + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, obs_index_list) + obs_name = f' "OBS_{Iindx+1}_{Jindx+1}_{Kindx+1}" ' + obs_list += obs_name + if obs_number < (nobs - 1): + obs_list += ", " + else: + obs_list += " ]" + file.write(obs_list) + file.write("\n") + pos = obs_positions[0] + file.write(f"{space2}param_group:\n") + file.write(f'{space3}add: ["{field_name}"]\n') + file.write(f"{space2}field_scale:\n") + file.write(f"{space3}method: from_file\n") + file.write(f'{space3}filename: "{scaling_param_file_name}"\n') + file.write(f'{space3}param_name: "SCALING"\n') + + +def generate_seed_file( + file_name: str, + start_seed: int = 9828862224, + number_of_seeds: int = 1000, +): + print(f"Generate random seed file: {file_name}") + random.seed(start_seed) + with open(file_name, "w", encoding="utf8") as file: + for _ in range(number_of_seeds): + file.write(f"{random.randint(1, 999999999)}\n") + + +def generate_segments( + polygon_file_name: str, + region_file_name: str, + grid_object, +): + if polygon_file_name is None or not os.path.exists(polygon_file_name): + raise ValueError( + f"Missing polygon file {polygon_file_name} when creating region parameter" + ) + dimensions = grid_object.dimensions + nx = dimensions[0] + ny = dimensions[1] + nz = dimensions[2] + codenames_dict = { + 1: "RegionA", + 2: "RegionB", + 3: "RegionC", + } + region_object = xtgeo.GridProperty( + ncol=nx, + nrow=ny, + nlay=nz, + name="Region", + discrete=True, + values=np.zeros((nx, ny, nz), dtype=np.int32), + codes=codenames_dict, + grid=grid_object, + ) + + print(f"Use polygon file {polygon_file_name} to create region parameter ") + polygon_object = xtgeo.polygons_from_file(polygon_file_name, fformat="xyz") + for poly_id in [0, 1, 2]: + wpoly = polygon_object.copy() + wpoly.dataframe = wpoly.dataframe[wpoly.dataframe.POLY_ID == poly_id] + region_object.set_inside(wpoly, poly_id + 1) + + print(f"Write region parameter: {region_file_name} ") + region_object.to_file(region_file_name, fformat="grdecl") + + +def create_ert_config_file( + template_file_name: str, + case_name: str, + ensemble_seed_file_name: str, + nreal: int, + ert_start_seed: int, + response_file_name_prefix: str, + grid_file_name: str, + upscaled_grid_file_name: str, + initial_field_param_file_prefix: str, + updated_field_param_file_prefix: str, + field_file_format: str, + use_localisation: bool, + output_config_file_name: str = "sim_field.ert", +) -> None: + try: + with open(template_file_name, "r", encoding="utf-8") as file: + lines = file.readlines() + except IOError: + raise IOError(f"Cannot open and read file: {template_file_name}") + + load_workflow = "LOAD_WORKFLOW localisation.wf LOCALISATION_WORKFLOW" + hook_workflow = "HOOK_WORKFLOW LOCALISATION_WORKFLOW PRE_FIRST_UPDATE" + local = "_local" if use_localisation else "" + + strings_to_replace_dict = { + "CASE_NAME": "sim_field_" + case_name + local, + "ENSEMBLE_SEED_FILE": ensemble_seed_file_name, + "NREAL": str(nreal), + "ERT_START_SEED": str(ert_start_seed), + "RESPONSE_FILE_PREFIX": response_file_name_prefix, + "GRID_FILE_NAME": grid_file_name, + "GRID_FILE_NAME_UPSCALED": upscaled_grid_file_name, + "INITIAL_FIELDPARAM_FILE_NAME": initial_field_param_file_prefix + + "." + + field_file_format.lower(), + "UPDATED_FIELDPARAM_FILE_NAME": updated_field_param_file_prefix + + "." + + field_file_format.lower(), + "LOAD_LOCALISATION_WORKFLOW": load_workflow + if use_localisation + else "-- " + load_workflow, + "HOOK_LOCALISATION_WORKFLOW": hook_workflow + if use_localisation + else "-- " + hook_workflow, + } + template_file_contents = Template("".join(lines)) + updated_contents = template_file_contents.safe_substitute(strings_to_replace_dict) + + if use_localisation: + print(f"Write ERT config file with localisation: {output_config_file_name}") + else: + print(f"Write ERT config file: {output_config_file_name}") + with open(output_config_file_name, "w", encoding="utf-8") as file: + file.write(updated_contents) + + +def initialize_case(settings): + # Create seed file + generate_seed_file(settings.field.seed_file) + + # Create grid for the field parameter + grid_object = create_grid( + settings.field.grid_file_name, + settings.field.grid_dimension, + settings.model_size.size, + settings.model_size.use_eclipse_grid_index_origo, + settings.model_size.polygon_file, + ) + + # Create coarse grid to be used in QC of upscaled field parameter + create_grid( + settings.response.grid_file_name, + settings.response.grid_dimension, + settings.model_size.size, + settings.model_size.use_eclipse_grid_index_origo, + settings.model_size.polygon_file, + ) + + 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 + iteration = 0 + upscaled_values = generate_field_and_upscale( + real_number, + iteration, + settings.field.seed_file, + settings.field.algorithm, + settings.field.name, + settings.field.initial_file_name_prefix, + settings.field.file_format, + settings.field.grid_dimension, + settings.model_size.size, + settings.field.variogram, + settings.field.correlation_range, + settings.field.correlation_azimuth, + settings.field.correlation_dip, + settings.field.correlation_exponent, + settings.field.trend_use, + settings.field.trend_params, + settings.field.trend_relstd, + settings.response.name, + settings.response.response_function, + settings.response.upscaled_file_name, + settings.response.grid_dimension, + settings.response.write_upscaled_field, + settings.model_size.use_eclipse_grid_index_origo, + ) + + # Create observations by extracting from existing upscaled field + print( + "Selected grid cells having observations: " + f"{settings.observation.selected_grid_cells}" + ) + write_gen_obs( + upscaled_values, + settings.observation.directory, + settings.observation.file_name, + settings.observation.data_dir, + settings.observation.selected_grid_cells, + settings.observation.rel_error, + settings.observation.min_abs_error, + ) + + # 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, + upscaled_field_name=settings.observation.reference_field_name, + selected_cell_index_list=settings.observation.selected_grid_cells, + file_format=settings.field.file_format, + ) + + # Write file for non-adaptive localisation using distance based localisation + write_localisation_config( + settings.observation.obs_positions, + settings.observation.selected_grid_cells, + settings.field.name, + settings.field.correlation_range, + settings.field.correlation_azimuth, + config_file_name="local_config.yml", + write_scaling=True, + localisation_method=settings.localisation.method, + segment_file_name=settings.localisation.region_file, + scaling_param_file_name=settings.localisation.scaling_file, + ) + + if settings.localisation.method == "region": + generate_segments( + settings.localisation.region_polygons, + settings.localisation.region_file, + grid_object, + ) + + create_ert_config_file( + settings.response.ert_config_template_file, + settings.case_name, + settings.field.seed_file, + 10, + 59716487, + settings.response.gen_data_file_prefix, + settings.field.grid_file_name, + settings.response.grid_file_name, + settings.field.initial_file_name_prefix, + settings.field.updated_file_name_prefix, + settings.field.file_format, + settings.localisation.use_localisation, + settings.response.ert_config_file, + ) + + +def example_cases(name): + """ + Define the different cases here. + They define how to modify default settings + for the varios cases to test. + """ + if name == "A": + params = { + "case_name": "A", + "model_size": { + "use_eclipse_grid_index_origo": True, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD_UPSCALED.EGRID", + }, + "observation": { + "obs_positions": [ + [750.0, 750.0, 25.0], + [250.0, 1750.0, 25.0], + [250.0, 250.0, 25.0], + ], + }, + "localisation": { + "use_localisation": True, + }, + } + elif name == "B": + params = { + "case_name": "B", + "model_size": { + "use_eclipse_grid_index_origo": True, + }, + "field": { + "file_format": "GRDECL", + "grid_file_name": "GRID_STANDARD.EGRID", + }, + "response": { + "file_format": "GRDECL", + "grid_file_name": "GRID_STANDARD_UPSCALED.EGRID", + }, + "observation": { + "obs_positions": [[750.0, 750.0, 25.0], [250.0, 1750.0, 25.0]], + }, + "localisation": { + "use_localisation": True, + }, + } + elif name == "C": + params = { + "case_name": "C", + "model_size": { + "use_eclipse_grid_index_origo": False, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_RMS_ORIGO.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_RMS_ORIGO_UPSCALED.EGRID", + }, + "observation": { + "obs_positions": [[750.0, 750.0, 25.0], [250.0, 1750.0, 25.0]], + }, + "localisation": { + "use_localisation": True, + }, + } + elif name == "A2": + params = { + "case_name": "A2", + "model_size": { + "use_eclipse_grid_index_origo": True, + "polygon_file": "init_files/polygons.txt", + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_WITH_ACTNUM.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "UpscaleGrid.EGRID", + }, + "observation": { + "obs_positions": [[750.0, 750.0, 25.0], [250.0, 1750.0, 25.0]], + }, + "localisation": { + "use_localisation": True, + }, + } + elif name == "D": + params = { + "case_name": "D", + "model_size": { + "use_eclipse_grid_index_origo": True, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD_UPSCALED.EGRID", + }, + "localisation": { + "method": "constant", + "use_localisation": True, + }, + "observation": { + "obs_positions": [[750.0, 750.0, 25.0], [250.0, 1750.0, 25.0]], + }, + } + elif name == "E": + params = { + "case_name": "E", + "model_size": { + "use_eclipse_grid_index_origo": True, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD_UPSCALED.EGRID", + }, + "localisation": { + "method": "region", + "region_polygons": "init_files/region_polygons.txt", + "region_file": "regions.grdecl", + "use_localisation": True, + }, + "observation": { + "obs_positions": [[450.0, 1750.0, 25.0], [250.0, 250.0, 25.0]], + }, + } + elif name == "F": + params = { + "case_name": "F", + "model_size": { + "use_eclipse_grid_index_origo": True, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_STANDARD_UPSCALED.EGRID", + }, + "localisation": { + "method": "scaling_file", + "scaling_file": "init_files/scaling_factor.grdecl", + "use_localisation": True, + }, + "observation": { + "obs_positions": [[650.0, 850.0, 25.0]], + }, + } + elif name == "G": + params = { + "case_name": "G", + "model_size": { + "use_eclipse_grid_index_origo": False, + "polygon_file": None, + }, + "field": { + "file_format": "ROFF", + "grid_file_name": "GRID_RMS_ORIGO.EGRID", + }, + "response": { + "file_format": "ROFF", + "grid_file_name": "GRID_RMS_ORIGO_UPSCALED.EGRID", + }, + "localisation": { + "method": "scaling_file", + "scaling_file": "init_files/scaling_factor_rms_origo.grdecl", + "use_localisation": True, + }, + "observation": { + "obs_positions": [[650.0, 850.0, 25.0]], + }, + } + return params diff --git a/tests/workflows/localisation/example_case/scripts/make_reference_data.py b/tests/workflows/localisation/example_case/scripts/make_reference_data.py new file mode 100755 index 000000000..cfd701531 --- /dev/null +++ b/tests/workflows/localisation/example_case/scripts/make_reference_data.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +""" +This script can be used to create reference data for the pytest test_full.py +It uses the same configurations, the same code and random seed and run ERT +for each case using localisation. Note that each time the reference data +(GRDECL files ofr one selected realization) need to be updated, they must +be quality checked that they are correct. Visualize them , compare runs +with and without localisation to check the differences. +""" +# pylint: disable=import-error,missing-function-docstring,redefined-outer-name + +import copy +import subprocess +import yaml +from common_functions import ( + Settings, + initialize_case, + example_cases, +) + + +def example_config(case_name, use_localisation): + settings = Settings() + settings.reset_to_default() + new_settings = example_cases(case_name) + settings.update(new_settings) + + updated_settings = copy.deepcopy(settings) + updated_settings.localisation.use_localisation = use_localisation + + # Write yml file for the sim_fields.py script + main_settings_dict = updated_settings.to_dict() + with open("example_config.yml", "w", encoding="utf-8") as file: + file.write( + yaml.safe_dump(main_settings_dict, indent=4, default_flow_style=False) + ) + return updated_settings + + +def run_case(settings, select_real=5, select_iter=1): + initialize_case(settings) + # Run case in ERT + print("Run ERT") + case_name = settings.case_name + use_localisation = settings.localisation.use_localisation + local = "_local" if use_localisation else "" + command = [ + "ert", + "ensemble_smoother", + "--target-case", + f"case_{case_name}{local}", + "sim_field.ert", + ] + subprocess.run(command, check=True) + + grid_file_name = settings.field.grid_file_name + file_format = settings.field.file_format.lower() + # Select one of the realizations for the initial and updated + # ensemble as a reference for each case. + # Convert the files to GRDECL format. If the cases have + # generated correct results, save the references + # to git as reference data for the test_full.py pytest script. + print("Convert reference file to GRDECL format") + command = [ + "cp", + f"simulations/sim_field_{case_name}{local}/" + f"realization-{select_real}/iter-0/init_files/FieldParam.{file_format}", + f"init_files/FieldParam_real{select_real}_iter0_{case_name}{local}." + f"{file_format}", + ] + subprocess.run(command, check=True) + + command = [ + "cp", + f"simulations/sim_field_{case_name}{local}/" + f"realization-{select_real}/iter-{select_iter}/FieldParam.{file_format}", + f"init_files/FieldParam_real{select_real}_iter{select_iter}_{case_name}{local}." + f"{file_format}", + ] + subprocess.run(command, check=True) + + command = [ + "./scripts/roff_to_grdecl.py", + f"init_files/FieldParam_real{select_real}_iter0_{case_name}{local}." + f"{file_format}", + f"init_files/FieldParam_real{select_real}_iter0_{case_name}{local}.grdecl", + f"{grid_file_name}", + ] + subprocess.run(command, check=True) + + command = [ + "./scripts/roff_to_grdecl.py", + f"init_files/FieldParam_real{select_real}_iter{select_iter}_{case_name}{local}." + f"{file_format}", + f"init_files/FieldParam_real{select_real}_iter{select_iter}_{case_name}{local}." + "grdecl", + f"{grid_file_name}", + ] + subprocess.run(command, check=True) + + +if __name__ == "__main__": + # Realisation number selected to be used as reference realisation + SELECT_REAL = 5 + # Use ensemble smoother + SELECT_ITER = 1 + for case_name in ["A", "B", "C", "D", "E", "F", "G", "A2"]: + print(f"Case: {case_name}") + # Make the file example_config.yml to be used in the ERT + # forward model sim_field.py + settings_with_localisation = example_config(case_name, use_localisation=True) + settings_without_localisation = example_config( + case_name, use_localisation=False + ) + + # Initialize the case: + # - create seed file, + # - create grids, + # - simulate one unconditioned realization, + # - calculate response, + # - extract synthetic observations from response, + # - create localisation config file, (local_config.yml) + # - create ert config file (sim_field.ert) + # - prepare region parameter for case using regions + + print("Run without localisation") + run_case( + settings_without_localisation, + select_real=SELECT_REAL, + select_iter=SELECT_ITER, + ) + + print("\nRun with localisation") + run_case( + settings_with_localisation, + select_real=SELECT_REAL, + select_iter=SELECT_ITER, + ) diff --git a/tests/workflows/localisation/example_case/scripts/roff_to_grdecl.py b/tests/workflows/localisation/example_case/scripts/roff_to_grdecl.py new file mode 100755 index 000000000..a79b0e3ee --- /dev/null +++ b/tests/workflows/localisation/example_case/scripts/roff_to_grdecl.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +""" +Script converting a grid parameter file from ROFF to GRDECL +""" + +import sys +from pathlib import PurePath + +import xtgeo + + +def main(argv): + """ + Convert a grid parameter file from ROFF to GRDECL + and can also take as input a GRDECL file and write + to another GRDECL file with fixed format + """ + input_file = argv[1] + output_file = argv[2] + grid_file = argv[3] + param_name = "FIELDPAR" + grid_obj = xtgeo.grid_from_file(grid_file, fformat="egrid") + # Check extension to find input format + suffix = PurePath(input_file).suffix + if suffix.upper() == ".ROFF": + print(f"Read file: {input_file} in ROFF format") + field_obj = xtgeo.gridproperty_from_file( + input_file, fformat="roff", name=param_name, grid=grid_obj + ) + field_obj.mask_undef() + print(f"Write file: {output_file} in GRDECL format") + field_obj.to_file(output_file, fformat="grdecl", fmt="%20.6f") + elif suffix.upper() == ".GRDECL": + # Ensure the grdecl file use a fixed format for the values + # to more easily compare it with a reference + print(f"Read file: {input_file} in GRDECL format") + field_obj = xtgeo.gridproperty_from_file( + input_file, fformat="grdecl", name=param_name, grid=grid_obj + ) + field_obj.mask_undef() + print(f"Write file: {output_file} in GRDECL format") + field_obj.to_file(output_file, fformat="grdecl", fmt="%20.6f") + + +if __name__ == "__main__": + args = sys.argv + if len(args) < 4: + print( + "Usage: roff_to_grdecl.py " + " " + ) + else: + main(args) diff --git a/tests/workflows/localisation/example_case/scripts/sim_fields.py b/tests/workflows/localisation/example_case/scripts/sim_fields.py new file mode 100755 index 000000000..dbdf2885b --- /dev/null +++ b/tests/workflows/localisation/example_case/scripts/sim_fields.py @@ -0,0 +1,209 @@ +#!/usr/bin/env python +""" +Script used as forward model in ERT to test localisation. +""" +import os +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_from_cell_index_list, + read_config_file, + read_field_from_file, + read_obs_field_from_file, + read_observations, + read_upscaled_field_from_file, + upscaling, + write_obs_pred_diff_field, +) + + +def write_prediction_gen_data( + upscaled_values, cell_indx_list: list, response_file_name_prefix: str +): + """ + Write GEN_DATA file with predicted values of observables (selected upscaled values) + """ + print(response_file_name_prefix) + response_file_name = response_file_name_prefix + "_0.txt" + 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_from_cell_index_list(cell_indx_list) + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, cell_indx_list) + value = upscaled_values[Iindx, Jindx, Kindx] + file.write(f"{value}\n") + + +# pylint: disable=too-many-arguments,too-many-locals +def write_obs_and_predictions( + config_path: str, + upscaled_values, + cell_index_list: list, + observation_dir: str, + obs_data_dir: str, + predicted_obs_file_name: str = "obs_and_prediction.txt", +): + obs_values = read_observations( + config_path, observation_dir, obs_data_dir, cell_index_list + ) + nobs = get_nobs_from_cell_index_list(cell_index_list) + filename = config_path + "/" + predicted_obs_file_name + print(f"Write file: {filename}") + with open(predicted_obs_file_name, "w", encoding="utf-8") as file: + file.write(" Cell_index Obs_value Predicted_obs_value Difference\n") + for obs_number in range(nobs): + (Iindx, Jindx, Kindx) = get_cell_indices(obs_number, cell_index_list) + predicted_obs_values = upscaled_values[Iindx, Jindx, Kindx] + obs_value = obs_values[obs_number] + diff_obs_pred = obs_value - predicted_obs_values + file.write( + f"({Iindx+1}, {Jindx+1}, {Kindx + 1}) " + f"{obs_value:10.5f} {predicted_obs_values:10.5f} " + f"{diff_obs_pred:10.5f} \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] + + config_path = argv[4] + return iteration, real_number, config_file_name, config_path + + +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, + config_path, + ) = get_iteration_real_number_config_file(args) + settings = read_config_file(config_file_name) + + print(f"Config path: {config_path}") + if iteration == 0: + print(f"Generate new field parameter realization:{real_number} ") + # Simulate field (with trend) + upscaled_values = generate_field_and_upscale( + real_number, + iteration, + os.path.join(config_path, settings.field.seed_file), + settings.field.algorithm, + settings.field.name, + settings.field.initial_file_name_prefix, + settings.field.file_format, + settings.field.grid_dimension, + settings.model_size.size, + settings.field.variogram, + settings.field.correlation_range, + settings.field.correlation_azimuth, + settings.field.correlation_dip, + settings.field.correlation_exponent, + settings.field.trend_use, + settings.field.trend_params, + settings.field.trend_relstd, + settings.response.name, + settings.response.response_function, + settings.response.upscaled_file_name, + settings.response.grid_dimension, + settings.response.write_upscaled_field, + settings.model_size.use_eclipse_grid_index_origo, + ) + + else: + print(f"Import updated field parameter realization: {real_number} ") + field_object = read_field_from_file( + settings.field.updated_file_name_prefix, + settings.field.name, + settings.field.file_format, + settings.field.grid_file_name, + ) + field_values = field_object.values + + # Calculate upscaled values for selected coarse grid cells + upscaled_values = upscaling( + field_values, + settings.response.response_function, + settings.response.file_format, + settings.response.name, + settings.response.write_upscaled_field, + settings.response.upscaled_file_name, + settings.response.grid_dimension, + iteration=iteration, + ) + # Write GEN_DATA file + write_prediction_gen_data( + upscaled_values, + settings.observation.selected_grid_cells, + settings.response.gen_data_file_prefix, + ) + + # 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( + settings.response.file_format, + os.path.join(config_path, settings.observation.reference_param_file), + settings.response.grid_file_name, + os.path.join(config_path, settings.observation.reference_field_name), + ) + upscaled_field_object = read_upscaled_field_from_file( + iteration, + settings.response.upscaled_file_name, + settings.response.file_format, + settings.response.name, + settings.response.grid_file_name, + ) + write_obs_pred_diff_field( + upscaled_field_object, obs_field_object, settings.field.file_format + ) + + write_obs_and_predictions( + config_path, + upscaled_values, + settings.observation.selected_grid_cells, + settings.observation.directory, + settings.observation.data_dir, + ) + + +if __name__ == "__main__": + # Command line arguments are iteration real_number test_case_config_file + main(sys.argv) diff --git a/tests/workflows/localisation/example_case/test_full.py b/tests/workflows/localisation/example_case/test_full.py new file mode 100644 index 000000000..aa13b3398 --- /dev/null +++ b/tests/workflows/localisation/example_case/test_full.py @@ -0,0 +1,267 @@ +""" +Test of full workflow using non-adaptive localisation +- Gaussian fields are simulated +- Response variables are upscaled values of simulated gaussian fields +- Some selected positions within the upscaled grid are used to extract + synthetic observations. +- Localisation config file is generated. +- Running ERT using the generated localisation file. +- The ERT forward model (simulating and upscaling gaussian fields + is done by the script 'sim_fields.py') +- For iteration > 0, the updated field parameter is imported from ERT + and upscaled. Predictions of observed values are extracted and + saved to ERT using GEN_DATA keyword. +- The final intial and updated ensemble is used when comparing with + reference values for the field. One selected realization is used + when comparing ERT result with reference result. +- The test depends on test example configurations saved in yml file. + Parameters in this test example configuration is modified by the test functions. +- Reference case realisations are created previously and are data checked + into git as ascii grdecl files. +- Any changes in test example configuration may require a separate file for + the reference file in GRDECL format. +- The reference case when replaced must be visualized ot QC the reference. +""" +import shutil +from argparse import ArgumentParser +from pathlib import Path +from typing import Any, Dict + +import numpy as np +import pytest +import xtgeo +import yaml +from ert import LibresFacade +from ert.__main__ import ert_parser +from ert.cli import ENSEMBLE_SMOOTHER_MODE +from ert.cli.main import run_cli +from ert.shared.plugins.plugin_manager import ErtPluginContext +from ert.storage import open_storage + +from scripts.common_functions import ( + Settings, + initialize_case, + example_cases, +) + +# pylint: disable=invalid-name +# pylint: disable=too-many-locals +# pylint: disable=too-many-arguments +# pylint: disable=missing-function-docstring +# pylint: disable=too-many-statements + + +@pytest.mark.parametrize( + "new_settings", + [ + pytest.param(example_cases("A")), + pytest.param(example_cases("B")), + pytest.param(example_cases("C")), + pytest.param(example_cases("A2")), + pytest.param(example_cases("D")), + pytest.param(example_cases("E")), + pytest.param(example_cases("F")), + pytest.param(example_cases("G")), + ], +) +# pylint: disable=too-many-branches +def test_that_localization_works_with_different_settings( + tmp_path: Path, monkeypatch: pytest.MonkeyPatch, new_settings: Dict[str, Any] +): + monkeypatch.chdir(tmp_path) + print(f"Setup test case on tmp_path: {tmp_path}") + settings = Settings() + settings.reset_to_default() + settings.update(new_settings) + + # Write yml file for the sim_fields.py script + main_settings_dict = settings.to_dict() + with open("example_config.yml", "w", encoding="utf-8") as file: + file.write( + yaml.safe_dump(main_settings_dict, indent=4, default_flow_style=False) + ) + + (tmp_path / "init_files").mkdir() + (tmp_path / "reference_files").mkdir() + + # Make available data to generate grid, region parameters and scaling factor + polygon_file = None + if settings.case_name == "A2": + polygon_file = "init_files/polygons.txt" + shutil.copy( + Path(__file__).parent / settings.model_size.polygon_file, + polygon_file, + ) + + if settings.case_name == "E": + region_polygon_file = "init_files/region_polygons.txt" + shutil.copy( + Path(__file__).parent / settings.localisation.region_polygons, + region_polygon_file, + ) + + if settings.case_name == "F": + scaling_factor_param_file = "init_files/scaling_factor.grdecl" + shutil.copy( + Path(__file__).parent / settings.localisation.scaling_file, + scaling_factor_param_file, + ) + + if settings.case_name == "G": + scaling_factor_param_file = "init_files/scaling_factor_rms_origo.grdecl" + shutil.copy( + Path(__file__).parent / settings.localisation.scaling_file, + scaling_factor_param_file, + ) + + # Make ERT template file available + ert_config_template_file = "init_files/sim_field_template.ert" + shutil.copy( + Path(__file__).parent / settings.response.ert_config_template_file, + ert_config_template_file, + ) + + initialize_case(settings) + + parser = ArgumentParser(prog="test_main") + if settings.case_name == "A": + reference_file_initial = "FieldParam_real5_iter0_A_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_A_local.grdecl" + grid_file_name = "GRID_STANDARD.EGRID" + elif settings.case_name == "B": + reference_file_initial = "FieldParam_real5_iter0_A_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_A_local.grdecl" + grid_file_name = "GRID_STANDARD.EGRID" + elif settings.case_name == "C": + reference_file_initial = "FieldParam_real5_iter0_C_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_C_local.grdecl" + grid_file_name = "GRID_RMS_ORIGO.EGRID" + elif settings.case_name == "A2": + reference_file_initial = "FieldParam_real5_iter0_A2_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_A2_local.grdecl" + grid_file_name = "GRID_WITH_ACTNUM.EGRID" + elif settings.case_name == "D": + # Scaling factor =1 and one correlation group + # The result should be identical to not running localisation like + # case A without localisation + reference_file_initial = "FieldParam_real5_iter0_D.grdecl" + reference_file_updated = "FieldParam_real5_iter1_D.grdecl" + grid_file_name = "GRID_STANDARD.EGRID" + elif settings.case_name == "E": + reference_file_initial = "FieldParam_real5_iter0_E_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_E_local.grdecl" + grid_file_name = "GRID_STANDARD.EGRID" + elif settings.case_name == "F": + reference_file_initial = "FieldParam_real5_iter0_F_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_F_local.grdecl" + grid_file_name = "GRID_STANDARD.EGRID" + elif settings.case_name == "G": + reference_file_initial = "FieldParam_real5_iter0_G_local.grdecl" + reference_file_updated = "FieldParam_real5_iter1_G_local.grdecl" + grid_file_name = "GRID_RMS_ORIGO.EGRID" + + reference_path_initial = "reference_files/" + reference_file_initial + reference_path_updated = "reference_files/" + reference_file_updated + shutil.copy( + Path(__file__).parent / "init_files" / reference_file_initial, + reference_path_initial, + ) + shutil.copy( + Path(__file__).parent / "init_files" / reference_file_updated, + reference_path_updated, + ) + shutil.copy(Path(__file__).parent / "localisation.wf", "localisation.wf") + Path("scripts").mkdir(parents=True, exist_ok=True) + shutil.copy( + Path(__file__).parent / "scripts" / "FM_SIM_FIELD", "scripts/FM_SIM_FIELD" + ) + shutil.copy( + Path(__file__).parent / "scripts" / "sim_fields.py", "scripts/sim_fields.py" + ) + shutil.copy( + Path(__file__).parent / "scripts" / "common_functions.py", + "scripts/common_functions.py", + ) + ert_config_file = settings.response.ert_config_file + parsed = ert_parser( + parser, + [ + ENSEMBLE_SMOOTHER_MODE, + "--current-case", + "es_prior", + "--target-case", + "es_posterior", + ert_config_file, + ], + ) + with ErtPluginContext() as _: + run_cli(parsed) + + facade = LibresFacade.from_config_file(ert_config_file) + + grid_file = xtgeo.grid_from_file(grid_file_name, fformat="egrid") + es_prior_expected = xtgeo.gridproperty_from_file( + reference_path_initial, + fformat="grdecl", + name="FIELDPAR", + grid=grid_file, + ) + es_prior_expected.mask_undef() + es_posterior_expected = xtgeo.gridproperty_from_file( + reference_path_updated, + fformat="grdecl", + name="FIELDPAR", + grid=grid_file, + ) + es_posterior_expected.mask_undef() + dims = es_prior_expected.dimensions + with open_storage(facade.enspath) as storage: + realization = 5 + es_prior = storage.get_ensemble_by_name("es_prior") + es_prior_xdata = es_prior.load_parameters("FIELDPAR").sel( + realizations=realization + ) + es_prior_values_from_storage = es_prior_xdata["values"].values + + es_posterior = storage.get_ensemble_by_name("es_posterior") + es_posterior_xdata = es_posterior.load_parameters("FIELDPAR").sel( + realizations=realization + ) + es_posterior_values_from_storage = es_posterior_xdata["values"].values + + # Write to file for easier QC of differences + es_prior_from_storage = xtgeo.GridProperty( + ncol=dims[0], + nrow=dims[1], + nlay=dims[2], + name="prior_storage", + values=es_prior_values_from_storage, + ) + es_prior_from_storage.mask_undef() + es_prior_from_storage.to_file("prior_storage.roff", fformat="roff") + + # Write to file for easier QC of differences + es_posterior_from_storage = xtgeo.GridProperty( + ncol=dims[0], + nrow=dims[1], + nlay=dims[2], + name="posterior_storage", + values=es_posterior_values_from_storage, + ) + es_posterior_from_storage.mask_undef() + es_posterior_from_storage.to_file("posterior_storage.roff", fformat="roff") + + # Check with reference + assert np.allclose( + es_prior_expected.values3d, + np.round(es_prior_values_from_storage, 4), + atol=1e-4, + equal_nan=True, + ) + + assert np.allclose( + es_posterior_expected.values3d, + np.round(es_posterior_values_from_storage, 4), + atol=1e-4, + equal_nan=True, + )