3
0
mirror of https://github.com/triqs/dft_tools synced 2025-05-01 20:55:06 +02:00

revert auto formatting from prev commits

This commit is contained in:
the-hampel 2025-01-09 14:11:50 +01:00
parent de701d17af
commit 2b2b86846c

View File

@ -1,3 +1,4 @@
########################################################################## ##########################################################################
# #
# TRIQS: a Toolbox for Research in Interacting Quantum Systems # TRIQS: a Toolbox for Research in Interacting Quantum Systems
@ -23,7 +24,6 @@
General SumK class and helper functions for combining ab-initio code and triqs General SumK class and helper functions for combining ab-initio code and triqs
""" """
import os
from types import * from types import *
import numpy as np import numpy as np
import triqs.utility.dichotomy as dichotomy import triqs.utility.dichotomy as dichotomy
@ -121,33 +121,26 @@ class SumkDFT(object):
self.block_structure = BlockStructure() self.block_structure = BlockStructure()
# Read input from HDF: # Read input from HDF:
req_things_to_read = ['energy_unit', 'n_k', 'k_dep_projection', 'SP', 'SO', 'charge_below', req_things_to_read = ['energy_unit', 'n_k', 'k_dep_projection', 'SP', 'SO', 'charge_below', 'density_required',
'density_required', 'symm_op', 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'use_rotations', 'rot_mat',
'symm_op', 'n_shells', 'shells', 'n_corr_shells', 'corr_shells', 'use_rotations', 'rot_mat_time_inv', 'n_reps', 'dim_reps', 'T', 'n_orbitals', 'proj_mat', 'bz_weights', 'hopping',
'rot_mat',
'rot_mat_time_inv', 'n_reps', 'dim_reps', 'T', 'n_orbitals', 'proj_mat', 'bz_weights',
'hopping',
'n_inequiv_shells', 'corr_to_inequiv', 'inequiv_to_corr'] 'n_inequiv_shells', 'corr_to_inequiv', 'inequiv_to_corr']
self.subgroup_present, self.values_not_read = self.read_input_from_hdf( self.subgroup_present, self.values_not_read = self.read_input_from_hdf(
subgrp=self.dft_data, things_to_read=req_things_to_read) subgrp=self.dft_data, things_to_read=req_things_to_read)
# test if all required properties have been found # test if all required properties have been found
if len(self.values_not_read) > 0 and mpi.is_master_node: if len(self.values_not_read) > 0 and mpi.is_master_node:
raise ValueError( raise ValueError('ERROR: One or more necessary SumK input properties have not been found in the given h5 archive:', self.values_not_read)
'ERROR: One or more necessary SumK input properties have not been found in the given h5 archive:',
self.values_not_read)
# optional properties to load # optional properties to load
# soon bz_weights is depraced and replaced by kpt_weights, kpts_basis and kpts will become required to read soon # soon bz_weights is depraced and replaced by kpt_weights, kpts_basis and kpts will become required to read soon
optional_things_to_read = ['proj_mat_csc', 'proj_or_hk', 'kpt_basis', 'kpts', 'kpt_weights', 'dft_code'] optional_things_to_read = ['proj_mat_csc', 'proj_or_hk', 'kpt_basis', 'kpts', 'kpt_weights', 'dft_code']
subgroup_present, self.optional_values_not_read = self.read_input_from_hdf(subgrp=self.dft_data, subgroup_present, self.optional_values_not_read = self.read_input_from_hdf(subgrp=self.dft_data, things_to_read=optional_things_to_read)
things_to_read=optional_things_to_read)
# warning if dft_code was not read (old h5 structure) # warning if dft_code was not read (old h5 structure)
if 'dft_code' in self.optional_values_not_read: if 'dft_code' in self.optional_values_not_read:
self.dft_code = None self.dft_code = None
mpi.report( mpi.report('\nWarning: old h5 archive without dft_code input flag detected. Please specify sumk.dft_code manually!\n')
'\nWarning: old h5 archive without dft_code input flag detected. Please specify sumk.dft_code manually!\n')
if self.symm_op: if self.symm_op:
self.symmcorr = Symmetry(hdf_file, subgroup=self.symmcorr_data) self.symmcorr = Symmetry(hdf_file, subgroup=self.symmcorr_data)
@ -170,13 +163,11 @@ class SumkDFT(object):
# GF structure used for the local things in the k sums # GF structure used for the local things in the k sums
# Most general form allowing for all hybridisation, i.e. largest # Most general form allowing for all hybridisation, i.e. largest
# blocks possible # blocks possible
self.gf_struct_sumk = [ self.gf_struct_sumk = [[(sp, self.corr_shells[icrsh]['dim']) for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]]
[(sp, self.corr_shells[icrsh]['dim']) for sp in self.spin_block_names[self.corr_shells[icrsh]['SO']]]
for icrsh in range(self.n_corr_shells)] for icrsh in range(self.n_corr_shells)]
# First set a standard gf_struct solver (add _0 here for consistency with analyse_block_structure): # First set a standard gf_struct solver (add _0 here for consistency with analyse_block_structure):
self.gf_struct_solver = [dict([(sp+'_0', self.corr_shells[self.inequiv_to_corr[ish]]['dim']) self.gf_struct_solver = [dict([(sp+'_0', self.corr_shells[self.inequiv_to_corr[ish]]['dim'])
for sp in for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]])
self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]])
for ish in range(self.n_inequiv_shells)] for ish in range(self.n_inequiv_shells)]
# Set standard (identity) maps from gf_struct_sumk <-> # Set standard (identity) maps from gf_struct_sumk <->
# gf_struct_solver # gf_struct_solver
@ -486,8 +477,7 @@ class SumkDFT(object):
gf_rotated.from_L_G_R(rot_mat[ish].conjugate( gf_rotated.from_L_G_R(rot_mat[ish].conjugate(
), gf_rotated, rot_mat[ish].transpose()) ), gf_rotated, rot_mat[ish].transpose())
else: else:
gf_rotated.from_L_G_R(rot_mat[ish], gf_rotated, rot_mat[ gf_rotated.from_L_G_R(rot_mat[ish], gf_rotated, rot_mat[ish].conjugate().transpose())
ish].conjugate().transpose())
elif direction == 'toLocal': elif direction == 'toLocal':
@ -550,8 +540,7 @@ class SumkDFT(object):
else: # Check that existing GF is consistent else: # Check that existing GF is consistent
G_latt = self.G_latt G_latt = self.G_latt
GFsize = [gf.target_shape[0] for bname, gf in G_latt] GFsize = [gf.target_shape[0] for bname, gf in G_latt]
unchangedsize = all([self.n_orbitals[ik, ntoi[spn[isp]]] == GFsize[ unchangedsize = all([self.n_orbitals[ik, ntoi[spn[isp]]] == GFsize[isp] for isp in range(self.n_spin_blocks[self.SO])])
isp] for isp in range(self.n_spin_blocks[self.SO])])
if (not mesh is None) or (not unchangedsize): if (not mesh is None) or (not unchangedsize):
set_up_G_latt = True set_up_G_latt = True
@ -578,8 +567,7 @@ class SumkDFT(object):
mesh_values = self.mesh_values mesh_values = self.mesh_values
elif not mesh is None: elif not mesh is None:
assert isinstance(mesh, assert isinstance(mesh, (MeshReFreq, MeshDLRImFreq, MeshImFreq)), "mesh must be a triqs MeshReFreq or MeshImFreq"
(MeshReFreq, MeshDLRImFreq, MeshImFreq)), "mesh must be a triqs MeshReFreq or MeshImFreq"
if isinstance(mesh, MeshImFreq): if isinstance(mesh, MeshImFreq):
mesh_values = np.linspace(mesh(mesh.first_index()), mesh(mesh.last_index()), len(mesh)) mesh_values = np.linspace(mesh(mesh.first_index()), mesh(mesh.last_index()), len(mesh))
elif isinstance(mesh, MeshDLRImFreq): elif isinstance(mesh, MeshDLRImFreq):
@ -662,12 +650,9 @@ class SumkDFT(object):
self.Sigma_imp = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, space='sumk') self.Sigma_imp = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, space='sumk')
for icrsh in range(self.n_corr_shells)] for icrsh in range(self.n_corr_shells)]
SK_Sigma_imp = self.Sigma_imp SK_Sigma_imp = self.Sigma_imp
elif isinstance(self.mesh, MeshReFreq) and all( elif isinstance(self.mesh, MeshReFreq) and all(isinstance(gf, Gf) and isinstance(gf.mesh, MeshReFreq) and gf.mesh == self.mesh for bname, gf in Sigma_imp[0]):
isinstance(gf, Gf) and isinstance(gf.mesh, MeshReFreq) and gf.mesh == self.mesh for bname, gf in
Sigma_imp[0]):
# Real frequency Sigma: # Real frequency Sigma:
self.Sigma_imp = [ self.Sigma_imp = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, gf_function=Gf, space='sumk')
self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, gf_function=Gf, space='sumk')
for icrsh in range(self.n_corr_shells)] for icrsh in range(self.n_corr_shells)]
SK_Sigma_imp = self.Sigma_imp SK_Sigma_imp = self.Sigma_imp
@ -689,11 +674,8 @@ class SumkDFT(object):
if self.min_band_energy is None or self.max_band_energy is None: if self.min_band_energy is None or self.max_band_energy is None:
self.calculate_min_max_band_energies() self.calculate_min_max_band_energies()
mesh = np.linspace(self.mesh.w_min, self.mesh.w_max, len(self.mesh)) mesh = np.linspace(self.mesh.w_min, self.mesh.w_max, len(self.mesh))
if mesh[0] > (self.min_band_energy - self.chemical_potential) or mesh[-1] < ( if mesh[0] > (self.min_band_energy - self.chemical_potential) or mesh[-1] < (self.max_band_energy - self.chemical_potential):
self.max_band_energy - self.chemical_potential): warn('The given Sigma is on a mesh which does not cover the band energy range. The Sigma MeshReFreq runs from %f to %f, while the band energy (minus the chemical potential) runs from %f to %f'%(mesh[0], mesh[-1], self.min_band_energy, self.max_band_energy))
warn(
'The given Sigma is on a mesh which does not cover the band energy range. The Sigma MeshReFreq runs from %f to %f, while the band energy (minus the chemical potential) runs from %f to %f' % (
mesh[0], mesh[-1], self.min_band_energy, self.max_band_energy))
def transform_to_sumk_blocks(self, Sigma_imp, Sigma_out=None): def transform_to_sumk_blocks(self, Sigma_imp, Sigma_out=None):
r""" transform Sigma from solver to sumk space r""" transform Sigma from solver to sumk space
@ -714,8 +696,7 @@ class SumkDFT(object):
"transform_to_sumk_blocks: give exactly one Sigma for each inequivalent corr. shell!" "transform_to_sumk_blocks: give exactly one Sigma for each inequivalent corr. shell!"
if Sigma_out is None: if Sigma_out is None:
Sigma_out = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[self.corr_to_inequiv[icrsh]].mesh, Sigma_out = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[self.corr_to_inequiv[icrsh]].mesh, space='sumk')
space='sumk')
for icrsh in range(self.n_corr_shells)] for icrsh in range(self.n_corr_shells)]
else: else:
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
@ -892,12 +873,10 @@ class SumkDFT(object):
""" """
if dm is None: if dm is None:
warn( warn("WARNING: No density matrix given. Calculating density matrix with default parameters. This will be deprecated in future releases.")
"WARNING: No density matrix given. Calculating density matrix with default parameters. This will be deprecated in future releases.")
dm = self.density_matrix(method='using_gf', transform_to_solver_blocks=False) dm = self.density_matrix(method='using_gf', transform_to_solver_blocks=False)
assert len( assert len(dm) == self.n_corr_shells, "The number of density matrices must be equal to the number of correlated shells."
dm) == self.n_corr_shells, "The number of density matrices must be equal to the number of correlated shells."
dens_mat = [dm[self.inequiv_to_corr[ish]] dens_mat = [dm[self.inequiv_to_corr[ish]]
for ish in range(self.n_inequiv_shells)] for ish in range(self.n_inequiv_shells)]
if hloc is None: if hloc is None:
@ -912,8 +891,7 @@ class SumkDFT(object):
self.solver_to_sumk_block[ish] = {} self.solver_to_sumk_block[ish] = {}
for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]: for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]:
assert sp in dens_mat[ assert sp in dens_mat[ish], f"The density matrix does not contain the block {sp}. Is the input dm given in sumk block structure?"
ish], f"The density matrix does not contain the block {sp}. Is the input dm given in sumk block structure?"
n_orb = self.corr_shells[self.inequiv_to_corr[ish]]['dim'] n_orb = self.corr_shells[self.inequiv_to_corr[ish]]['dim']
# gives an index list of entries larger that threshold # gives an index list of entries larger that threshold
dmbool = (abs(dens_mat[ish][sp]) > threshold) dmbool = (abs(dens_mat[ish][sp]) > threshold)
@ -1013,8 +991,7 @@ class SumkDFT(object):
# make a GfImTime from the supplied GfImFreq # make a GfImTime from the supplied GfImFreq
if all(isinstance(g_sh.mesh, MeshImFreq) for g_sh in G): if all(isinstance(g_sh.mesh, MeshImFreq) for g_sh in G):
gf = [BlockGf(name_block_generator = [(name, GfImTime(beta=block.mesh.beta, gf = [BlockGf(name_block_generator = [(name, GfImTime(beta=block.mesh.beta,
indices=block.indices, n_points=len(block.mesh) + 1)) indices=block.indices,n_points=len(block.mesh)+1)) for name, block in g_sh],
for name, block in g_sh],
make_copies=False) for g_sh in G] make_copies=False) for g_sh in G]
for ish in range(len(gf)): for ish in range(len(gf)):
for name, g in gf[ish]: for name, g in gf[ish]:
@ -1036,7 +1013,6 @@ class SumkDFT(object):
w0 = w w0 = w
else: else:
return w-w0 return w-w0
gf = [BlockGf(name_block_generator = [(name, GfReFreq( gf = [BlockGf(name_block_generator = [(name, GfReFreq(
window=(-np.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)), window=(-np.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh)),
np.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh))), np.pi*(len(block.mesh)-1) / (len(block.mesh)*get_delta_from_mesh(block.mesh))),
@ -1051,6 +1027,8 @@ class SumkDFT(object):
raise Exception("G must be a list of BlockGf of either GfImFreq, GfImTime, GfReFreq or GfReTime") raise Exception("G must be a list of BlockGf of either GfImFreq, GfImTime, GfReFreq or GfReTime")
return gf return gf
def analyse_block_structure_from_gf(self, G, threshold=1.e-5, include_shells=None, analyse_deg_shells = True): def analyse_block_structure_from_gf(self, G, threshold=1.e-5, include_shells=None, analyse_deg_shells = True):
r""" r"""
Determines the block structure of local Green's functions by analysing Determines the block structure of local Green's functions by analysing
@ -1084,8 +1062,7 @@ class SumkDFT(object):
""" """
assert isinstance(G, list), "G must be a list (with elements for each correlated shell)" assert isinstance(G, list), "G must be a list (with elements for each correlated shell)"
assert len( assert len(G) == self.n_corr_shells, "G must have one element for each correlated shell, run extract_G_loc with transform_to_solver_blocks=False to get the correct G"
G) == self.n_corr_shells, "G must have one element for each correlated shell, run extract_G_loc with transform_to_solver_blocks=False to get the correct G"
gf = self._get_hermitian_quantity_from_gf(G) gf = self._get_hermitian_quantity_from_gf(G)
@ -1099,8 +1076,7 @@ class SumkDFT(object):
self.solver_to_sumk[ish] = {} self.solver_to_sumk[ish] = {}
self.solver_to_sumk_block[ish] = {} self.solver_to_sumk_block[ish] = {}
for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]: for sp in self.spin_block_names[self.corr_shells[self.inequiv_to_corr[ish]]['SO']]:
assert sp in gf[self.inequiv_to_corr[ assert sp in gf[self.inequiv_to_corr[ish]].indices, f"The Green's function does not contain the block {sp}. Is the input G given in sumk block structure?"
ish]].indices, f"The Green's function does not contain the block {sp}. Is the input G given in sumk block structure?"
n_orb = self.corr_shells[self.inequiv_to_corr[ish]]['dim'] n_orb = self.corr_shells[self.inequiv_to_corr[ish]]['dim']
# gives an index list of entries larger that threshold # gives an index list of entries larger that threshold
@ -1269,15 +1245,13 @@ class SumkDFT(object):
# product to get a linear problem, which consists # product to get a linear problem, which consists
# of finding the null space of M vec T = 0. # of finding the null space of M vec T = 0.
M = np.kron(np.eye(*gf1.target_shape), gf2.data[0]) - np.kron(gf1.data[0].transpose(), M = np.kron(np.eye(*gf1.target_shape),gf2.data[0])-np.kron(gf1.data[0].transpose(),np.eye(*gf1.target_shape))
np.eye(*gf1.target_shape))
N = null(M, threshold) N = null(M, threshold)
# now we get the intersection of the null spaces # now we get the intersection of the null spaces
# of all values of tau # of all values of tau
for i in range(1,len(gf1.data)): for i in range(1,len(gf1.data)):
M = np.kron(np.eye(*gf1.target_shape), gf2.data[i]) - np.kron(gf1.data[i].transpose(), M = np.kron(np.eye(*gf1.target_shape),gf2.data[i])-np.kron(gf1.data[i].transpose(),np.eye(*gf1.target_shape))
np.eye(*gf1.target_shape))
# transform M into current null space # transform M into current null space
M = np.dot(M, N) M = np.dot(M, N)
N = np.dot(N, null(M, threshold)) N = np.dot(N, null(M, threshold))
@ -1311,7 +1285,6 @@ class SumkDFT(object):
Then, it calculates the chi2 of Then, it calculates the chi2 of
sum y[i] N[:,:,i] y[j].conjugate() N[:,:,j].conjugate().transpose() - eye. sum y[i] N[:,:,i] y[j].conjugate() N[:,:,j].conjugate().transpose() - eye.
""" """
def chi2(y): def chi2(y):
# reinterpret y as complex number # reinterpret y as complex number
y = y.view(complex) y = y.view(complex)
@ -1372,8 +1345,7 @@ class SumkDFT(object):
# C1(v1^dagger G1 v1) = C2(v2^dagger G2 v2) # C1(v1^dagger G1 v1) = C2(v2^dagger G2 v2)
if (ind1 < 0) and (ind2 >= 0): if (ind1 < 0) and (ind2 >= 0):
if conjugate: if conjugate:
self.deg_shells[ish][ind2][block1] = np.dot(T.conjugate().transpose(), self.deg_shells[ish][ind2][block1] = np.dot(T.conjugate().transpose(), v2[0].conjugate()), not v2[1]
v2[0].conjugate()), not v2[1]
else: else:
self.deg_shells[ish][ind2][block1] = np.dot(T.conjugate().transpose(), v2[0]), v2[1] self.deg_shells[ish][ind2][block1] = np.dot(T.conjugate().transpose(), v2[0]), v2[1]
# the first block is already present # the first block is already present
@ -1404,8 +1376,7 @@ class SumkDFT(object):
# a block was found, break out of the loop # a block was found, break out of the loop
break break
def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=True, def calculate_diagonalization_matrix(self, prop_to_be_diagonal='eal', calc_in_solver_blocks=True, write_to_blockstructure = True, shells=None):
write_to_blockstructure=True, shells=None):
""" """
Calculates the diagonalisation matrix, and (optionally) stores it in the BlockStructure. Calculates the diagonalisation matrix, and (optionally) stores it in the BlockStructure.
@ -1541,12 +1512,12 @@ class SumkDFT(object):
for sp in dens_mat[icrsh]: for sp in dens_mat[icrsh]:
if self.rot_mat_time_inv[icrsh] == 1: if self.rot_mat_time_inv[icrsh] == 1:
dens_mat[icrsh][sp] = dens_mat[icrsh][sp].conjugate() dens_mat[icrsh][sp] = dens_mat[icrsh][sp].conjugate()
dens_mat[icrsh][sp] = np.dot( dens_mat[icrsh][sp] = np.dot(np.dot(self.rot_mat[icrsh].conjugate().transpose(), dens_mat[icrsh][sp]),
np.dot(self.rot_mat[icrsh].conjugate().transpose(), dens_mat[icrsh][sp]),
self.rot_mat[icrsh]) self.rot_mat[icrsh])
return dens_mat return dens_mat
def density_matrix(self, method='using_gf', mu=None, with_Sigma=True, with_dc=True, broadening=None, def density_matrix(self, method='using_gf', mu=None, with_Sigma=True, with_dc=True, broadening=None,
transform_to_solver_blocks=True, show_warnings=True): transform_to_solver_blocks=True, show_warnings=True):
"""Calculate density matrices in one of two ways. """Calculate density matrices in one of two ways.
@ -1588,8 +1559,7 @@ class SumkDFT(object):
transform_to_solver_blocks, show_warnings) transform_to_solver_blocks, show_warnings)
dens_mat = [G.density() for G in Gloc] dens_mat = [G.density() for G in Gloc]
elif method == "using_point_integration": elif method == "using_point_integration":
warn( warn("WARNING: density_matrix: method 'using_point_integration' is deprecated. Use 'density_matrix_using_point_integration' instead. All additionally provided arguments are ignored.")
"WARNING: density_matrix: method 'using_point_integration' is deprecated. Use 'density_matrix_using_point_integration' instead. All additionally provided arguments are ignored.")
dens_mat = self.density_matrix_using_point_integration() dens_mat = self.density_matrix_using_point_integration()
else: else:
raise ValueError("density_matrix: the method '%s' is not supported." % method) raise ValueError("density_matrix: the method '%s' is not supported." % method)
@ -1648,8 +1618,7 @@ class SumkDFT(object):
for ik in range(self.n_k): for ik in range(self.n_k):
n_orb = self.n_orbitals[ik, ind] n_orb = self.n_orbitals[ik, ind]
MMat = np.identity(n_orb, complex) MMat = np.identity(n_orb, complex)
MMat = self.hopping[ MMat = self.hopping[ik, ind, 0:n_orb, 0:n_orb] - (1 - 2 * isp) * self.h_field * MMat
ik, ind, 0:n_orb, 0:n_orb] - (1 - 2 * isp) * self.h_field * MMat
projmat = self.proj_mat[ik, ind, icrsh, 0:dim, 0:n_orb] projmat = self.proj_mat[ik, ind, icrsh, 0:dim, 0:n_orb]
self.Hsumk[icrsh][sp] += self.bz_weights[ik] * np.dot(np.dot(projmat, MMat), self.Hsumk[icrsh][sp] += self.bz_weights[ik] * np.dot(np.dot(projmat, MMat),
projmat.conjugate().transpose()) projmat.conjugate().transpose())
@ -1664,8 +1633,7 @@ class SumkDFT(object):
if self.rot_mat_time_inv[icrsh] == 1: if self.rot_mat_time_inv[icrsh] == 1:
self.Hsumk[icrsh][sp] = self.Hsumk[ self.Hsumk[icrsh][sp] = self.Hsumk[
icrsh][sp].conjugate() icrsh][sp].conjugate()
self.Hsumk[icrsh][sp] = np.dot( self.Hsumk[icrsh][sp] = np.dot(np.dot(self.rot_mat[icrsh].conjugate().transpose(), self.Hsumk[icrsh][sp]),
np.dot(self.rot_mat[icrsh].conjugate().transpose(), self.Hsumk[icrsh][sp]),
self.rot_mat[icrsh]) self.rot_mat[icrsh])
# add to matrix: # add to matrix:
@ -1801,8 +1769,7 @@ class SumkDFT(object):
use_dc_formula = "sAMF" use_dc_formula = "sAMF"
for sp in spn: for sp in spn:
DC_val, E_val = compute_DC_from_density(N_tot=Ncrtot, U=U_interact, J=J_hund, n_orbitals=dim, DC_val, E_val = compute_DC_from_density(N_tot=Ncrtot,U=U_interact, J=J_hund, n_orbitals=dim, N_spin=Ncr[sp], method=use_dc_formula)
N_spin=Ncr[sp], method=use_dc_formula)
self.dc_imp[icrsh][sp] *= DC_val self.dc_imp[icrsh][sp] *= DC_val
self.dc_energ[icrsh] = E_val self.dc_energ[icrsh] = E_val
@ -1844,8 +1811,7 @@ class SumkDFT(object):
for bname, gf in sigma_minus_dc[icrsh]: for bname, gf in sigma_minus_dc[icrsh]:
# Transform dc_imp to global coordinate system # Transform dc_imp to global coordinate system
if self.use_rotations: if self.use_rotations:
gf -= np.dot(self.rot_mat[icrsh], gf -= np.dot(self.rot_mat[icrsh], np.dot(self.dc_imp[icrsh][bname], self.rot_mat[icrsh].conjugate().transpose()))
np.dot(self.dc_imp[icrsh][bname], self.rot_mat[icrsh].conjugate().transpose()))
else: else:
gf -= self.dc_imp[icrsh][bname] gf -= self.dc_imp[icrsh][bname]
@ -1998,11 +1964,9 @@ class SumkDFT(object):
beta = 1 / broadening beta = 1 / broadening
if isinstance(self.mesh, MeshReFreq): if isinstance(self.mesh, MeshReFreq):
def tot_den(bgf): def tot_den(bgf): return bgf.total_density(beta)
return bgf.total_density(beta)
else: else:
def tot_den(bgf): def tot_den(bgf): return bgf.total_density()
return bgf.total_density()
dens = 0.0 dens = 0.0
ikarray = np.array(list(range(self.n_k))) ikarray = np.array(list(range(self.n_k)))
@ -2062,7 +2026,6 @@ class SumkDFT(object):
within specified precision. within specified precision.
""" """
def find_bounds(function, x_init, delta_x, max_loops=1000): def find_bounds(function, x_init, delta_x, max_loops=1000):
mpi.report("Finding bounds on chemical potential") mpi.report("Finding bounds on chemical potential")
x = x_init x = x_init
@ -2097,11 +2060,8 @@ class SumkDFT(object):
# previous implementation # previous implementation
def F_bisection(mu): def F_bisection(mu): return self.total_density(mu=mu, broadening=broadening, beta=beta).real
return self.total_density(mu=mu, broadening=broadening, beta=beta).real
density = self.density_required - self.charge_below density = self.density_required - self.charge_below
# using scipy.optimize # using scipy.optimize
def F_optimize(mu): def F_optimize(mu):
@ -2155,8 +2115,7 @@ class SumkDFT(object):
return self.chemical_potential return self.chemical_potential
def calc_density_correction(self, filename=None, dm_type=None, spinave=False, kpts_to_write=None, broadening=None, def calc_density_correction(self, filename=None, dm_type=None, spinave=False, kpts_to_write=None, broadening=None, beta=None):
beta=None):
r""" r"""
Calculates the charge density correction and stores it into a file. Calculates the charge density correction and stores it into a file.
@ -2281,15 +2240,13 @@ class SumkDFT(object):
G2 = np.sum(self.kpts_cart[ik, :] ** 2) G2 = np.sum(self.kpts_cart[ik, :] ** 2)
# Kerker mixing # Kerker mixing
mix_fac = self.charge_mixing_alpha * G2 / (G2 + self.charge_mixing_gamma ** 2) mix_fac = self.charge_mixing_alpha * G2 / (G2 + self.charge_mixing_gamma ** 2)
deltaN[bname][ik][diag_inds] = (1.0 - mix_fac) * self.deltaNOld[bname][ik][ deltaN[bname][ik][diag_inds] = (1.0 - mix_fac) * self.deltaNOld[bname][ik][diag_inds] + mix_fac * deltaN[bname][ik][diag_inds]
diag_inds] + mix_fac * deltaN[bname][ik][diag_inds]
dens[bname] -= self.bz_weights[ik] * dens_mat_dft[bname][ik].sum().real dens[bname] -= self.bz_weights[ik] * dens_mat_dft[bname][ik].sum().real
isp = ntoi[bname] isp = ntoi[bname]
b1, b2 = band_window[isp][ik, :2] b1, b2 = band_window[isp][ik, :2]
nb = b2 - b1 + 1 nb = b2 - b1 + 1
assert nb == self.n_orbitals[ik, ntoi[bname]], "Number of bands is inconsistent at ik = %s"%(ik) assert nb == self.n_orbitals[ik, ntoi[bname]], "Number of bands is inconsistent at ik = %s"%(ik)
band_en_correction += np.dot(deltaN[bname][ik], self.hopping[ik, isp, :nb, :nb]).trace().real * \ band_en_correction += np.dot(deltaN[bname][ik], self.hopping[ik, isp, :nb, :nb]).trace().real * self.bz_weights[ik]
self.bz_weights[ik]
# mpi reduce: # mpi reduce:
for bname in deltaN: for bname in deltaN:
@ -2299,6 +2256,8 @@ class SumkDFT(object):
self.deltaNOld = copy.copy(deltaN) self.deltaNOld = copy.copy(deltaN)
mpi.barrier() mpi.barrier()
band_en_correction = mpi.all_reduce(band_en_correction) band_en_correction = mpi.all_reduce(band_en_correction)
# now save to file: # now save to file:
@ -2325,10 +2284,8 @@ class SumkDFT(object):
f.write("%s\n" % self.n_orbitals[ik, 0]) f.write("%s\n" % self.n_orbitals[ik, 0])
for inu in range(self.n_orbitals[ik, 0]): for inu in range(self.n_orbitals[ik, 0]):
for imu in range(self.n_orbitals[ik, 0]): for imu in range(self.n_orbitals[ik, 0]):
valre = (deltaN['up'][ik][ valre = (deltaN['up'][ik][inu, imu].real + deltaN['down'][ik][inu, imu].real) / 2.0
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
valim = (deltaN['up'][ik][
inu, imu].imag + deltaN['down'][ik][inu, imu].imag) / 2.0
f.write("%.14f %.14f " % (valre, valim)) f.write("%.14f %.14f " % (valre, valim))
f.write("\n") f.write("\n")
f.write("\n") f.write("\n")
@ -2347,8 +2304,7 @@ class SumkDFT(object):
fout.write("%s\n" % self.n_orbitals[ik, isp]) fout.write("%s\n" % self.n_orbitals[ik, isp])
for inu in range(self.n_orbitals[ik, isp]): for inu in range(self.n_orbitals[ik, isp]):
for imu in range(self.n_orbitals[ik, isp]): for imu in range(self.n_orbitals[ik, isp]):
fout.write("%.14f %.14f " % (deltaN[sp][ik][ fout.write("%.14f %.14f " % (deltaN[sp][ik][inu, imu].real, deltaN[sp][ik][inu, imu].imag))
inu, imu].real, deltaN[sp][ik][inu, imu].imag))
fout.write("\n") fout.write("\n")
fout.write("\n") fout.write("\n")
fout.close() fout.close()
@ -2396,7 +2352,6 @@ class SumkDFT(object):
f.write("\n") f.write("\n")
elif dm_type == 'elk': elif dm_type == 'elk':
# output each k-point density matrix for Elk # output each k-point density matrix for Elk
if mpi.is_master_node(): if mpi.is_master_node():
@ -2413,8 +2368,7 @@ class SumkDFT(object):
beta = self.mesh.beta * self.energy_unit beta = self.mesh.beta * self.energy_unit
mu = self.chemical_potential/self.energy_unit mu = self.chemical_potential/self.energy_unit
# ouput n_k, nspin and max orbitals - a check # ouput n_k, nspin and max orbitals - a check
f.write(" %d %d %d %.14f %.14f ! nkpt, nspin, nstmax, beta, mu\n" % ( f.write(" %d %d %d %.14f %.14f ! nkpt, nspin, nstmax, beta, mu\n"%(self.n_k, n_spin_blocks, nbmax, beta, mu))
self.n_k, n_spin_blocks, nbmax, beta, mu))
for ik in range(self.n_k): for ik in range(self.n_k):
for ispn in range(n_spin_blocks): for ispn in range(n_spin_blocks):
#Determine the SO density matrix band indices from the spinor band indices #Determine the SO density matrix band indices from the spinor band indices
@ -2432,10 +2386,8 @@ class SumkDFT(object):
for imu in range(self.n_orbitals[ik, ispn]): for imu in range(self.n_orbitals[ik, ispn]):
#output non-magnetic or spin-averaged density matrix #output non-magnetic or spin-averaged density matrix
if((self.SP==0) or (spinave)): if((self.SP==0) or (spinave)):
valre = (deltaN['up'][ik][inu, imu].real + deltaN['down'][ik][ valre = (deltaN['up'][ik][inu, imu].real + deltaN['down'][ik][inu, imu].real) / 2.0
inu, imu].real) / 2.0 valim = (deltaN['up'][ik][inu, imu].imag + deltaN['down'][ik][inu, imu].imag) / 2.0
valim = (deltaN['up'][ik][inu, imu].imag + deltaN['down'][ik][
inu, imu].imag) / 2.0
else: else:
valre = deltaN[spn[ispn]][ik][inu, imu].real valre = deltaN[spn[ispn]][ik][inu, imu].real
valim = deltaN[spn[ispn]][ik][inu, imu].imag valim = deltaN[spn[ispn]][ik][inu, imu].imag
@ -2444,8 +2396,7 @@ class SumkDFT(object):
elif dm_type == 'qe': elif dm_type == 'qe':
if self.SP == 0: if self.SP == 0:
mpi.report( mpi.report("SUMK calc_density_correction: WARNING! Averaging out spin-polarized correction in the density channel")
"SUMK calc_density_correction: WARNING! Averaging out spin-polarized correction in the density channel")
subgrp = 'dft_update' subgrp = 'dft_update'
delta_N = np.zeros([self.n_k, max(self.n_orbitals[:,0]), max(self.n_orbitals[:,0])], dtype=complex) delta_N = np.zeros([self.n_k, max(self.n_orbitals[:,0]), max(self.n_orbitals[:,0])], dtype=complex)
@ -2506,8 +2457,7 @@ class SumkDFT(object):
dim = self.corr_shells[icrsh]['dim'] dim = self.corr_shells[icrsh]['dim']
n_orb = self.n_orbitals[ik, 0] n_orb = self.n_orbitals[ik, 0]
projmat = self.proj_mat[ik, 0, icrsh, 0:dim, 0:n_orb] projmat = self.proj_mat[ik, 0, icrsh, 0:dim, 0:n_orb]
dens_mat[icrsh][ dens_mat[icrsh][:, :] += np.dot(projmat, projmat.transpose().conjugate()) * self.bz_weights[ik]
:, :] += np.dot(projmat, projmat.transpose().conjugate()) * self.bz_weights[ik]
if self.symm_op != 0: if self.symm_op != 0:
dens_mat = self.symmcorr.symmetrize(dens_mat) dens_mat = self.symmcorr.symmetrize(dens_mat)
@ -2517,8 +2467,7 @@ class SumkDFT(object):
for icrsh in range(self.n_corr_shells): for icrsh in range(self.n_corr_shells):
if self.rot_mat_time_inv[icrsh] == 1: if self.rot_mat_time_inv[icrsh] == 1:
dens_mat[icrsh] = dens_mat[icrsh].conjugate() dens_mat[icrsh] = dens_mat[icrsh].conjugate()
dens_mat[icrsh] = np.dot(np.dot(self.rot_mat[icrsh].conjugate().transpose(), dens_mat[icrsh]), dens_mat[icrsh] = np.dot(np.dot(self.rot_mat[icrsh].conjugate().transpose(), dens_mat[icrsh]),self.rot_mat[icrsh])
self.rot_mat[icrsh])
return dens_mat return dens_mat
@ -2542,50 +2491,38 @@ class SumkDFT(object):
# after introducing the block_structure class # after introducing the block_structure class
def __get_gf_struct_sumk(self): def __get_gf_struct_sumk(self):
return self.block_structure.gf_struct_sumk return self.block_structure.gf_struct_sumk
def __set_gf_struct_sumk(self,value): def __set_gf_struct_sumk(self,value):
self.block_structure.gf_struct_sumk = value self.block_structure.gf_struct_sumk = value
gf_struct_sumk = property(__get_gf_struct_sumk,__set_gf_struct_sumk) gf_struct_sumk = property(__get_gf_struct_sumk,__set_gf_struct_sumk)
def __get_gf_struct_solver(self): def __get_gf_struct_solver(self):
return self.block_structure.gf_struct_solver return self.block_structure.gf_struct_solver
def __set_gf_struct_solver(self,value): def __set_gf_struct_solver(self,value):
self.block_structure.gf_struct_solver = value self.block_structure.gf_struct_solver = value
gf_struct_solver = property(__get_gf_struct_solver,__set_gf_struct_solver) gf_struct_solver = property(__get_gf_struct_solver,__set_gf_struct_solver)
def __get_solver_to_sumk(self): def __get_solver_to_sumk(self):
return self.block_structure.solver_to_sumk return self.block_structure.solver_to_sumk
def __set_solver_to_sumk(self,value): def __set_solver_to_sumk(self,value):
self.block_structure.solver_to_sumk = value self.block_structure.solver_to_sumk = value
solver_to_sumk = property(__get_solver_to_sumk,__set_solver_to_sumk) solver_to_sumk = property(__get_solver_to_sumk,__set_solver_to_sumk)
def __get_sumk_to_solver(self): def __get_sumk_to_solver(self):
return self.block_structure.sumk_to_solver return self.block_structure.sumk_to_solver
def __set_sumk_to_solver(self,value): def __set_sumk_to_solver(self,value):
self.block_structure.sumk_to_solver = value self.block_structure.sumk_to_solver = value
sumk_to_solver = property(__get_sumk_to_solver,__set_sumk_to_solver) sumk_to_solver = property(__get_sumk_to_solver,__set_sumk_to_solver)
def __get_solver_to_sumk_block(self): def __get_solver_to_sumk_block(self):
return self.block_structure.solver_to_sumk_block return self.block_structure.solver_to_sumk_block
def __set_solver_to_sumk_block(self,value): def __set_solver_to_sumk_block(self,value):
self.block_structure.solver_to_sumk_block = value self.block_structure.solver_to_sumk_block = value
solver_to_sumk_block = property(__get_solver_to_sumk_block,__set_solver_to_sumk_block) solver_to_sumk_block = property(__get_solver_to_sumk_block,__set_solver_to_sumk_block)
def __get_deg_shells(self): def __get_deg_shells(self):
return self.block_structure.deg_shells return self.block_structure.deg_shells
def __set_deg_shells(self,value): def __set_deg_shells(self,value):
self.block_structure.deg_shells = value self.block_structure.deg_shells = value
deg_shells = property(__get_deg_shells,__set_deg_shells) deg_shells = property(__get_deg_shells,__set_deg_shells)
@property @property
@ -2606,16 +2543,12 @@ class SumkDFT(object):
def __get_corr_to_inequiv(self): def __get_corr_to_inequiv(self):
return self.block_structure.corr_to_inequiv return self.block_structure.corr_to_inequiv
def __set_corr_to_inequiv(self, value): def __set_corr_to_inequiv(self, value):
self.block_structure.corr_to_inequiv = value self.block_structure.corr_to_inequiv = value
corr_to_inequiv = property(__get_corr_to_inequiv, __set_corr_to_inequiv) corr_to_inequiv = property(__get_corr_to_inequiv, __set_corr_to_inequiv)
def __get_inequiv_to_corr(self): def __get_inequiv_to_corr(self):
return self.block_structure.inequiv_to_corr return self.block_structure.inequiv_to_corr
def __set_inequiv_to_corr(self, value): def __set_inequiv_to_corr(self, value):
self.block_structure.inequiv_to_corr = value self.block_structure.inequiv_to_corr = value
inequiv_to_corr = property(__get_inequiv_to_corr, __set_inequiv_to_corr) inequiv_to_corr = property(__get_inequiv_to_corr, __set_inequiv_to_corr)