Coverage for gpaw/xc/tools.py: 93%
54 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-19 00:19 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-19 00:19 +0000
1import numpy as np
2from ase.units import Ha
4from gpaw.xc import XC
5from gpaw.utilities import pack_hermitian, unpack_density, unpack_hermitian
8def vxc(gs, xc=None, coredensity=True, n1=0, n2=0):
9 """Calculate XC-contribution to eigenvalues."""
11 if n2 <= 0:
12 n2 += gs.bd.nbands
14 ham = gs.hamiltonian
15 dens = gs.density
17 if xc is None:
18 xc = ham.xc
19 elif isinstance(xc, str):
20 xc = XC(xc)
22 if dens.nt_sg is None:
23 dens.interpolate_pseudo_density()
25 thisisatest = not True
27 if xc.orbital_dependent:
28 gs.get_xc_difference(xc)
30 # Calculate XC-potential:
31 vxct_sg = ham.finegd.zeros(gs.nspins)
32 xc.calculate(dens.finegd, dens.nt_sg, vxct_sg)
33 vxct_sG = ham.restrict_and_collect(vxct_sg)
34 if thisisatest:
35 vxct_sG[:] = 1
37 # ... and PAW corrections:
38 dvxc_asii = {}
39 for a, D_sp in dens.D_asp.items():
40 dvxc_sp = np.zeros_like(D_sp)
42 pawdata = gs.pawdatasets.by_atom[a]
43 if pawdata.hubbard_u is not None:
44 _, dHU_sii = pawdata.hubbard_u.calculate(pawdata,
45 unpack_density(D_sp))
46 dvxc_sp += pack_hermitian(dHU_sii)
47 xc.calculate_paw_correction(pawdata, D_sp, dvxc_sp, a=a,
48 addcoredensity=coredensity)
50 dvxc_asii[a] = [unpack_hermitian(dvxc_p) for dvxc_p in dvxc_sp]
51 if thisisatest:
52 dvxc_asii[a] = [pawdata.dO_ii]
54 vxc_un = np.empty((gs.kd.mynk * gs.nspins, gs.bd.mynbands))
55 for u, vxc_n in enumerate(vxc_un):
56 kpt = gs.kpt_u[u]
57 vxct_G = vxct_sG[kpt.s]
58 for n in range(gs.bd.mynbands):
59 if n1 <= n + gs.bd.beg < n2:
60 psit_G = gs.get_wave_function_array(u, n)
61 vxc_n[n] = gs.gd.integrate((psit_G * psit_G.conj()).real,
62 vxct_G, global_integral=False)
64 for a, dvxc_sii in dvxc_asii.items():
65 m1 = max(n1, gs.bd.beg) - gs.bd.beg
66 m2 = min(n2, gs.bd.end) - gs.bd.beg
67 if m1 < m2:
68 P_ni = kpt.P_ani[a][m1:m2]
69 vxc_n[m1:m2] += ((P_ni @ dvxc_sii[kpt.s]) *
70 P_ni.conj()).sum(1).real
72 gs.gd.comm.sum(vxc_un)
73 vxc_skn = gs.kd.collect(vxc_un, broadcast=True)
75 if xc.orbital_dependent:
76 vxc_skn += xc.exx_skn
78 vxc_skn = gs.bd.collect(vxc_skn.T.copy(), broadcast=True).T
79 return vxc_skn[:, :, n1:n2] * Ha