File: test_lj.py

package info (click to toggle)
python-ase 3.21.1-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 13,936 kB
  • sloc: python: 122,428; xml: 946; makefile: 111; javascript: 47
file content (132 lines) | stat: -rw-r--r-- 3,605 bytes parent folder | download | duplicates (2)
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import numpy as np
import pytest

from ase import Atoms
from ase.build import bulk
from ase.calculators.lj import LennardJones


# test non-bulk properties
reference_potential_energy = pytest.approx(-1.0)


def systems_minimum():
    """two atoms at potential minimum"""

    atoms = Atoms('H2', positions=[[0, 0, 0], [0, 0, 2 ** (1.0 / 6.0)]])
    calc = LennardJones(rc=1.0e5)
    atoms.calc = calc
    yield atoms

    calc = LennardJones(rc=1.0e5, smooth=True)
    atoms.calc = calc
    yield atoms


def test_minimum_energy():
    # testing at the minimum to see if anything is on fire
    # See https://en.wikipedia.org/wiki/Lennard-Jones_potential
    # Minimum is at r=2^(1/6)*sigma, and it's -1.

    for atoms in systems_minimum():
        assert atoms.get_potential_energy() == reference_potential_energy
        assert atoms.get_potential_energies().sum() == reference_potential_energy


def test_minimum_forces():
    # forces should be zero
    for atoms in systems_minimum():
        np.testing.assert_allclose(atoms.get_forces(), 0, atol=1e-14)


def test_system_changes():
    # https://gitlab.com/ase/ase/-/merge_requests/1817

    for atoms in systems_minimum():
        atoms.calc.calculate(atoms, system_changes=['positions'])
        assert atoms.get_potential_energy() == reference_potential_energy


def test_finite_difference():
    # ensure that we got the modified forces right
    h = 1e-10
    r = 8.0
    calc = LennardJones(smooth=True, ro=6, rc=10, sigma=3)
    atoms = Atoms('H2', positions=[[0, 0, 0], [r, 0, 0]])
    atoms2 = Atoms('H2', positions=[[0, 0, 0], [r + h, 0, 0]])
    atoms.calc = calc
    atoms2.calc = calc

    fd_force = (atoms2.get_potential_energy() - atoms.get_potential_energy()) / h
    force = atoms.get_forces()[0, 0]

    np.testing.assert_allclose(fd_force, force)


# test bulk properties
stretch = 1.5
reference_force = pytest.approx(1.57190846e-05)
reference_pressure = pytest.approx(1.473229212e-05)


def systems_bulk():
    atoms = bulk("Ar", cubic=True)
    atoms.set_cell(atoms.cell * stretch, scale_atoms=True)

    calc = LennardJones(rc=10)
    atoms.calc = calc

    yield atoms

    atoms = bulk("Ar", cubic=True)
    atoms.set_cell(atoms.cell * stretch, scale_atoms=True)

    # somewhat hand-picked parameters, but ok for comparison
    calc = LennardJones(rc=12, ro=10, smooth=True)
    atoms.calc = calc

    yield atoms


def test_bulk_energies():
    # check energies

    for atoms in systems_bulk():
        assert np.allclose(
            atoms.get_potential_energy(), atoms.get_potential_energies().sum()
        )
        # energies should be equal in this high-symmetry structure
        assert atoms.get_potential_energies().std() == pytest.approx(0.0)


def test_bulk_forces():
    for atoms in systems_bulk():
        # displace atom for 0.03 \AA
        atoms.positions[0, 0] += 0.03

        # check forces sum to zero
        assert np.allclose(atoms.get_forces().sum(axis=0), 0)

        # check reference force
        assert atoms.get_forces()[0, 0] == reference_force


def test_bulk_stress():
    # check stress computation for sanity and reference
    # reference value computed for "non-smooth" LJ, so
    # we only test that
    atoms = bulk("Ar", cubic=True)
    atoms.set_cell(atoms.cell * stretch, scale_atoms=True)

    calc = LennardJones(rc=10)
    atoms.calc = calc

    stress = atoms.get_stress()
    stresses = atoms.get_stresses()

    assert np.allclose(stress, stresses.sum(axis=0))

    # check reference pressure
    pressure = sum(stress[:3]) / 3

    assert pressure == reference_pressure