import numpy as np
from gpaw.utilities import pack_density
def get_density(rho_MM, wfs, density, density_type='comp', u=0):
if wfs.ksl.using_blacs:
raise NotImplementedError('Scalapack is not supported')
rho_G = density.gd.zeros()
kpt = wfs.kpt_u[u]
assert kpt.q == 0
wfs.basis_functions.construct_density(rho_MM.astype(wfs.dtype),
rho_G, kpt.q)
# Uncomment this if you want to add the static part
# rho_G += density.nct_G
if density_type == 'pseudocoarse':
return rho_G
rho_g = density.finegd.zeros()
density.distribute_and_interpolate(rho_G, rho_g)
rho_G = None
if density_type == 'pseudo':
return rho_g
if density_type == 'comp':
D_asp = density.atom_partition.arraydict(density.D_asp.shapes_a)
Q_aL = {}
for a, D_sp in D_asp.items():
P_Mi = wfs.P_aqMi[a][kpt.q]
assert np.max(np.absolute(P_Mi.imag)) == 0
P_Mi = P_Mi.real
assert P_Mi.dtype == float
D_ii = np.dot(np.dot(P_Mi.T.conj(), rho_MM), P_Mi)
D_sp[:] = pack_density(D_ii)[np.newaxis, :]
Q_aL[a] = np.dot(D_sp.sum(axis=0), wfs.setups[a].Delta_pL)
density.ghat.add(rho_g, Q_aL)
return rho_g
raise RuntimeError('Unknown density type: %s' % density_type)
[docs]
class DensityMatrix:
def __init__(self, paw):
self.wfs = paw.wfs
self.density = paw.density
self.using_blacs = self.wfs.ksl.using_blacs
self.tag = None
def zeros(self, dtype):
ksl = self.wfs.ksl
if self.using_blacs:
return ksl.mmdescriptor.zeros(dtype=dtype)
else:
return np.zeros((ksl.mynao, ksl.nao), dtype=dtype)
def _calculate_density_matrix(self, wfs, kpt):
if self.using_blacs:
ksl = wfs.ksl
rho_MM = ksl.calculate_blocked_density_matrix(kpt.f_n, kpt.C_nM)
else:
rho_MM = wfs.calculate_density_matrix(kpt.f_n, kpt.C_nM)
wfs.bd.comm.sum(rho_MM, root=0)
# TODO: should the sum over bands be moved to
# OrbitalLayouts.calculate_density_matrix()
return rho_MM
def get_density_matrix(self, tag=None):
if tag is None or self.tag != tag:
self.rho_uMM = []
for kpt in self.wfs.kpt_u:
rho_MM = self._calculate_density_matrix(self.wfs, kpt)
self.rho_uMM.append(rho_MM)
self.tag = tag
return self.rho_uMM
def get_density(self, rho_uMM=None, density_type='comp'):
assert len(self.wfs.kpt_u) == 1, 'K-points not implemented'
u = 0
if rho_uMM is None:
rho_uMM = self.rho_uMM
return get_density(rho_uMM[u], self.wfs, self.density, density_type, u)