File: test_langevin_switching.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 (61 lines) | stat: -rw-r--r-- 2,066 bytes parent folder | download
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
import numpy as np
import pytest
from ase.build import bulk
from ase import units
from ase.md.velocitydistribution import MaxwellBoltzmannDistribution
from ase.calculators.harmonic import SpringCalculator
from ase.md.switch_langevin import SwitchLangevin


@pytest.mark.slow
def test_langevin_switching():
    # params
    size = 6
    T = 300
    n_steps = 500
    k1 = 2.0
    k2 = 4.0
    dt = 10

    # for reproducibility
    np.random.seed(42)

    # setup atoms and calculators
    atoms = bulk('Al').repeat(size)
    calc1 = SpringCalculator(atoms.positions, k1)
    calc2 = SpringCalculator(atoms.positions, k2)

    # theoretical diff
    n_atoms = len(atoms)
    calc1.atoms = atoms
    calc2.atoms = atoms
    F1 = calc1.get_free_energy(T) / n_atoms
    F2 = calc2.get_free_energy(T) / n_atoms
    dF_theory = F2 - F1

    # switch_forward
    dyn_forward = SwitchLangevin(atoms, calc1, calc2, dt * units.fs,
                                 temperature_K=T, friction=0.01,
                                 n_eq=n_steps, n_switch=n_steps)
    MaxwellBoltzmannDistribution(atoms, temperature_K=2 * T)
    dyn_forward.run()
    dF_forward = dyn_forward.get_free_energy_difference() / len(atoms)

    # switch_backwards
    dyn_backward = SwitchLangevin(atoms, calc2, calc1, dt * units.fs,
                                  temperature_K=T, friction=0.01,
                                  n_eq=n_steps, n_switch=n_steps)
    MaxwellBoltzmannDistribution(atoms, temperature_K=2 * T)
    dyn_backward.run()
    dF_backward = -dyn_backward.get_free_energy_difference() / len(atoms)

    # summary
    dF_switch = (dF_forward + dF_backward) / 2.0
    error = dF_switch - dF_theory

    # print('delta_F analytical: {:12.6f} eV/atom'.format(dF_theory))
    # print('delta_F forward:    {:12.6f} eV/atom'.format(dF_forward))
    # print('delta_F backward:   {:12.6f} eV/atom'.format(dF_backward))
    # print('delta_F average:    {:12.6f} eV/atom'.format(dF_switch))
    # print('delta_F error:      {:12.6f} eV/atom'.format(error))
    assert abs(error) < 1e-3