From 0774438a2001706e8bebc34b2828604fa0c905a3 Mon Sep 17 00:00:00 2001 From: Dan Sava Date: Wed, 2 Oct 2024 07:04:20 +0200 Subject: [PATCH] Raise warning when summary key and no simulator job present in ert config --- src/ert/config/summary_config.py | 20 ++++-- .../ert/snake_oil_field/snake_oil_surface.ert | 4 +- .../ert/unit_tests/config/test_ert_config.py | 62 +++++++++++++++++++ 3 files changed, 79 insertions(+), 7 deletions(-) diff --git a/src/ert/config/summary_config.py b/src/ert/config/summary_config.py index bcd08a37bc8..9aeb037dd30 100644 --- a/src/ert/config/summary_config.py +++ b/src/ert/config/summary_config.py @@ -3,14 +3,14 @@ import logging from dataclasses import dataclass from datetime import datetime -from typing import TYPE_CHECKING, Optional, Set, Union +from typing import TYPE_CHECKING, Optional, Set, Union, no_type_check import xarray as xr from ._read_summary import read_summary from .ensemble_config import Refcase from .parsing import ConfigDict, ConfigKeys -from .parsing.config_errors import ConfigValidationError +from .parsing.config_errors import ConfigValidationError, ConfigWarning from .response_config import ResponseConfig from .responses_index import responses_index @@ -57,17 +57,27 @@ def read_from_file(self, run_path: str, iens: int) -> xr.Dataset: def response_type(self) -> str: return "summary" + @no_type_check @classmethod def from_config_dict(cls, config_dict: ConfigDict) -> Optional[SummaryConfig]: refcase = Refcase.from_config_dict(config_dict) - if summary_keys := config_dict.get(ConfigKeys.SUMMARY, []): # type: ignore - eclbase: Optional[str] = config_dict.get("ECLBASE") # type: ignore + if summary_keys := config_dict.get(ConfigKeys.SUMMARY, []): + eclbase: Optional[str] = config_dict.get("ECLBASE") if eclbase is None: raise ConfigValidationError( "In order to use summary responses, ECLBASE has to be set." ) time_map = set(refcase.dates) if refcase is not None else None - + forward_model = config_dict.get(ConfigKeys.FORWARD_MODEL, []) + names = [fm_step[0] for fm_step in forward_model] + simulation_step_exists = any( + any(sim in _name.lower() for sim in ["eclipse", "flow"]) + for _name in names + ) + if not simulation_step_exists: + ConfigWarning.warn( + "Config contains a SUMMARY key but no forward model steps known to generate a summary file" + ) return cls( name="summary", input_files=[eclbase.replace("%d", "")], diff --git a/test-data/ert/snake_oil_field/snake_oil_surface.ert b/test-data/ert/snake_oil_field/snake_oil_surface.ert index aa4177bfb23..9f5d339b42a 100644 --- a/test-data/ert/snake_oil_field/snake_oil_surface.ert +++ b/test-data/ert/snake_oil_field/snake_oil_surface.ert @@ -22,11 +22,11 @@ REFCASE refcase/SNAKE_OIL_FIELD TIME_MAP refcase/time_map.txt OBS_CONFIG observations/observations.txt -INSTALL_JOB SNAKE_OIL_SIMULATOR jobs/SNAKE_OIL_SIMULATOR +INSTALL_JOB SNAKE_OIL_ECLIPSE_SIMULATOR jobs/SNAKE_OIL_SIMULATOR INSTALL_JOB SNAKE_OIL_NPV jobs/SNAKE_OIL_NPV INSTALL_JOB SNAKE_OIL_DIFF jobs/SNAKE_OIL_DIFF -FORWARD_MODEL SNAKE_OIL_SIMULATOR +FORWARD_MODEL SNAKE_OIL_ECLIPSE_SIMULATOR FORWARD_MODEL SNAKE_OIL_NPV FORWARD_MODEL SNAKE_OIL_DIFF diff --git a/tests/ert/unit_tests/config/test_ert_config.py b/tests/ert/unit_tests/config/test_ert_config.py index 8da0cca6511..c711883d38c 100644 --- a/tests/ert/unit_tests/config/test_ert_config.py +++ b/tests/ert/unit_tests/config/test_ert_config.py @@ -1609,3 +1609,65 @@ def test_general_option_in_local_config_has_priority_over_site_config(): assert config.queue_config.max_running == 13 assert config.queue_config.submit_sleep == 14 assert config.queue_config.queue_system == QueueSystem.TORQUE + + +@pytest.mark.usefixtures("use_tmpdir") +def test_warning_raised_when_summary_key_and_no_simulation_job_present(caplog, recwarn): + caplog.set_level(logging.WARNING) + + with open("job_file", "w", encoding="utf-8") as fout: + fout.write("EXECUTABLE echo\nARGLIST \n") + + with open("config_file.ert", "w", encoding="utf-8") as fout: + # Write a minimal config file + fout.write("NUM_REALIZATIONS 1\n") + fout.write("SUMMARY *\n") + fout.write("ECLBASE RESULT_SUMMARY\n") + + fout.write("INSTALL_JOB job_name job_file\n") + fout.write( + "FORWARD_MODEL job_name(=A/, =/x)\n" + ) + + ErtConfig.from_file("config_file.ert") + + # Check no warning is logged when config contains + # forward model step with and as arguments + assert not caplog.text + assert len(recwarn) == 1 + assert issubclass(recwarn[0].category, ConfigWarning) + assert ( + recwarn[0].message.info.message + == "Config contains a SUMMARY key but no forward model steps known to generate a summary file" + ) + + +@pytest.mark.parametrize( + "job_name", ["eclipse", "eclipse100", "flow", "FLOW", "ECLIPSE100"] +) +@pytest.mark.usefixtures("use_tmpdir") +def test_no_warning_when_summary_key_and_simulation_job_present( + caplog, recwarn, job_name +): + caplog.set_level(logging.WARNING) + + with open("job_file", "w", encoding="utf-8") as fout: + fout.write("EXECUTABLE echo\nARGLIST \n") + + with open("config_file.ert", "w", encoding="utf-8") as fout: + # Write a minimal config file + fout.write("NUM_REALIZATIONS 1\n") + fout.write("SUMMARY *\n") + fout.write("ECLBASE RESULT_SUMMARY\n") + + fout.write(f"INSTALL_JOB {job_name} job_file\n") + fout.write( + f"FORWARD_MODEL {job_name}(=A/, =/x)\n" + ) + + ErtConfig.from_file("config_file.ert") + + # Check no warning is logged when config contains + # forward model step with and as arguments + assert not caplog.text + assert len(recwarn) == 0