Coverage for gpaw/lcaotddft/densitymatrix.py: 90%
62 statements
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
« prev ^ index » next coverage.py v7.7.1, created at 2025-07-09 00:21 +0000
1import numpy as np
3from gpaw.utilities import pack_density
6def get_density(rho_MM, wfs, density, density_type='comp', u=0):
7 if wfs.ksl.using_blacs:
8 raise NotImplementedError('Scalapack is not supported')
10 rho_G = density.gd.zeros()
11 kpt = wfs.kpt_u[u]
12 assert kpt.q == 0
13 wfs.basis_functions.construct_density(rho_MM.astype(wfs.dtype),
14 rho_G, kpt.q)
16 # Uncomment this if you want to add the static part
17 # rho_G += density.nct_G
19 if density_type == 'pseudocoarse':
20 return rho_G
22 rho_g = density.finegd.zeros()
23 density.distribute_and_interpolate(rho_G, rho_g)
24 rho_G = None
26 if density_type == 'pseudo':
27 return rho_g
29 if density_type == 'comp':
30 D_asp = density.atom_partition.arraydict(density.D_asp.shapes_a)
31 Q_aL = {}
32 for a, D_sp in D_asp.items():
33 P_Mi = wfs.P_aqMi[a][kpt.q]
34 assert np.max(np.absolute(P_Mi.imag)) == 0
35 P_Mi = P_Mi.real
36 assert P_Mi.dtype == float
37 D_ii = np.dot(np.dot(P_Mi.T.conj(), rho_MM), P_Mi)
38 D_sp[:] = pack_density(D_ii)[np.newaxis, :]
39 Q_aL[a] = np.dot(D_sp.sum(axis=0), wfs.setups[a].Delta_pL)
40 density.ghat.add(rho_g, Q_aL)
41 return rho_g
43 raise RuntimeError('Unknown density type: %s' % density_type)
46class DensityMatrix:
48 def __init__(self, paw):
49 self.wfs = paw.wfs
50 self.density = paw.density
51 self.using_blacs = self.wfs.ksl.using_blacs
52 self.tag = None
54 def zeros(self, dtype):
55 ksl = self.wfs.ksl
56 if self.using_blacs:
57 return ksl.mmdescriptor.zeros(dtype=dtype)
58 else:
59 return np.zeros((ksl.mynao, ksl.nao), dtype=dtype)
61 def _calculate_density_matrix(self, wfs, kpt):
62 if self.using_blacs:
63 ksl = wfs.ksl
64 rho_MM = ksl.calculate_blocked_density_matrix(kpt.f_n, kpt.C_nM)
65 else:
66 rho_MM = wfs.calculate_density_matrix(kpt.f_n, kpt.C_nM)
67 wfs.bd.comm.sum(rho_MM, root=0)
68 # TODO: should the sum over bands be moved to
69 # OrbitalLayouts.calculate_density_matrix()
70 return rho_MM
72 def get_density_matrix(self, tag=None):
73 if tag is None or self.tag != tag:
74 self.rho_uMM = []
75 for kpt in self.wfs.kpt_u:
76 rho_MM = self._calculate_density_matrix(self.wfs, kpt)
77 self.rho_uMM.append(rho_MM)
78 self.tag = tag
79 return self.rho_uMM
81 def get_density(self, rho_uMM=None, density_type='comp'):
82 assert len(self.wfs.kpt_u) == 1, 'K-points not implemented'
83 u = 0
84 if rho_uMM is None:
85 rho_uMM = self.rho_uMM
86 return get_density(rho_uMM[u], self.wfs, self.density, density_type, u)