Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/aiida_quantumespresso_ph/workflows/dynamical_matrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def define(cls, spec):
required=False,
help='The structure for which the dynamical matrix is computed.'
)
spec.output('pw_output_parameters', valid_type=orm.Dict)
spec.output('pw_output_parameters', valid_type=orm.Dict, required=False)
spec.output('ph_output_parameters', valid_type=orm.Dict)
spec.output('ph_retrieved', valid_type=orm.FolderData)

Expand Down Expand Up @@ -165,7 +165,8 @@ def results(self):
"""Attach the desired output nodes directly as outputs of the workchain."""
self.report('workchain succesfully completed')

self.out('pw_output_parameters', self.ctx.workchain_relax.outputs.output_parameters)
if 'workchain_relax' in self.ctx:
self.out('pw_output_parameters', self.ctx.workchain_relax.outputs.output_parameters)
self.out('ph_output_parameters', self.ctx.workchain_ph.outputs.output_parameters)
self.out('ph_retrieved', self.ctx.workchain_ph.outputs.retrieved)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

from aiida_quantumespresso_ph.calculations.functions.merge_para_ph_outputs import merge_para_ph_outputs


PhBaseWorkChain = WorkflowFactory('quantumespresso.ph.base')
distribute_qpoints = CalculationFactory('quantumespresso_ph.distribute_qpoints')
recollect_qpoints = CalculationFactory('quantumespresso_ph.recollect_qpoints')
Expand Down
9 changes: 8 additions & 1 deletion src/aiida_quantumespresso_ph/workflows/ph_interpolate.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
PhCalculation = CalculationFactory('quantumespresso.ph')



class PhInterpolateWorkChain(WorkChain):
"""Workchain to compute the interpolation steps for a phonon dispersion from the already computed Dyn mat."""

Expand Down Expand Up @@ -75,5 +76,11 @@ def results(self):
"""Run the final step after computing the dispersion steps."""
matdyn_calc = self.ctx.workflow_matdyn

# Output parameters as is
self.out('output_parameters', matdyn_calc.outputs.output_parameters)
self.out('output_phonon_bands', matdyn_calc.outputs.output_phonon_bands)

# Output phonon bands from matdyn calculation
if 'output_phonon_bands' in matdyn_calc.outputs:
self.out('output_phonon_bands', matdyn_calc.outputs.output_phonon_bands)
else:
self.report('Warning: Matdyn calculation did not produce output_phonon_bands.')
61 changes: 61 additions & 0 deletions src/aiida_quantumespresso_ph/workflows/phonon_bands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
from aiida import orm
from aiida.engine import WorkChain, ToContext

from .dynamical_matrix import DynamicalMatrixWorkChain
from .ph_interpolate import PhInterpolateWorkChain

class PhononBandsWorkChain(WorkChain):
"""
WorkChain to compute Phonon Bands starting from a structure.
Wraps DynamicalMatrixWorkChain (SCF + PH) and PhInterpolateWorkChain (Q2R + Matdyn).
"""

@classmethod
def define(cls, spec):
super().define(spec)

# Expose inputs from sub-workchains
spec.expose_inputs(DynamicalMatrixWorkChain, namespace='dynamical_matrix')
spec.expose_inputs(PhInterpolateWorkChain, namespace='interpolate', exclude=('dynmat_folder',))

spec.outline(
cls.run_dynamical_matrix,
cls.run_interpolate,
cls.results,
)

spec.output('output_phonon_bands', valid_type=orm.BandsData)
spec.output('output_parameters', valid_type=orm.Dict)

spec.exit_code(401, 'ERROR_SUB_PROCESS_FAILED_DYNAMICAL_MATRIX', message='The DynamicalMatrixWorkChain sub process failed')
spec.exit_code(402, 'ERROR_SUB_PROCESS_FAILED_INTERPOLATE', message='The PhInterpolateWorkChain sub process failed')

def run_dynamical_matrix(self):
inputs = self.exposed_inputs(DynamicalMatrixWorkChain, namespace='dynamical_matrix')
running = self.submit(DynamicalMatrixWorkChain, **inputs)
self.report(f'Submitted DynamicalMatrixWorkChain<{running.pk}>')
return ToContext(dynamical_matrix=running)

def run_interpolate(self):
dynamical_matrix = self.ctx.dynamical_matrix
if not dynamical_matrix.is_finished_ok:
self.report(f'DynamicalMatrixWorkChain failed with status {dynamical_matrix.exit_status}')
return self.exit_codes.ERROR_SUB_PROCESS_FAILED_DYNAMICAL_MATRIX

inputs = self.exposed_inputs(PhInterpolateWorkChain, namespace='interpolate')
# Connect outputs
inputs['dynmat_folder'] = dynamical_matrix.outputs.ph_retrieved

running = self.submit(PhInterpolateWorkChain, **inputs)
self.report(f'Submitted PhInterpolateWorkChain<{running.pk}>')
return ToContext(interpolate=running)

def results(self):
interpolate = self.ctx.interpolate
if not interpolate.is_finished_ok:
self.report(f'PhInterpolateWorkChain failed with status {interpolate.exit_status}')
return self.exit_codes.ERROR_SUB_PROCESS_FAILED_INTERPOLATE

self.out('output_phonon_bands', interpolate.outputs.output_phonon_bands)
self.out('output_parameters', interpolate.outputs.output_parameters)
self.report('PhononBandsWorkChain finished successfully')