diff --git a/aiida_lammps/calculations/base.py b/aiida_lammps/calculations/base.py index 81ee22e8..25f520ea 100644 --- a/aiida_lammps/calculations/base.py +++ b/aiida_lammps/calculations/base.py @@ -198,7 +198,7 @@ def define(cls, spec): spec.exit_code( 309, "ERROR_PARSER_DETECTED_LAMMPS_RUN_ERROR", - message="The parser detected the lampps error :{error}", + message="The parser detected the lammps error :{error}", ) spec.exit_code( 400, diff --git a/aiida_lammps/calculations/raw.py b/aiida_lammps/calculations/raw.py index 32046517..73bb4302 100644 --- a/aiida_lammps/calculations/raw.py +++ b/aiida_lammps/calculations/raw.py @@ -49,6 +49,11 @@ def define(cls, spec): required=True, help="The data extracted from the lammps out file", ) + spec.exit_code( + 309, + "ERROR_PARSER_DETECTED_LAMMPS_RUN_ERROR", + message="The parser detected the lammps error :{error}", + ) spec.exit_code( 351, "ERROR_OUTFILE_MISSING", diff --git a/aiida_lammps/parsers/base.py b/aiida_lammps/parsers/base.py index d2283f3a..adfd17a4 100644 --- a/aiida_lammps/parsers/base.py +++ b/aiida_lammps/parsers/base.py @@ -58,7 +58,6 @@ def parse(self, **kwargs): return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER list_of_files = out_folder.base.repository.list_object_names() - # Check the output file outputfile_filename = self.node.get_option("output_filename") if outputfile_filename not in list_of_files: @@ -70,9 +69,11 @@ def parse(self, **kwargs): ) if parsed_data["global"]["errors"]: + # Output the data for checking what was parsed + self.out("results", orm.Dict({"compute_variables": parsed_data["global"]})) for entry in parsed_data["global"]["errors"]: self.logger.error(f"LAMMPS emitted the error {entry}") - return self.exit_codes.ERROR_PARSER_DECTECTED_LAMMPS_RUN_ERROR.format( + return self.exit_codes.ERROR_PARSER_DETECTED_LAMMPS_RUN_ERROR.format( error=entry ) @@ -223,11 +224,9 @@ def parse_restartfile( and not restart_found and temp_folder ): - restartfiles = glob.glob(f"{temp_folder}/{input_restart_filename}*") if restartfiles: - _files = [] for entry in restartfiles: try: diff --git a/aiida_lammps/parsers/raw.py b/aiida_lammps/parsers/raw.py index 58dc7b02..a384f00f 100644 --- a/aiida_lammps/parsers/raw.py +++ b/aiida_lammps/parsers/raw.py @@ -26,6 +26,15 @@ def parse(self, **kwargs): if parsed_data is None: return self.exit_codes.ERROR_PARSING_OUTFILE + if parsed_data["global"]["errors"]: + # Output the data for checking what was parsed + self.out("results", orm.Dict({"compute_variables": parsed_data["global"]})) + for entry in parsed_data["global"]["errors"]: + self.logger.error(f"LAMMPS emitted the error {entry}") + return self.exit_codes.ERROR_PARSER_DETECTED_LAMMPS_RUN_ERROR.format( + error=entry + ) + global_data = parsed_data["global"] results = {"compute_variables": global_data} diff --git a/conftest.py b/conftest.py index b74c0cca..52b40345 100644 --- a/conftest.py +++ b/conftest.py @@ -9,7 +9,7 @@ import pathlib import shutil import tempfile -from typing import Any +from typing import Any, Optional from aiida import orm from aiida.common import AttributeDict, CalcInfo, LinkType, exceptions @@ -86,7 +86,6 @@ def fixture_code(fixture_localhost): """Return an ``InstalledCode`` instance configured to run calculations of given entry point on localhost.""" def _fixture_code(entry_point_name): - label = f"test.{entry_point_name}" try: @@ -637,12 +636,11 @@ def _generate_calc_job_node( if test_name is not None: basepath = os.path.dirname(os.path.abspath(__file__)) filepath_folder = os.path.join(TEST_DIR, test_name) - entry_point = format_entry_point_string("aiida.calculations", entry_point_name) node = orm.CalcJobNode(computer=computer, process_type=entry_point) node.base.attributes.set("input_filename", "input.in") - node.base.attributes.set("output_filename", "lammps_output") + node.base.attributes.set("output_filename", "lammps.out") node.set_option("resources", {"num_machines": 1, "num_mpiprocs_per_machine": 1}) node.set_option("max_wallclock_seconds", 1800) node.set_metadata_inputs( @@ -683,7 +681,6 @@ def _generate_calc_job_node( if filepath_folder: retrieved = orm.FolderData() retrieved.base.repository.put_object_from_tree(filepath_folder) - # Remove files that are supposed to be only present in the retrieved temporary folder if retrieve_temporary: for filename in filenames: @@ -793,7 +790,6 @@ def get_structure_data(): def _get_structure_data(pkey): """return test structure data""" if pkey == "Fe": - cell = [ [2.848116, 0.000000, 0.000000], [0.000000, 2.848116, 0.000000], @@ -810,7 +806,6 @@ def _get_structure_data(pkey): names = ["Fe1", "Fe2"] elif pkey == "Ar": - cell = [ [3.987594, 0.000000, 0.000000], [-1.993797, 3.453358, 0.000000], @@ -826,7 +821,6 @@ def _get_structure_data(pkey): fractional = True elif pkey == "GaN": - cell = [ [3.1900000572, 0, 0], [-1.5950000286, 2.762621076, 0], @@ -844,7 +838,6 @@ def _get_structure_data(pkey): symbols = names = ["Ga", "Ga", "N", "N"] elif pkey == "pyrite": - cell = [ [5.38, 0.000000, 0.000000], [0.000000, 5.38, 0.000000], @@ -1038,7 +1031,7 @@ def generate_singlefile_data(): def _generate_singlefile_data( computer: orm.Computer, label: str = "restartfile", - entry_point_name: str = None, + entry_point_name: str | None = None, ): entry_point = format_entry_point_string("aiida.calculations", entry_point_name) @@ -1067,7 +1060,7 @@ def generate_lammps_trajectory(): def _generate_lammps_trajectory( computer: orm.Computer, label: str = "trajectory", - entry_point_name: str = None, + entry_point_name: str | None = None, ): entry_point = format_entry_point_string("aiida.calculations", entry_point_name) @@ -1098,8 +1091,8 @@ def generate_lammps_results(): def _generate_lammps_results( computer: orm.Computer, label: str = "results", - entry_point_name: str = None, - data: dict = None, + entry_point_name: str | None = None, + data: dict | None = None, ): entry_point = format_entry_point_string("aiida.calculations", entry_point_name) diff --git a/tests/parsers/fixtures/base/error/lammps.out b/tests/parsers/fixtures/base/error/lammps.out new file mode 100644 index 00000000..cffe9d81 --- /dev/null +++ b/tests/parsers/fixtures/base/error/lammps.out @@ -0,0 +1,3 @@ +LAMMPS (23 Jun 2022 - Update 1) +ERROR: Cannot open file data.rhodo: No such file or directory (src/read_data.cpp:331) +Last command: read_data data.rhodo diff --git a/tests/parsers/fixtures/raw/error/lammps.out b/tests/parsers/fixtures/raw/error/lammps.out new file mode 100644 index 00000000..cffe9d81 --- /dev/null +++ b/tests/parsers/fixtures/raw/error/lammps.out @@ -0,0 +1,3 @@ +LAMMPS (23 Jun 2022 - Update 1) +ERROR: Cannot open file data.rhodo: No such file or directory (src/read_data.cpp:331) +Last command: read_data data.rhodo diff --git a/tests/parsers/test_raw.py b/tests/parsers/test_raw.py index 049ecdf8..16a3bd3a 100644 --- a/tests/parsers/test_raw.py +++ b/tests/parsers/test_raw.py @@ -31,3 +31,17 @@ def test_alt_timing_info(generate_calc_job_node, data_regression, fixture_localh assert calcfunction.is_finished, calcfunction.exception assert calcfunction.is_finished_ok, calcfunction.exit_message data_regression.check({"results": results["results"].get_dict()}) + + +def test_raw_parser_error(generate_calc_job_node, data_regression, fixture_localhost): + """Test the parser when an error is found in the output file.""" + node = generate_calc_job_node( + computer=fixture_localhost, + entry_point_name="lammps.raw", + test_name="parsers/fixtures/raw/error", + ) + parser = ParserFactory("lammps.raw") + results, calcfunction = parser.parse_from_node(node, store_provenance=False) + assert calcfunction.is_finished, calcfunction.exception + assert calcfunction.exit_status == 309, calcfunction.exit_message + data_regression.check({"results": results["results"].get_dict()}) diff --git a/tests/parsers/test_raw/test_raw_parser_error.yml b/tests/parsers/test_raw/test_raw_parser_error.yml new file mode 100644 index 00000000..f0c941cb --- /dev/null +++ b/tests/parsers/test_raw/test_raw_parser_error.yml @@ -0,0 +1,6 @@ +results: + compute_variables: + errors: + - command: 'Last command: read_data data.rhodo' + message: 'ERROR: Cannot open file data.rhodo: No such file or directory (src/read_data.cpp:331)' + warnings: [] diff --git a/tests/test_calculations.py b/tests/test_calculations.py index 40d40f91..c3d400f5 100644 --- a/tests/test_calculations.py +++ b/tests/test_calculations.py @@ -232,13 +232,13 @@ def test_lammps_restart_generation( else: # Check that if the file was not asked to be stored that it is not stored assert ( - not "restartfile" in results + "restartfile" not in results ), "The restartfile is stored even when it was not requested" if restart_parameters.restart.get("print_final", False): _msg = "The restartfile is in the retrieved folder even when it was not requested" assert ( - not node.get_option("restart_filename") - in results["retrieved"].base.repository.list_object_names() + node.get_option("restart_filename") + not in results["retrieved"].base.repository.list_object_names() ), _msg # Check that the final restartfile is printed diff --git a/tests/test_parsers.py b/tests/test_parsers.py index 5e2acf83..74d073ac 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -3,6 +3,8 @@ """ import os +from aiida.plugins import ParserFactory + from aiida_lammps.parsers.parse_raw import parse_final_data, parse_outputfile from .utils import TEST_DIR @@ -39,3 +41,17 @@ def test_parse_final_variables(): assert "final_step" in parsed_data, "no step information present" assert "final_etotal" in parsed_data, "no total energy information present" + + +def test_base_parser_error(generate_calc_job_node, data_regression, fixture_localhost): + """Test the parser when an error is found in the output file.""" + node = generate_calc_job_node( + computer=fixture_localhost, + entry_point_name="lammps.base", + test_name="parsers/fixtures/base/error", + ) + parser = ParserFactory("lammps.base") + results, calcfunction = parser.parse_from_node(node, store_provenance=False) + assert calcfunction.is_finished, calcfunction.exception + assert calcfunction.exit_status == 309, calcfunction.exit_message + data_regression.check({"results": results["results"].get_dict()}) diff --git a/tests/test_parsers/test_base_parser_error.yml b/tests/test_parsers/test_base_parser_error.yml new file mode 100644 index 00000000..f0c941cb --- /dev/null +++ b/tests/test_parsers/test_base_parser_error.yml @@ -0,0 +1,6 @@ +results: + compute_variables: + errors: + - command: 'Last command: read_data data.rhodo' + message: 'ERROR: Cannot open file data.rhodo: No such file or directory (src/read_data.cpp:331)' + warnings: []