Hello all,
I have been trying to get excited states of the Hubbard model as an approximation to the continuum.
I have essentially adapted the example provided here:
https://www.itensor.org/docs.cgi?vers=cppv3&page=formulas/excited_dmrg
Here is the code:
#include "itensor/all.h"
using namespace itensor;
int main()
{
auto N = 200;//system size
auto Npart = 5; //particle number
auto L = 10.;
float a = L/N;
float t1 = 0.5/(aa);
auto g = 10.;
float U = g/a;
auto Ns = 10; //number of excited states
float s = 1/(aa);
println("number of sites ",N);
println("system length ",L);
println("lattice spacing ",a);
println("hopping ",t1);
auto sites = Electron(N,{"ConserveQNs=", true});
auto ampo = AutoMPO(sites);
for(int i = 1; i <= N; ++i)
{
ampo += U,"Nupdn",i;
}
for(int i = 1; i <= N; ++i)
{
ampo += s,"Nup",i;
ampo += s,"Ndn",i;
//ampo += V*(i),"Nup",i;
//ampo += V,"Ndn",i;
}
for(int b = 1; b < N; ++b)
{
ampo += -t1,"Cdagup",b,"Cup",b+1;
ampo += -t1,"Cdagup",b+1,"Cup",b;
ampo += -t1,"Cdagdn",b,"Cdn",b+1;
ampo += -t1,"Cdagdn",b+1,"Cdn",b;
}
auto H = toMPO(ampo);
auto state = InitState(sites);
int p = Npart;
for(int i = N; i >= 1; --i)
{
if(p > i)
{
println("Doubly occupying site ",i);
state.set(i,"UpDn");
p -= 2;
}
else
if(p > 0)
{
println("Singly occupying site ",i);
state.set(i,(i%2==1 ? "Up" : "Dn"));
p -= 1;
}
else
{
state.set(i,"Emp");
}
}
auto psiA = MPS(state);
auto sweeps = Sweeps(25);
sweeps.maxdim() = 10E4;
sweeps.cutoff() = 1E-10;
sweeps.niter() = 4;
sweeps.noise() = 1E-7,1E-8,0.0;
println(sweeps);
auto [en0,psi0] = dmrg(H,psiA,sweeps,"Quiet");
auto wfs = std::vector<MPS>(0);
wfs.push_back(psi0);
Vector energies(Ns+1);
energies(0) = en0;
for(int j = 1; j <= Ns; ++j)
{
auto [en,psi] = dmrg(H,wfs,psi0,sweeps,{"Quiet=",true,"Weight=",100.0});
energies(j) = en;
wfs.push_back(psi);
printfln("\n%fth Excited State Energy = %f",j,en);
printfln("\nOverlap <psi0|psi%f> = %E",j,inner(psi0,psi));
}
std::ofstream file("hub_spectrum.dat");
for(int j = 0; j <= Ns; ++j)
{
printfln(file,"%d %f",j,energies(j));
}
file.close();
return 0;
}
I have a few issues when running this:
- I If I try to use psiA (the Neel state) as the initial guess for the excited state search I get the error
div(T1)=QN({"Sz",-2}) must equal div(T2)=QN() when adding T1+T2
which has also been reported here:
http://itensor.org/support/1581/error-when-calculating-excited-states-conserved-quantities?show=1581#q1581
- If I use psi0 (the ground state found by dmrg) as the initial guess, I get a bunch of energies, but they are often out of order (not necessarily increasing in value). In fact, the first excited state seem nearly degenerate with the ground state, which should not be the case. Notice that I am requiring that the new state be orthogonal to the previous ones.
So my questions are:
- How can I optimise the code to get the correct excited state energies, in the right order?
- Is there a particular choice of initial state guess that would solve these issues (and why does that neel state fails for the excited state search)?
- Making the "Weight" parameter larger does not necessarily improve the result. Why is that?
Best regards,
Rafael