Coverage for gpaw/test/hubbard/test_hubbard_U_noncollinear.py: 100%
29 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
1import pytest
3import numpy as np
4from ase.units import Ha
6from gpaw.hubbard import hubbard
9def test_hubbard_U_noncollinear():
10 rng = np.random.default_rng(seed=555)
12 # Generate random data simulating a setup with
13 # s and p bounded and unbounded partial waves.
15 D_sii = (rng.random([4, 8, 8], dtype=np.float64)
16 + 1j * rng.random([4, 8, 8], dtype=np.float64))
17 # Make Hermitian
18 D_sii = (D_sii + np.transpose(D_sii.conj(), (0, 2, 1))) / 2
19 n_j = [2, 2, -1, -1]
20 l_j = [0, 1, 0, 1]
22 # Hubbard correction on the p orbitals
23 l = 1
24 U = 4 # eV
26 # Generate inner products for the p-orbitals
27 N0_q = np.zeros(len(l_j) * (len(l_j) + 1) // 2)
28 N0_q[4] = 0.9 # Bounded-bounded
29 N0_q[6] = 1.1 # Bounded-unbounded
30 N0_q[9] = 1.2 # Unbounded-unbounded
32 eU, V_sii = hubbard(D_sii, U / Ha, l, l_j, n_j, N0_q, scale=True)
33 eU_onlyreal, _ = hubbard(D_sii.real, U / Ha, l, l_j, n_j, N0_q, scale=True)
34 assert eU.imag == pytest.approx(0, abs=1e-10)
36 # Assert that disregarding the complex values will alter the energy
37 assert eU == pytest.approx(-7.825104, abs=1.e-2)
38 assert eU_onlyreal == pytest.approx(-7.546553, abs=1.e-2)
40 # Now, we check that the Hubbard Hamiltonian is calculated correctly by
41 # comparing it with an energy derivative w.r.t. a density matrix element
42 # calculated through finite difference.
44 diff = 1e-5
46 D1_sii = D_sii.copy()
47 D1_sii[0, 1, 2] += diff / 2
49 eU1, _ = hubbard(D1_sii, U / Ha, l, l_j, n_j, N0_q, scale=True)
51 D2_sii = D_sii.copy()
52 D2_sii[0, 1, 2] -= diff / 2
54 eU2, _ = hubbard(D2_sii, U / Ha, l, l_j, n_j, N0_q, scale=True)
56 # print(eU1)
57 # print(eU2)
58 # print(V_sii[0, 1:4, 1:4])
59 assert (eU1 - eU2) / diff == pytest.approx(V_sii[0, 1, 2], abs=1e-8)