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

1from functools import partial 

2 

3import pytest 

4from ase.units import Ha 

5import numpy as np 

6 

7from gpaw.occupations import (fermi_dirac, marzari_vanderbilt, 

8 methfessel_paxton, FermiDiracCalculator, 

9 ZeroWidth) 

10from gpaw.tetrahedron import TetrahedronMethod 

11 

12 

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)) 

20 

21 

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 

36 

37 

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)