Skip to content

Commit d9cc29f

Browse files
committed
PhononWorkChain: add max concurrent running pw workchains
Fixes #52 Add the `settings.max_concurrent_base_workchains` input to the `PhononWorkChain` to run only up to a maximum number of PwBaseWorkChain at the same time. This is particularly useful for low symmetry materials where many displacements are generated. This avoids to overload both the AiiDA daemon and especially the HPC. Moreover, this even allows for running on the local machine (where AiiDA is installed) this workflow.
1 parent 835266a commit d9cc29f

File tree

3 files changed

+67
-8
lines changed

3 files changed

+67
-8
lines changed

src/aiida_vibroscopy/workflows/phonons/base.py

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from aiida import orm
1515
from aiida.common.extendeddicts import AttributeDict
1616
from aiida.common.lang import type_check
17-
from aiida.engine import WorkChain, calcfunction, if_
17+
from aiida.engine import WorkChain, calcfunction, if_, while_
1818
from aiida.plugins import CalculationFactory, DataFactory, WorkflowFactory
1919
from aiida_quantumespresso.calculations.functions.create_kpoints_from_distance import create_kpoints_from_distance
2020
from aiida_quantumespresso.workflows.protocols.utils import ProtocolMixin
@@ -133,6 +133,10 @@ def define(cls, spec):
133133
'settings.sleep_submission_time', valid_type=(int, float), non_db=True, default=3.0,
134134
help='Time in seconds to wait before submitting subsequent displaced structure scf calculations.',
135135
)
136+
spec.input(
137+
'settings.max_concurrent_base_workchains', valid_type=int, non_db=True, default=20,
138+
help='Maximum number of concurrent running `PwBaseWorkChain`.'
139+
)
136140
spec.input(
137141
'clean_workdir', valid_type=orm.Bool, default=lambda: orm.Bool(False),
138142
help='If `True`, work directories of all called calculation will be cleaned at the end of execution.'
@@ -143,7 +147,10 @@ def define(cls, spec):
143147
cls.set_reference_kpoints,
144148
cls.run_base_supercell,
145149
cls.inspect_base_supercell,
146-
cls.run_forces,
150+
cls.run_supercells,
151+
while_(cls.should_run_forces)(
152+
cls.run_forces,
153+
),
147154
cls.inspect_all_runs,
148155
cls.set_phonopy_data,
149156
if_(cls.should_run_phonopy)(
@@ -379,8 +386,8 @@ def inspect_base_supercell(self):
379386
fermi_energy = parameters.fermi_energy
380387
self.ctx.is_insulator, _ = orm.find_bandgap(bands, fermi_energy=fermi_energy)
381388

382-
def run_forces(self):
383-
"""Run an scf for each supercell with displacements."""
389+
def run_supercells(self):
390+
"""Run supercell with displacements."""
384391
if self.ctx.plus_hubbard or self.ctx.old_plus_hubbard:
385392
supercells = get_supercells_for_hubbard(
386393
preprocess_data=self.ctx.preprocess_data,
@@ -389,12 +396,27 @@ def run_forces(self):
389396
else:
390397
supercells = self.ctx.preprocess_data.calcfunctions.get_supercells_with_displacements()
391398

399+
self.ctx.supercells = []
400+
for key, value in supercells.items():
401+
self.ctx.supercells.append((key, value))
402+
392403
self.out('supercells', supercells)
393404

405+
def should_run_forces(self):
406+
"""Whether to run or not forces."""
407+
return len(self.ctx.supercells) > 0
408+
409+
def run_forces(self):
410+
"""Run an scf for each supercell with displacements."""
394411
base_key = f'{self._RUN_PREFIX}_0'
395412
base_out = self.ctx[base_key].outputs
396413

397-
for key, supercell in supercells.items():
414+
n_base_parallel = self.inputs.settings.max_concurrent_base_workchains
415+
if self.inputs.settings.max_concurrent_base_workchains < 0:
416+
n_base_parallel = len(self.ctx.supercells)
417+
418+
for _ in self.ctx.supercells[:n_base_parallel]:
419+
key, supercell = self.ctx.supercells.pop(0)
398420
num = key.split('_')[-1]
399421
label = f'{self._RUN_PREFIX}_{num}'
400422

tests/workflows/phonons/test_phonon.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#################################################################################
99
"""Tests for the :mod:`workflows.phonons.phonon` module."""
1010
from aiida import orm
11+
from aiida.common import AttributeDict
1112
from aiida_quantumespresso.data.hubbard_structure import HubbardStructureData
1213
import pytest
1314

@@ -29,13 +30,13 @@ def _generate_workchain_phonon(structure=None, append_inputs=None, return_inputs
2930
inputs = {
3031
'scf': scf_inputs,
3132
'settings': {
32-
'sleep_submission_time': 0.
33+
'sleep_submission_time': 0.,
3334
},
3435
'symmetry': {},
3536
}
3637

3738
if return_inputs:
38-
return inputs
39+
return AttributeDict(inputs)
3940

4041
if append_inputs is not None:
4142
inputs.update(append_inputs)
@@ -223,23 +224,53 @@ def test_inspect_base_supercell(
223224
assert process.ctx.is_insulator
224225

225226

227+
@pytest.mark.usefixtures('aiida_profile')
228+
def test_run_supercells(generate_workchain_phonon):
229+
"""Test `PhononWorkChain.run_supercells` method."""
230+
process = generate_workchain_phonon()
231+
process.setup()
232+
process.run_supercells()
233+
234+
assert 'supercells' in process.outputs
235+
assert 'supercells' in process.ctx
236+
assert 'supercell_1' in process.outputs['supercells']
237+
238+
239+
@pytest.mark.usefixtures('aiida_profile')
240+
def test_should_run_forces(generate_workchain_phonon):
241+
"""Test `PhononWorkChain.should_run_forces` method."""
242+
process = generate_workchain_phonon()
243+
process.setup()
244+
process.run_supercells()
245+
assert process.should_run_forces()
246+
247+
226248
@pytest.mark.usefixtures('aiida_profile')
227249
def test_run_forces(generate_workchain_phonon, generate_base_scf_workchain_node):
228250
"""Test `PhononWorkChain.run_forces` method."""
229-
process = generate_workchain_phonon()
251+
append_inputs = {
252+
'settings': {
253+
'sleep_submission_time': 0.,
254+
'max_concurrent_base_workchains': 1,
255+
}
256+
}
257+
process = generate_workchain_phonon(append_inputs=append_inputs)
230258

231259
process.setup()
232260
process.set_reference_kpoints()
233261
process.run_base_supercell()
262+
process.run_supercells()
234263

235264
assert 'scf_supercell_0'
236265

266+
num_supercells = len(process.ctx.supercells)
237267
process.ctx.scf_supercell_0 = generate_base_scf_workchain_node()
238268
process.run_forces()
239269

240270
assert 'supercells' in process.outputs
241271
assert 'supercell_1' in process.outputs['supercells']
242272
assert 'scf_supercell_1' in process.ctx
273+
assert num_supercells == len(process.ctx.supercells) + 1
243274

244275

245276
@pytest.mark.usefixtures('aiida_profile')
@@ -251,6 +282,7 @@ def test_run_forces_with_hubbard(generate_workchain_phonon, generate_base_scf_wo
251282
process.setup()
252283
process.set_reference_kpoints()
253284
process.run_base_supercell()
285+
process.run_supercells()
254286

255287
assert 'scf_supercell_0'
256288

@@ -261,6 +293,7 @@ def test_run_forces_with_hubbard(generate_workchain_phonon, generate_base_scf_wo
261293
assert 'supercell_1' in process.outputs['supercells']
262294
assert isinstance(process.outputs['supercells']['supercell_1'], HubbardStructureData)
263295
assert 'scf_supercell_1' in process.ctx
296+
assert len(process.ctx.supercells) == 0
264297

265298

266299
@pytest.mark.parametrize(('expected_result', 'exit_status'),

tests/workflows/protocols/test_phonon.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,15 @@ def test_overrides(fixture_code, generate_structure):
8282
'displacement_generator': {
8383
'distance': 0.005
8484
},
85+
'settings': {
86+
'max_concurrent_base_workchains': 1,
87+
}
8588
}
8689
builder = PhononWorkChain.get_builder_from_protocol(code, structure, overrides=overrides)
8790

8891
assert builder.primitive_matrix.get_list() == [[1, 0, 0], [0, 1, 0], [0, 0, 1]]
8992
assert builder.displacement_generator.get_dict() == {'distance': 0.005}
93+
assert builder.settings.max_concurrent_base_workchains == 1
9094

9195

9296
def test_phonon_properties(fixture_code, generate_structure):

0 commit comments

Comments
 (0)