3
0
mirror of https://github.com/triqs/dft_tools synced 2024-12-22 20:34:38 +01:00
dft_tools/test/python/analyse_block_structure_from_gf2.py
Alexander Hampel b355173cf1
[feat] improved standard behavior of block struct (#248)
* previously the default gf_struct_solver had keys up / down,
inconsistent with the default behavior after analyse_block_structure was
run: up_0 / down_0. Now the default solver structure always has the _0
in the key.
* old behavior resulted in error when analyse_block_structure was called
twice
* fixed analyse block structure tests with new changes
* to correctly use analyse_block_structure use now
extract_G_loc(transform_to_solver_blocks=False)
* changed density_matrix function to use directly extract_G_loc() if
using_gf is selected.
* print deprecation warning in density_matrix, same can be achieved via
extract_G_loc and [G.density() for G in Gloc]
* new function density_matrix_using_point_integration()
* enforce in analyse block structure that input dm or G is list with
length of n_corr_shells
* correct doc string for how include_shells are given
* fixed other tests accordingly
* fixed small bug in initial block structure regarding length of lists
2024-02-26 14:50:24 -05:00

119 lines
4.7 KiB
Python

from triqs.gf import *
from triqs_dft_tools.sumk_dft import SumkDFT
import numpy as np
from triqs.utility.comparison_tests import assert_block_gfs_are_close
# here we test the SK.analyse_block_structure_from_gf function
# with GfReFreq, GfReTime
# helper function to get random Hermitian matrix
def get_random_hermitian(dim):
herm = np.random.rand(dim,dim)+1.0j*np.random.rand(dim,dim)
herm = herm + herm.conjugate().transpose()
return herm
# helper function to get random unitary matrix
def get_random_transformation(dim):
herm = get_random_hermitian(dim)
T = expm(1.0j*herm)
return T
# construct a random block-diagonal Hloc
Hloc = np.zeros((10,10), dtype=complex)
# the Hloc of the first three 2x2 blocks is equal
Hloc0 = get_random_hermitian(2)
Hloc[:2,:2] = Hloc0
Hloc[2:4,2:4] = Hloc0
Hloc[4:6,4:6] = Hloc0
# the Hloc of the last two 2x2 blocks is equal
Hloc1 = get_random_hermitian(2)
Hloc[6:8,6:8] = Hloc1
Hloc[8:,8:] = Hloc1
# construct the hybridization delta
# this is equal for all 2x2 blocks
V = get_random_hermitian(2) # the hopping elements from impurity to bath
b1 = np.random.rand() # the bath energy of the first bath level
b2 = np.random.rand() # the bath energy of the second bath level
delta = GfReFreq(window=(-10,10), indices=list(range(2)), n_points=1001)
delta[0,0] << (V[0,0]*V[0,0].conjugate()*inverse(Omega-b1)+V[0,1]*V[0,1].conjugate()*inverse(Omega-b2+0.02j))/2.0
delta[0,1] << (V[0,0]*V[1,0].conjugate()*inverse(Omega-b1)+V[0,1]*V[1,1].conjugate()*inverse(Omega-b2+0.02j))/2.0
delta[1,0] << (V[1,0]*V[0,0].conjugate()*inverse(Omega-b1)+V[1,1]*V[0,1].conjugate()*inverse(Omega-b2+0.02j))/2.0
delta[1,1] << (V[1,0]*V[1,0].conjugate()*inverse(Omega-b1)+V[1,1]*V[1,1].conjugate()*inverse(Omega-b2+0.02j))/2.0
# construct G
G = BlockGf(name_block_generator=[('ud',GfReFreq(window=(-10,10), indices=list(range(10)), n_points=1001))], make_copies=False)
for i in range(0,10,2):
G['ud'][i:i+2,i:i+2] << inverse(Omega-delta+0.02j)
G['ud'] << inverse(inverse(G['ud']) - Hloc)
SK = SumkDFT(hdf_file = 'SrIrO3_rot.h5', use_dft_blocks=False)
G_new = SK.analyse_block_structure_from_gf([G]*2)
G_new_symm = G_new[0].copy()
SK.symm_deg_gf(G_new_symm, 0)
assert_block_gfs_are_close(G_new[0], G_new_symm)
assert SK.gf_struct_sumk == [[('ud', 10)], [('ud', 10)]],\
"wrong gf_struct_sumk"
for i in range(5):
assert 'ud_{}'.format(i) in SK.gf_struct_solver[0], "missing block"
assert SK.gf_struct_solver[0]['ud_{}'.format(i)] == 2, "wrong block size"
for i in range(10):
assert SK.sumk_to_solver[0]['ud',i] == ('ud_{}'.format(i//2), i%2), "wrong mapping"
assert len(SK.deg_shells[0]) == 2, "wrong number of equivalent groups found"
assert sorted([len(d) for d in SK.deg_shells[0]]) == [2,3], "wrong number of members in the equivalent groups found"
for d in SK.deg_shells[0]:
if len(d)==2:
assert 'ud_3' in d, "shell ud_3 missing"
assert 'ud_4' in d, "shell ud_4 missing"
if len(d)==3:
assert 'ud_0' in d, "shell ud_0 missing"
assert 'ud_1' in d, "shell ud_1 missing"
assert 'ud_2' in d, "shell ud_2 missing"
def get_delta_from_mesh(mesh):
w0 = None
for w in mesh:
if w0 is None:
w0 = w
else:
return w-w0
Gt = BlockGf(name_block_generator = [(name,
GfReTime(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))),
n_points=len(block.mesh),
indices=block.indices)) for name, block in G], make_copies=False)
known_moments = np.zeros((2,10,10), dtype=complex)
known_moments[1,:] = np.eye(10)
tail, err = fit_tail(G['ud'], known_moments)
Gt['ud'].set_from_fourier(G['ud'], tail)
G_new = SK.analyse_block_structure_from_gf([Gt] * 2)
G_new_symm = G_new[0].copy()
SK.symm_deg_gf(G_new_symm, 0)
assert_block_gfs_are_close(G_new[0], G_new_symm)
assert SK.gf_struct_sumk == [[('ud', 10)], [('ud', 10)]],\
"wrong gf_struct_sumk"
for i in range(5):
assert 'ud_{}'.format(i) in SK.gf_struct_solver[0], "missing block"
assert SK.gf_struct_solver[0]['ud_{}'.format(i)] == 2, "wrong block size"
for i in range(10):
assert SK.sumk_to_solver[0]['ud',i] == ('ud_{}'.format(i//2), i%2), "wrong mapping"
assert len(SK.deg_shells[0]) == 2, "wrong number of equivalent groups found"
assert sorted([len(d) for d in SK.deg_shells[0]]) == [2,3], "wrong number of members in the equivalent groups found"
for d in SK.deg_shells[0]:
if len(d)==2:
assert 'ud_3' in d, "shell ud_3 missing"
assert 'ud_4' in d, "shell ud_4 missing"
if len(d)==3:
assert 'ud_0' in d, "shell ud_0 missing"
assert 'ud_1' in d, "shell ud_1 missing"
assert 'ud_2' in d, "shell ud_2 missing"