Source code for aiida_orca.workchains.base

# -*- coding: utf-8 -*-
"""Base work chain to run an ORCA calculation"""

from aiida.common import AttributeDict
from aiida.engine import BaseRestartWorkChain, ProcessHandlerReport, process_handler, while_
from aiida.plugins import CalculationFactory

OrcaCalculation = CalculationFactory('orca.orca')


[docs]class OrcaBaseWorkChain(BaseRestartWorkChain): """Workchain to run a orca calculation with automated error handling and restarts.""" _process_class = OrcaCalculation
[docs] @classmethod def define(cls, spec): super().define(spec) spec.expose_inputs(OrcaCalculation, namespace='orca') spec.outline( cls.setup, while_(cls.should_run_process)( cls.run_process, cls.inspect_process, ), cls.results, ) spec.expose_outputs(OrcaCalculation) spec.exit_code( 300, 'ERROR_UNKNOWN_UNRECOVERABLE_FAILURE', message='The calculation failed with an unidentified unrecoverable error.' ) spec.exit_code( 301, 'ERROR_AIIDA_ORCA_UNRECOVERABLE_FAILURE', message='The calculation failed with an unrecoverable error coming from aiida-orca.' )
[docs] def setup(self): """Call the `setup` of the `BaseRestartWorkChain` and then create the inputs dictionary in `self.ctx.inputs`. This `self.ctx.inputs` dictionary will be used by the `BaseRestartWorkChain` to submit the calculations in the internal loop.""" super().setup() self.ctx.inputs = AttributeDict(self.exposed_inputs(OrcaCalculation, 'orca'))
[docs] def report_error_handled(self, calculation, action): """Report an action taken for a calculation that has failed. This should be called in a registered error handler if its condition is met and an action was taken. :param calculation: the failed calculation node :param action: a string message with the action taken""" self.report( f'{calculation.process_label}<{calculation.pk}> failed with exit status ' f'{calculation.exit_status}: {calculation.exit_message}' ) self.report(f'Action taken: {action}')
[docs] @process_handler() def handle_known_unrecoverable_failure(self, calculation): """Handle exit status between 300-399. These errors should come from aiida-orca plugin and are not recoverable. """ if calculation.is_failed and calculation.exit_status < 400 and calculation.exit_status > 299: self.report_error_handled(calculation, 'unrecoverable aiida-orca error, aborting...') return ProcessHandlerReport(True, self.exit_codes.ERROR_AIIDA_ORCA_UNRECOVERABLE_FAILURE) # pylint: disable=no-member
[docs] @process_handler() def handle_unknown_unrecoverable_failure(self, calculation): """Handle exit status between 1-299 These errors come from outside of aiida-orca plugin. For now we suppose that all of these are unrecoverable. """ if calculation.is_failed and calculation.exit_status < 300: self.report_error_handled(calculation, 'unknown unrecoverable error, aborting...') return ProcessHandlerReport(True, self.exit_codes.ERROR_UNKNOWN_UNRECOVERABLE_FAILURE) # pylint: disable=no-member