Skip to content

Commit dc3dbbe

Browse files
authored
Update VASP integration for aiida-vasp v5.0 compatibility (#350)
* Compatibility update with aiida-vasp 5.0 * Remove unnecessary DataFactory calls (since the workchain now implements automatic conversion to AiiDA data types) * Update CI to drop support for python 3.9 (aiida-vasp support python >=3.10 only)
1 parent 8a70baf commit dc3dbbe

File tree

7 files changed

+396
-97
lines changed

7 files changed

+396
-97
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434

3535
strategy:
3636
matrix:
37-
python-version: ['3.9', '3.10', '3.11', '3.12']
37+
python-version: ['3.10', '3.11', '3.12']
3838

3939
services:
4040
rabbitmq:
@@ -70,7 +70,7 @@ jobs:
7070

7171
strategy:
7272
matrix:
73-
python-version: ['3.9']
73+
python-version: ['3.10']
7474

7575
steps:
7676
- uses: actions/checkout@v2

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ version: 2
33
build:
44
os: ubuntu-22.04
55
tools:
6-
python: '3.9'
6+
python: '3.10'
77
apt_packages:
88
- gfortran # This is necessary for the `sisl` dependency of `aiida-siesta`
99

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ all_plugins = [
6767
'aiida-orca~=0.6.0',
6868
'aiida-quantumespresso~=4.4',
6969
'aiida-siesta~=2.0',
70-
'aiida-vasp~=3.1',
70+
'aiida-vasp~=5.0',
7171
'aiida-wien2k~=0.2.0',
7272
'masci-tools~=0.9'
7373
]
@@ -118,7 +118,7 @@ tests = [
118118
'pytest-regressions~=1.0'
119119
]
120120
vasp = [
121-
'aiida-vasp~=3.1'
121+
'aiida-vasp~=5.0'
122122
]
123123
wien2k = [
124124
'aiida-wien2k~=0.2.0'

src/aiida_common_workflows/workflows/relax/vasp/generator.py

Lines changed: 57 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
"""Implementation of `aiida_common_workflows.common.relax.generator.CommonRelaxInputGenerator` for VASP."""
2+
3+
import os
24
import pathlib
35
import typing as t
46

@@ -81,16 +83,16 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR091
8183
builder = self.process_class.get_builder()
8284

8385
# Set code
84-
builder.code = engines['relax']['code']
86+
builder.vasp.code = engines['relax']['code']
8587

8688
# Set structure
8789
builder.structure = structure
8890

8991
# Set options
90-
builder.options = plugins.DataFactory('core.dict')(dict=engines['relax']['options'])
92+
builder.vasp.calc.metadata.options = engines['relax']['options']
9193

9294
# Set workchain related inputs, in this case, give more explicit output to report
93-
builder.verbose = plugins.DataFactory('core.bool')(True)
95+
builder.verbose = True
9496

9597
# Fetch initial parameters from the protocol file.
9698
# Here we set the protocols fast, moderate and precise. These currently have no formal meaning.
@@ -115,50 +117,30 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR091
115117
settings.update(
116118
{
117119
'parser_settings': {
118-
'critical_notifications': {
119-
'add_brmix': True,
120-
'add_cnormn': False,
121-
'add_denmp': True,
122-
'add_dentet': True,
123-
'add_edddav_zhegv': True,
124-
'add_eddrmm_zhegv': True,
125-
'add_edwav': True,
126-
'add_fexcp': True,
127-
'add_fock_acc': True,
128-
'add_non_collinear': True,
129-
'add_not_hermitian': True,
130-
'add_pzstein': True,
131-
'add_real_optlay': True,
132-
'add_rhosyg': True,
133-
'add_rspher': True,
134-
'add_set_indpw_full': True,
135-
'add_sgrcon': True,
136-
'add_no_potimm': True,
137-
'add_magmom': True,
138-
'add_bandocc': True,
139-
},
140-
'add_energies': True,
141-
'add_forces': True,
142-
'add_stress': True,
143-
'add_misc': {
144-
'type': 'dict',
145-
'quantities': [
146-
'total_energies',
147-
'maximum_stress',
148-
'maximum_force',
149-
'magnetization',
150-
'notifications',
151-
'run_status',
152-
'run_stats',
153-
'version',
154-
],
155-
'link_name': 'misc',
156-
},
120+
'energy_types': ['energy_extrapolated', 'energy_free', 'energy_no_entropy'],
121+
'critical_notification_errors': [
122+
'brmix',
123+
'edddav',
124+
'eddwav',
125+
'fexcp',
126+
'fock_acc',
127+
'non_collinear',
128+
'not_hermitian',
129+
'pzstein',
130+
'real_optlay',
131+
'rhosyg',
132+
'rspher',
133+
'set_indpw_full',
134+
'sgrcon',
135+
'no_potimm',
136+
'magmom',
137+
'bandocc',
138+
],
157139
'energy_type': ['energy_free', 'energy_no_entropy'],
158140
}
159141
}
160142
)
161-
builder.settings = plugins.DataFactory('core.dict')(dict=settings)
143+
builder.vasp.settings = settings
162144

163145
# Configure the handlers
164146
handler_overrides = {
@@ -169,17 +151,17 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR091
169151
'handler_unfinished_calc_generic': {'enabled': False},
170152
'handler_electronic_conv': {'enabled': False},
171153
}
172-
builder.handler_overrides = plugins.DataFactory('core.dict')(dict=handler_overrides)
154+
builder.vasp.handler_overrides = handler_overrides
173155

174156
# Set the parameters on the builder, put it in the code namespace to pass through
175157
# to the code inputs
176-
builder.parameters = plugins.DataFactory('core.dict')(dict={'incar': parameters_dict})
158+
builder.vasp.parameters = {'incar': parameters_dict}
177159

178160
# Set potentials and their mapping
179-
builder.potential_family = plugins.DataFactory('str')(protocol['potential_family'])
180-
builder.potential_mapping = plugins.DataFactory('core.dict')(
181-
dict=self._potential_mapping[protocol['potential_mapping']]
182-
)
161+
if os.environ.get('PYTEST_CURRENT_TEST') is not None:
162+
builder.vasp._port_namespace['potential_family'].validator = None
163+
builder.vasp.potential_family = protocol['potential_family']
164+
builder.vasp.potential_mapping = self._potential_mapping[protocol['potential_mapping']]
183165

184166
# Set the kpoint grid from the density in the protocol
185167
kpoints = plugins.DataFactory('core.array.kpoints')()
@@ -191,52 +173,51 @@ def _construct_builder(self, **kwargs) -> engine.ProcessBuilder: # noqa: PLR091
191173
)
192174
else:
193175
kpoints.set_kpoints_mesh_from_density(protocol['kpoint_distance'])
194-
builder.kpoints = kpoints
176+
builder.vasp.kpoints = kpoints
195177

196178
# Set the relax parameters
197-
relax = AttributeDict()
179+
relax_settings = AttributeDict()
198180
if relax_type != RelaxType.NONE:
199181
# Perform relaxation of cell or positions
200-
relax.perform = plugins.DataFactory('core.bool')(True)
201-
relax.algo = plugins.DataFactory('str')(protocol['relax']['algo'])
202-
relax.steps = plugins.DataFactory('int')(protocol['relax']['steps'])
182+
relax_settings.perform = True
183+
relax_settings.algo = protocol['relax']['algo']
184+
relax_settings.steps = protocol['relax']['steps']
203185
if relax_type == RelaxType.POSITIONS:
204-
relax.positions = plugins.DataFactory('core.bool')(True)
205-
relax.shape = plugins.DataFactory('core.bool')(False)
206-
relax.volume = plugins.DataFactory('core.bool')(False)
186+
relax_settings.positions = True
187+
relax_settings.shape = False
188+
relax_settings.volume = False
207189
elif relax_type == RelaxType.CELL:
208-
relax.positions = plugins.DataFactory('core.bool')(False)
209-
relax.shape = plugins.DataFactory('core.bool')(True)
210-
relax.volume = plugins.DataFactory('core.bool')(True)
190+
relax_settings.positions = False
191+
relax_settings.shape = True
192+
relax_settings.volume = True
211193
elif relax_type == RelaxType.VOLUME:
212-
relax.positions = plugins.DataFactory('core.bool')(False)
213-
relax.shape = plugins.DataFactory('core.bool')(False)
214-
relax.volume = plugins.DataFactory('core.bool')(True)
194+
relax_settings.positions = False
195+
relax_settings.shape = False
196+
relax_settings.volume = True
215197
elif relax_type == RelaxType.SHAPE:
216-
relax.positions = plugins.DataFactory('core.bool')(False)
217-
relax.shape = plugins.DataFactory('core.bool')(True)
218-
relax.volume = plugins.DataFactory('core.bool')(False)
198+
relax_settings.positions = False
199+
relax_settings.shape = True
200+
relax_settings.volume = False
219201
elif relax_type == RelaxType.POSITIONS_CELL:
220-
relax.positions = plugins.DataFactory('core.bool')(True)
221-
relax.shape = plugins.DataFactory('core.bool')(True)
222-
relax.volume = plugins.DataFactory('core.bool')(True)
202+
relax_settings.positions = True
203+
relax_settings.shape = True
204+
relax_settings.volume = True
223205
elif relax_type == RelaxType.POSITIONS_SHAPE:
224-
relax.positions = plugins.DataFactory('core.bool')(True)
225-
relax.shape = plugins.DataFactory('core.bool')(True)
226-
relax.volume = plugins.DataFactory('core.bool')(False)
206+
relax_settings.positions = True
207+
relax_settings.shape = True
208+
relax_settings.volume = False
227209
else:
228210
# Do not perform any relaxation
229-
relax.perform = plugins.DataFactory('core.bool')(False)
230-
211+
relax_settings.perform = False
231212
if threshold_forces is not None:
232213
threshold = threshold_forces
233214
else:
234215
threshold = protocol['relax']['threshold_forces']
235-
relax.force_cutoff = plugins.DataFactory('float')(threshold)
216+
relax_settings.force_cutoff = threshold
236217

237218
if threshold_stress is not None:
238219
raise ValueError('Using a stress threshold is not directly available in VASP during relaxation.')
239220

240-
builder.relax = relax
221+
builder.relax_settings = relax_settings
241222

242223
return builder

0 commit comments

Comments
 (0)