Discrete Lehmann Representation#

Theory#

We explain how to transform expansion coefficients in IR to the discrete Lehmann representation (DLR) [1]. In sparse-ir, we choose poles based on the exrema of \(V_l(\omega)\) [2] (In the original paper [1], a more systematic way is proposed). We model the spectral function as

\[ \rho(\omega) = \sum_{p=1}^L c_p \delta(\omega - \bar{\omega}_p), \]

where sampling frequencies \(\{\bar{\omega}_1, \cdots, \bar{\omega}_{L}\}\) are chosen to the extrema of \(V'_{L-1}(\omega)\). This choice is heuristic but allows us a numerically stable transform between \(\rho_l\) and \(c_p\) through the relation

\[ \rho_l = \sum_{p=1}^L \boldsymbol{V}_{lp} c_p, \]

where the matrix \(\boldsymbol{V}_{lp}~[\equiv V_l(\bar{\omega}_p)]\) is well-conditioned. As a result, in SPR, the Green’s function is represented as

\[ G(\mathrm{i}\omega_n) = \sum_{p=1}^L \frac{c_p}{\mathrm{i}\omega_n - \bar{\omega}_p}. \]

[1] J. Kaye, K. Chen, O. Parcollet, Phys. Rev. B 105, 235115 (2022).
[2] H. Shinaoka et al., arXiv:2106.12685v2.

We consider the semi circular DOS

\[ \rho(\omega) = \sqrt{\frac{2}{\pi}} \sqrt{1-\omega^2}. \]

The corresponding Green’s function is given by

\[ G(\mathrm{i}\omega_n) = \int_{-1}^1 \mathrm{d}\omega \frac{\rho(\omega)}{\mathrm{i}\omega_n - \omega}. \]

The Green’s function is expanded in IR as

\[ G_l = - S_l \int_{-1}^1 \mathrm{d}\omega \rho(\omega) V_l(\omega). \]

Below, we demonstrate how to transform \(G_l\) to the DLR coefficients \(c_p\).

import numpy as np
from sparse_ir import FiniteTempBasis, MatsubaraSampling
from sparse_ir.dlr import DiscreteLehmannRepresentation

%matplotlib inline
from matplotlib import pyplot as plt
plt.rcParams['font.size'] = 15

Implementation#

Create basis object#

wmax = 1.0
lambda_ = 1e+4
beta = lambda_/wmax

basis = FiniteTempBasis("F", beta, wmax, eps=1e-15)
print(basis.size)
104

Setup model#

rho = lambda omega: np.sqrt(1-omega**2)/np.sqrt(0.5*np.pi)

omega = np.linspace(-wmax, wmax, 1000)
plt.xlabel(r'$\omega$')
plt.ylabel(r'$\rho(\omega)$')
plt.plot(omega, rho(omega))
plt.show()
../_images/c1aa3c0bb8ef755afa7d23ad5fdd992a7c637691f51ba3fe3afb164c9b5d0ae2.png
rhol = basis.v.overlap(rho)
ls = np.arange(basis.size)
plt.semilogy(ls[::2], np.abs(rhol)[::2], marker="x")
plt.ylim([1e-5, None])
plt.show()
../_images/8f43432077a636fb377bc9baf5f2fcfba85e9af8d9abee1365eb19e2aa851307.png
gl = - basis.s * rhol
plt.semilogy(ls[::2], np.abs(gl)[::2], marker="x")
plt.ylim([1e-5, None])
plt.show()
../_images/781f6204eb7ccfdd0923160237690c15015d1f56ff2f3e7a5f5ed9ed1a5dc3de.png

Create a DLR object and perform transformation#

dlr = DiscreteLehmannRepresentation(basis)

# To DLR
g_dlr = dlr.from_IR(gl)

plt.plot(dlr.sampling_points, g_dlr, marker="x", ls="")
plt.show()
../_images/3432897fe6b03efe265d83dae33365ead3d553df1486ed07a38dae4da8f26404.png
# Transform back to IR from SPR
gl_reconst = dlr.to_IR(g_dlr)

plt.semilogy(np.abs(gl), label="Exact", ls="", marker="+")
plt.semilogy(np.abs(gl_reconst), label="Reconstructed from DLR", ls="", marker="x")
plt.semilogy(np.abs(gl-gl_reconst), label="error")
plt.ylim([1e-18,None])
plt.ylabel("$|g_l|$")
plt.legend(loc="best", frameon=False)
plt.show()
../_images/887bd325c9edc1658b2f799ec3633a857187a76e370e5086431f65f346831164.png

Evaluation on Matsubara frequencies#

v = 2*np.arange(-1000, 1000, 10) + 1
iv = 1j * v * (np.pi/beta)

transmat = 1/(iv[:,None] - dlr.sampling_points[None,:])
giv = transmat @ g_dlr

giv_exact = MatsubaraSampling(basis, v).evaluate(gl)

plt.plot(iv.imag, giv_exact.imag, ls="", marker="x", label="Exact")
plt.plot(iv.imag, giv.imag, ls="", marker="x", label="Reconstructed from SPR")
plt.xlabel(r"$\nu$")
plt.ylabel(r"Im $G(\mathrm{i}\omega_n)$")

plt.show()
/home/jovyan/.venv/default/lib/python3.11/site-packages/sparse_ir/sampling.py:129: ConditioningWarning: Sampling matrix is poorly conditioned (kappa = 3.2e+15)
  warn(f"Sampling matrix is poorly conditioned "
../_images/d8c244aa60dae382ac8272da8f62a7a222cd4c16f98e8c51a6faa9882672129c.png