Skip to content

Commit 080a47f

Browse files
authored
💥🔄 Add EpwBaseWorkChain and refactor EPW workflows
Large refactoring of the `aiida-epw` plugin package. The main changes are the addition of a new `EpwBaseWorkChain` for error recovery and renaming `EpwWorkChain` to `EpwPrepWorkChain` to better clarify its purpose. Additional changes: - Expose EpwCalculation inputs in EpwBaseWorkChain for better flexibility - Add comprehensive input validation for k/q-point compatibility - `EpwCalculation`: Add `parent_folder_chk` input for Wannier90 checkpoint files - `EpwCalculation`: Add `w90_chk_to_ukk_script` input for chk→ukk conversion - `EpwCalculation`: Implement validation for `wannierize` parameter compatibility - `EpwCalculation`: Add `nstemp` parameter bounds checking with `_MAX_NSTEMP` limit - `EpwCalculation`: Support copying .chk, .bvec, and .mmn files from parent folders Bug fixes: - Update entry points from `quantumespresso.*` to `epw.*` namespace - Add workflow entry points for `epw.base`, `epw.epw`, and `epw.supercon` - Fix parser import path from `aiida_quantumespresso` to `aiida_epw` - Add empty `parsers/__init__.py` for proper package structure Minor additions: - Add `dev/` directory to .gitignore - Add `tools/kpoints.py` with `check_kpoints_qpoints_compatibility()` function - Add `bcs_gap_function()` to `tools/calculators.py` for BCS gap calculations
1 parent db2ad99 commit 080a47f

File tree

15 files changed

+790
-199
lines changed

15 files changed

+790
-199
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,3 +208,5 @@ __marimo__/
208208

209209
# MyST documentation build
210210
docs/_build
211+
212+
dev/

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,15 @@ dependencies = [
3131
Source = "https://github.com/aiidaplugins/aiida-epw"
3232

3333
[project.entry-points.'aiida.calculations']
34-
'quantumespresso.epw' = 'aiida_quantumespresso.calculations.epw:EpwCalculation'
34+
'epw.epw' = 'aiida_epw.calculations.epw:EpwCalculation'
3535

3636
[project.entry-points.'aiida.parsers']
37-
'quantumespresso.epw' = 'aiida_quantumespresso.parsers.epw:EpwParser'
37+
'epw.epw' = 'aiida_epw.parsers.epw:EpwParser'
3838

39+
[project.entry-points.'aiida.workflows']
40+
'epw.base' = 'aiida_epw.workflows.base:EpwBaseWorkChain'
41+
'epw.epw_prep' = 'aiida_epw.workflows.prep:EpwPrepWorkChain'
42+
'epw.supercon' = 'aiida_epw.workflows.supercon:SuperConWorkChain'
3943

4044
[tool.hatch.version]
4145
path = "src/aiida_epw/__about__.py"

src/aiida_epw/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
"""AiiDA plugin package for interfacing with the Electron Phonon Wannier (EPW) code."""
2+
3+
__version__ = '0.1.0'

src/aiida_epw/calculations/epw.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,11 +57,22 @@ def define(cls, spec):
5757
spec.input('settings', valid_type=orm.Dict, required=False, help='')
5858
spec.input('parent_folder_nscf', required=False, valid_type=orm.RemoteData,
5959
help='the folder of a completed nscf `PwCalculation`')
60+
spec.input('parent_folder_chk', required=False, valid_type=orm.RemoteData,
61+
help='the folder of a completed wannier90 `Wannier90Calculation`')
6062
spec.input('parent_folder_ph', required=False, valid_type=orm.RemoteData,
6163
help='the folder of a completed `PhCalculation`')
6264
spec.input('parent_folder_epw', required=False, valid_type=(orm.RemoteData, orm.RemoteStashFolderData),
6365
help='folder that contains all files required to restart an `EpwCalculation`')
64-
spec.inputs['metadata']['options']['parser_name'].default = 'quantumespresso.epw'
66+
spec.input(
67+
'w90_chk_to_ukk_script',
68+
valid_type=orm.RemoteData,
69+
required=False,
70+
help=(
71+
"The script to convert the chk file to a ukk file"
72+
)
73+
)
74+
75+
spec.inputs['metadata']['options']['parser_name'].default = 'epw.epw'
6576

6677
spec.output('output_parameters', valid_type=orm.Dict,
6778
help='The `output_parameters` output node of the successful calculation.')
@@ -131,6 +142,28 @@ def test_offset(offset):
131142
Path(parent_folder_nscf.get_remote_path(), PwCalculation._OUTPUT_SUBFOLDER).as_posix(),
132143
self._OUTPUT_SUBFOLDER,
133144
))
145+
146+
# If parent_folder_chk is provided, we need to copy the .chk, .bvec, and .mmn files to the epw folder.
147+
# We can do symlink for .chk and .bvec. .mmn file is already a symlink as defined in wannier workflow.
148+
# Note that we do some modification to the .mmn file in site so here we rename it to avoid overwriting.
149+
if 'parent_folder_chk' in self.inputs:
150+
parent_folder_chk = self.inputs.parent_folder_chk
151+
152+
for suffix in ['chk', 'bvec']:
153+
remote_list.append(
154+
(
155+
parent_folder_chk.computer.uuid,
156+
Path(parent_folder_chk.get_remote_path(), self._PREFIX + '.' + suffix).as_posix(),
157+
self._PREFIX + '.' + suffix
158+
)
159+
)
160+
remote_list.append(
161+
(
162+
parent_folder_chk.computer.uuid,
163+
Path(parent_folder_chk.get_remote_path(), self._PREFIX + '.mmn').as_posix(),
164+
self._PREFIX + '.wannier90.mmn'
165+
)
166+
)
134167

135168
if 'parent_folder_ph' in self.inputs:
136169
parent_folder_ph = self.inputs.parent_folder_ph
@@ -207,6 +240,21 @@ def test_offset(offset):
207240
remote_list.append(
208241
(parent_folder_epw.computer.uuid, Path(epw_path, filename).as_posix(), Path(filename).as_posix())
209242
)
243+
# check if wannierize is True and if parent_folder_epw or parent_folder_chk is provided
244+
wannierize = parameters['INPUTEPW'].get('wannierize', False)
245+
246+
if wannierize and any(
247+
_ in self.inputs
248+
for _ in ["parent_folder_epw", "parent_folder_chk"]
249+
):
250+
self.report("Should not have a parent folder of epw or chk if wannierize is True")
251+
return self.exit_codes.ERROR_PARAMETERS_NOT_VALID
252+
253+
# check if nstemp is too large
254+
nstemp = parameters['INPUTEPW'].get('nstemp', None)
255+
if nstemp and nstemp > self._MAX_NSTEMP:
256+
self.report(f'nstemp too large, reset it to maximum allowed: {self._MAX_NSTEMP}')
257+
parameters['INPUTEPW']['nstemp'] = self._MAX_NSTEMP
210258

211259
parameters['INPUTEPW']['outdir'] = self._OUTPUT_SUBFOLDER
212260
parameters['INPUTEPW']['dvscf_dir'] = self._FOLDER_SAVE

src/aiida_epw/parsers/__init__.py

Whitespace-only changes.

src/aiida_epw/parsers/epw.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from aiida import orm
44
import numpy
55

6-
from aiida_quantumespresso.calculations.epw import EpwCalculation
6+
from aiida_epw.calculations.epw import EpwCalculation
77
from aiida_quantumespresso.parsers.base import BaseParser
88
from aiida_quantumespresso.utils.mapping import get_logging_container
99

src/aiida_epw/tools/calculators.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,7 @@ def calculate_lambda_omega(frequency: ArrayLike, spectrum: ArrayLike) -> tuple:
2727
omega_log = omega_log * meV_to_Kelvin
2828

2929
return lambda_, omega_log
30+
31+
# This function is taken from https://www.sciencedirect.com/science/article/pii/S0010465516302260 eq.81
32+
def bcs_gap_function(T, Tc, p, Delta_0):
33+
return Delta_0 * numpy.sqrt(1 - (T/Tc)**p)

src/aiida_epw/tools/kpoints.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
def check_kpoints_qpoints_compatibility(
2+
kpoints,
3+
qpoints,
4+
) -> tuple[bool, str ]:
5+
"""Check if the kpoints and qpoints are compatible."""
6+
7+
kpoints_mesh, kpoints_shift = kpoints.get_kpoints_mesh()
8+
qpoints_mesh, qpoints_shift = qpoints.get_kpoints_mesh()
9+
10+
multiplicities = []
11+
remainder = []
12+
13+
for k, q in zip(kpoints_mesh, qpoints_mesh):
14+
multiplicities.append(k // q)
15+
remainder.append(k % q)
16+
17+
if kpoints_shift != [0.0, 0.0, 0.0] or qpoints_shift != [0.0, 0.0, 0.0]:
18+
return (False, "Shift grid is not supported.")
19+
else:
20+
if remainder == [0, 0, 0]:
21+
return (True, f"The kpoints and qpoints are compatible with multiplicities {multiplicities}.")
22+
else:
23+
return (False, "The kpoints and qpoints are not compatible.")
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
"""Workflows for the EPW code."""
2+
from .base import EpwBaseWorkChain
3+
from .prep import EpwPrepWorkChain
4+
from .supercon import SuperConWorkChain
5+
6+
__all__ = [
7+
'EpwBaseWorkChain',
8+
'EpwPrepWorkChain',
9+
'SuperConWorkChain',
10+
]

0 commit comments

Comments
 (0)