diff --git a/src/ert/resources/forward_models/run_reservoirsimulator.py b/src/ert/resources/forward_models/run_reservoirsimulator.py index 8bbdc18adee..cc4c812d611 100755 --- a/src/ert/resources/forward_models/run_reservoirsimulator.py +++ b/src/ert/resources/forward_models/run_reservoirsimulator.py @@ -127,7 +127,10 @@ class RunReservoirSimulator: Will initiate a limited number of reruns if license errors are detected, also in coupled simulations (not relevant for Flow) - PRT/ECLEND files are checked for errors, and exceptions will be raised. + By default, the class will check PRT/ECLEND files for errors after the run, and + raise exceptions accordingly. + + For eclrun, the request to do summary_conversion can be forwarded. """ def __init__( @@ -195,7 +198,6 @@ def eclrun_command(self) -> list[str]: self.data_file, "--summary-conversion", "yes" if self.summary_conversion else "no", - # "-np", self.num_cpu # eclrun detects automatically ] @property @@ -214,25 +216,6 @@ def flowrun_command(self) -> list[str]: str(self.num_cpu), ] - def run_flow(self) -> None: - return_code = subprocess.run(self.flowrun_command, check=False).returncode - OK_file = self.run_path / f"{self.base_name}.OK" - if not self.check_status: - OK_file.write_text( - "FLOW simulation complete - NOT checked for errors.", - encoding="utf-8", - ) - else: - if return_code != 0: - raise subprocess.CalledProcessError(return_code, self.flowrun_command) - self.assertECLEND() - if self.num_cpu > 1: - smry_file = find_unsmry(self.run_path / self.base_name) - if smry_file is not None: - await_completed_unsmry_file(smry_file) - - OK_file.write_text("FLOW simulation OK", encoding="utf-8") - LICENSE_FAILURE_RETRY_INITIAL_SLEEP = 90 LICENSE_RETRY_STAGGER_FACTOR = 60 LICENSE_RETRY_BACKOFF_EXPONENT = 3 @@ -258,7 +241,7 @@ def run_eclipseX00( if return_code != 0: raise subprocess.CalledProcessError(return_code, self.eclrun_command) try: - self.assertECLEND() + self.assert_eclend() except EclError as err: if err.failed_due_to_license_problems() and retries_left > 0: time_to_wait = backoff_sleep + int( @@ -285,11 +268,30 @@ def run_eclipseX00( OK_file.write_text("ECLIPSE simulation OK", encoding="utf-8") - def assertECLEND(self) -> None: + def run_flow(self) -> None: + return_code = subprocess.run(self.flowrun_command, check=False).returncode + OK_file = self.run_path / f"{self.base_name}.OK" + if not self.check_status: + OK_file.write_text( + "FLOW simulation complete - NOT checked for errors.", + encoding="utf-8", + ) + else: + if return_code != 0: + raise subprocess.CalledProcessError(return_code, self.flowrun_command) + self.assert_eclend() + if self.num_cpu > 1: + smry_file = find_unsmry(self.run_path / self.base_name) + if smry_file is not None: + await_completed_unsmry_file(smry_file) + + OK_file.write_text("FLOW simulation OK", encoding="utf-8") + + def assert_eclend(self) -> None: tail_length = 5000 - result = self.readECLEND() + result = self.read_eclend() if result.errors > 0: - error_list = self.parseErrors() + error_list = self.parse_errors() sep = "\n\n...\n\n" error_and_slave_msg = sep.join(error_list) extra_message = "" @@ -311,7 +313,7 @@ def assertECLEND(self) -> None: if result.bugs > 0: raise EclError(f"Eclipse simulation failed with:{result.bugs:d} bugs") - def readECLEND(self) -> EclipseResult: + def read_eclend(self) -> EclipseResult: error_regexp = re.compile(r"^\s*Errors\s+(\d+)\s*$") bug_regexp = re.compile(r"^\s*Bugs\s+(\d+)\s*$") @@ -337,14 +339,14 @@ def readECLEND(self) -> EclipseResult: return EclipseResult(errors=errors, bugs=bugs) - def parseErrors(self) -> list[str]: + def parse_errors(self) -> list[str]: """Extract multiline ERROR messages from the PRT file""" error_list = [] error_e100_regexp = re.compile(error_pattern_e100, re.MULTILINE) error_e300_regexp = re.compile(error_pattern_e300, re.MULTILINE) slave_started_regexp = re.compile(slave_started_pattern, re.MULTILINE) - with open(self.prt_path, encoding="utf-8") as filehandle: - content = filehandle.read() + + content = self.prt_path.read_text(encoding="utf-8") for regexp in [error_e100_regexp, error_e300_regexp, slave_started_regexp]: offset = 0 diff --git a/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py b/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py index 1c7447d7de0..a093ca1bb1d 100644 --- a/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py +++ b/tests/ert/unit_tests/resources/test_run_eclipse_simulator.py @@ -61,7 +61,7 @@ def test_ecl100_binary_can_produce_output(source_root): assert ok_path.exists() assert prt_path.stat().st_size > 0 - assert len(erun.parseErrors()) == 0 + assert len(erun.parse_errors()) == 0 assert not Path("SPE1.h5").exists(), "HDF conversion should not be run by default" @@ -87,7 +87,7 @@ def test_ecl100_binary_can_handle_extra_dots_in_casename(source_root): assert ok_path.exists() assert prt_path.stat().st_size > 0 - assert len(erun.parseErrors()) == 0 + assert len(erun.parse_errors()) == 0 @pytest.mark.integration_test @@ -421,7 +421,7 @@ def test_ecl100_license_error_is_caught(): "eclipse", "dummyversion", "FOO.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert exception_info.value.failed_due_to_license_problems() @@ -451,7 +451,7 @@ def test_ecl100_crash_is_not_mistaken_as_license_trouble(): "eclipse", "dummyversion", "FOO.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert not exception_info.value.failed_due_to_license_problems() @@ -489,7 +489,7 @@ def test_ecl300_license_error_is_caught(): "e300", "dummyversion", "FOO.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert exception_info.value.failed_due_to_license_problems() @@ -524,7 +524,7 @@ def test_ecl300_crash_is_not_mistaken_as_license_trouble(): "e300", "dummyversion", "FOO.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert not exception_info.value.failed_due_to_license_problems() @@ -587,7 +587,7 @@ def test_license_error_in_slave_is_caught(): "eclipse", "dummyversion", "EIGHTCELLS_MASTER.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert exception_info.value.failed_due_to_license_problems() @@ -639,7 +639,7 @@ def test_crash_in_slave_is_not_mistaken_as_license(): "eclipse", "dummyversion", "EIGHTCELLS_MASTER.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert not exception_info.value.failed_due_to_license_problems() @@ -666,7 +666,7 @@ def test_too_few_parsed_error_messages_gives_warning(): "eclipse", "dummyversion", "ECLCASE.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert "Warning, mismatch between stated Error count" in str(exception_info.value) @@ -699,7 +699,7 @@ def test_tail_of_prt_file_is_included_when_error_count_inconsistency(): "eclipse", "dummyversion", "ECLCASE.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert "this_should_be_included" in str(exception_info.value) assert "this_should_not_be_included" not in str(exception_info.value) @@ -727,7 +727,7 @@ def test_correct_number_of_parsed_error_messages_gives_no_warning(): "eclipse", "dummyversion", "ECLCASE.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert "Warning, mismatch between stated Error count" not in str( exception_info.value ) @@ -761,7 +761,7 @@ def test_slave_started_message_are_not_counted_as_errors(): "eclipse", "dummyversion", "ECLCASE.DATA" ) with pytest.raises(run_reservoirsimulator.EclError) as exception_info: - run.assertECLEND() + run.assert_eclend() assert "Warning, mismatch between stated Error count" not in str( exception_info.value ) @@ -833,5 +833,5 @@ def test_can_parse_errors(prt_error, expected_error_list): run = run_reservoirsimulator.RunReservoirSimulator( "eclipse", "dummyversion", "ECLCASE.DATA" ) - error_list = run.parseErrors() + error_list = run.parse_errors() assert error_list == expected_error_list