Semi-infinite chain

This tutorial shows how to setup a minimal impurity model, that of a single fermionic state, and solve it using triqs_soehyb. As the first example we pick the analytically solvable case of a semi-infinte chain. (By having the exact solution we will be able to see how the bold hybridization expansion converges as a function of expansion order.)

In the semi-infinite chain with nearest neighbour hopping \(t = 1\) the site with only one neighbour has a single particle Green’s function with semi-circular density of states (DOS). Thus the chain can be reformulated as an impurity problem of a single site (with zero energy) coupled to a hybridization function with semi-cicular DOS.

Initialization

First we spawn a solver instance and setting up a few general system parameters.

[2]:
from triqs_soehyb import Solver

S = Solver(
    beta=5.0, # Inverse temperature
    gf_struct=[('0', 1)], # Green's function structure 1st index: name, 2nd index: dimension of subspace
    eps=1e-8, # Accuracy of Discrete Lehmann Representation (DLR) used for imaginary time response functions
    w_max=2.0, # DLR freqiency cut-off (the spectrum of the model must be in the range [-w_max, +w_max]
    )

Warning: could not identify MPI environment!
  ___      ___    _  ___   _____
 / __| ___| __|__| || \ \ / / _ )
 \__ \/ _ \ _|___| __ |\ V /| _ \
 |___/\___/___|  |_||_| |_| |___/  [github.com/TRIQS/soehyb]

beta = 5.0, lamb = 1.00E+01, eps = 1.00E-08, N_DLR = 13
fundamental_operators = [1*c('0',0)]
H_mat.shape = (2, 2)
H_loc = 0

Starting serial run at: 2025-08-17 22:19:09.421767

Hybridization function

In the solver instance the hybridization function is located at S.Delta_tau and we set it to have the semi-circular shape of the semi-infinite chain.

[3]:
from triqs.gf import make_gf_dlr_imtime, make_gf_dlr_imfreq, SemiCircular

for bidx, delta_tau in S.Delta_tau:
    delta_w = make_gf_dlr_imfreq(delta_tau)
    delta_w << SemiCircular(2.0)
    delta_tau[:] = make_gf_dlr_imtime(delta_w)

Local many-body Hamiltonian

The local Hamiltonian of the single-site is in this case trivial with a single state at zero energy.

[4]:
from triqs.operators import c, c_dag

h_int = 0.0 * c_dag('0',0) * c('0',0)

Run solver

Finally we run the solver for a few different expansion orders.

[5]:
from h5 import HDFArchive

max_order = 4

for order in range(1, max_order+1):
    S.solve(h_int=h_int, order=order, maxiter=20)

    with HDFArchive(f'data_order_{order}.h5', 'w') as A:
        A['S'] = S
AdaPol: Hybridization fit accuracy 3.39E-07, using 5 poles.
(Order, N_Diags) = [(1, 1)]
max_order = 1

 iter |   conv   |    Z-1
------+----------+-----------
    1 | 3.28E-01 | +4.44E-16
    2 | 8.18E-02 | +1.89E-14
    3 | 1.96E-02 | +1.91E-14
    4 | 4.39E-03 | -1.22E-14
    5 | 9.45E-04 | +3.06E-14
    6 | 1.98E-04 | -4.44E-15
    7 | 4.06E-05 | -1.98E-14
    8 | 8.23E-06 | -4.55E-14
    9 | 1.65E-06 | -1.28E-14
   10 | 3.31E-07 | +1.78E-14
   11 | 6.58E-08 | -1.50E-14
   12 | 1.31E-08 | -8.88E-16
   13 | 2.58E-09 | -1.95E-14
   14 | 5.11E-10 | +3.11E-15

Timing:                               incl.     excl.
------------------------------------------------------------
Dyson equation:                       0.194     0.194  44.5% |-----------------|
Hybridization compression (AAA):      0.079     0.079  18.0% |------|
Pseudo-particle self-energy:          0.006     0.006   1.3% ||
Single particle Green's function:     0.000     0.000   0.0% |
Other:                                0.158     0.158  36.2% |-------------|
------------------------------------------------------------
Total:                                          0.437 100.0%

AdaPol: Hybridization fit accuracy 3.39E-07, using 5 poles.
(Order, N_Diags) = [(1, 1), (2, 10)]
max_order = 2

 iter |   conv   |    Z-1
------+----------+-----------
    1 | 3.28E-01 | +4.44E-16
    2 | 8.18E-02 | +9.10E-15
    3 | 1.96E-02 | +2.22E-14
    4 | 4.39E-03 | -6.88E-15
    5 | 9.45E-04 | +2.89E-15
    6 | 1.98E-04 | +1.93E-14
    7 | 4.06E-05 | -9.88E-15
    8 | 8.23E-06 | -5.55E-15
    9 | 1.65E-06 | +1.11E-15
   10 | 3.31E-07 | -1.04E-14
   11 | 6.58E-08 | +7.55E-15
   12 | 1.31E-08 | +1.62E-14
   13 | 2.58E-09 | -4.22E-15
   14 | 5.11E-10 | -3.67E-14

Timing:                               incl.     excl.
------------------------------------------------------------
Dyson equation:                       0.380     0.380  42.1% |----------------|
Hybridization compression (AAA):      0.093     0.093  10.3% |---|
Pseudo-particle self-energy:          0.170     0.170  18.9% |-------|
Single particle Green's function:     0.001     0.001   0.1% |
Other:                                0.258     0.258  28.6% |----------|
------------------------------------------------------------
Total:                                          0.902 100.0%

AdaPol: Hybridization fit accuracy 3.39E-07, using 5 poles.
(Order, N_Diags) = [(1, 1), (2, 10), (3, 100)]
max_order = 3

 iter |   conv   |    Z-1
------+----------+-----------
    1 | 2.95E-01 | +0.00E+00
    2 | 5.22E-02 | -1.52E-14
    3 | 6.72E-03 | +2.60E-14
    4 | 1.07E-03 | +2.62E-14
    5 | 2.58E-04 | -1.31E-14
    6 | 6.04E-05 | +9.10E-15
    7 | 1.14E-05 | -6.88E-15
    8 | 1.57E-06 | +2.13E-14
    9 | 2.18E-07 | +1.38E-14
   10 | 5.39E-08 | +8.88E-16
   11 | 1.26E-08 | +1.78E-15
   12 | 2.47E-09 | -2.22E-15
   13 | 3.63E-10 | +5.55E-15

Timing:                               incl.     excl.
------------------------------------------------------------
Dyson equation:                       0.793     0.793  18.8% |-------|
Hybridization compression (AAA):      0.117     0.117   2.8% ||
Pseudo-particle self-energy:          2.640     2.640  62.6% |------------------------|
Single particle Green's function:     0.193     0.193   4.6% |-|
Other:                                0.472     0.472  11.2% |---|
------------------------------------------------------------
Total:                                          4.215 100.0%

AdaPol: Hybridization fit accuracy 3.39E-07, using 5 poles.
(Order, N_Diags) = [(1, 1), (2, 10), (3, 100), (4, 1000)]
max_order = 4

 iter |   conv   |    Z-1
------+----------+-----------
    1 | 3.03E-01 | +0.00E+00
    2 | 5.92E-02 | -5.77E-15
    3 | 9.80E-03 | +5.33E-15
    4 | 1.14E-03 | +8.88E-16
    5 | 1.69E-04 | -7.44E-15
    6 | 3.97E-05 | +6.00E-15
    7 | 9.47E-06 | -2.75E-14
    8 | 1.90E-06 | -2.31E-14
    9 | 3.12E-07 | -8.10E-15
   10 | 3.57E-08 | -1.13E-14
   11 | 5.58E-09 | +2.00E-14
   12 | 1.31E-09 | -4.00E-15
   13 | 3.15E-10 | -1.11E-15

Timing:                               incl.     excl.
------------------------------------------------------------
Dyson equation:                       1.172     1.172   1.2% |
Hybridization compression (AAA):      0.162     0.162   0.2% |
Pseudo-particle self-energy:         88.449    88.449  93.8% |-------------------------------------|
Single particle Green's function:     3.736     3.736   4.0% |-|
Other:                                0.788     0.788   0.8% |
------------------------------------------------------------
Total:                                         94.308 100.0%

Visualization

To see the convergence with expansion order we plot the resulting single-particle Green’s function.

[6]:
from triqs.plot.mpl_interface import oplot, oplotr, oploti, plt

def plot_dlr_imtime(g_tau, label, n_tau=400, marker='x', linestyle='-', color=None):

    from triqs.gf import make_gf_imtime

    g_tau_fine = make_gf_imtime(g_tau, n_tau=n_tau)

    if color is None:
        color = plt.plot([], [], linestyle+marker, label=label)[0].get_color()
        label = None

    oplotr(g_tau, marker=marker, label=None, color=color)
    oplotr(g_tau_fine, label=label, color=color, linestyle=linestyle)
[7]:
import glob

filenames = np.sort(glob.glob('data_order_*.h5'))

results = []
for filename in filenames:
    print(f'--> Loading: {filename}')
    with HDFArchive(filename, 'r') as A:
        results.append(A['S'])
--> Loading: data_order_1.h5
--> Loading: data_order_2.h5
--> Loading: data_order_3.h5
--> Loading: data_order_4.h5
[8]:
for r in results:
    plot_dlr_imtime(r.G_tau['0'], label=f'Order {r.order}', linestyle='-' if r.order != 2 else ':')

delta_tau = results[0].Delta_tau['0']
plot_dlr_imtime(delta_tau, label='Exact', marker='', linestyle='-.', color='black')

plt.ylabel(r'$G(\tau)$'); plt.xlabel(r'$\tau$')
plt.legend(loc='best'); plt.grid(True); plt.ylim(top=0);
../_images/tutorials_Semi_infinite_chain_13_0.svg
[9]:
for r in results:
    diff_tau = delta_tau - r.G_tau['0']
    diff_tau.data[:] = np.abs(diff_tau.data)
    plot_dlr_imtime(diff_tau, label=f'Order {r.order}',
                    linestyle='-' if r.order != 2 else ':')

plt.semilogy([], [])
plt.legend(loc='best')

plt.ylabel(r'max$|G(\tau) - G_{exact}(\tau)|$')
plt.xlabel(r'$\tau$')
plt.grid(True)
../_images/tutorials_Semi_infinite_chain_14_0.svg

The convergence rate with expansion order is fast and the error at order 4 is about \(10^{-3}\).