Problems with modelling a fermionic ladder

How do I use this algorithm? What does that parameter do?
Post Reply
Lukas
Posts: 2
Joined: 04 Feb 2020, 13:37

Problems with modelling a fermionic ladder

Post by Lukas »

Hello community.

I had some problems with implementing my own model. The Hamiltonian I want do analyze with DMRG is
\(
\begin{equation}
H= \sum_{i,l}(-t\, c^\dagger_{i+1,l}c_{i,\bar{l}}+i\,s_l \,t \,c^\dagger_{i+1,l}c_{i,l}+ H.c.)+\sum_{i,l} \frac{\Delta \epsilon}{2}s_l n_{i,l}+\sum_{i,l} \frac{V}{2}n_{i,l} n_{i,\bar{l}}
\end{equation}
\)
where l={u,d} represents the rung of the ladder, and \(s_u=1 \) and \(s_d=-1 \). c are fermionic creation and annihilation operators. In the first term, if l=u, \(\bar{l}=d\) and vice versa, so there are hoppings between different rungs. For more information see this paper https://www.researchgate.net/publicatio ... gures?lo=1.
Since we have a spatial index i and the binary index l, I chose to build the model with the prebuilt class Ladder and FermionSite. Here is the code

Code: Select all

import matplotlib.pyplot as plt
import numpy as np
import tenpy.linalg.np_conserved as npc
from tenpy.networks.site import FermionSite
from tenpy.models.model import CouplingModel, MPOModel, CouplingMPOModel
from tenpy.models.lattice import Ladder
from tenpy.tools.params import get_parameter
import cmath

class CreutzHubbardLadder(CouplingModel,MPOModel):
    def __init__(self,model_params):

      name="creutz"
      L=get_parameter(model_params,'L',2,name)
      t=get_parameter(model_params,'t',1.,name)
      V=get_parameter(model_params,'V',1.,name)
      e=get_parameter(model_params,'e',1.,name)

 n=get_parameter(model_params,'n',0.5,name)

      bc_MPS=get_parameter(model_params,'bc_MPS','finite',name)

      site= FermionSite(None,filling=n)

      bc='periodic' if bc_MPS=='infinite' else 'open'

      lat=Ladder(L,site,bc=bc,bc_MPS=bc_MPS) #not sure mit bc und bc_MPS


      CouplingModel.__init__(self, lat)


      self.add_coupling(-t,0,'Cd',1,'C',-1,'JW', True)   #term1.1
      self.add_coupling(-np.conj(t),1,'Cd',0,'C',1,'JW', True) #h.c. term

      self.add_coupling(-t,1,'Cd',0,'C',-1,'JW', True)   #term1.2 PROBLEM!
      self.add_coupling(-np.conj(t),0,'Cd',0,'C',1,'JW', True) #h.c. term

      self.add_coupling(t*1j,1,'Cd',1,'C',-1,'JW', True)   #term2.1
      self.add_coupling(np.conj(t*1j),1,'Cd',1,'C',1,'JW', True) #h.c. term

      self.add_coupling(-t*1j,0,'Cd',0,'C',-1,'JW', True)   #term2.2
      self.add_coupling(-np.conj(t*1j),0,'Cd',0,'C',1,'JW', True)  #h.c. term

      self.add_coupling(V/2,0,'N',1,'N',0)  #onsite interactions
      self.add_coupling(V/2,1,'N',0,'N',0) 

      self.add_onsite(-e/2,0,'N')
      self.add_onsite(e/2,1,'N')        #onsiteterms


      MPOModel.__init__(self,lat,self.calc_H_MPO())

In my main.py code, I run the DMRG with the MPOModel I initialized in the last step. The programm gives me "Poorly Conditioned Lanczos" and it seems that it does not converge even after hundred of sweeps. When I get rid of the term 1.2, the DMRG finds a ground state without giving me the "Poorly Conditioned Lanczos" error.

Now I have the following question:

1. Is the Ladder automatically mapped to a 1d-chain as shown in https://github.com/tenpy/tenpy/blob/mas ... Ladder.pdf. If so, is the problem that the term 1.2. connects site 0 and 3 and 2,5...?

2. Can the Hubbard-like interactions be implemented \( \sum_{i,l} \frac{V}{2}n_{i,l} n_{i,\bar{l}} \) as I did it?

I hope there is some obvious mistake in my thinking.

Thanks for your help

Lukas
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Problems with modelling a fermionic ladder

Post by Johannes »

You got it almost right.
Just a single, but crucial typo in term 1.2 (which you correctly identified as the problem):
In the second line (h.c. term), you have a 0 instead of a 1 in the fourth argument.
This makes the Hamiltonian non-hermitian and obviously leads to problems when running DMRG (The Lanczos algorithm for diagonalization just assumes that the effective Hamiltonian is hermitian, it doesn't check it....).

A simple check to avoid such an error is to do a test of the initialized model.
There are some functions in test/test_model.py in the repository, but it might be easier to just do:

Code: Select all

    M = CreutzHubbardLadder({})
    print("MPO hermitian? ", M.H_MPO.is_hermitian())
To answer your questions:
  1. Yes, the ladder gets mapped to a 1D MPS as shown in the figure, unless you specify a different order.
    Jordan-Wigner terms are taken care of, whatever order you specify.
    Also, you don't need the argument str_on_first=True, as this is the default (for Jordan-Wigner strings). It's deprecated, so I might remove this argument soon, and then your code doesn't run with new versions anymore, so you better already remove it now.
  2. Yes, you got the (nearest neighbor) interactions on the rung right as

    Code: Select all

          self.add_coupling(V/2,0,'N',1,'N',0)
          self.add_coupling(V/2,1,'N',0,'N',0)
    
    Let me point out that by summing up these terms, this is equivalent to

    Code: Select all

          self.add_coupling(V,0,'N',1,'N',0)
    
    Both versions are correct and (should) lead to the same MPO in the end.

PS:
In the long term, I hope that we can also add an option add_hermitian_conjugate to the add_coupling method. However, that requires a way to get the names of hermitian conjugate operators (e.g., that "Cd" is the hermitian conjugate of "C") out of the sites, which is currently not (yet) implemented.
Lukas
Posts: 2
Joined: 04 Feb 2020, 13:37

Re: Problems with modelling a fermionic ladder

Post by Lukas »

Thanks a lot! It works very well right know. Now I face the problem that in order to see the Ising-like phase transition I want to calculate the correlation function

\( <\Psi_0 |T^y_i T^y_{i+r} |\Psi_0> \) with \(T^y_i= \frac{1}{2}(-i c^\dagger_{i,u}c_{i,d}+i c^\dagger_{i,d}c_{i,u})\) where u and d are again the rungs of the ladder. Since the Ladder gets mapped to a 1-d chain, this is somehow a 4-point correlation function. In the library, the correlation function only works for operators on two different sites. Do you have any solution to this problem? It is furthermore not possible to just calculate the expectation value \(<T_i^y>\) since this gives always zero.
User avatar
Johannes
Site Admin
Posts: 413
Joined: 21 Jul 2018, 12:52
Location: TU Munich

Re: Problems with modelling a fermionic ladder

Post by Johannes »

Lukas wrote: 05 Feb 2020, 12:18 Now I face the problem that in order to see the Ising-like phase transition I want to calculate the correlation function
\( <\Psi_0 |T^y_i T^y_{i+r} |\Psi_0> \) with \(T^y_i= \frac{1}{2}(-i c^\dagger_{i,u}c_{i,d}+i c^\dagger_{i,d}c_{i,u})\) where u and d are again the rungs of the ladder. Since the Ladder gets mapped to a 1-d chain, this is somehow a 4-point correlation function. In the library, the correlation function only works for operators on two different sites. Do you have any solution to this problem?
Extend the correlation function to allow for the more general case ;)
If you don't want to do that, you might want to try the MPS method expectation_value_term.
Lukas wrote: 05 Feb 2020, 12:18 It is furthermore not possible to just calculate the expectation value \(<T_i^y>\) since this gives always zero.
That should not be the case, unless you start from a state with no particles or completely filled.
Did you start from an initial state with half filling?

Code: Select all

psi = MPS.from_product_state(M.lat.mps_sites(), [0, 1]*M.lat.Ls[0], "finite")
(If you start from the product state with no particles, you will stay in that sector!)
Post Reply