Coverage for gpaw/test/tetrahedron/test_improved.py: 100%
42 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
1"""Test ITM with half-filled 1-d cosine band."""
2from math import pi
3import pytest
4import numpy as np
5from gpaw.tetrahedron import TetrahedronMethod
6from gpaw.dos import DOSCalculator
9def f(N: int, i: bool):
10 rcell = np.diag([1, 0.1, 0.1])
11 k = (np.linspace(-0.5, 0.5, N, endpoint=False) + 0.5 / N) * 2 * pi
12 e = -np.cos(k)[:, np.newaxis]
13 f = np.empty((N, 1))
14 w = np.zeros(N) + 1 / N
15 t = TetrahedronMethod(rcell, (N, 1, 1), improved=i)
16 ef, _ = t._calculate(0.5, e, w, f)
17 wfs = WFS(e, ef)
18 dos = DOSCalculator(wfs, cell=np.linalg.inv(rcell))
19 dosef = dos.raw_dos([ef], spin=0, width=0.0)[0]
20 return f.sum() / N, (f * e).sum() / N, ef, dosef
23class WFS:
24 def __init__(self, e, ef):
25 self.eig_skn = e[np.newaxis]
26 self.fermi_level = ef
27 self.size = (len(e), 1, 1)
28 self.bz2ibz_map = None
30 def weights(self):
31 n = self.size[0]
32 return np.zeros(n) + 1 / n
34 def eigenvalues(self):
35 return self.eig_skn
38@pytest.mark.serial
39def test_tm_1d():
40 # Improved:
41 nelectrons, eband, efermi, dosefermi = f(100, True)
42 assert nelectrons == pytest.approx(0.5, abs=1e-9)
43 assert eband == pytest.approx(-1 / pi, abs=1e-5)
44 assert efermi == pytest.approx(0.0, abs=1e-9)
45 assert dosefermi == pytest.approx(1 / pi, abs=1e-4)
47 # Standard:
48 nelectrons, eband100, efermi, dosefermi = f(100, not True)
49 assert nelectrons == pytest.approx(0.5, abs=1e-9)
50 assert efermi == pytest.approx(0.0, abs=1e-9)
51 assert dosefermi == pytest.approx(1 / pi, abs=1e-4)
53 # ebands converges as 1/N^2.
54 # Extrapolate to infinite number of k-points:
55 eband80 = f(80, not True)[1]
56 eband = np.polyval(np.polyfit([100**-2, 80**-2],
57 [eband100, eband80], 1), 0.0)
58 assert eband == pytest.approx(-1 / pi, abs=1e-7)