Skip to content

Commit

Permalink
Adding check for the raw calculation to see if lammps has exited with…
Browse files Browse the repository at this point in the history
… an error (#90)

* Adding check for the raw calculation to see if lammps has exited with an error. Addresses #87

* Adding a test for the parsing of files when lammps exits with an error.

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

---------

Co-authored-by: Jonathan Chico <jonathan.chico@sandvik.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 28, 2023
1 parent 12a4c95 commit 0affc72
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 21 deletions.
2 changes: 1 addition & 1 deletion aiida_lammps/calculations/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions aiida_lammps/calculations/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
7 changes: 3 additions & 4 deletions aiida_lammps/parsers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
)

Expand Down Expand Up @@ -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:
Expand Down
9 changes: 9 additions & 0 deletions aiida_lammps/parsers/raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down
19 changes: 6 additions & 13 deletions conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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],
Expand All @@ -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],
Expand All @@ -826,7 +821,6 @@ def _get_structure_data(pkey):
fractional = True

elif pkey == "GaN":

cell = [
[3.1900000572, 0, 0],
[-1.5950000286, 2.762621076, 0],
Expand All @@ -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],
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down
3 changes: 3 additions & 0 deletions tests/parsers/fixtures/base/error/lammps.out
Original file line number Diff line number Diff line change
@@ -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
3 changes: 3 additions & 0 deletions tests/parsers/fixtures/raw/error/lammps.out
Original file line number Diff line number Diff line change
@@ -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
14 changes: 14 additions & 0 deletions tests/parsers/test_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()})
6 changes: 6 additions & 0 deletions tests/parsers/test_raw/test_raw_parser_error.yml
Original file line number Diff line number Diff line change
@@ -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: []
6 changes: 3 additions & 3 deletions tests/test_calculations.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions tests/test_parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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()})
6 changes: 6 additions & 0 deletions tests/test_parsers/test_base_parser_error.yml
Original file line number Diff line number Diff line change
@@ -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: []

0 comments on commit 0affc72

Please sign in to comment.