-
Notifications
You must be signed in to change notification settings - Fork 12
/
ex12_k8s_neb.py
117 lines (101 loc) · 3.85 KB
/
ex12_k8s_neb.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
"""Running NEB calculations using kubernetes-isolated VaspInteractive processes
parallelization of neb calculations are achieved via multithreading on the local pod
Running NEB calculations using kubernetes ensures process isolation,
and no need to allocate large number of cpus at the same time. Setup is also easier than MPI-based parallelization
Example adapted from https://wiki.fysik.dtu.dk/ase/tutorials/neb/diffusion.html
"""
import time
import tempfile
import os
from ase.io import read
from ase.neb import NEB
from ase.optimize import BFGS
from copy import deepcopy, copy
from pathlib import Path
from ase.calculators.vasp import Vasp
from vasp_interactive import VaspInteractive
from vasp_interactive.kubernetes import KubeVaspInteractive, create_kube_pods
curdir = Path(__file__).parent
initial = read(curdir / "neb-trajs" / "initial.traj")
final = read(curdir / "neb-trajs" / "final.traj")
# Same vasp theoretical level for the initial / final structures
vasp_params = dict(xc="pbe", kspacing=0.5, encut=350, sigma=0.1, istart=0, lwave=False)
# Very rough
fmax = 0.25
def make_images(n_images=5):
"""Interpolate n_images - 2"""
images = [initial]
for i in range(n_images - 2):
images.append(initial.copy())
images.append(final)
return images
def run_neb(images, traj_name, **kwargs):
neb = NEB(images, **kwargs)
neb.interpolate()
t_ = time.perf_counter()
dyn = BFGS(neb, trajectory=traj_name)
dyn.run(fmax=fmax)
elasp = time.perf_counter() - t_
return elasp
def sequential_vasp(n_images=5):
print("*" * 50)
print("Running NEB with sequential VASP code")
images = make_images(n_images)
with tempfile.TemporaryDirectory() as tmpdir:
base_calc = Vasp(directory=tmpdir, **vasp_params)
for img in images[1 : n_images - 1]:
img.calc = deepcopy(base_calc)
elasp = run_neb(images, "neb-vasp-seq.traj")
energies = [img.get_potential_energy() for img in images]
print("Energies: ", energies)
print(f"Elasp time: {elasp:.2f} s")
return
def sequential_vasp_inter(n_images=5):
print("*" * 50)
print("Running NEB with sequential VaspInteractive code")
images = make_images(n_images)
with tempfile.TemporaryDirectory() as tmpdir:
base_calc = VaspInteractive(directory=tmpdir, **vasp_params)
for img in images[1 : n_images - 1]:
img.calc = base_calc
# All calculations share the same calculator instance
elasp = run_neb(images, "neb-vasp-inter-kube.traj", allow_shared_calculator=True)
energies = [img.get_potential_energy() for img in images]
print("Energies: ", energies)
print(f"Elasp time: {elasp:.2f} s")
# Finalize
for img in images[1 : n_images - 1]:
img.calc.finalize()
return
def k8s_vasp_inter(n_images=5):
# lazy cleanup
os.system("rm -rf /home/jovyan/data/scartch/*")
print("*" * 50)
print("Running NEB with KubeVaspInteractive code")
scale = n_images - 2
cluster, worker_pods = create_kube_pods(scale=n_images - 2, cpu=8, memory="4Gi")
images = make_images(n_images)
for i in range(n_images - 2):
images[i + 1].calc = KubeVaspInteractive(
directory=f"/home/jovyan/data/scartch/neb-{i + 1}",
pod=worker_pods[i],
**vasp_params,
)
# All calculations share the same calculator instance
elasp = run_neb(images, "neb-vasp-inter-kube.traj", parallel=True)
energies = [img.get_potential_energy() for img in images]
print("Energies: ", energies)
print(f"Elasp time: {elasp:.2f} s")
# not necessary to finalize processes as closing the cluster kills vasp
cluster.close()
return
if __name__ == "__main__":
"""Please run the code by
```
python ex12_k8s_neb.py 2>/dev/null
```
to plunge stderr message
"""
sequential_vasp(5)
sequential_vasp_inter(5)
k8s_vasp_inter(5)