# How to realize Kondo-Heisenberg model with good quantum number on ITensor-3

Hi, It's not a long time since I started using ITensor, I want to realize Kondo-Heisenberg model on ITensor-3. The model is :
H=\sum{\langle i,j\rangle\sigma}\text{\ensuremath{\left(c{i\sigma}^{\dagger}c{j\sigma}+h.c.\right)}}
+J
{k}\sum{i}c{i\sigma}^{\dagger}\tau{\sigma\sigma^{\prime}}^{\alpha}c{i\sigma^{\prime}}S{i}^{\alpha}
+J
{h}\sum{\langle i,j\rangle}S{i}\cdot S_{j}

I referred the example enter link description here and here is my code

#include "itensor/all.h"
using namespace itensor;
using kondoLattice = MixedSiteSet<ElectronSite, SpinHalfSite>;
int main(int argc, char* argv[])
{

auto L = 10;
auto N = 2 * L;
auto t = 1.0;
auto Jk = 1.0;
auto Jh = 1.0;

auto Npart = 10;

//auto sites = kondoLattice(N,{"ConserveQNs=", false});
auto sites = kondoLattice(N);

auto ampo = AutoMPO(sites);

for (int j = 1; j < N-2; j += 2)
{
ampo += -t, "Cup", j, "Cdagup", j+2;
ampo += -t, "Cdagup", j, "Cup", j+2;

ampo += -t, "Cdn", j, "Cdagdn", j+2;
ampo += -t, "Cdagdn", j, "Cdn", j+2;
}

for (int j = 1; j < N; j += 2)
{
ampo += 0.5 * Jk, "CSp", j, "Sm", j+1;
ampo += 0.5 * Jk, "CSm", j, "Sp", j+1;
ampo += Jk, "CSz", j, "Sz", j+1;
}

for (int j = 2; j < N-1; j += 2)
{
ampo += 0.5 * Jh, "Sp", j, "Sm", j+2;
ampo += 0.5 * Jh, "Sm", j, "Sp", j+2;
ampo += Jh, "Sz", j, "Sz", j+2;
}

auto H = toMPO(ampo);

auto state = InitState(sites);

int p = Npart;

for (int j = N; j > 0; j--)
{
int i = (j -1) / 2;

if(j % 2 != 0)
{
if (p > i+1)
{
printfln("Doublely occupying site", j);

state.set(j, "UpDn");
p -= 2;
}
else if (p >0)
{
printfln("Singlely occupying site", j);

state.set(j, (j%4 == 1 ? "Up" : "Dn"));
p -= 1;
}
else
{
state.set(j, "Emp");
}
}
else if (j % 4 ==2)
state.set(j,"Up");
else
state.set(j,"Dn");
}

auto psi0 = MPS(state);
auto psi1 = randomMPS(state);
auto sweeps = Sweeps(30);
sweeps.maxdim() = 50,100,200, 200;
sweeps.mindim() = 50;
sweeps.noise() = 1E-4, 1E-5, 1E-7, 1E-8, 0.0;
sweeps.cutoff() = 1E-12;

auto [Energy,psi] = dmrg(H, psi1, sweeps, {"Quiet=", true});

printfln("Ground State Energy= %1.10f", Energy);

return 0;
}

In my code , to distinguish between the spin operators of conduction electron and localized spin operators, I renamed the following operators CSp(S+) ,CSm(S-) and CSz(Sz) in the header file electron.h
In Kondo-Heisenberg model, the total number of conduction electron and total CSz+Sz are conserved. When I do not use any symmetry, I set {"ConserveQNs",false}, the code can run and the energy is converged, but the energy is disagree with my DMRG code.
When I use quantum number, based on my understanding, if I just use the particle number as good quantum number. In the electron.h file I just set

auto conserveQNs = args.getBool("ConserveQNs", true);
auto conserveNf = args.getBool("ConserveNf", ture);
auto conserveCSz = args.getBool("ConserveCSz", false);

Then the code can not run normally, the error is :
From line 1579, file itensor.cc
div(ITensor) not defined for non QN conserving ITensor
div(ITensor) not defined for non QN conserving ITensor
Aborted (core dumped)

when I just use (CSz+Sz) as a good quantum number, in the electron.h file

auto conserveQNs = args.getBool("ConserveQNs", true);
auto conserveNf = args.getBool("ConserveNf", false);
auto conserveCSz = args.getBool("ConserveCSz", false);

and in the spinhalf.h

auto conserveqns = args.getBool("ConserveQNs",true);
auto conserveSz = args.getBool("ConserveSz",ture);
auto conserveParity = args.getBool("ConserveParity",false);

the code can run but the energy does not converge. If (Sz+CSz) and Nf are used as good quantum numbers, the program can run but the ground state energy dose not converge.

Is there any problem in my code or I have incorrect understanding of MixesSiteSet and the use of good quantum number. And what should I do to realize Kondo-Heisenberg model on ITensor-3.

Hello,

The error you are seeing when you try to conserve Nf but not Sz is due to the fact that currently in ITensor, you can't use a SiteSet that has some indices with QNs and some without. When you set "ConserveSz=",false, in the SpinHalfSite definition it will lead to the case where the Index is made without any QNs. If you would like to make that case work, you could try changing this line:

https://github.com/ITensor/ITensor/blob/v3/itensor/mps/sites/spinhalf.h#L59

from s = Index(2,ts); to s = Index(QN(),2,ts); (I haven't tried it, so please let us know if that works). This will make an Index with an empty QN, which should work. It may be a good idea for us to add an option for that case. One could argue that if you set "ConserveQNs=",true and "ConserveSz=",false then it should default to making an Index with empty QNs.

As for the cases you are seeing that are running without error but are not converging, you may have to play around with the Sweeps object, like changing the bond dimension growth schedule, the noise, or the number of davidson iterations. Perhaps someone else (like Miles) can comment on strategies for getting more complicated Hamiltonians like this to converge with DMRG.

-Matt

commented by (270 points)
edited by
Thank you very much for your response. when I change  s = Index(2,ts); to s =Index(QN(),2,ts), then the program can run normally without conserving total Sz.
But the problem of non convergence still exists when I use good quantum number  Nf  and total Sz,  and I don't think the problem is related to Sweeps object. For a Kondo-Heisenberg chain with L=10(20 sites) and the number of electrons is 10 ， Sz-total=0.  When I set t =Jk= 0, Jh =1, I obtain the exact ground state energy of L=10 AFM Heisenberg chain. However, when I set t=1, and jk=Jh=0， the energy is not convergent and I can not obtain the energy of the corresponding one-dimensional free electron.  When I do not use any good quantum number, the result is convergent, but it is disagree with one-dimensional free electron.

-ZHOU Zongsheng
commented by (14.1k points)
It looks like it may be an issue with the way you order your fermionic operators (see https://itensor.org/docs.cgi?page=tutorials/fermions). I believe that you should use the ordering:

for (int j = 1; j < N-2; j += 2)
{
ampo += -t, "Cdagup", j+2, "Cup", j;
ampo += -t, "Cdagup", j, "Cup", j+2;
ampo += -t, "Cdagdn", j+2, "Cdn", j;
ampo += -t, "Cdagdn", j, "Cdn", j+2;
}

Otherwise, the terms should be negated. Could you try that and see if it helps?
commented by (270 points)
edited by
Thanks for your kind help, I tried this yesterday,  It works well .