Hubbard Dimer

This exercise will demonstrate how to handle hopping and multi-site problems within edrixs using the example of a Hubbard dimer. We want to solve the equation

\[\begin{equation} \hat{H} = \sum_{i,j} \sum_{\sigma} t_{i,j} \hat{f}^{\dagger}_{i,\sigma} \hat{f}_{j, \sigma} + U \sum_{i} \hat{n}_{i,\uparrow}\hat{n}_{i,\downarrow}, \end{equation}\]

which involves two sites labeled with indices \(i\) or \(j\) with two electrons of spin \(\sigma\in{\uparrow,\downarrow}\). \(t_{i,j}\) is the hopping between sites, \(\hat{f}^{\dagger}_{i,\sigma}\) is the creation operators, and \(\hat{n}^{\dagger}_{i,\sigma}=\hat{f}^{\dagger}_{i,\sigma}\hat{f}_{i,\sigma}\) is the number operator. The main task is to represent this Hamiltonian and the related spin operator using the EDRIXS two-fermion and four-fermion form where \(\alpha,\beta,\delta,\gamma\) are the indices of the single particle basis.

\[\begin{equation} \hat{H} = \sum_{\alpha,\beta} t_{\alpha,\beta} \hat{f}^{\dagger}_{\alpha} \hat{f}_{\beta} + \sum_{\alpha,\beta,\gamma,\delta} U_{\alpha,\beta,\gamma,\delta} \hat{f}^{\dagger}_{\alpha}\hat{f}^{\dagger}_{\beta}\hat{f}_{\gamma}\hat{f}_{\delta}. \end{equation}\]

Initialize matrices

We start by noting that each of the two sites is like an \(l=0\) \(s\)-orbital with two spin-orbitals each. We will include two electron occupation and build the Fock basis.

import numpy as np
import matplotlib.pyplot as plt
import scipy
import edrixs
np.set_printoptions(precision=4)


ll = 0
case = 's'
norb = 4
noccu = 2
basis = edrixs.get_fock_bin_by_N(norb, noccu)

Create function to populate and diagonalize matrices

The Coulomb and hopping matrices umat and emat will be represented by \(4\times4\times4\times4\) and \(4\times4\) matrices, respectively. Note that we needed to specify that these are, in general, complex, although they happen to contain only real numbers in this case. We follow the convention that these are ordered first by site and then by spin: \(|0\uparrow>, |0\downarrow>, |1\uparrow>, |1\downarrow>\). Consequently the \(2\times2\) and \(2\times2\times2\times2\) block diagonal structures of the matrices will contain the on-site interactions. The converse is true for the hopping between the sites. From here let us generate a function to build and diagonalize the Hamiltonian. We need to generate the Coulomb matrix for the on-site interactions and apply it to the block diagonal. The hopping connects off-site indices with the same spin.

def diagonalize(U, t, extra_emat=None):
    """Diagonalize 2 site Hubbard Hamiltonian"""
    umat = np.zeros((norb, norb, norb, norb), dtype=np.complex128)
    emat = np.zeros((norb, norb), dtype=np.complex128)
    U_mat_1site = edrixs.get_umat_slater('s', U)
    umat[:2, :2, :2, :2,] = umat[2:, 2:, 2:, 2:] = U_mat_1site
    emat[2, 0] = emat[3, 1] = emat[0, 2] = emat[1, 3] = t

    if extra_emat is not None:
        emat = emat + extra_emat

    H = (edrixs.build_opers(2, emat, basis)
         + edrixs.build_opers(4, umat, basis))

    e, v = scipy.linalg.eigh(H)
    return e, v

The large \(U\) limit

Let us see what happens with \(U \gg t\).

e, v = diagonalize(1000, 1)
print("Energies are")
print(e)
Energies are
[  -0.004    0.       0.       0.    1000.    1000.004]

To analyze what is going on we can determine the spin expectation values of the cluster. Building the operators follows the same form as the Hamiltonian and the previous example.

spin_mom_one_site = edrixs.get_spin_momentum(ll)
spin_mom = np.zeros((3, norb, norb), dtype=np.complex128)
spin_mom[:, :2, :2] = spin_mom[:, 2:, 2:] = spin_mom_one_site

opS = edrixs.build_opers(2, spin_mom, basis)
opS_squared = (np.dot(opS[0], opS[0]) + np.dot(opS[1], opS[1])
               + np.dot(opS[2], opS[2]))

This time let us include a tiny magnetic field along the \(z\)-axis, so that we have a well-defined measurement axis and print out the expectation values.

zeeman = np.zeros((norb, norb), dtype=np.complex128)
zeeman[:2, :2] = zeeman[2:, 2:] = 1e-8*spin_mom_one_site[2]
e, v = diagonalize(1000, 1, extra_emat=zeeman)

Ssq_exp = edrixs.cb_op(opS_squared, v).diagonal().real
Sz_exp = edrixs.cb_op(opS[2], v).diagonal().real

header = "{:<10s}\t{:<6s}\t{:<6s}"
print(header.format("E", "S(S+1)", "<Sz>"))
for i in range(len(e)):
    print("{:<2f}\t{:.1f}\t{:.1f}".format(e[i], Ssq_exp[i], Sz_exp[i]))
E               S(S+1)  <Sz>
-0.004000       0.0     0.0
-0.000000       2.0     -1.0
-0.000000       2.0     0.0
0.000000        2.0     1.0
1000.000000     0.0     0.0
1000.004000     0.0     0.0

For \(U \gg t\) the two states with double occupancy acquire an energy of approximately \(U\). The low energy states are a \(S=0\) singlet and and \(S=1\) triplet, which are split by \(4t^2/U\), which is the magnetic exchange term.

\(U\) dependence

Let us plot the changes in energy with \(U\).

plt.figure()

t = 1
Us = np.linspace(0.01, 10, 50)
Es = np.array([diagonalize(U, t, extra_emat=zeeman)[0] for U in Us])

plt.plot(Us/t, Es/t)
plt.xlabel('U/t')
plt.ylabel('Eigenstate energies/t')
plt.show()
example 6 Hubbard dimer

To help interpret this, we can represent the eigenvectors in terms of a sum of the single particle states.

def get_single_particle_repesentations(v):
    reps = []
    for i in range(6):
        rep = sum([vec*weight for weight, vec
                        in zip(v[:, i], np.array(basis))])
        reps.append(rep)

    return np.array(reps)

t = 1
for U in [10000, 0.0001]:
    e, v = diagonalize(U, t, extra_emat=zeeman)
    repesentations = get_single_particle_repesentations(v)
    print("For U={} t={} states  are".format(U,  t))
    print(repesentations.round(3).real)
    print("\n")
For U=10000 t=1 states  are
[[-0.707  0.707  0.707 -0.707]
 [ 0.     1.     0.     1.   ]
 [ 0.707  0.707  0.707  0.707]
 [-1.     0.    -1.     0.   ]
 [-0.707 -0.707  0.707  0.707]
 [ 0.707  0.707  0.707  0.707]]


For U=0.0001 t=1 states  are
[[-0.     1.     1.    -0.   ]
 [ 0.     1.     0.     1.   ]
 [ 0.707  0.707  0.707  0.707]
 [-1.     0.    -1.     0.   ]
 [-0.707 -0.707  0.707  0.707]
 [-1.    -0.    -0.    -1.   ]]

For \(U \gg t\) the ground state maximizes its magnetic exchange energy saving. In the \(U \ll t\) condition the ground state maximizes its kinetic energy saving. Since both states share the same parity, the cross-over between them is smooth. This type of physics is at play in current research on quantum materials [1] [2].

Footnotes

Total running time of the script: (0 minutes 0.100 seconds)

Gallery generated by Sphinx-Gallery