Coverage for gpaw/xc/noncollinear.py: 98%
57 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
2from scipy.linalg import eigh
4from gpaw.lcao.eigensolver import DirectLCAO
7class NonCollinearLDAKernel:
8 name = 'LDA'
9 type = 'LDA'
11 def __init__(self, kernel):
12 self.kernel = kernel
14 def calculate(self, e_g, n_sg, v_sg):
15 n_g = n_sg[0]
16 m_vg = n_sg[1:4]
17 m_g = (m_vg**2).sum(0)**0.5
18 nnew_sg = np.empty((2,) + n_g.shape)
19 nnew_sg[:] = n_g
20 nnew_sg[0] += m_g
21 nnew_sg[1] -= m_g
22 nnew_sg *= 0.5
23 vnew_sg = np.zeros_like(nnew_sg)
24 self.kernel.calculate(e_g, nnew_sg, vnew_sg)
25 v_sg[0] += 0.5 * vnew_sg.sum(0)
26 vnew_sg /= np.where(m_g < 1e-15, 1, m_g)
27 v_sg[1:4] += 0.5 * vnew_sg[0] * m_vg
28 v_sg[1:4] -= 0.5 * vnew_sg[1] * m_vg
31class NonCollinearLCAOEigensolver(DirectLCAO):
32 def iterate(self, ham, wfs):
33 wfs.timer.start('LCAO eigensolver')
35 wfs.timer.start('Potential matrix')
36 Vt_xdMM = [wfs.basis_functions.calculate_potential_matrices(vt_G)
37 for vt_G in ham.vt_xG]
38 wfs.timer.stop('Potential matrix')
40 for kpt in wfs.kpt_u:
41 self.iterate_one_k_point(ham, wfs, kpt, Vt_xdMM)
43 wfs.timer.stop('LCAO eigensolver')
45 def iterate_one_k_point(self, ham, wfs, kpt, Vt_xdMM):
46 assert wfs.gd.comm.size == 1, 'No quite sure this works!'
47 if wfs.bd.comm.size > 1 and wfs.bd.strided:
48 raise NotImplementedError
50 H_xMM = []
51 for x in range(4):
52 kpt.s = x
53 H_MM = self.calculate_hamiltonian_matrix(ham, wfs, kpt, Vt_xdMM[x],
54 root=0,
55 add_kinetic=(x == 0))
56 H_xMM.append(H_MM)
57 kpt.s = None
59 S_MM = wfs.S_qMM[kpt.q]
60 M = len(S_MM)
61 S2_MM = np.zeros((2 * M, 2 * M), complex)
62 H2_MM = np.zeros((2 * M, 2 * M), complex)
64 S2_MM[:M, :M] = S_MM
65 S2_MM[M:, M:] = S_MM
67 # We are ignoring x and y here.
68 # See gpaw.new.lcao.hamiltonian.NonCollinearHamiltonianMatrixCalculator
69 # for the correct way!
70 H2_MM[:M, :M] = H_xMM[0] + H_xMM[3]
71 H2_MM[M:, M:] = H_xMM[0] - H_xMM[3]
73 kpt.eps_n = np.empty(2 * wfs.bd.mynbands)
75 diagonalization_string = repr(self.diagonalizer)
76 wfs.timer.start(diagonalization_string)
77 kpt.eps_n, V_MM = eigh(H2_MM, S2_MM)
78 kpt.C_nM = V_MM.T.conj()
79 wfs.timer.stop(diagonalization_string)
80 kpt.C_nM.shape = (wfs.bd.mynbands * 4, M)