Coverage for gpaw/test/test_occupations.py: 100%
37 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
1from functools import partial
3import pytest
4from ase.units import Ha
5import numpy as np
7from gpaw.occupations import (fermi_dirac, marzari_vanderbilt,
8 methfessel_paxton, FermiDiracCalculator,
9 ZeroWidth)
10from gpaw.tetrahedron import TetrahedronMethod
13funcs = []
14for w in [0.1, 0.5]:
15 funcs.append(partial(fermi_dirac, fermi_level=0.0, width=w))
16 funcs.append(partial(marzari_vanderbilt, fermi_level=0.0, width=w))
17 for n in range(4):
18 funcs.append(partial(methfessel_paxton,
19 fermi_level=0.0, order=n, width=w))
22@pytest.mark.parametrize('func', funcs)
23@pytest.mark.ci
24def test_occupations(func):
25 for e in [-0.3 / Ha, 0, 0.1 / Ha, 1.2 / Ha]:
26 n0, d0, S0 = func(e)
27 x = 0.000001
28 fp, dp, Sp = func(e + x)
29 fm, dm, Sm = func(e - x)
30 d = -(fp - fm) / (2 * x)
31 dS = Sm - Sp
32 dn = fp - fm
33 print(d - d0, dS - e * dn)
34 assert abs(d - d0) < 3e-5
35 assert abs(dS - e * dn) < 1e-13
38@pytest.mark.parametrize(
39 'e_kn,w_k,ne',
40 [([[0.0, 1.0]], [1.0], 2),
41 ([[0.0, 1.0], [0.0, 2.0]], [0.5, 0.5], 1.5),
42 ([[0.0, 1.0, 2.0], [0.0, 2.0, 2.0]], [0.5, 0.5], 2)])
43@pytest.mark.ci
44def test_occ_obj(e_kn, w_k, ne):
45 print('*' * 42)
46 print(e_kn)
47 for occ in [FermiDiracCalculator(0.1),
48 ZeroWidth(),
49 TetrahedronMethod(np.diag([2, 1, 1]), (len(w_k), 1, 1))]:
50 f_kn, fl, s = occ.calculate(ne, np.array(e_kn), w_k)
51 print(occ)
52 print(f_kn)
53 print(fl, s, (w_k @ f_kn).sum())
54 assert (w_k @ f_kn).sum() == pytest.approx(ne, abs=1e-14)