Skip to content

Commit 38aace4

Browse files
committed
Add the AiiDAEnsemble class
The `AiiDAEnsemble` class is devised to automate the calculation and submission of ground-state calculations through the AiiDA infrastructure. This is solving many of the problematics of the custom `Cluster` modules, delegating all the submission related issues to the AiiDA workflow manager.
1 parent 5629f78 commit 38aace4

1 file changed

Lines changed: 125 additions & 0 deletions

File tree

Modules/aiida_ensemble.py

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
"""Module for handling automated calculation via aiida-quantumespress."""
2+
from __future__ import annotations
3+
4+
import time
5+
import numpy as np
6+
7+
from .Ensemble import Ensemble
8+
try:
9+
import aiida
10+
import aiida_quantumespresso
11+
except ImportError:
12+
import warnings
13+
warnings.warn('aiida or aiida-quantumespresso are not installed')
14+
15+
16+
class AiiDAEnsemble(Ensemble):
17+
"""Ensemble subclass to interface SSCHA with aiida-quantumespresso."""
18+
19+
def compute_ensemble(
20+
self,
21+
pw_code: str,
22+
profile: str | None = None,
23+
protocol: str = 'moderate',
24+
options: dict = None,
25+
overrides: dict = None,
26+
**kwargs
27+
):
28+
"""Get ensemble properties.
29+
30+
All the parameters refer to the
31+
:func:`aiida_quantumespresso.workflows.pw.base.PwBaseWorkChain.get_builder_from_protocol`
32+
method.
33+
34+
Parameters
35+
---------
36+
pw_code:
37+
The string associated with the AiiDA code for `pw.x`
38+
profile:
39+
AiiDA profile to use during the calculations. If None, the default is used
40+
protocol:
41+
The protocol to be used; available protocols are 'fast', 'moderate' and 'precise'
42+
options:
43+
The options for the calculations, such as the resources, wall-time, etc.
44+
overrides:
45+
The overrides for the get_builder_from_protocol
46+
kwargs:
47+
The kwargs for the get_builder_from_protocol
48+
"""
49+
from aiida import load_profile
50+
from aiida.engine import submit
51+
from aiida.plugins import WorkflowFactory
52+
from aiida.orm import StructureData
53+
54+
PwBaseWorkChain = WorkflowFactory('quantumespresso.pw')
55+
56+
if profile:
57+
load_profile(profile)
58+
else:
59+
load_profile()
60+
61+
# Check if not all the calculation needs to be done
62+
n_calcs = np.sum( self.force_computed.astype(int))
63+
computing_ensemble = self
64+
65+
if overrides:
66+
try:
67+
tstress = overrides['pw']['parameters']['CONTROL']['tstress']
68+
self.has_stress = tstress
69+
except KeyError:
70+
self.has_stress = True # by default we calculate stresses with the `get_builder_from_protocol`
71+
72+
# Check wheter compute the whole ensemble, or just a small part
73+
should_i_merge = False
74+
if n_calcs != self.N:
75+
should_i_merge = True
76+
computing_ensemble = self.get_noncomputed()
77+
self.remove_noncomputed()
78+
79+
# ============= HERE AIIDA PART ============= #
80+
structures_data = [StructureData(ase=cc.get_ase_atoms()) for cc in self.structures]
81+
workchains = []
82+
83+
for i, structure in enumerate(structures_data):
84+
builder = PwBaseWorkChain.get_builder_from_protocol(
85+
code=pw_code,
86+
structure=structure,
87+
options=options,
88+
overrides=overrides,
89+
**kwargs
90+
)
91+
builder.label = str(i)
92+
workchains.append(submit(builder))
93+
94+
workchains_success = []
95+
workchains_failed = []
96+
97+
while(workchains):
98+
for workchain in workchains:
99+
if workchain.is_finished:
100+
if workchain.is_failed:
101+
workchains_failed.append(workchain)
102+
else:
103+
workchains_success.append(workchain)
104+
workchains.remove(workchain) # here it may be critical
105+
106+
time.sleep(60) # wait before checking again
107+
108+
# ---- TO DO
109+
# * Take energies, forces, stresses
110+
# * Print which one was successfull
111+
# * Add correct labels to workchains to gather afterwards
112+
# * For sure something else
113+
# * Add the possibility of adding wc to group
114+
# * Keep track is some better way (printing?) of the workchains submitted
115+
# ============= HERE AIIDA PART ============= #
116+
117+
print("CE BEFORE MERGE:", len(self.force_computed))
118+
119+
if should_i_merge:
120+
# Remove the noncomputed ensemble from here, and merge
121+
self.merge(computing_ensemble)
122+
print("CE AFTER MERGE:", len(self.force_computed))
123+
124+
print('ENSEMBLE ALL PROPERTIES:', self.all_properties)
125+

0 commit comments

Comments
 (0)