Sparse sampling#

In this page, we describe how to infer IR expansion coefficients using the sparse-sampling techiniques.

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

Setup#

We consider a semicircular spectral modeli (full bandwidth of 2):

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

First, we compute the numerically exact expansion coefficients \(g_l\). Below, we plot the data for even \(l\).

def rho(omega):
    if np.abs(omega) < 1:
        return (2/np.pi) * np.sqrt(1-omega**2)
    else:
        return 0.0

beta = 10000
wmax = 1
basis = sparse_ir.FiniteTempBasis("F", beta, wmax, eps=1e-15)

rhol = basis.v.overlap(rho)
gl = - basis.s * rhol

ls = np.arange(basis.size)
plt.semilogy(ls[::2], np.abs(gl[::2]), marker="x", label=r"$|g_l|$")
plt.xlabel(r"$l$")
plt.ylabel(r"$|g_l|$")
plt.ylim([1e-15, 10])
plt.legend()
plt.show()
../_images/8b80106bba4afb2c36d51a546e5a49d669b249c6e1d198c0344423d434b0d23a.png

From sampling times#

We first create a TauSampling object for the default sampling times.

smpl_tau = sparse_ir.TauSampling(basis)
print("sampling times: ", smpl_tau.sampling_points)
print("Condition number: ", smpl_tau.cond)
sampling times:  [6.47259411e-02 3.41743000e-01 8.43021447e-01 1.57374357e+00
 2.54146656e+00 3.75645685e+00 5.23203838e+00 6.98503912e+00
 9.03635582e+00 1.14116536e+01 1.41422159e+01 1.72659575e+01
 2.08286083e+01 2.48850703e+01 2.95009414e+01 3.47541980e+01
 4.07370279e+01 4.75578203e+01 5.53433349e+01 6.42411056e+01
 7.44221521e+01 8.60840959e+01 9.94547772e+01 1.14796470e+02
 1.32410787e+02 1.52644359e+02 1.75895379e+02 2.02621103e+02
 2.33346379e+02 2.68673315e+02 3.09292122e+02 3.55993176e+02
 4.09680252e+02 4.71384769e+02 5.42280708e+02 6.23699556e+02
 7.17144194e+02 8.24299996e+02 9.47040430e+02 1.08742317e+03
 1.24767097e+03 1.43012945e+03 1.63719162e+03 1.87117715e+03
 2.13415420e+03 2.42769528e+03 2.75256828e+03 3.10838360e+03
 3.49324565e+03 3.90348920e+03 4.33360019e+03 4.77640949e+03
 5.22359051e+03 5.66639981e+03 6.09651080e+03 6.50675435e+03
 6.89161640e+03 7.24743172e+03 7.57230472e+03 7.86584580e+03
 8.12882285e+03 8.36280838e+03 8.56987055e+03 8.75232903e+03
 8.91257683e+03 9.05295957e+03 9.17570000e+03 9.28285581e+03
 9.37630044e+03 9.45771929e+03 9.52861523e+03 9.59031975e+03
 9.64400682e+03 9.69070788e+03 9.73132669e+03 9.76665362e+03
 9.79737890e+03 9.82410462e+03 9.84735564e+03 9.86758921e+03
 9.88520353e+03 9.90054522e+03 9.91391590e+03 9.92557785e+03
 9.93575889e+03 9.94465667e+03 9.95244218e+03 9.95926297e+03
 9.96524580e+03 9.97049906e+03 9.97511493e+03 9.97917139e+03
 9.98273404e+03 9.98585778e+03 9.98858835e+03 9.99096364e+03
 9.99301496e+03 9.99476796e+03 9.99624354e+03 9.99745853e+03
 9.99842626e+03 9.99915698e+03 9.99965826e+03 9.99993527e+03]
Condition number:  51.83054439165556

The condition number is around 50, indicating that 1–2 significant digits may be lost in a fit from the sampling times. Let us fit from the sampling times!

# Evaluate G(τ) on the sampling times
gtau_smpl = smpl_tau.evaluate(gl)
plt.plot(smpl_tau.sampling_points, gtau_smpl, marker="x", ls="")
plt.xlabel(r"$\tau$")
plt.ylabel(r"$G(\tau)$")
plt.show()

# Fit G(τ) on the sampling times
gl_reconst_from_tau = smpl_tau.fit(gtau_smpl)
../_images/e507ececc8fdbf0b40f437b53ea0899108788ca8884302495b9a15ba8485b12e.png

From sampling frequencies#

We create a MatsubaraSampling object for the default sampling frequencies.

smpl_matsu = sparse_ir.MatsubaraSampling(basis)
print("sampling frequencies: ", smpl_matsu.sampling_points)
print("Condition number: ", smpl_matsu.cond)
sampling frequencies:  [-45241 -14981  -8871  -6213  -4709  -3733  -3041  -2523  -2121  -1797
  -1533  -1315  -1131   -975   -843   -729   -631   -547   -475   -411
   -357   -309   -269   -233   -203   -177   -153   -133   -115   -101
    -87    -75    -65    -57    -49    -43    -37    -33    -29    -25
    -23    -21    -19    -17    -15    -13    -11     -9     -7     -5
     -3     -1      1      3      5      7      9     11     13     15
     17     19     21     23     25     29     33     37     43     49
     57     65     75     87    101    115    133    153    177    203
    233    269    309    357    411    475    547    631    729    843
    975   1131   1315   1533   1797   2121   2523   3041   3733   4709
   6213   8871  14981  45241]
Condition number:  213.18566918576917

The condition number is slightly larger than that for the sampling times.

# Evaluate G(iv) on the sampling frequencies
giv_smpl = smpl_matsu.evaluate(gl)
plt.plot((np.pi/beta)*smpl_matsu.wn, giv_smpl.imag, marker="x", ls="")
plt.xlabel(r"$\nu$")
plt.ylabel(r"Im $G(\mathrm{i}\nu)$")
plt.show()

# Fit G(τ) on the sampling times
gl_reconst_from_matsu = smpl_matsu.fit(giv_smpl)
../_images/fd0418454739cce02cc6228365e50f3ad5b924c987f8a04d92c460f9d2a06e8c.png

Comparison with exact results#

We now compare the reconstructed expansion coefficients with the exact one. For clarity, we plot only the data for even \(l\).

plt.semilogy(ls[::2], np.abs(gl[::2]), marker="", ls="-", label="Exact")
plt.semilogy(ls[::2], np.abs(gl_reconst_from_tau[::2]), marker="x", label="from sampling times")
plt.semilogy(ls[::2], np.abs(gl_reconst_from_matsu[::2]), marker="+", label="from sampling frequencies")
plt.xlabel(r"$l$")
plt.ylabel(r"$|g_l|$")
plt.ylim([1e-17, 10])
plt.legend(frameon=False)
plt.show()
../_images/eb62b5718092a10fa64703e5c3372c42ceb72718ce8d1b159477166bb1f088ae.png

We saw a perfect match! Let us plot the differences from the exact one.

plt.semilogy(ls[::2], np.abs((gl_reconst_from_tau-gl)[::2]), marker="x", label="from sampling times")
plt.semilogy(ls[::2], np.abs((gl_reconst_from_matsu-gl)[::2]), marker="+", label="from sampling frequencies")
plt.xlabel(r"$l$")
plt.ylabel(r"Error in $g_l$")
plt.ylim([1e-18, 10])
plt.legend()
plt.show()
../_images/7b2fcd2e9cd3f5360aef712bbce94ab4d5e8ff0d7ccfed65eed800420d504283.png