Coverage for gpaw/test/noncollinear/test_complex_densmat.py: 100%
41 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-08 00:17 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-08 00:17 +0000
1import numpy as np
2import pytest
4from gpaw.new.pot_calc import calculate_non_local_potential1
5from gpaw.new.xc import create_functional
6from gpaw.setup import create_setup
7from gpaw.core import UGDesc
8from gpaw.xc import XC
11@pytest.mark.soc
12def test_energy_from_complex_densmat():
14 # Set up objects and matrices
16 setup = create_setup('Ga')
17 grid = UGDesc(cell=[1, 1, 1], size=[9, 9, 9])
18 xc = create_functional(XC('LDA', collinear=False), grid)
19 soc = True
20 err = 1.0e-6
21 D_sii = np.zeros((4, setup.ni, setup.ni), complex)
22 D_sii[0, 0, 0] = 2
24 # Calculate non-local potential energy for some random state
26 P_sm = np.array([[0.2 + 0.3j, 0.1 + 0.2j, 0.3 + 0.4j],
27 [0.4 - 0.5j, 0.2 + 0.3j, 0.6 - 0.7j]])
29 D_ssmm = np.einsum('si, zj -> szij', P_sm.conj(), P_sm)
30 D_sii[:, 1:4, 1:4] = [D_ssmm[0, 0] + D_ssmm[1, 1],
31 D_ssmm[0, 1] + D_ssmm[1, 0],
32 -1j * (D_ssmm[0, 1] - D_ssmm[1, 0]),
33 D_ssmm[0, 0] - D_ssmm[1, 1]]
35 def calc_energies(D_sii):
36 _, energies = calculate_non_local_potential1(
37 setup, xc, D_sii, np.zeros(1), soc, [], 0)
38 return energies
40 energies1 = calc_energies(D_sii)
42 assert energies1['kinetic_correction'] == pytest.approx(
43 0.04340694003, abs=err)
44 assert energies1['coulomb'] == pytest.approx(-5.5575386716, abs=err)
45 assert energies1['zero'] == pytest.approx(-2.432694074696, abs=err)
46 assert energies1['xc'] == pytest.approx(1.5938337327, abs=err)
48 # Rotate the state 90 degrees around the z-axis (x -> y, y -> -x, z -> z).
49 # Assert that this does not change the energies.
51 # First rotate the spins
52 P_sm = [P_sm[0, :] * (1 - 1j), P_sm[1, :] * (1 + 1j)] / np.sqrt(2)
53 # Then rotate the density
54 P_sm = np.matmul([[0, 0, 1], [0, 1, 0], [-1, 0, 0]], P_sm.T).T
56 D_ssmm = np.einsum('si, zj -> szij', P_sm.conj(), P_sm)
57 D_sii[:, 1:4, 1:4] = [D_ssmm[0, 0] + D_ssmm[1, 1],
58 D_ssmm[0, 1] + D_ssmm[1, 0],
59 -1j * (D_ssmm[0, 1] - D_ssmm[1, 0]),
60 D_ssmm[0, 0] - D_ssmm[1, 1]]
62 energies2 = calc_energies(D_sii)
64 assert energies2['kinetic_correction'] == pytest.approx(
65 energies1['kinetic_correction'], abs=err)
66 assert energies2['coulomb'] == pytest.approx(energies1['coulomb'], abs=err)
67 assert energies2['zero'] == pytest.approx(energies1['zero'], abs=err)
68 assert energies2['xc'] == pytest.approx(energies1['xc'], abs=err)
70 # Assert that only the kinetic energy changes when the density
71 # matrix is forced to be real
73 energies3 = calc_energies(D_sii.real)
75 assert energies3['kinetic_correction'] == pytest.approx(
76 0.0446930609623, abs=err)
77 assert energies3['coulomb'] == pytest.approx(energies1['coulomb'], abs=err)
78 assert energies3['zero'] == pytest.approx(energies1['zero'], abs=err)
79 assert energies3['xc'] == pytest.approx(energies1['xc'], abs=err)