# How do I distinguish between right moving and left moving fermions in ITensor?

+1 vote

Hi!
I want to study a system with two species of fermions, that is right movers and left movers. I want to label the operators as c{R} and c{L} for right and left movers respectively . Is there any way to do this in ITensor?

commented by (70.1k points)
Hi, thanks for the question. Could please elaborate a bit more so I can be sure to give the most helpful answer? When you say right and left moving fermions, do you mean in the context of say a Luttinger liquid or relatedly the low-energy description of one-dimensional fermions?

If so, I think my answer will be mostly in the negative, that I don't know a good way to treat these using tensor networks on a discrete lattice. But the main issues aren't ITensor-specific: rather there are a number of deep obstructions to representing relativistic fermion theories faithfully using discretized lattice models (e.g. the fermion doubling problem and other issues).

But maybe your question is a different one, just about having multiple "species" of fermions?

If you could point me to a precise lattice Hamiltonian (such as in a paper) you are trying to simulate that would be the most helpful info you could give.

Miles
commented by (230 points)
edited
H!
Thank you for the response. Sorry for not elaborating the question properly.
So basically the lattice Hamiltonian i want to simulate is
$$H_0 = - t\sum_{i=1}^{N} c^{\dagger}_{R,i}c_{R,i+1} - t\sum_{i=1}^{N} c^{\dagger}_{L,i}c_{L,i+1}- t\sum_{i=1}^{N} c^{\dagger}_{R,i+1}c_{R,i} \\ - t\sum_{i=1}^{N} c^{\dagger}_{L,i+1}c_{L,i}$$
plus an interaction part of the type
$$H_{I} = v_0 \sum_{i=1}^{N} n_i n_{i+1}$$
where @@ n_i = c^{\dagger}_{R,i}c_{R,i} +  c^{\dagger}_{L,i}c_{L,i} @@.

Like you mentioned there are difficulties in treating the Luttinger liquid fermions in a lattice model, but I want to simulate  in some sense a toy lattice model that  tries to capture some of the physics of a Luttinger liquid with only short range forward - scattering interactions.

So I want to be able to define creation and annihilation operators for two species of fermions that I label R (right) and L (left).  I'm using C++ v3 by the way.

Best Regards

Thanks for the extra info above.

So the easiest way to do this with the setup available in ITensor is to define (in your head, more so than in the code) the odd numbered sites to be "L" fermions and the even numbered sites to be "R" fermions. Then this choice is enforced by how you construct the Hamiltonian, such as only inputting hopping terms which connect even to even or odd to odd sites.

Does that approach seem clear to you? Note that converging this setup in DMRG may become a bit harder because two-site DMRG becomes effectively one-site DMRG, but you can overcome this with a good choice of initial state and the use of the noise term.

In the Julia version of ITensor, we offer some more customizability of operators, as used by the AutoMPO system. So there you can introduce custom fermionic operator types and it would be possible to put the L and R fermions on the same site (making dimension 4 site, sort of like in the Hubbard model but with L,R taking the place of spin).

Best,
Miles

commented by (230 points)
Thanks for the answer. I'll try to implement this in the Julia version and see if I can put L and R fermions on the same site.
commented by (70.1k points)
Ok great. Since you're interested in going that route, the key thing to learn about is the has_fermion_string function overloads, which you can see in these files which define the various fermionic site types included in ITensors.jl:
https://github.com/ITensor/ITensors.jl/blob/master/src/physics/site_types/fermion.jl
https://github.com/ITensor/ITensors.jl/blob/master/src/physics/site_types/electron.jl
(See the very end of each of these files.)

As long as you (1) define these functions to return true for any fermionic operator you define and (2) define that operator correctly so that it has the right commutation relations in an on-site way too (note the minus signs for "Cdn" and "Cdagdn" in the Electron site definitions, which are these 'on site' signs I'm referring to, since down electrons are taken to be ordered 'after' up electrons in our convention), then you will be guaranteed to get the correct result from the AutoMPO system when using it to make a Hamiltonian with your custom operators.

This capability isn't available in the C++ version currently, because there we just hard-wired which fermionic operators AutoMPO knows about. It's a lot easier to extend library code in Julia which is one of the reasons we switched to it for the newest version of ITensor.

Best,
Miles
commented by (700 points)
Hi Miles, I actually tried the odd sites even sites approach. I wrote the simplest code with two fermion species and they hop around independently. In this case, indeed I have convergence issue. To be precise, the system got stuck in the initial product state configuration.

You mentioned in the above answer that this issue could be resolved by choosing a better initial state or adding a noise term. My questions are the following:
1. For the initial state, do we have better options other than product state if we want to conserve the quantum numbers?
2. For the noise term method, it seems that we need to modify the density matrix during the process based on the original paper by White. Is there a convenient way to implement it in ITensor?

Thanks a lot
Mason
commented by (70.1k points)
Hi Mason,
Which version of ITensor are using? In the Julia version, regarding question (1) there is a capability to use a better initial state than a product state even when conserving QNs.

For (2), yes we already offer the noise term for all of our DMRG codes. Please look at the example codes such as in the example/dmrg folder of the Julia version or the sample/ folder (such as sample/exthubbard.cc) for examples of DMRG codes which set the noise term strength.

Best,
Miles
commented by (700 points)
Hi Miles, thanks for replying. I'm using the Julia version.
In this case, how do we construct the initial state?
Thanks again.
-Mason
commented by (70.1k points)
Hi Mason,
That's good - so there is a function called randomMPS which takes an extra variable state which is an array of strings or integers specifying the initial product state which is then randomized to make a random MPS. The reason for specifying this initial state is you can choose which total QN you want the state to have, and the randomMPS function will respect this choice. It is documented here:
https://itensor.github.io/ITensors.jl/stable/MPSandMPO.html#ITensors.randomMPS-Tuple{Array{#s131,1}%20where%20#s131<:Index,Any}

For the case of spinless fermions, an example of using it would be:

s = siteinds("Fermion",N;conserve_qns=true)
state = ["Emp","Occ","Emp","Occ"] # product, or Fock, state with two fermions
psi = randomMPS(s,state,4) # make a randomMPS of bond dimension 4
commented by (700 points)
This is really helpful. Thanks Miles!
commented by (700 points)
Hi Miles,

Sorry to bother you again, but another issue popped up when initializing the random state this way. The QN-conserving random MPS conserves the total fermion number, but the numbers for each flavor (i.e. the total number on odd or even sites) are not separately conserved.

I tried to define the sites_odd and sites_even separately using siteinds(...), and then combine them into a single sites array, but it doesn't work.

Thanks a lot for your time.
Mason
commented by (70.1k points)
Hi, so for that to work you will need to define custom quantum numbers ("QN" objects) which use a different name for the two types of fermions. Then when you make the array of site indices (so you will need to either overload the siteinds function or just make an array in a loop) you should switch off the QNs in odd versus even sites to have the appropriate QNs labeling their subspaces.

Best,
Miles
commented by (70.1k points)
You could use this example to see how things work:
http://itensor.org/docs.cgi?vers=julia&page=formulas/mixed_sites_dmrg

If you print out the sites array, you'll see that it's nothing but a plain Julia array of Index objects. Then if you look at the QN structure of each of these Index objects you will see it alternates from site to site. So if you construct a similar array with QNs reflective of your system then it ought to just work the way you want.

Miles
commented by (700 points)
Hi Miles, I tried to define a new site type "Electrons_two_flavors" by including the flavor index at each site and try to conserve the $\tau_z$ QN, which is defined to be the onsite number difference between the two flavors. Here is the beginning part of the code (I can post the rest if you need it):

function space(::SiteType"Electron_two_flavors";
conserve_qns = false,
conserve_sz = conserve_qns,
conserve_nf = conserve_qns,
conserve_nfparity = conserve_qns,
qnname_sz = "Sz",
qnname_tauz = "Tauz",
qnname_nf = "Nf",
qnname_nfparity = "NfParity",
# Deprecated
conserve_parity = nothing)

However, when I run this  I got the error "LoadError: String is too long for SmallString. Maximum length is 8". I tried to reduce the lengths of the defined OpNames and StateNames to be within 8, but the error is still there.

Another question is, is there a way to incorporate this new site type into my ITensor so that I don't have to run it every time before running the other code?

Thanks a lot for your time
Mason