test_ase.py 3.68 KB
Newer Older
Gao, Xiang's avatar
Gao, Xiang committed
1
2
from ase.lattice.cubic import Diamond
from ase.md.langevin import Langevin
3
from ase.md.nptberendsen import NPTBerendsen
4
from ase import units
5
from ase.io import read
Gao, Xiang's avatar
Gao, Xiang committed
6
from ase.calculators.test import numeric_force
Jinze Xue's avatar
Jinze Xue committed
7
from torchani.testing import TestCase
Gao, Xiang's avatar
Gao, Xiang committed
8
import numpy as np
Gao, Xiang's avatar
Gao, Xiang committed
9
10
11
import torch
import torchani
import unittest
12
13
14
import os

path = os.path.dirname(os.path.realpath(__file__))
Gao, Xiang's avatar
Gao, Xiang committed
15
16
17


def get_numeric_force(atoms, eps):
18
    fn = torch.zeros((len(atoms), 3), dtype=torch.double)
Gao, Xiang's avatar
Gao, Xiang committed
19
20
21
22
23
24
    for i in range(len(atoms)):
        for j in range(3):
            fn[i, j] = numeric_force(atoms, i, j, eps)
    return fn


Jinze Xue's avatar
Jinze Xue committed
25
class TestASE(TestCase):
Gao, Xiang's avatar
Gao, Xiang committed
26

27
    def setUp(self):
28
        self.model = torchani.models.ANI1x(model_index=0).double()
29

30
    def testWithNumericalForceWithPBCEnabled(self):
Gao, Xiang's avatar
Gao, Xiang committed
31
32
33
        # Run a Langevin thermostat dynamic for 100 steps and after the dynamic
        # check once that the numerical and analytical force agree to a given
        # relative tolerance
34
        atoms = Diamond(symbol="C", pbc=True)
35
        calculator = self.model.ase()
Gao, Xiang's avatar
Gao, Xiang committed
36
37
38
        atoms.set_calculator(calculator)
        dyn = Langevin(atoms, 5 * units.fs, 30000000 * units.kB, 0.002)
        dyn.run(100)
39
        f = atoms.get_forces()
Gao, Xiang's avatar
Gao, Xiang committed
40
        fn = get_numeric_force(atoms, 0.001)
Jinze Xue's avatar
Jinze Xue committed
41
        self.assertEqual(f, fn, rtol=0.1, atol=0.1)
Gao, Xiang's avatar
Gao, Xiang committed
42

43
    def testWithNumericalStressWithPBCEnabled(self):
Gao, Xiang's avatar
Gao, Xiang committed
44
45
46
47
        # Run NPT dynamics for some steps and periodically check that the
        # numerical and analytical stresses agree up to a given
        # absolute difference
        filename = os.path.join(path, '../tools/generate-unit-test-expect/others/Benzene.json')
48
        benzene = read(filename)
Gao, Xiang's avatar
Gao, Xiang committed
49
50
51
52
53
54
        # set velocities to a very small value to avoid division by zero
        # warning due to initial zero temperature.
        #
        # Note that there are 4 benzene molecules, thus, 48 atoms in
        # Benzene.json
        benzene.set_velocities(np.full((48, 3), 1e-15))
55
        calculator = self.model.ase()
56
57
58
59
60
61
62
63
64
        benzene.set_calculator(calculator)
        dyn = NPTBerendsen(benzene, timestep=0.1 * units.fs,
                           temperature=300 * units.kB,
                           taut=0.1 * 1000 * units.fs, pressure=1.01325,
                           taup=1.0 * 1000 * units.fs, compressibility=4.57e-5)

        def test_stress():
            stress = benzene.get_stress()
            numerical_stress = calculator.calculate_numerical_stress(benzene)
65
66
67
            self.assertEqual(stress, numerical_stress)
        dyn.attach(test_stress, interval=30)
        dyn.run(120)
68

Gao, Xiang's avatar
Gao, Xiang committed
69

70
class TestASEWithPTI(unittest.TestCase):
Gao, Xiang's avatar
Gao, Xiang committed
71
72
73
    # Tests that the values obtained by wrapping a BuiltinModel or
    # BuiltinEnsemble with a calculator are the same with and without
    # periodic_table_index
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

    def setUp(self):
        self.model_pti = torchani.models.ANI1x(periodic_table_index=True).double()
        self.model = torchani.models.ANI1x().double()

    def testEqualEnsemblePTI(self):
        calculator_pti = self.model_pti.ase()
        calculator = self.model.ase()
        atoms = Diamond(symbol="C", pbc=True)
        atoms_pti = Diamond(symbol="C", pbc=True)
        atoms.set_calculator(calculator)
        atoms_pti.set_calculator(calculator_pti)
        self.assertEqual(atoms.get_potential_energy(), atoms_pti.get_potential_energy())

    def testEqualOneModelPTI(self):
        calculator_pti = self.model_pti[0].ase()
        calculator = self.model[0].ase()
        atoms = Diamond(symbol="C", pbc=True)
        atoms_pti = Diamond(symbol="C", pbc=True)
        atoms.set_calculator(calculator)
        atoms_pti.set_calculator(calculator_pti)
        self.assertEqual(atoms.get_potential_energy(), atoms_pti.get_potential_energy())


Gao, Xiang's avatar
Gao, Xiang committed
98
99
if __name__ == '__main__':
    unittest.main()