Lehmann
This package provides subroutines to represent and manuipulate Green's functions in the imaginarytime or in the Matsubarafrequency domain.
Imaginarytime Green's functions encode the thermodynamic properites of quantum manybody systems. At low temperature, they are typically very singular and hard to deal with in numerical calculations.
Features
We provide the following components to ease the numerical manipulation of the Green's functions:

Algorithms to generate the discrete Lehamnn representation (DLR), which is a generic and compact representation of Green's functions proposed in the Ref. [1]. In general, DLR only requres ~ log(1/T)log(1/ϵ) numbers to represent a Green's function at a temperature T up to a given accuracy ϵ. In this package, two algorithms are provided: one algorithm is based on conventional QR algorithm, another is based on a functional QR algorithm. The latter extends DLR to extremely low temperature.

Dedicated DLR for Green's functions with the particlehole symmetry (e.g. phonon propagator) or with the particlehole antisymmetry (e.g. superconductor gap function).

Fast and accurate Fourier transform between the imaginarytime domain and the Matsubarafrequency domain with a cost O(log(1/T)log(1/ϵ)) and an accuracy ~100ϵ.

Fast and accurate Green's function interpolation with a cost O(log(1/T)log(1/ϵ)) and an accuracy ~100ϵ.

Fit a Green's function with noisy.
Installation
This package has been registered. So, simply type import Pkg; Pkg.add("Lehmann")
in the Julia REPL to install.
Basic Usage
In the following demo, we will show how to compress a Green's function of ~10000 data point into ~20 DLR coefficients, and perform fast interpolation and fourier transform up to the accuracy ~1e10.
using Lehmann
β = 100.0 # inverse temperature
Euv = 1.0 # ultraviolt energy cutoff of the Green's function
rtol = 1e8 # accuracy of the representation
isFermi = false
symmetry = :none # :ph if particlehole symmetric, :pha is antisymmetric, :none if there is no symmetry
diff(a, b) = maximum(abs.(a  b)) # return the maximum deviation between a and b
dlr = DLRGrid(Euv, β, rtol, isFermi, symmetry) #initialize the DLR parameters and basis
# A set of most representative grid points are generated:
# dlr.ω gives the realfrequency grids
# dlr.τ gives the imaginarytime grids
# dlr.ωn and dlr.n gives the Matsubarafrequency grids. The latter is the integer version.
println("Prepare the Green's function sample ...")
Nτ, Nωn = 10000, 10000 # many τ and n points are needed because Gτ is quite singular near the boundary
τgrid = collect(LinRange(0.0, β, Nτ)) # create a τ grid
Gτ = Sample.SemiCircle(dlr, :τ, τgrid) # Use semicircle spectral density to generate the sample Green's function in τ
ngrid = collect(Nωn:Nωn) # create a set of Matsubarafrequency points
Gn = Sample.SemiCircle(dlr, :n, ngrid) # Use semicircle spectral density to generate the sample Green's function in ωn
println("Compress Green's function into ~20 coefficients ...")
spectral_from_Gτ = tau2dlr(dlr, Gτ, τgrid)
spectral_from_Gω = matfreq2dlr(dlr, Gn, ngrid)
# You can use the above functions to fit noisy data by providing the named parameter ``error``
println("Prepare the target Green's functions to benchmark with ...")
τ = collect(LinRange(0.0, β, Nτ * 2)) # create a dense τ grid to interpolate
Gτ_target = Sample.SemiCircle(dlr, :τ, τ)
n = collect(2Nωn:2Nωn) # create a set of Matsubarafrequency points
Gn_target = Sample.SemiCircle(dlr, :n, n)
println("Interpolation benchmark ...")
Gτ_interp = dlr2tau(dlr, spectral_from_Gτ, τ)
println("τ → τ accuracy: ", diff(Gτ_interp, Gτ_target))
Gn_interp = dlr2matfreq(dlr, spectral_from_Gω, n)
println("iω → iω accuracy: ", diff(Gn_interp, Gn_target))
println("Fourier transform benchmark...")
Gτ_to_n = dlr2matfreq(dlr, spectral_from_Gτ, n)
println("τ → iω accuracy: ", diff(Gτ_to_n, Gn_target))
Gn_to_τ = dlr2tau(dlr, spectral_from_Gω, τ)
println("iω → τ accuracy: ", diff(Gn_to_τ, Gτ_target))
Build DLR basis file
A set of basis files have been precalcualted and stored in the folder basis. They cover most of the use cases. For edge case, you may generate your own basis file use this script.
In the above script, user can choose the folder to store the generated basis file. To use the new basis file, simply pass the folder as an argument when create DLRGrid
struct. More information can be found in the documentation
Citation
If this library helps you to create software or publications, please let us know, and cite
Related Package
libdlr by Jason Kaye and Hugo U.R. Strand.
Questions and Contributions
Contributions are very welcome, as are feature requests and suggestions. Please open an issue if you encounter any problems.