11import sys
22import numpy as np
3- import sparse_ir
43
54"""
6- Fourier transform on the imaginary axis based on IR basis and the sparse sampling technique.
5+ Fourier transform on the imaginary axis based on IR basis and the sparse sampling technique.
76"""
87
98
@@ -45,6 +44,7 @@ class IAFT(object):
4544 nw_b: int
4645 Number of bosonic frequency sampling points
4746 """
47+
4848 def __init__ (self , beta : float , lmbda : float , prec : float = 1e-15 , verbal : bool = True ):
4949 """
5050 :param beta: float
@@ -54,6 +54,10 @@ def __init__(self, beta: float, lmbda: float, prec: float = 1e-15, verbal: bool
5454 :param prec: float
5555 Precision for IR basis
5656 """
57+ try :
58+ import sparse_ir
59+ except ImportError :
60+ raise ImportError ('sparse_ir is required for IAFT functionality. ' 'Install with: pip install sparse-ir[xprec]' )
5761 self .beta = beta
5862 self .lmbda = lmbda
5963 self .prec = prec
@@ -89,14 +93,15 @@ def __init__(self, beta: float, lmbda: float, prec: float = 1e-15, verbal: bool
8993 sys .stdout .flush ()
9094
9195 def __str__ (self ):
92- return ("Mesh details on the imaginary axis\n " \
93- "----------------------------------\n " \
94- "precision = {}\n " \
95- "beta = {}\n " \
96- "lambda = {}\n " \
97- "nt_f, nw_f = {}, {}\n " \
98- "nt_b, nw_b = {}, {}\n " .format (self .prec , self .beta , self .lmbda , self .nt_f , self .nw_f ,
99- self .nt_b , self .nw_b ))
96+ return (
97+ 'Mesh details on the imaginary axis\n '
98+ '----------------------------------\n '
99+ 'precision = {}\n '
100+ 'beta = {}\n '
101+ 'lambda = {}\n '
102+ 'nt_f, nw_f = {}, {}\n '
103+ 'nt_b, nw_b = {}, {}\n ' .format (self .prec , self .beta , self .lmbda , self .nt_f , self .nw_f , self .nt_b , self .nw_b )
104+ )
100105
101106 def wn_mesh (self , stats : str , ir_notation : bool = True ):
102107 """
@@ -111,11 +116,10 @@ def wn_mesh(self, stats: str, ir_notation: bool = True):
111116 Matsubara frequency indices
112117 """
113118 if stats not in self .statisics :
114- raise ValueError ("Unknown statistics '{}'. "
115- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
119+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
116120 wn_mesh = np .array (self ._wn_mesh_f , dtype = int ) if stats == 'f' else np .array (self ._wn_mesh_b , dtype = int )
117121 if not ir_notation :
118- wn_mesh = (wn_mesh - 1 ) // 2 if stats == 'f' else wn_mesh // 2
122+ wn_mesh = (wn_mesh - 1 ) // 2 if stats == 'f' else wn_mesh // 2
119123 return wn_mesh
120124
121125 def tau_to_w (self , Ot , stats : str ):
@@ -130,12 +134,10 @@ def tau_to_w(self, Ot, stats: str):
130134 Matsubara-frequency object with dimensions (nw, ...)
131135 """
132136 if stats not in self .statisics :
133- raise ValueError ("Unknown statistics '{}'. "
134- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
137+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
135138 Twt = self .Twt_ff if stats == 'f' else self .Twt_bb
136139 if Ot .shape [0 ] != Twt .shape [1 ]:
137- raise ValueError (
138- "tau_to_w: Number of tau points are inconsistent: {} and {}" .format (Ot .shape [0 ], Twt .shape [1 ]))
140+ raise ValueError ('tau_to_w: Number of tau points are inconsistent: {} and {}' .format (Ot .shape [0 ], Twt .shape [1 ]))
139141
140142 Ot_shape = Ot .shape
141143 Ot = Ot .reshape (Ot .shape [0 ], - 1 )
@@ -157,13 +159,12 @@ def tau_to_w_phsym(self, Ot, stats: str):
157159 Matsubara-frequency object with dimensions (nw, ...)
158160 """
159161 if stats != 'b' :
160- raise ValueError (" FT w/ particle-hole symmetry only support bosonic correlation functions" )
162+ raise ValueError (' FT w/ particle-hole symmetry only support bosonic correlation functions' )
161163
162164 nw_half = self .nw_b // 2 if self .nw_b % 2 == 0 else self .nw_b // 2 + 1
163165 nt_half = self .nt_b // 2 if self .nt_b % 2 == 0 else self .nt_b // 2 + 1
164166 if Ot .shape [0 ] != nt_half :
165- raise ValueError (
166- "tau_to_w_phsym: Number of tau points are inconsistent: {} and {}" .format (Ot .shape [0 ], nt_half ))
167+ raise ValueError ('tau_to_w_phsym: Number of tau points are inconsistent: {} and {}' .format (Ot .shape [0 ], nt_half ))
167168
168169 Twt_pos = np .zeros ((nw_half , nt_half ), dtype = self .Twt_bb .dtype )
169170 for n in range (nw_half ):
@@ -193,12 +194,10 @@ def w_to_tau(self, Ow, stats):
193194 Imaginary-time object with dimensions (nt, ...)
194195 """
195196 if stats not in self .statisics :
196- raise ValueError ("Unknown statistics '{}'. "
197- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
197+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
198198 Ttw = self .Ttw_ff if stats == 'f' else self .Ttw_bb
199199 if Ow .shape [0 ] != Ttw .shape [1 ]:
200- raise ValueError (
201- "w_to_tau: Number of w points are inconsistent: {} and {}" .format (Ow .shape [0 ], Ttw .shape [1 ]))
200+ raise ValueError ('w_to_tau: Number of w points are inconsistent: {} and {}' .format (Ow .shape [0 ], Ttw .shape [1 ]))
202201
203202 Ow_shape = Ow .shape
204203 Ow = Ow .reshape (Ow .shape [0 ], - 1 )
@@ -221,13 +220,12 @@ def w_to_tau_phsym(self, Ow, stats):
221220 Imaginary-time object with dimensions (nt, ...)
222221 """
223222 if stats != 'b' :
224- raise ValueError (" FT w/ particle-hole symmetry only support bosonic correlation functions" )
223+ raise ValueError (' FT w/ particle-hole symmetry only support bosonic correlation functions' )
225224
226225 nw_half = self .nw_b // 2 if self .nw_b % 2 == 0 else self .nw_b // 2 + 1
227226 nt_half = self .nt_b // 2 if self .nt_b % 2 == 0 else self .nt_b // 2 + 1
228227 if Ow .shape [0 ] != nw_half :
229- raise ValueError (
230- "w_to_tau_phsym: Number of w points are inconsistent: {} and {}" .format (Ow .shape [0 ], nw_half ))
228+ raise ValueError ('w_to_tau_phsym: Number of w points are inconsistent: {} and {}' .format (Ow .shape [0 ], nw_half ))
231229
232230 Ttw_pos = np .zeros ((nt_half , nw_half ), dtype = self .Ttw_bb .dtype )
233231 for it in range (nt_half ):
@@ -244,7 +242,6 @@ def w_to_tau_phsym(self, Ow, stats):
244242 Ot = Ot .reshape ((Ttw_pos .shape [0 ],) + Ow_shape [1 :])
245243 return Ot
246244
247-
248245 def w_interpolate (self , Ow , wn_mesh_interp , stats : str , ir_notation : bool = True ):
249246 """
250247 Interpolate a dynamic object to arbitrary points on the Matsubara axis.
@@ -264,16 +261,14 @@ def w_interpolate(self, Ow, wn_mesh_interp, stats: str, ir_notation: bool = True
264261 Matsubara-frequency object with dimensions (nw_interp, ...)
265262 """
266263 if stats not in self .statisics :
267- raise ValueError ("Unknown statistics '{}'. "
268- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
264+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
269265 if ir_notation :
270266 wn_indices = np .asarray (wn_mesh_interp )
271267 else :
272- wn_indices = np .array ([2 * n + 1 if stats == 'f' else 2 * n for n in wn_mesh_interp ], dtype = int )
268+ wn_indices = np .array ([2 * n + 1 if stats == 'f' else 2 * n for n in wn_mesh_interp ], dtype = int )
273269 Tlw = self .Tlw_ff if stats == 'f' else self .Tlw_bb
274270 if Ow .shape [0 ] != Tlw .shape [1 ]:
275- raise ValueError (
276- "w_interpolate: Number of w points are inconsistent: {} and {}" .format (Ow .shape [0 ], Tlw .shape [1 ]))
271+ raise ValueError ('w_interpolate: Number of w points are inconsistent: {} and {}' .format (Ow .shape [0 ], Tlw .shape [1 ]))
277272
278273 Twl_interp = self .bases .basis_f .uhat (wn_indices ).T if stats == 'f' else self .bases .basis_b .uhat (wn_indices ).T
279274 Tww = np .dot (Twl_interp , Tlw )
@@ -305,18 +300,17 @@ def w_interpolate_phsym(self, Ow, wn_mesh_interp, stats: str, ir_notation: bool
305300 Matsubara-frequency object with dimensions (nw_interp, ...)
306301 """
307302 if stats != 'b' :
308- raise ValueError (" FT w/ particle-hole symmetry only support bosonic correlation functions" )
303+ raise ValueError (' FT w/ particle-hole symmetry only support bosonic correlation functions' )
309304
310305 nw_half = self .nw_b // 2 if self .nw_b % 2 == 0 else self .nw_b // 2 + 1
311306 nt_half = self .nt_b // 2 if self .nt_b % 2 == 0 else self .nt_b // 2 + 1
312307 if Ow .shape [0 ] != nw_half :
313- raise ValueError (
314- "w_interpolate_phsym: Number of w points are inconsistent: {} and {}" .format (Ow .shape [0 ], nw_half ))
308+ raise ValueError ('w_interpolate_phsym: Number of w points are inconsistent: {} and {}' .format (Ow .shape [0 ], nw_half ))
315309
316310 if ir_notation :
317311 wn_indices = np .asarray (wn_mesh_interp )
318312 else :
319- wn_indices = np .array ([2 * n for n in wn_mesh_interp ], dtype = int )
313+ wn_indices = np .array ([2 * n for n in wn_mesh_interp ], dtype = int )
320314 Tlw = self .Tlw_bb
321315 Tlw_pos = np .zeros ((Tlw .shape [0 ], nw_half ), dtype = Tlw .dtype )
322316 for l in range (Tlw .shape [0 ]):
@@ -351,12 +345,10 @@ def tau_interpolate(self, Ot, tau_mesh_interp, stats: str):
351345 Imaginary-time object with dimensions (nt_interp, ...)
352346 """
353347 if stats not in self .statisics :
354- raise ValueError ("Unknown statistics '{}'. "
355- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
348+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
356349 Tlt = self .Tlt_ff if stats == 'f' else self .Tlt_bb
357350 if Ot .shape [0 ] != Tlt .shape [1 ]:
358- raise ValueError (
359- "t_interpolate: Number of tau points are inconsistent: {} and {}" .format (Ot .shape [0 ], Tlt .shape [1 ]))
351+ raise ValueError ('t_interpolate: Number of tau points are inconsistent: {} and {}' .format (Ot .shape [0 ], Tlt .shape [1 ]))
360352
361353 Ttl_interp = self .bases .basis_f .u (tau_mesh_interp ).T if stats == 'f' else self .bases .basis_b .u (tau_mesh_interp ).T
362354 Ttt = np .dot (Ttl_interp , Tlt )
@@ -384,13 +376,12 @@ def tau_interpolate_phsym(self, Ot, tau_mesh_interp, stats: str):
384376 Imaginary-time object with dimensions (nt_interp, ...)
385377 """
386378 if stats != 'b' :
387- raise ValueError (" FT w/ particle-hole symmetry only support bosonic correlation functions" )
379+ raise ValueError (' FT w/ particle-hole symmetry only support bosonic correlation functions' )
388380
389381 nw_half = self .nw_b // 2 if self .nw_b % 2 == 0 else self .nw_b // 2 + 1
390382 nt_half = self .nt_b // 2 if self .nt_b % 2 == 0 else self .nt_b // 2 + 1
391383 if Ot .shape [0 ] != nt_half :
392- raise ValueError (
393- "tau_interpolate_phsym: Number of tau points are inconsistent: {} and {}" .format (Ot .shape [0 ], nw_half ))
384+ raise ValueError ('tau_interpolate_phsym: Number of tau points are inconsistent: {} and {}' .format (Ot .shape [0 ], nw_half ))
394385
395386 Tlt = self .Tlt_ff if stats == 'f' else self .Tlt_bb
396387 Tlt_pos = np .zeros ((Tlt .shape [0 ], nt_half ), dtype = Tlt .dtype )
@@ -410,7 +401,7 @@ def tau_interpolate_phsym(self, Ot, tau_mesh_interp, stats: str):
410401 Ot_interp = Ot_interp .reshape ((np .shape (tau_mesh_interp )[0 ],) + Ot_shape [1 :])
411402 return Ot_interp
412403
413- def check_leakage (self , Ot , stats : str , name : str = "" , w_input : bool = False ):
404+ def check_leakage (self , Ot , stats : str , name : str = '' , w_input : bool = False ):
414405 """
415406 Check decay of the IR coefficients to assess the quality of IR basis for the beta and lambda.
416407 The coefficients should decay exponentially, and the leakage is defined as:
@@ -427,12 +418,11 @@ def check_leakage(self, Ot, stats: str, name: str = "", w_input: bool = False):
427418 return
428419
429420 if stats not in self .statisics :
430- raise ValueError ("Unknown statistics '{}'. "
431- "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
421+ raise ValueError ("Unknown statistics '{}'. " "Acceptable options are 'f' for fermion and 'b' for bosons." .format (stats ))
432422 nts = self .nt_f if stats == 'f' else self .nt_b
433423 Tlt = self .Tlt_ff if stats == 'f' else self .Tlt_bb
434424 if nts != Ot .shape [0 ]:
435- raise ValueError (" Inconsistency between nts = {} and Ot.shape[0] = {}" .format (nts , Ot .shape [0 ]))
425+ raise ValueError (' Inconsistency between nts = {} and Ot.shape[0] = {}' .format (nts , Ot .shape [0 ]))
436426
437427 # coeff_first
438428 O_l0_i = np .einsum ('t,ti->i' , Tlt [0 ], Ot .reshape (nts , - 1 ))
@@ -442,11 +432,14 @@ def check_leakage(self, Ot, stats: str, name: str = "", w_input: bool = False):
442432 O_lm2_t = np .einsum ('lt,ti->li' , Tlt [- 2 :], Ot .reshape (nts , - 1 ))
443433 coeff_last = np .max (np .abs (O_lm2_t ))
444434
445- leakage = coeff_last / coeff_first
446- print ("IAFT leakage of {}: {}" .format (name , leakage ))
447- if leakage >= 1e-8 :
448- print ("[WARNING] check_leakage: coeff_last/coeff_first = {} >= 1e-8; "
449- "coeff_last = {}, coeff_first = {}" .format (leakage , coeff_last , coeff_first ))
435+ leakage = coeff_last / coeff_first
436+ print ('IAFT leakage of {}: {}' .format (name , leakage ))
437+ if leakage >= 1e-5 :
438+ print (
439+ '[WARNING] check_leakage: coeff_last/coeff_first = {} >= 1e-8; ' 'coeff_last = {}, coeff_first = {}' .format (
440+ leakage , coeff_last , coeff_first
441+ )
442+ )
450443 sys .stdout .flush ()
451444
452445
@@ -466,12 +459,12 @@ def check_leakage(self, Ot, stats: str, name: str = "", w_input: bool = False):
466459 print (Gt_interp .shape )
467460
468461 # wn in spare_ir notation
469- w_interp = np .array ([- 1 ,1 , 3 , 5 ], dtype = int )
462+ w_interp = np .array ([- 1 , 1 , 3 , 5 ], dtype = int )
470463 Gw_interp = ft .w_interpolate (Gw , w_interp , 'f' , True )
471464 print (Gw_interp .shape )
472465
473466 # wn in physical notation
474- w_interp = np .array ([- 1 ,0 , 1 , 2 , 3 , 4 ], dtype = int )
467+ w_interp = np .array ([- 1 , 0 , 1 , 2 , 3 , 4 ], dtype = int )
475468 Gw_interp = ft .w_interpolate (Gw , w_interp , 'f' , False )
476469 print (Gw_interp .shape )
477470
0 commit comments