Regarding my code, below I send a minimal working example for my particular problem.
The function DMRGconvE is something that I've made to run DMRG iteratively until I reach convergence in the groundstate energy. All the rest is pretty much standard.
I've also chosen some particular parameters for which calculations run fast and for which I have other type of calculations (configuration interaction method) that give me a gap.
Finally, let me add that I've tried different Sz=0 and Sz=1 initial states (all of them Fock states), and different values of Nuc, and so far I always got a 0 gap.
#include "itensor/all.h"
using namespace std;
using namespace itensor;
//function to generate <Sz>=0 Neel MPS at hf
auto Neelhf(auto sites, int Nsites)
{
auto state = InitState(sites);
for(int i=1; i <= Nsites; i++)
{
if(i%2 == 1)
state.set(i,"Up");
else
state.set(i,"Dn");
}
auto stateMPS = MPS(state);
return(stateMPS);
}
//function to generate a given <Sz>=1 MPS at hf
auto Sz1test1(auto sites, int Nsites)
{
auto state = InitState(sites);
for(int i=1; i <= Nsites; i++)
{
if(i%2 == 1)
state.set(i,"Up");
else
state.set(i,"Dn");
}
state.set(Nsites/2,"Up");
state.set(Nsites/2 + 1,"Up");
auto stateMPS = MPS(state);
return(stateMPS);
}
//function to generate MPO of TB Hubbard Hamiltonian
auto TBHub(double t1, double t2, double U, int Nuc, int Natuc, auto sites)
{
auto ampoH = AutoMPO(sites);
for(int i=1; i<Nuc; i++)
{
for(int j=1; j<Natuc; j++)
{
ampoH += t1,"Cdagup",Natuc*i,"Cup",Natuc*i-j;
ampoH += t1,"Cdagup",Natuc*i-j,"Cup",Natuc*i;
ampoH += t1,"Cdagdn",Natuc*i,"Cdn",Natuc*i-j;
ampoH += t1,"Cdagdn",Natuc*i-j,"Cdn",Natuc*i;
ampoH += U,"Nupdn",Natuc*i-j;
}
ampoH += t2,"Cdagup",Natuc*i,"Cup",Natuc*i+Natuc;
ampoH += t2,"Cdagup",Natuc*i+Natuc,"Cup",Natuc*i;
ampoH += t2,"Cdagdn",Natuc*i,"Cdn",Natuc*i+Natuc;
ampoH += t2,"Cdagdn",Natuc*i+Natuc,"Cdn",Natuc*i;
ampoH += U,"Nupdn",Natuc*i;
}
for(int j=1; j<Natuc; j++)
{
ampoH += t1,"Cdagup",Natuc*Nuc,"Cup",Natuc*Nuc-j;
ampoH += t1,"Cdagup",Natuc*Nuc-j,"Cup",Natuc*Nuc;
ampoH += t1,"Cdagdn",Natuc*Nuc,"Cdn",Natuc*Nuc-j;
ampoH += t1,"Cdagdn",Natuc*Nuc-j,"Cdn",Natuc*Nuc;
ampoH += U,"Nupdn",Natuc*Nuc-j;
}
ampoH += U,"Nupdn",Natuc*Nuc;
auto H = toMPO(ampoH);
return(H);
}
//routine to implement DMRG until convergence in energy
tuple<Real,MPS> DMRGconvE(auto H, auto psi0, auto sweepsdflt,
auto sweepsextra, int maxdimi, int maxdimstep, double precE)
{
//default run
auto [Edflt,psidflt] = dmrg(H,psi0,sweepsdflt,"Quiet");
//extra runs until convergence set by precE
double E = 0;
auto psi = psi0;
int maxdim = maxdimi;
while(true)
{
auto [Eextra,psiextra] = dmrg(H,psidflt,sweepsextra,"Quiet");
maxdim += maxdimstep;
sweepsextra.maxdim() = maxdim;
if(fabs(Edflt-Eextra) < precE)
{
E = Eextra;
psi = psiextra;
break;
}
Edflt = Eextra;
psidflt = psiextra;
}
return( tuple<Real,MPS>(E,psi) );
}
// main
int main()
{
/* parameters */
double t1 = 1; //all energies in units of t1
double t2 = 0.1;
double U = 1;
int Nuc = 2;
double precE = 0.001;
/* */
/* system */
int Natuc = 4;
int Nsites = Natuc*Nuc; //nr of sites
auto sitesNtSzt = Electron(Nsites,{"ConserveNf",true,"ConserveSz",true});
//conserves <N> and <Sz> given by the intial state (default)
/* */
/* initial state */
auto psi0Neelhf = Neelhf(sitesNtSzt,Nsites); //<Sz>=0 Neel MPS at hf
auto psi0Sz1test1 = Sz1test1(sitesNtSzt,Nsites); //a given <Sz>=1 MPS at hf
/* */
/* Hamiltonian */
auto HNtSzt = TBHub(t1,t2,U,Nuc,Natuc,sitesNtSzt); //MPO of SSH Hubbard Hamiltonian (for NtSzt)
/* */
/* DMRG parameters */
//default sweeps (corresponding runs should be fast)
auto sweepsdflt = Sweeps(5);
sweepsdflt.maxdim() = 20,50,100,100,200;
sweepsdflt.cutoff() = 1E-5,1E-5,1E-5,1E-8,1E-8;
sweepsdflt.noise() = 1E-5,1E-6,1E-8,1E-10,1E-12;
//extra sweeps
auto sweepsextra = Sweeps(1);
sweepsextra.cutoff() = 1E-8; //fixed at every sweep
int maxdim;
int maxdimi = 300;
int maxdimstep = 100;
sweepsextra.maxdim() = maxdimi; //updated at every sweep
/* */
/* run DMRG */
//(for NtSzt, Neelhf)
auto [ENtSztNeelhf, psiNtSztNeelhf] =
DMRGconvE(HNtSzt,psi0Neelhf,sweepsdflt,sweepsextra,maxdimi,maxdimstep,precE);
//(for NtSzt, Sz1test1)
auto [ENtSztSz1test1, psiNtSztSz1test1] =
DMRGconvE(HNtSzt,psi0Sz1test1,sweepsdflt,sweepsextra,maxdimi,maxdimstep,precE);
/* */
/* outputs */
//gs energy
cout << endl;
cout << "#gs energy (NtSzt, Neelhf) = " << ENtSztNeelhf << " [t1]" << endl;
cout << "#gs energy (NtSzt, Sz1test1) = " << ENtSztSz1test1 << " [t1]" << endl;
/* */
return 0;
}