Skip to content

Commit b58f676

Browse files
committed
[feat] add option to use DLR mesh in Sumk (#254)
allow using the MeshDLRImFreq to be used as general Sumk mesh during the DMFT loop for all functions.
1 parent 756761a commit b58f676

File tree

4 files changed

+76
-19
lines changed

4 files changed

+76
-19
lines changed

doc/ChangeLog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ DFTTools Version 3.3.0 is a release that
88
* is compatible with TRIQS 3.3.x
99
* includes the latest app4triqs changes
1010
* introduce `dc_imp_dyn` attribute in sumk object to store dynamic part of DC potential
11+
* allows using MeshDLRImFreq as Sumk mesh
1112
* improved standard behavior of block struct (#248) (see below for details)
1213

1314
We thank all contributors: Sophie Beck, Thomas Hahn, Alexander Hampel, Henri Menke, Dylan Simon, Nils Wentzell
@@ -21,6 +22,7 @@ Find below an itemized list of changes in this release.
2122
### feat
2223
* allow dict/np.ndarrays input in `symm_deg_gf`
2324
* introduce `dc_imp_dyn` attribute in sumk object to store dynamic part of DC potential
25+
* allows using MeshDLRImFreq as Sumk mesh
2426
* previously the default `gf_struct_solver` in a initialized blockstructure had keys `up` / `down`, inconsistent with the default behavior after running `analyse_block_structure`: `up_0` / `down_0`. Now the default solver structure always has the `_0`
2527
in the key.
2628
* old behavior resulted in error when analyse_block_structure was called

python/triqs_dft_tools/sumk_dft.py

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ def __init__(self, hdf_file, h_field=0.0, mesh=None, beta=40, n_iw=1025, use_dft
5858
The value of magnetic field to add to the DFT Hamiltonian.
5959
The contribution -h_field*sigma is added to diagonal elements of the Hamiltonian.
6060
It cannot be used with the spin-orbit coupling on; namely h_field is set to 0 if self.SO=True.
61-
mesh: MeshImFreq or MeshReFreq, optional. Frequency mesh of Sigma.
61+
mesh: MeshImFreq, MeshDLRImFreq, or MeshReFreq, optional. Frequency mesh of Sigma.
6262
beta : real, optional
6363
Inverse temperature. Used to construct imaginary frequency if mesh is not given.
6464
n_iw : integer, optional
@@ -115,6 +115,9 @@ def __init__(self, hdf_file, h_field=0.0, mesh=None, beta=40, n_iw=1025, use_dft
115115
self.mesh_values = np.linspace(self.mesh(self.mesh.first_index()),
116116
self.mesh(self.mesh.last_index()),
117117
len(self.mesh))
118+
elif isinstance(mesh, MeshDLRImFreq):
119+
self.mesh = mesh
120+
self.mesh_values = np.array([iwn.value for iwn in mesh.values()])
118121
elif isinstance(mesh, MeshReFreq):
119122
self.mesh = mesh
120123
self.mesh_values = np.linspace(self.mesh.w_min, self.mesh.w_max, len(self.mesh))
@@ -563,16 +566,20 @@ def lattice_gf(self, ik, mu=None, broadening=None, mesh=None, with_Sigma=True, w
563566
mesh = Sigma_imp[0].mesh
564567
if isinstance(mesh, MeshImFreq):
565568
mesh_values = np.linspace(mesh(mesh.first_index()), mesh(mesh.last_index()), len(mesh))
569+
elif isinstance(mesh, MeshDLRImFreq):
570+
mesh_values = np.array([iwn.value for iwn in mesh.values()])
566571
else:
567572
mesh_values = np.linspace(mesh.w_min, mesh.w_max, len(mesh))
568573
else:
569574
mesh = self.mesh
570575
mesh_values = self.mesh_values
571576

572577
elif not mesh is None:
573-
assert isinstance(mesh, MeshReFreq) or isinstance(mesh, MeshImFreq), "mesh must be a triqs MeshReFreq or MeshImFreq"
578+
assert isinstance(mesh, (MeshReFreq, MeshDLRImFreq, MeshImFreq)), "mesh must be a triqs MeshReFreq or MeshImFreq"
574579
if isinstance(mesh, MeshImFreq):
575580
mesh_values = np.linspace(mesh(mesh.first_index()), mesh(mesh.last_index()), len(mesh))
581+
elif isinstance(mesh, MeshDLRImFreq):
582+
mesh_values = np.array([iwn.value for iwn in mesh.values()])
576583
else:
577584
mesh_values = np.linspace(mesh.w_min, mesh.w_max, len(mesh))
578585
else:
@@ -586,12 +593,8 @@ def lattice_gf(self, ik, mu=None, broadening=None, mesh=None, with_Sigma=True, w
586593
gf_struct = [(spn[isp], block_structure[isp])
587594
for isp in range(self.n_spin_blocks[self.SO])]
588595
block_ind_list = [block for block, inner in gf_struct]
589-
if isinstance(mesh, MeshImFreq):
590-
glist = lambda: [Gf(mesh=mesh, target_shape=[len(inner),len(inner)])
591-
for block, inner in gf_struct]
592-
else:
593-
glist = lambda: [Gf(mesh=mesh, target_shape=[len(inner),len(inner)])
594-
for block, inner in gf_struct]
596+
glist = lambda: [Gf(mesh=mesh, target_shape=[len(inner),len(inner)])
597+
for block, inner in gf_struct]
595598
G_latt = BlockGf(name_list=block_ind_list,
596599
block_list=glist(), make_copies=False)
597600
G_latt.zero()
@@ -603,7 +606,7 @@ def lattice_gf(self, ik, mu=None, broadening=None, mesh=None, with_Sigma=True, w
603606
for ibl, (block, gf) in enumerate(G_latt):
604607
ind = ntoi[spn[ibl]]
605608
n_orb = self.n_orbitals[ik, ind]
606-
if isinstance(mesh, MeshImFreq):
609+
if isinstance(mesh, (MeshImFreq, MeshDLRImFreq)):
607610
gf.data[:, :, :] = (idmat[ibl] * (mesh_values[:, None, None] + mu + self.h_field*(1-2*ibl))
608611
- self.hopping[ik, ind, 0:n_orb, 0:n_orb])
609612
else:
@@ -647,7 +650,10 @@ def put_Sigma(self, Sigma_imp, transform_to_sumk_blocks=True):
647650
assert len(Sigma_imp) == self.n_corr_shells,\
648651
"put_Sigma: give exactly one Sigma for each corr. shell!"
649652

650-
if isinstance(self.mesh, MeshImFreq) and all(isinstance(gf.mesh, MeshImFreq) and isinstance(gf, Gf) and gf.mesh == self.mesh for bname, gf in Sigma_imp[0]):
653+
if (isinstance(self.mesh, (MeshImFreq, MeshDLRImFreq)) and
654+
all(isinstance(gf.mesh, (MeshImFreq, MeshDLRImFreq)) and
655+
isinstance(gf, Gf) and
656+
gf.mesh == self.mesh for bname, gf in Sigma_imp[0])):
651657
# Imaginary frequency Sigma:
652658
self.Sigma_imp = [self.block_structure.create_gf(ish=icrsh, mesh=Sigma_imp[icrsh].mesh, space='sumk')
653659
for icrsh in range(self.n_corr_shells)]

test/python/calc_mu.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131
class test_solver(unittest.TestCase):
3232

3333
def setUp(self):
34-
self.iw_mesh = MeshImFreq(beta=40, S='Fermion', n_iw=300)
34+
self.iw_mesh = MeshImFreq(beta=40, statistic='Fermion', n_iw=300)
35+
self.dlr_mesh = MeshDLRImFreq(beta=40, statistic='Fermion', w_max=10, eps=1e-10)
3536
self.w_mesh = MeshReFreq(n_w=1001, window=(-3,3))
3637
# magic reference value for the Wien2k SVO t2g example
3738
self.ref_mu = 0.281
@@ -42,6 +43,11 @@ def test_dichotomy(self):
4243
mu = sumk.calc_mu(method='dichotomy', precision=0.001, delta=0.1)
4344
self.assertTrue(abs(self.ref_mu - mu) < 0.01)
4445

46+
def test_dichotomy_dlr(self):
47+
sumk = SumkDFT('SrVO3.ref.h5', mesh=self.dlr_mesh)
48+
mu = sumk.calc_mu(method='dichotomy', precision=0.001, delta=0.1)
49+
self.assertTrue(abs(self.ref_mu - mu) < 0.01)
50+
4551
def test_dichotomy_real(self):
4652
sumk = SumkDFT('SrVO3.ref.h5', mesh=self.w_mesh)
4753
mu = sumk.calc_mu(method='dichotomy', precision=0.001, delta=0.1, broadening = 0.01, beta=1000)

test/python/srvo3_Gloc.py

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,35 +19,78 @@
1919
#
2020
################################################################################
2121

22-
from h5 import *
23-
from triqs.gf import *
24-
from triqs_dft_tools.sumk_dft import *
25-
from triqs_dft_tools.converters.wien2k import *
22+
from h5 import HDFArchive
23+
from triqs.utility import mpi
24+
from triqs.gf import MeshImFreq, MeshDLRImFreq, Gf, BlockGf, make_gf_dlr, make_gf_imfreq
25+
from triqs_dft_tools.sumk_dft import SumkDFT
2626
from triqs.operators.util import set_operator_structure
27-
from triqs.utility.comparison_tests import *
27+
from triqs.utility.comparison_tests import assert_block_gfs_are_close
2828
from triqs.utility.h5diff import h5diff
2929

30+
import time
31+
3032
# Basic input parameters
3133
beta = 40
34+
n_iw = 1025
35+
36+
# classic full Matsubara mesh
37+
mpi.report(f"{'#'*12}\nregular Matsubara mesh test\n")
3238

33-
# Init the SumK class
34-
SK=SumkDFT(hdf_file='SrVO3.ref.h5',use_dft_blocks=True)
39+
# Init the SumK class (reference data with n_iw=1025)
40+
iw_mesh = MeshImFreq(n_iw=n_iw,beta=beta, statistic='Fermion')
41+
SK=SumkDFT(hdf_file='SrVO3.ref.h5',mesh=iw_mesh,use_dft_blocks=True)
3542

3643
num_orbitals = SK.corr_shells[0]['dim']
3744
l = SK.corr_shells[0]['l']
3845
spin_names = ['down','up']
3946
orb_hybridized = False
4047

4148
gf_struct = set_operator_structure(spin_names,num_orbitals,orb_hybridized)
42-
glist = [ GfImFreq(target_shape=(bl_size,bl_size),beta=beta) for bl, bl_size in gf_struct]
49+
glist = [ Gf(target_shape=(bl_size,bl_size),mesh=iw_mesh) for bl, bl_size in gf_struct]
4350
Sigma_iw = BlockGf(name_list = [bl for bl, bl_size in gf_struct], block_list = glist, make_copies = False)
4451

4552
SK.set_Sigma([Sigma_iw])
53+
54+
if mpi.is_master_node():
55+
start_time = time.time()
56+
4657
Gloc = SK.extract_G_loc()
4758

59+
if mpi.is_master_node():
60+
mpi.report(f'extract_G_loc time: {(time.time()-start_time)*1000:.1f} msec')
61+
4862
if mpi.is_master_node():
4963
with HDFArchive('srvo3_Gloc.out.h5','w') as ar:
5064
ar['Gloc'] = Gloc[0]
5165

5266
if mpi.is_master_node():
5367
h5diff("srvo3_Gloc.out.h5","srvo3_Gloc.ref.h5")
68+
69+
mpi.report(f"{'#'*12}\n")
70+
71+
72+
# DLR Matsubara mesh
73+
mpi.report(f"{'#'*12}\nDLR Matsubara mesh test\n")
74+
75+
dlr_mesh = MeshDLRImFreq(beta=beta, statistic='Fermion', w_max=10, eps=1e-10)
76+
SK=SumkDFT(hdf_file='SrVO3.ref.h5',mesh=dlr_mesh,use_dft_blocks=True)
77+
78+
glist_dlr = [ Gf(target_shape=(bl_size,bl_size),mesh=dlr_mesh) for bl, bl_size in gf_struct]
79+
Sigma_dlr = BlockGf(name_list = [bl for bl, bl_size in gf_struct], block_list = glist_dlr, make_copies = False)
80+
SK.set_Sigma([Sigma_dlr])
81+
82+
if mpi.is_master_node():
83+
start_time = time.time()
84+
85+
Gloc_dlr_iw = SK.extract_G_loc()
86+
87+
if mpi.is_master_node():
88+
mpi.report(f'extract_G_loc time: {(time.time()-start_time)*1000:.1f} msec')
89+
90+
with HDFArchive('srvo3_Gloc.out.h5','a') as ar:
91+
ar['Gloc_dlr'] = make_gf_imfreq(make_gf_dlr(Gloc_dlr_iw[0]),n_iw=n_iw)
92+
# get full Giw and compare
93+
Gloc_iw_full = make_gf_imfreq(make_gf_dlr(Gloc_dlr_iw[0]),n_iw=n_iw)
94+
assert_block_gfs_are_close(Gloc[0], Gloc_iw_full)
95+
96+
mpi.report(f"{'#'*12}\n")

0 commit comments

Comments
 (0)