Coverage for gpaw/test/test_watermodel.py: 95%
66 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-14 00:18 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-14 00:18 +0000
1import time
3import ase.units as units
4import numpy as np
5import pytest
6from ase import Atoms
7from ase.calculators.tip3p import TIP3P, angleHOH, rOH
8from ase.constraints import FixBondLengths
9from ase.io import read
10from ase.io.trajectory import Trajectory
11from ase.md import Langevin as Langevin0
13from gpaw.utilities.watermodel import FixBondLengthsWaterModel, TIP3PWaterModel
16def Langevin(*args, **kwargs):
17 try:
18 return Langevin0(*args, **kwargs)
19 except TypeError:
20 kT = kwargs.pop('temperature_K') * units.kB
21 return Langevin0(*args, **kwargs, temperature=kT)
24@pytest.mark.slow
25def test_watermodel(in_tmp_dir):
26 NSTEPS = 600
27 SCALE = 200
29 cutoff = 4.0
31 # Set up water box at 20 deg C density
32 x = angleHOH * np.pi / 180 / 2
33 pos = [[0, 0, 0],
34 [0, rOH * np.cos(x), rOH * np.sin(x)],
35 [0, rOH * np.cos(x), -rOH * np.sin(x)]]
36 atoms = Atoms('OH2', positions=pos)
38 vol = ((18.01528 / 6.022140857e23) / (0.9982 / 1e24))**(1 / 3.)
39 atoms.set_cell((vol, vol, vol))
40 atoms.center()
42 N = 4
43 atoms = atoms.repeat((N, N, N))
44 atoms.set_pbc(True)
46 pairs = [(3 * i + j, 3 * i + (j + 1) % 3)
47 for i in range(len(atoms) // 3)
48 for j in [0, 1, 2]]
50 # Create atoms object with old constraints for reference
51 atoms_ref = atoms.copy()
52 atoms_ref.constraints = FixBondLengths(pairs)
54 # RATTLE-type constraints on O-H1, O-H2, H1-H2.
55 atoms.constraints = FixBondLengthsWaterModel(pairs)
57 atoms.calc = TIP3PWaterModel(rc=cutoff)
58 atoms_ref.calc = TIP3P(rc=cutoff)
60 rng = np.random.RandomState(123)
61 md = Langevin(atoms, 1 * units.fs, temperature_K=300,
62 rng=rng,
63 friction=0.01, logfile='C.log')
64 traj = Trajectory('C.traj', 'w', atoms)
65 md.attach(traj.write, interval=1)
67 start = time.time()
68 with md:
69 md.run(NSTEPS)
70 end = time.time()
71 Cversion = end - start
72 print("%d steps of C-MD took %.3fs (%.0f ms/step)" % (
73 NSTEPS, Cversion,
74 Cversion / NSTEPS * 1000))
75 traj.close()
77 rng = np.random.RandomState(123)
78 md_ref = Langevin(atoms_ref, 1 * units.fs, temperature_K=300,
79 rng=rng,
80 friction=0.01, logfile='ref.log')
81 traj_ref = Trajectory('ref.traj', 'w', atoms_ref)
82 md_ref.attach(traj_ref.write, interval=1)
83 start = time.time()
84 with md_ref:
85 md_ref.run(NSTEPS / SCALE)
86 end = time.time()
87 Pyversion = (end - start) * SCALE
88 print("%d steps of Py-MD took %.3fs (%.0f ms/step)" % (
89 NSTEPS / SCALE,
90 Pyversion / SCALE, Pyversion / NSTEPS * 1000))
91 traj_ref.close()
93 # Compare trajectories
94 images = read('C.traj@:')
95 images_ref = read('ref.traj@:')
96 for img1, img2 in zip(images, images_ref):
97 norm = np.linalg.norm(img1.get_positions() - img2.get_positions())
98 print(norm)
99 assert norm < 1e-11
101 print("Speedup", Pyversion / Cversion)