Coverage for gpaw/test/test_lvlmm.py: 100%
58 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 numpy as np
2import pytest
3from gpaw.spinorbit import get_L_vlmm
6class QuantumState:
7 """Quantum State, representing real Y_lm or complex Y_l^m"""
8 def __init__(self, l: int, m: int, factor: complex = 1.0):
9 assert type(l) is int
10 assert type(m) is int
11 self.l = l
12 self.m = m
13 self.factor = factor
16def real_to_complex_quantum_state(state: QuantumState):
17 """represent the real Y_lm in complex Y_l^m"""
18 if state.m == 0:
19 return [QuantumState(state.l, state.m, 1.0)]
20 elif state.m > 0:
21 return [
22 QuantumState(state.l, -1 * state.m,
23 1 / np.sqrt(2.0) * state.factor),
24 QuantumState(state.l, state.m,
25 (-1.0) ** state.m / np.sqrt(2.0) * state.factor)]
26 else: # state.m < 0:
27 return [
28 QuantumState(state.l, state.m, 1j / np.sqrt(2.0) * state.factor),
29 QuantumState(
30 state.l,
31 -1 * state.m,
32 -1j * (-1.0) ** state.m / np.sqrt(2.0) * state.factor,
33 ),
34 ]
37def matrix_element(bra: QuantumState, ket: QuantumState, operator):
38 """<Y_lm' | O | Y_lm >"""
39 assert bra.l == ket.l
40 result = 0.0
41 kets_complex = real_to_complex_quantum_state(ket)
42 bras_complex = real_to_complex_quantum_state(bra)
43 for b in bras_complex:
44 for k in kets_complex:
45 operator_factor, newk = operator(k)
46 if newk.m != b.m:
47 continue
48 result += np.conj(b.factor) * newk.factor * operator_factor
49 return result
52def Lz(ket: QuantumState):
53 """L_z acting on complex Y_l^m"""
54 return ket.m, QuantumState(ket.l, ket.m, ket.factor)
57def Lp(ket: QuantumState):
58 """L_+ acting on complex Y_l^m"""
59 if ket.m < ket.l:
60 result = np.sqrt(ket.l * (ket.l + 1) - ket.m * (ket.m + 1))
61 else:
62 result = 0
63 return result, QuantumState(ket.l, ket.m + 1, ket.factor)
66def Lm(ket: QuantumState):
67 """L_- acting on complex Y_l^m"""
68 if ket.m > -ket.l:
69 result = np.sqrt(ket.l * (ket.l + 1) - ket.m * (ket.m - 1))
70 else:
71 result = 0
72 return result, QuantumState(ket.l, ket.m - 1, ket.factor)
75def test_lvlmm():
77 L_vlmm = get_L_vlmm()
79 for l in [0, 1, 2, 3]:
80 # print(f"Doing {'spdf'[l]}:")
81 result_lz = np.zeros((2 * l + 1, 2 * l + 1), dtype=complex)
82 result_lp = np.zeros((2 * l + 1, 2 * l + 1), dtype=complex)
83 result_lm = np.zeros((2 * l + 1, 2 * l + 1), dtype=complex)
84 for mp in range(-l, l + 1):
85 bra = QuantumState(l, mp) # real Y_lm
86 for m in range(-l, l + 1):
87 ket = QuantumState(l, m) # real Y_lm
88 result_lz[mp + l, m + l] = matrix_element(bra, ket, Lz)
89 result_lp[mp + l, m + l] = matrix_element(bra, ket, Lp)
90 result_lm[mp + l, m + l] = matrix_element(bra, ket, Lm)
92 result_lx = (result_lp + result_lm) / 2.0
93 result_ly = (result_lp - result_lm) / 2j
95 L_vlmm[0][l] == pytest.approx(result_lx)
96 L_vlmm[1][l] == pytest.approx(result_ly)
97 L_vlmm[2][l] == pytest.approx(result_lz)