Usage examples

3 orbital impurity with Hubbard-Kanamori interaction

  1from itertools import product
  2import numpy as np
  3from mpi4py import MPI
  4
  5# TRIQS many-body operator objects
  6from triqs.operators import c, c_dag, n
  7
  8# Compatibility layer between EDIpack and TRIQS
  9from edipack2triqs.solver import EDIpackSolver
 10
 11# Fundamental sets for impurity degrees of freedom
 12fops_imp_up = [('up', 0), ('up', 1), ('up', 2)]
 13fops_imp_dn = [('dn', 0), ('dn', 1), ('dn', 2)]
 14
 15# Fundamental sets for bath degrees of freedom
 16fops_bath_up = [('B_up', i) for i in range(3 * 2)]
 17fops_bath_dn = [('B_dn', i) for i in range(3 * 2)]
 18
 19# Define the Hamiltonian
 20orbs = range(3)
 21
 22## Non-interacting part of the impurity Hamiltonian
 23h_loc = np.diag([-0.7, -0.5, -0.7])
 24H = sum(h_loc[o1, o2] * c_dag(spin, o1) * c(spin, o2)
 25        for spin, o1, o2 in product(('up', 'dn'), orbs, orbs))
 26
 27## Interaction part
 28U = 3.0     # Local intra-orbital interactions U
 29Ust = 1.2   # Local inter-orbital interaction U'
 30Jh = 0.2    # Hund's coupling
 31Jx = 0.15   # Spin-exchange coupling constant
 32Jp = 0.1    # Pair-hopping coupling constant
 33
 34H += U * sum(n('up', o) * n('dn', o) for o in orbs)
 35H += Ust * sum(int(o1 != o2) * n('up', o1) * n('dn', o2)
 36               for o1, o2 in product(orbs, orbs))
 37H += (Ust - Jh) * sum(int(o1 < o2) * n(s, o1) * n(s, o2)
 38                      for s, o1, o2 in product(('up', 'dn'), orbs, orbs))
 39H -= Jx * sum(int(o1 != o2)
 40              * c_dag('up', o1) * c('dn', o1) * c_dag('dn', o2) * c('up', o2)
 41              for o1, o2 in product(orbs, orbs))
 42H += Jp * sum(int(o1 != o2)
 43              * c_dag('up', o1) * c_dag('dn', o1) * c('dn', o2) * c('up', o2)
 44              for o1, o2 in product(orbs, orbs))
 45
 46## Bath part
 47
 48# Matrix dimensions of eps and V: 3 orbitals x 2 bath states
 49eps = np.array([[-0.1, 0.1],
 50                [-0.2, 0.2],
 51                [-0.3, 0.3]])
 52V = np.array([[0.1, 0.2],
 53              [0.1, 0.2],
 54              [0.1, 0.2]])
 55
 56H += sum(eps[o, nu] * c_dag("B_" + s, nu * 3 + o) * c("B_" + s, nu * 3 + o)
 57         for s, o, nu in product(('up', 'dn'), orbs, range(2)))
 58H += sum(V[o, nu] * (c_dag(s, o) * c("B_" + s, nu * 3 + o)
 59                     + c_dag("B_" + s, nu * 3 + o) * c(s, o))
 60         for s, o, nu in product(('up', 'dn'), orbs, range(2)))
 61
 62# Create a solver object that wraps EDIpack functionality
 63# See help(EDIpackSolver) for a complete list of parameters
 64solver = EDIpackSolver(H,
 65                       fops_imp_up, fops_imp_dn, fops_bath_up, fops_bath_dn,
 66                       lanc_dim_threshold=16)
 67
 68# Solve the impurity model
 69beta = 100.0  # Inverse temperature
 70n_iw = 1024   # Number of Matsubara frequencies for impurity GF calculations
 71energy_window = (-2.0, 2.0)  # Energy window for real-frequency GF calculations
 72n_w = 4000    # Number of real-frequency points for impurity GF calculations
 73broadening = 0.005  # Broadening on the real axis for impurity GF calculations
 74
 75solver.solve(beta=beta,
 76             n_iw=n_iw,
 77             energy_window=energy_window,
 78             n_w=n_w,
 79             broadening=broadening)
 80
 81# On master node, output results of calculation
 82if MPI.COMM_WORLD.Get_rank() == 0:
 83    print("Using SciFortran", solver.scifor_version)
 84    print("Using EDIpack", solver.edipack_version)
 85
 86    print("Densities (per orbital):", solver.densities)
 87    print("Double occupancy (per orbital):", solver.double_occ)
 88    print("Magnetization M_x (per orbital):", solver.magnetization[:, 0])
 89    print("Magnetization M_y (per orbital):", solver.magnetization[:, 1])
 90    print("Magnetization M_z (per orbital):", solver.magnetization[:, 2])
 91
 92    from triqs.plot.mpl_interface import plt, oplot
 93
 94    # Extract the Matsubara GF from the solver and plot it
 95    g_iw = solver.g_iw
 96
 97    plt.figure()
 98    for spin in ('up', 'dn'):
 99        for orb in range(3):
100            label = r"g_{%s,%i%i}(i\omega_n)$" % (spin, orb, orb)
101            oplot(g_iw[spin][orb, orb].real, label=r"$\Re " + label)
102            oplot(g_iw[spin][orb, orb].imag, label=r"$\Im " + label)
103    plt.legend(loc='lower center', ncols=3)
104    plt.savefig("g_iw.pdf")
105
106    # Extract the Matsubara self-energy from the solver and plot it
107    Sigma_iw = solver.Sigma_iw
108
109    plt.figure()
110    for spin in ('up', 'dn'):
111        for orb in range(3):
112            label = r"\Sigma_{%s,%i%i}(i\omega_n)$" % (spin, orb, orb)
113            oplot(Sigma_iw[spin][orb, orb].real, label=r"$\Re " + label)
114            oplot(Sigma_iw[spin][orb, orb].imag, label=r"$\Im " + label)
115    plt.legend(loc='lower center', ncols=3)
116    plt.savefig("Sigma_iw.pdf")
117
118    # Extract the real-frequency GF from the solver and plot it
119    g_w = solver.g_w
120
121    plt.figure()
122    for spin in ('up', 'dn'):
123        for orb in range(3):
124            label = r"g_{%s,%i%i}(\omega)$" % (spin, orb, orb)
125            oplot(g_w[spin][orb, orb].real, label=r"$\Re " + label)
126            oplot(g_w[spin][orb, orb].imag, label=r"$\Im " + label)
127    plt.legend(loc='lower center', ncols=3)
128    plt.savefig("g_w.pdf")
129
130    # Extract the real-frequency self-energy from the solver and plot it
131    Sigma_w = solver.Sigma_w
132
133    plt.figure()
134    for spin in ('up', 'dn'):
135        for orb in range(3):
136            label = r"\Sigma_{%s,%i%i}(\omega)$" % (spin, orb, orb)
137            oplot(Sigma_w[spin][orb, orb].real, label=r"$\Re " + label)
138            oplot(Sigma_w[spin][orb, orb].imag, label=r"$\Im " + label)
139    plt.legend(loc='lower center', ncols=3)
140    plt.savefig("Sigma_w.pdf")
141
142# It is possible to change some parameters of the Hamiltonian and to diagonalize
143# it again.
144
145# Change a matrix element of h_loc
146# Since the non-interacting part of the original Hamiltonian is spin-symmetric,
147# solver.hloc() returns an array of shape (1, 1, 3, 3). In presence of a spin
148# energy splitting the shape would be (2, 2, 3, 3).
149solver.hloc[0, 0, 1, 1] = -0.6  # spin1 = spin2 = up and down, orb1 = orb2 = 1
150
151# Change Jp
152solver.Jp = 0.15
153
154# Update some bath parameters
155solver.bath.eps[0, 2, 1] = -0.4  # spin = up and down, orb1 = 2, nu = 1
156solver.bath.V[0, 0, 1] = 0.3     # spin = up and down, orb1 = 0, nu = 1
157
158solver.solve(beta=beta)

DMFT study of superconductivity in the attractive Hubbard model

  1from itertools import product
  2import numpy as np
  3
  4# TRIQS modules
  5from triqs.gf import (Gf, BlockGf, MeshImFreq, MeshProduct,
  6                      iOmega_n, conjugate, inverse)
  7from triqs.gf.tools import dyson
  8from triqs.operators import c, c_dag, n, dagger
  9from triqs.lattice.tight_binding import TBLattice
 10from h5 import HDFArchive
 11
 12# edipack2triqs modules
 13from edipack2triqs.solver import EDIpackSolver
 14from edipack2triqs.fit import BathFittingParams
 15
 16
 17# Parameters
 18Nspin = 1
 19Nloop = 100
 20Nsuccess = 1
 21threshold = 1e-6
 22wmixing = 0.5
 23Norb = 1
 24Nbath = 4
 25n_k = 20
 26U = -3.0      # Local intra-orbital interactions U
 27Ust = 1.2     # Local inter-orbital interaction U'
 28Jh = 0.2      # Hund's coupling
 29Jx = 0.15     # Spin-exchange coupling constant
 30Jp = 0.1      # Pair-hopping coupling constant
 31beta = 100.0  # Inverse temperature
 32n_iw = 1024   # Number of Matsubara frequencies for impurity GF calculations
 33t = 0.5
 34# Energy window for real-frequency GF calculations
 35energy_window = (-2.0 * t, 2.0 * t)
 36n_w = 4000    # Number of real-frequency points for impurity GF calculations
 37broadening = 0.005  # Broadening on the real axis for impurity GF calculations
 38
 39spins = ('up', 'dn')
 40orbs = range(Norb)
 41
 42# Fundamental sets for impurity degrees of freedom
 43fops_imp_up = [('up', o) for o in orbs]
 44fops_imp_dn = [('dn', o) for o in orbs]
 45
 46# Fundamental sets for bath degrees of freedom
 47fops_bath_up = [('B_up', i) for i in range(Norb * Nbath)]
 48fops_bath_dn = [('B_dn', i) for i in range(Norb * Nbath)]
 49
 50# Non-interacting part of the impurity Hamiltonian
 51xmu = U / 2 + (Norb - 1) * Ust / 2 + (Norb - 1) * (Ust - Jh) / 2
 52
 53h_loc = -xmu * np.eye(Norb)
 54H = sum(h_loc[o1, o2] * c_dag(spin, o1) * c(spin, o2)
 55        for spin, o1, o2 in product(spins, orbs, orbs))
 56
 57# Interaction part
 58H += U * sum(n('up', o) * n('dn', o) for o in orbs)
 59H += Ust * sum(int(o1 != o2) * n('up', o1) * n('dn', o2)
 60               for o1, o2 in product(orbs, orbs))
 61H += (Ust - Jh) * sum(int(o1 < o2) * n(s, o1) * n(s, o2)
 62                      for s, o1, o2 in product(spins, orbs, orbs))
 63H -= Jx * sum(int(o1 != o2)
 64              * c_dag('up', o1) * c('dn', o1) * c_dag('dn', o2) * c('up', o2)
 65              for o1, o2 in product(orbs, orbs))
 66H += Jp * sum(int(o1 != o2)
 67              * c_dag('up', o1) * c_dag('dn', o1) * c('dn', o2) * c('up', o2)
 68              for o1, o2 in product(orbs, orbs))
 69
 70# Lattice Hamiltonian
 71units = [(1, 0, 0), (0, 1, 0)]
 72orbital_positions = [(0.0, 0.0, 0.0) for i in range(Norb)]
 73hoppings = {(1, 0): t * np.eye(Norb),
 74            (-1, 0): t * np.eye(Norb),
 75            (0, 1): t * np.eye(Norb),
 76            (0, -1): t * np.eye(Norb)}
 77
 78TBL = TBLattice(units=units,
 79                hoppings=hoppings,
 80                orbital_positions=orbital_positions)
 81kmesh = TBL.get_kmesh(n_k=(n_k, n_k, 1))
 82enk = TBL.fourier(kmesh)
 83
 84nambu_shape = (2 * Norb, 2 * Norb)
 85h0_nambu_k = Gf(mesh=kmesh, target_shape=nambu_shape)
 86for k in kmesh:
 87    h0_nambu_k[k][:Norb, :Norb] = enk(k)
 88    h0_nambu_k[k][Norb:, Norb:] = -enk(-k)
 89
 90# Matrix dimensions of eps and V: 3 orbitals x 2 bath states
 91eps = np.array([[-1.0, -0.5, 0.5, 1.0] for i in range(Norb)])
 92V = 0.5 * np.ones((Norb, Nbath))
 93D = -0.2 * np.eye(Norb * Nbath)
 94
 95# Bath
 96H += sum(eps[o, nu]
 97         * c_dag("B_" + s, o * Nbath + nu) * c("B_" + s, o * Nbath + nu)
 98         for s, o, nu in product(spins, orbs, range(Nbath)))
 99
100H += sum(V[o, nu] * (c_dag(s, o) * c("B_" + s, o * Nbath + nu)
101                     + c_dag("B_" + s, o * Nbath + nu) * c(s, o))
102         for s, o, nu in product(spins, orbs, range(Nbath)))
103
104# Anomalous bath
105H += sum(D[o, q] * (c('B_up', o) * c('B_dn', q))
106         + dagger(D[o, q] * (c('B_up', o) * c('B_dn', q)))
107         for o, q in product(range(Norb * Nbath), range(Norb * Nbath)))
108
109# Create solver object
110fit_params = BathFittingParams(method="minimize", grad="numeric")
111solver = EDIpackSolver(H,
112                       fops_imp_up, fops_imp_dn, fops_bath_up, fops_bath_dn,
113                       lanc_dim_threshold=1024,
114                       verbose=1,
115                       bath_fitting_params=fit_params)
116
117
118# Compute local GF from bare lattice Hamiltonian and self-energy
119def get_gloc(s, s_an):
120    z = Gf(mesh=s.mesh, target_shape=nambu_shape)
121    if isinstance(s.mesh, MeshImFreq):
122        z[:Norb, :Norb] << iOmega_n + xmu - s
123        z[:Norb, Norb:] << -s_an
124        z[Norb:, :Norb] << -s_an
125        z[Norb:, Norb:] << iOmega_n - xmu + conjugate(s)
126    else:
127        z[:Norb, Norb:] << -s_an
128        z[Norb:, :Norb] << -s_an
129        for w in z.mesh:
130            z[w][:Norb, :Norb] = \
131                (w + 1j * broadening + xmu) * np.eye(Norb) - s[w]
132            z[w][Norb:, Norb:] = \
133                (w + 1j * broadening - xmu) * np.eye(Norb) + conjugate(s(-w))
134
135    g_k = Gf(mesh=MeshProduct(kmesh, z.mesh), target_shape=nambu_shape)
136    for k in kmesh:
137        g_k[k, :] << inverse(z - h0_nambu_k[k])
138
139    g_loc_nambu = sum(g_k[k, :] for k in kmesh) / len(kmesh)
140
141    g_loc = s.copy()
142    g_loc_an = s_an.copy()
143    g_loc[:] = g_loc_nambu[:Norb, :Norb]
144    g_loc_an[:] = g_loc_nambu[:Norb, Norb:]
145    return g_loc, g_loc_an
146
147
148# Compute Weiss field from local GF and self-energy
149def dmft_weiss_field(g_iw, g_an_iw, s_iw, s_an_iw):
150    g_nambu_iw = Gf(mesh=g_iw.mesh, target_shape=nambu_shape)
151    s_nambu_iw = Gf(mesh=s_iw.mesh, target_shape=nambu_shape)
152
153    g_nambu_iw[:Norb, :Norb] = g_iw
154    g_nambu_iw[:Norb, Norb:] = g_an_iw
155    g_nambu_iw[Norb:, :Norb] = g_an_iw
156    g_nambu_iw[Norb:, Norb:] = -conjugate(g_iw)
157
158    s_nambu_iw[:Norb, :Norb] = s_iw
159    s_nambu_iw[:Norb, Norb:] = s_an_iw
160    s_nambu_iw[Norb:, :Norb] = s_an_iw
161    s_nambu_iw[Norb:, Norb:] = -conjugate(s_iw)
162
163    g0_nambu_iw = dyson(G_iw=g_nambu_iw, Sigma_iw=s_nambu_iw)
164
165    g0_iw = g_iw.copy()
166    g0_an_iw = g_an_iw.copy()
167    g0_iw[:] = g0_nambu_iw[:Norb, :Norb]
168    g0_an_iw[:] = g0_nambu_iw[:Norb, Norb:]
169    return g0_iw, g0_an_iw
170
171
172#
173# DMFT loop
174#
175
176gooditer = 0
177g0_prev = np.zeros((2, 2 * n_iw, Norb, Norb), dtype=complex)
178for iloop in range(Nloop):
179    print(f"\nLoop {iloop + 1} of {Nloop}")
180
181    # Solve the effective impurity problem
182    solver.solve(beta=beta,
183                 n_iw=n_iw,
184                 energy_window=energy_window,
185                 n_w=n_w,
186                 broadening=broadening)
187
188    # Normal and anomalous components of computed self-energy
189    s_iw = solver.Sigma_iw["up"]
190    s_an_iw = solver.Sigma_an_iw["up_dn"]
191
192    # Compute local Green's function
193    g_iw, g_an_iw = get_gloc(s_iw, s_an_iw)
194    # Compute Weiss field
195    g0_iw, g0_an_iw = dmft_weiss_field(g_iw, g_an_iw, s_iw, s_an_iw)
196
197    # Bath fitting and mixing
198    G0_iw = BlockGf(name_list=spins, block_list=[g0_iw, g0_iw])
199    G0_an_iw = BlockGf(name_list=["up_dn"], block_list=[g0_an_iw])
200
201    bath_new = solver.chi2_fit_bath(G0_iw, G0_an_iw)[0]
202    solver.bath = wmixing * bath_new + (1 - wmixing) * solver.bath
203
204    # Check convergence of the Weiss field
205
206    g0 = np.asarray([g0_iw.data, g0_an_iw.data])
207    errvec = np.real(np.sum(abs(g0 - g0_prev), axis=1)
208                     / np.sum(abs(g0), axis=1))
209    # First iteration
210    if iloop == 0:
211        errvec = np.ones_like(errvec)
212    errmin, err, errmax = np.min(errvec), np.average(errvec), np.max(errvec)
213
214    g0_prev = np.copy(g0)
215
216    if err < threshold:
217        gooditer += 1  # Increase good iterations count
218    else:
219        gooditer = 0  # Reset good iterations count
220    iloop += 1
221    conv_bool = ((err < threshold) and (gooditer > Nsuccess)
222                 and (iloop < Nloop)) or (iloop >= Nloop)
223
224    # Print convergence message
225    if iloop < Nloop:
226        if errvec.size > 1:
227            print(f"max error={errmax:.6e}")
228        print("    " * (errvec.size > 1) + f"error={err:.6e}")
229        if errvec.size > 1:
230            print(f"min error={errmin:.6e}")
231    else:
232        if errvec.size > 1:
233            print(f"max error={errmax:.6e}")
234        print("    " * (errvec.size > 1) + f"error={err:.6e}")
235        if errvec.size > 1:
236            print(f"min error={errmin:.6e}")
237        print(f"Not converged after {Nloop} iterations.")
238
239    if conv_bool:
240        break
241
242
243# Calculate local Green's function on the real axis
244s_w = solver.Sigma_w["up"]
245s_an_w = solver.Sigma_an_w["up_dn"]
246g_w, g_an_w = get_gloc(s_w, s_an_w)
247
248# Save calculation results
249with HDFArchive('ahm.h5', 'w') as ar:
250    ar["s_iw"] = s_iw
251    ar["s_an_iw"] = s_an_iw
252    ar["g_iw"] = g_iw
253    ar["g_an_iw"] = g_an_iw
254    ar["g_w"] = g_w
255    ar["g_an_w"] = g_an_w
256
257print("Done...")