File: test_mixingcalc.py

package info (click to toggle)
python-ase 3.26.0-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,484 kB
  • sloc: python: 148,112; xml: 2,728; makefile: 110; javascript: 47
file content (95 lines) | stat: -rw-r--r-- 2,909 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
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
# fmt: off
import numpy as np
import pytest

from ase.build import fcc111
from ase.calculators.calculator import CalculatorSetupError
from ase.calculators.emt import EMT
from ase.calculators.mixing import (
    AverageCalculator,
    LinearCombinationCalculator,
    MixedCalculator,
    Mixer,
    SumCalculator,
)
from ase.constraints import FixAtoms


def test_mixingcalc():
    """This test checks the basic functionality of the MixingCalculators.
    The example system is based on the SinglePointCalculator test case.
    """

    # Calculate reference values:
    atoms = fcc111("Cu", (2, 2, 1), vacuum=10.0)
    atoms[0].x += 0.2

    # First run the test with EMT similarly to the test of the single point
    # calculator.
    calc = EMT()
    atoms.calc = calc
    forces = atoms.get_forces()
    voigt_stress = atoms.get_stress()
    stress_tensor = atoms.get_stress(voigt=False)

    # Mixer: check that stresses of different shapes are handled correctly
    stresses = [voigt_stress, stress_tensor]
    reshape_stress = Mixer.make_stress_voigt(stresses)
    assert np.isclose(reshape_stress[0], reshape_stress[1]).all()

    # SumCalculator: Only one way to associate a calculator with an atoms
    # object.
    atoms1 = atoms.copy()
    calc1 = SumCalculator([EMT(), EMT()])
    atoms1.calc = calc1

    # Check the results.
    assert np.isclose(2 * forces, atoms1.get_forces()).all()
    assert np.isclose(2 * voigt_stress, atoms1.get_stress()).all()
    assert atoms1.get_stress().shape == (6,)

    # testing  step
    atoms1[0].x += 0.2
    assert not np.isclose(2 * forces, atoms1.get_forces()).all()

    # Check constraints
    atoms1.set_constraint(FixAtoms(indices=[atom.index for atom in atoms]))
    assert np.isclose(0, atoms1.get_forces()).all()

    # AverageCalculator:

    atoms1 = atoms.copy()
    calc1 = AverageCalculator([EMT(), EMT()])
    atoms1.calc = calc1

    # LinearCombinationCalculator:

    atoms2 = atoms.copy()
    calc2 = LinearCombinationCalculator([EMT(), EMT()], weights=[0.5, 0.5])
    atoms2.calc = calc2

    # Check the results (it should be the same because it is tha average of
    # the same values).
    assert np.isclose(forces, atoms1.get_forces()).all()
    assert np.isclose(forces, atoms2.get_forces()).all()

    # testing  step
    atoms1[0].x += 0.2
    assert not np.isclose(2 * forces, atoms1.get_forces()).all()

    with pytest.raises(CalculatorSetupError):
        calc1 = LinearCombinationCalculator([], [])

    with pytest.raises(CalculatorSetupError):
        calc1 = AverageCalculator([])

    # test  MixedCalculator and energy contributions
    w1, w2 = 0.78, 0.22
    atoms1 = atoms.copy()
    atoms1.calc = EMT()
    E_tot = atoms1.get_potential_energy()

    calc1 = MixedCalculator(EMT(), EMT(), w1, w2)
    E1, E2 = calc1.get_energy_contributions(atoms1)
    assert np.isclose(E1, E_tot)
    assert np.isclose(E2, E_tot)