Skip to content

Commit

Permalink
Fix: retrieve the last structure even if the calculation has failed.
Browse files Browse the repository at this point in the history
  • Loading branch information
yakutovicha committed Jan 31, 2024
1 parent 979c619 commit 867b4de
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 38 deletions.
59 changes: 26 additions & 33 deletions aiida_cp2k/parsers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,47 +6,41 @@
###############################################################################
"""AiiDA-CP2K output parser."""

from aiida.common import exceptions
from aiida.engine import ExitCode
from aiida.orm import Dict
import ase
from aiida import common, engine, orm, parsers, plugins

# +
from aiida.parsers import Parser
from aiida.plugins import DataFactory
from .. import utils

from aiida_cp2k import utils
StructureData = plugins.DataFactory("core.structure")
BandsData = plugins.DataFactory("core.array.bands")

# -

StructureData = DataFactory("core.structure")
BandsData = DataFactory("core.array.bands")


class Cp2kBaseParser(Parser):
class Cp2kBaseParser(parsers.Parser):
"""Basic AiiDA parser for the output of CP2K."""

def parse(self, **kwargs):
"""Receives in input a dictionary of retrieved nodes. Does all the logic here."""

try:
_ = self.retrieved
except exceptions.NotExistent:
except common.NotExistent:
return self.exit_codes.ERROR_NO_RETRIEVED_FOLDER

exit_code = self._parse_stdout()
if exit_code is not None:
return exit_code

# Even though the simpulation might have failed, we still want to parse the output structure.
try:
returned = self._parse_trajectory()
if isinstance(returned, StructureData):
self.out("output_structure", returned)
else: # in case this is an error code
return returned
except exceptions.NotExistent:
pass
last_structure = self._parse_final_structure()
if isinstance(last_structure, StructureData):
self.out("output_structure", last_structure)
except common.NotExistent:
self.logger.warning("No Restart file found in the retrieved folder.")

return ExitCode(0)
if exit_code is not None:
return exit_code
if isinstance(last_structure, engine.ExitCode):
return last_structure
return engine.ExitCode(0)

def _parse_stdout(self):
"""Basic CP2K output file parser."""
Expand All @@ -63,19 +57,16 @@ def _parse_stdout(self):

# Parse the standard output.
result_dict = utils.parse_cp2k_output(output_string)
self.out("output_parameters", Dict(dict=result_dict))
self.out("output_parameters", orm.Dict(dict=result_dict))
return None

def _parse_trajectory(self):
def _parse_final_structure(self):
"""CP2K trajectory parser."""

from ase import Atoms

fname = self.node.process_class._DEFAULT_RESTART_FILE_NAME

# Check if the restart file is present.
if fname not in self.retrieved.base.repository.list_object_names():
raise exceptions.NotExistent(
raise common.NotExistent(
"No restart file available, so the output trajectory can't be extracted"
)

Expand All @@ -85,7 +76,9 @@ def _parse_trajectory(self):
except OSError:
return self.exit_codes.ERROR_OUTPUT_STDOUT_READ

return StructureData(ase=Atoms(**utils.parse_cp2k_trajectory(output_string)))
return StructureData(
ase=ase.Atoms(**utils.parse_cp2k_trajectory(output_string))
)

def _check_stdout_for_errors(self, output_string):
"""This function checks the CP2K output file for some basic errors."""
Expand Down Expand Up @@ -169,7 +162,7 @@ def _parse_stdout(self):
)
self.out("output_bands", bnds)

self.out("output_parameters", Dict(dict=result_dict))
self.out("output_parameters", orm.Dict(dict=result_dict))
return None


Expand Down Expand Up @@ -208,5 +201,5 @@ def _parse_stdout(self):
except KeyError:
pass

self.out("output_parameters", Dict(dict=result_dict))
self.out("output_parameters", orm.Dict(dict=result_dict))
return None
7 changes: 2 additions & 5 deletions aiida_cp2k/utils/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import math
import re

import numpy as np


def parse_cp2k_output(fstring):
"""Parse CP2K output into a dictionary."""
Expand Down Expand Up @@ -323,8 +325,6 @@ def _parse_bands_cp2k_greater_81(lines, line_n):
def _parse_bands(lines, n_start, cp2k_version):
"""Parse band structure from the CP2K output."""

import numpy as np

kpoints = []
labels = []
bands_s1 = []
Expand Down Expand Up @@ -377,9 +377,6 @@ def _parse_bands(lines, n_start, cp2k_version):

def parse_cp2k_trajectory(content):
"""CP2K trajectory parser."""

import numpy as np

# Parse coordinate section
match = re.search(r"\n\s*&COORD\n(.*?)\n\s*&END COORD\n", content, re.DOTALL)
coord_lines = [line.strip().split() for line in match.group(1).splitlines()]
Expand Down

0 comments on commit 867b4de

Please sign in to comment.