mirror of
https://github.com/triqs/dft_tools
synced 2024-08-29 07:22:01 +02:00
Added calculation of GAMMA to SumkDFT
Function 'calc_density_correction()' has now two options. VASP-type calculations include not only a density-matrix correction (which is defined differently compared to Wien2K) but also a correction to the band energy.
This commit is contained in:
parent
daf40074b2
commit
041d1c6c40
@ -1163,7 +1163,7 @@ class SumkDFT:
|
|||||||
return self.chemical_potential
|
return self.chemical_potential
|
||||||
|
|
||||||
|
|
||||||
def calc_density_correction(self, filename='dens_mat.dat'):
|
def calc_density_correction(self, filename=None, dm_type='wien2k'):
|
||||||
r"""
|
r"""
|
||||||
Calculates the charge density correction and stores it into a file.
|
Calculates the charge density correction and stores it into a file.
|
||||||
|
|
||||||
@ -1188,11 +1188,37 @@ class SumkDFT:
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
assert type(filename) == StringType, "calc_density_correction: filename has to be a string!"
|
# assert type(filename) == StringType, "calc_density_correction: filename has to be a string!"
|
||||||
|
assert dm_type in ('vasp', 'wien2k'), "'dm_type' must be either 'vasp' or 'wienk'"
|
||||||
|
|
||||||
|
if filename is None:
|
||||||
|
if dm_type == 'wien2k':
|
||||||
|
filename = 'dens_mat.dat'
|
||||||
|
elif dm_type == 'vasp':
|
||||||
|
filename = 'GAMMA'
|
||||||
|
|
||||||
ntoi = self.spin_names_to_ind[self.SO]
|
ntoi = self.spin_names_to_ind[self.SO]
|
||||||
spn = self.spin_block_names[self.SO]
|
spn = self.spin_block_names[self.SO]
|
||||||
dens = {sp: 0.0 for sp in spn}
|
dens = {sp: 0.0 for sp in spn}
|
||||||
|
band_en_correction = 0.0
|
||||||
|
|
||||||
|
# Fetch Fermi weights and energy window band indices
|
||||||
|
if dm_type == 'vasp':
|
||||||
|
fermi_weights = 0
|
||||||
|
band_window = 0
|
||||||
|
if mpi.is_master_node():
|
||||||
|
ar = HDFArchive(self.hdf_file,'r')
|
||||||
|
fermi_weights = ar['dft_misc_input']['dft_fermi_weights']
|
||||||
|
band_window = ar['dft_misc_input']['band_window']
|
||||||
|
del ar
|
||||||
|
fermi_weights = mpi.bcast(fermi_weights)
|
||||||
|
band_window = mpi.bcast(band_window)
|
||||||
|
|
||||||
|
# Convert Fermi weights to a density matrix
|
||||||
|
dens_mat_dft = {}
|
||||||
|
for sp in spn:
|
||||||
|
dens_mat_dft[sp] = [fermi_weights[ik, ntoi[sp], :].astype(numpy.complex_) for ik in xrange(self.n_k)]
|
||||||
|
|
||||||
|
|
||||||
# Set up deltaN:
|
# Set up deltaN:
|
||||||
deltaN = {}
|
deltaN = {}
|
||||||
@ -1205,6 +1231,17 @@ class SumkDFT:
|
|||||||
for bname,gf in G_latt_iw:
|
for bname,gf in G_latt_iw:
|
||||||
deltaN[bname][ik] = G_latt_iw[bname].density()
|
deltaN[bname][ik] = G_latt_iw[bname].density()
|
||||||
dens[bname] += self.bz_weights[ik] * G_latt_iw[bname].total_density()
|
dens[bname] += self.bz_weights[ik] * G_latt_iw[bname].total_density()
|
||||||
|
if dm_type == 'vasp':
|
||||||
|
# In 'vasp'-mode subtract the DFT density matrix
|
||||||
|
diag_inds = numpy.diag_indices(self.n_orbitals[ik, ntoi[bname]])
|
||||||
|
deltaN[bname][ik][diag_inds] -= dens_mat_dft[bname][ik]
|
||||||
|
dens[bname] -= self.bz_weights[ik] * dens_mat_dft[bname][ik].sum().real
|
||||||
|
isp = ntoi[bname]
|
||||||
|
b1, b2 = self.band_window[isp][ik, :2]
|
||||||
|
nb = b2 - b1 + 1
|
||||||
|
assert nb == self.n_orbitals[ik, ntoi[bname]], "Number of bands is inconsistent at ik = %s"%(ik)
|
||||||
|
band_en_correction += numpy.dot(deltaN[bname][ik], self.hopping[ik, isp, :nb, :nb]).trace().real * self.bz_weights[ik]
|
||||||
|
|
||||||
|
|
||||||
# mpi reduce:
|
# mpi reduce:
|
||||||
for bname in deltaN:
|
for bname in deltaN:
|
||||||
@ -1212,51 +1249,77 @@ class SumkDFT:
|
|||||||
deltaN[bname][ik] = mpi.all_reduce(mpi.world, deltaN[bname][ik], lambda x,y : x+y)
|
deltaN[bname][ik] = mpi.all_reduce(mpi.world, deltaN[bname][ik], lambda x,y : x+y)
|
||||||
dens[bname] = mpi.all_reduce(mpi.world, dens[bname], lambda x,y : x+y)
|
dens[bname] = mpi.all_reduce(mpi.world, dens[bname], lambda x,y : x+y)
|
||||||
mpi.barrier()
|
mpi.barrier()
|
||||||
|
band_en_correction = mpi.all_reduce(mpi.world, band_en_correction, lambda x,y : x+y)
|
||||||
|
|
||||||
# now save to file:
|
# now save to file:
|
||||||
if mpi.is_master_node():
|
if dm_type == 'wien2k':
|
||||||
if self.SP == 0:
|
if mpi.is_master_node():
|
||||||
f = open(filename,'w')
|
if self.SP == 0:
|
||||||
else:
|
f = open(filename,'w')
|
||||||
f = open(filename+'up','w')
|
else:
|
||||||
f1 = open(filename+'dn','w')
|
f = open(filename+'up','w')
|
||||||
# write chemical potential (in Rydberg):
|
f1 = open(filename+'dn','w')
|
||||||
f.write("%.14f\n"%(self.chemical_potential/self.energy_unit))
|
# write chemical potential (in Rydberg):
|
||||||
if self.SP != 0: f1.write("%.14f\n"%(self.chemical_potential/self.energy_unit))
|
f.write("%.14f\n"%(self.chemical_potential/self.energy_unit))
|
||||||
# write beta in rydberg-1
|
if self.SP != 0: f1.write("%.14f\n"%(self.chemical_potential/self.energy_unit))
|
||||||
f.write("%.14f\n"%(G_latt_iw.mesh.beta*self.energy_unit))
|
# write beta in rydberg-1
|
||||||
if self.SP != 0: f1.write("%.14f\n"%(G_latt_iw.mesh.beta*self.energy_unit))
|
f.write("%.14f\n"%(G_latt_iw.mesh.beta*self.energy_unit))
|
||||||
|
if self.SP != 0: f1.write("%.14f\n"%(G_latt_iw.mesh.beta*self.energy_unit))
|
||||||
|
|
||||||
if self.SP == 0: # no spin-polarization
|
if self.SP == 0: # no spin-polarization
|
||||||
|
|
||||||
for ik in range(self.n_k):
|
|
||||||
f.write("%s\n"%self.n_orbitals[ik,0])
|
|
||||||
for inu in range(self.n_orbitals[ik,0]):
|
|
||||||
for imu in range(self.n_orbitals[ik,0]):
|
|
||||||
valre = (deltaN['up'][ik][inu,imu].real + deltaN['down'][ik][inu,imu].real) / 2.0
|
|
||||||
valim = (deltaN['up'][ik][inu,imu].imag + deltaN['down'][ik][inu,imu].imag) / 2.0
|
|
||||||
f.write("%.14f %.14f "%(valre,valim))
|
|
||||||
f.write("\n")
|
|
||||||
f.write("\n")
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
elif self.SP == 1: # with spin-polarization
|
|
||||||
|
|
||||||
# dict of filename: (spin index, block_name)
|
|
||||||
if self.SO == 0: to_write = {f: (0, 'up'), f1: (1, 'down')}
|
|
||||||
if self.SO == 1: to_write = {f: (0, 'ud'), f1: (0, 'ud')}
|
|
||||||
for fout in to_write.iterkeys():
|
|
||||||
isp, sp = to_write[fout]
|
|
||||||
for ik in range(self.n_k):
|
for ik in range(self.n_k):
|
||||||
fout.write("%s\n"%self.n_orbitals[ik,isp])
|
f.write("%s\n"%self.n_orbitals[ik,0])
|
||||||
for inu in range(self.n_orbitals[ik,isp]):
|
for inu in range(self.n_orbitals[ik,0]):
|
||||||
for imu in range(self.n_orbitals[ik,isp]):
|
for imu in range(self.n_orbitals[ik,0]):
|
||||||
fout.write("%.14f %.14f "%(deltaN[sp][ik][inu,imu].real,deltaN[sp][ik][inu,imu].imag))
|
valre = (deltaN['up'][ik][inu,imu].real + deltaN['down'][ik][inu,imu].real) / 2.0
|
||||||
fout.write("\n")
|
valim = (deltaN['up'][ik][inu,imu].imag + deltaN['down'][ik][inu,imu].imag) / 2.0
|
||||||
fout.write("\n")
|
f.write("%.14f %.14f "%(valre,valim))
|
||||||
fout.close()
|
f.write("\n")
|
||||||
|
f.write("\n")
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
elif self.SP == 1: # with spin-polarization
|
||||||
|
|
||||||
|
# dict of filename: (spin index, block_name)
|
||||||
|
if self.SO == 0: to_write = {f: (0, 'up'), f1: (1, 'down')}
|
||||||
|
if self.SO == 1: to_write = {f: (0, 'ud'), f1: (0, 'ud')}
|
||||||
|
for fout in to_write.iterkeys():
|
||||||
|
isp, sp = to_write[fout]
|
||||||
|
for ik in range(self.n_k):
|
||||||
|
fout.write("%s\n"%self.n_orbitals[ik,isp])
|
||||||
|
for inu in range(self.n_orbitals[ik,isp]):
|
||||||
|
for imu in range(self.n_orbitals[ik,isp]):
|
||||||
|
fout.write("%.14f %.14f "%(deltaN[sp][ik][inu,imu].real,deltaN[sp][ik][inu,imu].imag))
|
||||||
|
fout.write("\n")
|
||||||
|
fout.write("\n")
|
||||||
|
fout.close()
|
||||||
|
elif dm_type == 'vasp':
|
||||||
|
assert self.SP == 0, "Spin-polarized density matrix is not implemented"
|
||||||
|
|
||||||
|
if mpi.is_master_node():
|
||||||
|
with open(filename, 'w') as f:
|
||||||
|
f.write(" %i -1 ! Number of k-points, default number of bands\n"%(self.n_k))
|
||||||
|
for ik in xrange(self.n_k):
|
||||||
|
ib1 = band_window[0][ik, 0]
|
||||||
|
ib2 = band_window[0][ik, 1]
|
||||||
|
f.write(" %i %i %i\n"%(ik + 1, ib1, ib2))
|
||||||
|
for inu in xrange(self.n_orbitals[ik, 0]):
|
||||||
|
for imu in xrange(self.n_orbitals[ik, 0]):
|
||||||
|
valre = (deltaN['up'][ik][inu, imu].real + deltaN['down'][ik][inu, imu].real) / 2.0
|
||||||
|
valim = (deltaN['up'][ik][inu, imu].imag + deltaN['down'][ik][inu, imu].imag) / 2.0
|
||||||
|
f.write(" %.14f %.14f"%(valre, valim))
|
||||||
|
f.write("\n")
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Unknown density matrix type: '%s'"%(dm_type))
|
||||||
|
|
||||||
|
res = deltaN, dens
|
||||||
|
|
||||||
|
if dm_type == 'vasp':
|
||||||
|
res += (band_en_correction,)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
return deltaN, dens
|
|
||||||
|
|
||||||
################
|
################
|
||||||
# FIXME LEAVE UNDOCUMENTED
|
# FIXME LEAVE UNDOCUMENTED
|
||||||
|
Loading…
Reference in New Issue
Block a user