3
0
mirror of https://github.com/triqs/dft_tools synced 2024-06-29 08:24:54 +02:00

Merge simple_point_dens_mat and density_gf into a single function density_matrix

density_matrix takes as argument method == using_gf or using_point_integration
This commit is contained in:
Priyanka Seth 2014-11-16 18:02:04 +01:00
parent 4cb0d67e02
commit 5eaa27a946
4 changed files with 42 additions and 72 deletions

View File

@ -58,3 +58,4 @@ setattr(self,it,mpi.bcast(getattr(self,it))
* replaced long archive saves in converters by setattr construction * replaced long archive saves in converters by setattr construction
* removed G_upfolded_id -- looked redundant * removed G_upfolded_id -- looked redundant
* write corr_to_inequiv, inequiv_to_corr, n_inequiv_shells (shellmap, invshellmap, n_inequiv_corr_shells) in converter * write corr_to_inequiv, inequiv_to_corr, n_inequiv_shells (shellmap, invshellmap, n_inequiv_corr_shells) in converter
* merge simple_point_dens_mat and density_gf into a single function density_matrix

View File

@ -295,35 +295,46 @@ class SumkLDA:
return self.G_upfold return self.G_upfold
def simple_point_dens_mat(self): def density_matrix(self, method = 'using_gf', beta=40.0):
"""Calculate density matrices in one of two ways:
ntoi = self.spin_names_to_ind[self.SO] if 'using_gf': First get upfolded gf (g_loc is not set up), then density matrix.
bln = self.spin_block_names[self.SO] It is useful for Hubbard I, and very quick.
No assumption on the hopping structure is made (ie diagonal or not).
MMat = [numpy.zeros( [self.n_orbitals[0,ntoi[bl]],self.n_orbitals[0,ntoi[bl]]], numpy.complex_) for bl in bln] if 'using_point_integration': Only works for diagonal hopping matrix (true in wien2k).
"""
dens_mat = [ {} for icrsh in range(self.n_corr_shells)] dens_mat = [ {} for icrsh in range(self.n_corr_shells)]
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
for bl in self.spin_block_names[self.corr_shells[icrsh][4]]: for bl in self.spin_block_names[self.corr_shells[icrsh][4]]:
dens_mat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_) dens_mat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_)
ikarray = numpy.array(range(self.n_k)) ikarray = numpy.array(range(self.n_k))
for ik in mpi.slice_array(ikarray): for ik in mpi.slice_array(ikarray):
unchangedsize = all( [ self.n_orbitals[ik,ntoi[bln[ibl]]] == len(MMat[ibl]) if method == "using_gf":
for ibl in range(self.n_spin_blocks[self.SO]) ] )
if not unchangedsize: G_upfold = self.lattice_gf_matsubara(ik=ik, beta=beta, mu=self.chemical_potential)
MMat = [numpy.zeros( [self.n_orbitals[ik,ntoi[bl]],self.n_orbitals[ik,ntoi[bl]]], numpy.complex_) for bl in bln] G_upfold *= self.bz_weights[ik]
dm = G_upfold.density()
MMat = [dm[bl] for bl in self.spin_block_names[self.SO]]
for ibl, bl in enumerate(bln): elif method == "using_point_integration":
ind = ntoi[bl]
for inu in range(self.n_orbitals[ik,ind]): ntoi = self.spin_names_to_ind[self.SO]
if (self.hopping[ik,ind,inu,inu] - self.h_field*(1-2*ibl)) < 0.0: # only works for diagonal hopping matrix (true in wien2k) bln = self.spin_block_names[self.SO]
MMat[ibl][inu,inu] = 1.0 unchangedsize = all( [self.n_orbitals[ik,ntoi[bl]] == self.n_orbitals[0,ntoi[bl]] for bl in bln] )
else: if unchangedsize:
MMat[ibl][inu,inu] = 0.0 dim = self.n_orbitals[0,ntoi[bl]]
else:
dim = self.n_orbitals[ik,ntoi[bl]]
MMat = [numpy.zeros( [dim,dim], numpy.complex_) for bl in bln]
for ibl, bl in enumerate(bln):
ind = ntoi[bl]
for inu in range(self.n_orbitals[ik,ind]):
if (self.hopping[ik,ind,inu,inu] - self.h_field*(1-2*ibl)) < 0.0: # only works for diagonal hopping matrix (true in wien2k)
MMat[ibl][inu,inu] = 1.0
else:
MMat[ibl][inu,inu] = 0.0
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
for ibl, bn in enumerate(self.spin_block_names[self.corr_shells[icrsh][4]]): for ibl, bn in enumerate(self.spin_block_names[self.corr_shells[icrsh][4]]):
@ -331,8 +342,12 @@ class SumkLDA:
dim = self.corr_shells[icrsh][3] dim = self.corr_shells[icrsh][3]
n_orb = self.n_orbitals[ik,isp] n_orb = self.n_orbitals[ik,isp]
projmat = self.proj_mat[ik,isp,icrsh,0:dim,0:n_orb] projmat = self.proj_mat[ik,isp,icrsh,0:dim,0:n_orb]
dens_mat[icrsh][bn] += self.bz_weights[ik] * numpy.dot( numpy.dot(projmat,MMat[ibl]) , if method == "using_gf":
projmat.transpose().conjugate() ) dens_mat[icrsh][bn] += numpy.dot( numpy.dot(projmat,MMat[ibl]),
projmat.transpose().conjugate() )
elif method == "using_point_integration":
dens_mat[icrsh][bn] += self.bz_weights[ik] * numpy.dot( numpy.dot(projmat,MMat[ibl]) ,
projmat.transpose().conjugate() )
# get data from nodes: # get data from nodes:
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
@ -347,57 +362,11 @@ class SumkLDA:
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
for bn in dens_mat[icrsh]: for bn in dens_mat[icrsh]:
if self.rot_mat_time_inv[icrsh] == 1: dens_mat[icrsh][bn] = dens_mat[icrsh][bn].conjugate() if self.rot_mat_time_inv[icrsh] == 1: dens_mat[icrsh][bn] = dens_mat[icrsh][bn].conjugate()
dens_mat[icrsh][bn] = numpy.dot( numpy.dot(self.rot_mat[icrsh].conjugate().transpose(),dens_mat[icrsh][bn]) , dens_mat[icrsh][bn] = numpy.dot( numpy.dot(self.rot_mat[icrsh].conjugate().transpose(),dens_mat[icrsh][bn]),
self.rot_mat[icrsh] ) self.rot_mat[icrsh] )
return dens_mat return dens_mat
# Calculate upfolded gf, then density matrix. No assumption on the structure made here (ie diagonal or not).
def density_gf(self,beta):
"""Calculates the density without setting up Gloc. It is useful for Hubbard I, and very quick."""
dens_mat = [ {} for icrsh in range(self.n_corr_shells)]
for icrsh in range(self.n_corr_shells):
for bl in self.spin_block_names[self.corr_shells[icrsh][4]]:
dens_mat[icrsh][bl] = numpy.zeros([self.corr_shells[icrsh][3],self.corr_shells[icrsh][3]], numpy.complex_)
ikarray = numpy.array(range(self.n_k))
for ik in mpi.slice_array(ikarray):
G_upfold = self.lattice_gf_matsubara(ik=ik, beta=beta, mu=self.chemical_potential)
G_upfold *= self.bz_weights[ik]
dm = G_upfold.density()
MMat = [dm[bl] for bl in self.spin_block_names[self.SO]]
for icrsh in range(self.n_corr_shells):
for ibl, bn in enumerate(self.spin_block_names[self.corr_shells[icrsh][4]]):
isp = self.spin_names_to_ind[self.corr_shells[icrsh][4]][bn]
dim = self.corr_shells[icrsh][3]
n_orb = self.n_orbitals[ik,isp]
projmat = self.proj_mat[ik,isp,icrsh,0:dim,0:n_orb]
dens_mat[icrsh][bn] += numpy.dot( numpy.dot(projmat,MMat[ibl]),
projmat.transpose().conjugate() )
# get data from nodes:
for icrsh in range(self.n_corr_shells):
for bname in dens_mat[icrsh]:
dens_mat[icrsh][bname] = mpi.all_reduce(mpi.world, dens_mat[icrsh][bname], lambda x,y : x+y)
mpi.barrier()
if self.symm_op != 0: dens_mat = self.symmcorr.symmetrize(dens_mat)
# Rotate to local coordinate system:
if self.use_rotations:
for icrsh in range(self.n_corr_shells):
for bn in dens_mat[icrsh]:
if self.rot_mat_time_inv[icrsh] == 1: dens_mat[icrsh][bn] = dens_mat[icrsh][bn].conjugate()
dens_mat[icrsh][bn] = numpy.dot( numpy.dot(self.rot_mat[icrsh].conjugate().transpose(),dens_mat[icrsh][bn]) ,
self.rot_mat[icrsh] )
return dens_mat
def analyse_block_structure(self, threshold = 0.00001, include_shells = None, dm = None): def analyse_block_structure(self, threshold = 0.00001, include_shells = None, dm = None):
""" Determines the Green function block structure from simple point integration.""" """ Determines the Green function block structure from simple point integration."""
@ -407,7 +376,7 @@ class SumkLDA:
self.solver_to_sumk = [ {} for ish in range(self.n_inequiv_shells) ] self.solver_to_sumk = [ {} for ish in range(self.n_inequiv_shells) ]
self.solver_to_sumk_block = [ {} for ish in range(self.n_inequiv_shells) ] self.solver_to_sumk_block = [ {} for ish in range(self.n_inequiv_shells) ]
if dm is None: dm = self.simple_point_dens_mat() if dm is None: dm = self.density_matrix(method = 'using_point_integration')
dens_mat = [ dm[self.inequiv_to_corr[ish]] for ish in range(self.n_inequiv_shells) ] dens_mat = [ dm[self.inequiv_to_corr[ish]] for ish in range(self.n_inequiv_shells) ]
if include_shells is None: include_shells = range(self.n_inequiv_shells) if include_shells is None: include_shells = range(self.n_inequiv_shells)
@ -499,7 +468,7 @@ class SumkLDA:
for bl in degsh: ss += gf_to_symm[bl] / (1.0*Ndeg) for bl in degsh: ss += gf_to_symm[bl] / (1.0*Ndeg)
for bl in degsh: gf_to_symm[bl] << ss for bl in degsh: gf_to_symm[bl] << ss
# for simple dft input, get crystal field splittings. # For simple dft input, get crystal field splittings.
def eff_atomic_levels(self): def eff_atomic_levels(self):
"""Calculates the effective atomic levels needed as input for the Hubbard I Solver.""" """Calculates the effective atomic levels needed as input for the Hubbard I Solver."""

View File

@ -37,7 +37,7 @@ class TransBasis:
if prop_to_be_diagonal == 'eal': if prop_to_be_diagonal == 'eal':
prop = self.SK.eff_atomic_levels()[0] prop = self.SK.eff_atomic_levels()[0]
elif prop_to_be_diagonal == 'dm': elif prop_to_be_diagonal == 'dm':
prop = self.SK.simple_point_dens_mat()[0] prop = self.SK.density_matrix(method = 'using_point_integration')[0]
else: else:
mpi.report("trans_basis: not a valid quantitiy to be diagonal. Choices are 'eal' or 'dm'.") mpi.report("trans_basis: not a valid quantitiy to be diagonal. Choices are 'eal' or 'dm'.")
return 0 return 0

View File

@ -26,7 +26,7 @@ from pytriqs.applications.dft.sumk_lda_tools import SumkLDATools
SK = SumkLDATools(hdf_file = 'SrVO3.h5') SK = SumkLDATools(hdf_file = 'SrVO3.h5')
dm = SK.density_gf(40) dm = SK.density_matrix(method = 'using_gf', beta = 40)
dm_pc = SK.partial_charges(40) dm_pc = SK.partial_charges(40)
ar = HDFArchive('sumklda_basic.output.h5','w') ar = HDFArchive('sumklda_basic.output.h5','w')