Difficulty adding fermionic IQTensors with sum(psi1,psi2)

+1 vote
asked Aug 2 by JonSpalding (380 points)

I am attempting to create a trial wavefunction that is a superposition of two wavefunctions.

My code does roughly the following:

Hubbard sites;
auto sites1,sites2 = sites; // N is even
sites = Hubbard(N);
sites1 = sites;
sites2 = sites;

IQMPS psi1, psi2;

auto state1 = InitState(sites1);
auto state2 = InitState(sites2);
loop over sites;
      for odd sites, state1.set(i, "UpDn")
      for even sites, state2.set(i, "UpDn")
      other sites are empty

psi1 = IQMPS(state1);
psi2 = IQMPS(state2);
psi = sum(psi1,psi2);        // I also tried out sum(psi1, psi1) as a check

psi.norm();

The electron densities that result for psi are
8 8 8 8 8 8
whereas I was expecting
1 1 1 1 1 1

Notes:
The above code works fine for a single wavefunction. That is, if I just set psi = psi1 or psi = psi2, just the odd or just the even sites are filled, the electron density is
2 0 2 0 2 0
or
0 2 0 2 0 2

When I set psi = sum(psi1, psi1) the electron density is
8 0 8 0 8 0

The only portion of the code that isn't working, from what I can tell, is the sum( , ) function. Is there a bug in sum() that is not conserving quantum numbers? Is there another function that I can use to conserve quantum numbers while adding wavefunctions?

commented Aug 7 by JonSpalding (380 points)
I forgot to mention my method for measuring the electron density. I used the method in the ITensor Samples folder, exthubbard.cc:

    loop over j
    psi.position(j);
    upd(j) = (dag(prime(psi.A(j),Site))*sites.op("Nup",j)*psi.A(j)).real();
    dnd(j) = (dag(prime(psi.A(j),Site))*sites.op("Ndn",j)*psi.A(j)).real();

and then output the sum of upd and dnd for each j.

After I do the git pull I will post whether this works or not.

1 Answer

+1 vote
answered Aug 5 by hermit0308 (760 points)
edited Aug 22 by hermit0308

Hi Jon,

I get the correct density (222222) with the latest version of ITensor. My code is

#include "itensor/all.h"

using namespace itensor;

int main()
{
auto sites = Hubbard(8);
auto sites1 = sites;
auto sites2 = sites;

IQMPS psi1, psi2;

auto state1 = InitState(sites1);
auto state2 = InitState(sites2);
for(int j = 1; j <= 8; ++j)
{
    if(j%2 == 1)
    {
        state1.set(j, "UpDn");
        state2.set(j, "Emp");
    }
    else
    {
        state2.set(j, "UpDn");
        state1.set(j, "Emp");
    }
}

psi1 = IQMPS(state1);
psi2 = IQMPS(state2);
auto psi = sum(psi1,psi2);        // I also tried out sum(psi1, psi1) as a check
Print(psi);
for(int j = 1; j <= 8; ++j)
{
    auto Ni = sites1.op("Ntot", j);
    auto ket = psi.A(j);
    auto bra = dag(prime(ket, Site));
    std::cout << (bra*Ni*ket).real() << std::endl;
}
return 0;
}

The last part gives electron density 2 on every site. Is that what you expect? Thanks.

Jin

commented Aug 6 by miles (18,230 points)
Hi Jin,
Thanks a lot for posting a quality reply. I did notice that in your measurement loop, though, there is no call to psi.position(j) to ensure that the gauge/orthogonality center is at site j before doing the measurement. Can you check that if you include this line in your test code that it does continue to give the right answer?
commented Aug 7 by JonSpalding (380 points)
Thanks Jin and Miles! I'll do a fresh git pull to use the latest revision.
commented Aug 7 by JonSpalding (380 points)
Ok guys I got it working, thanks a lot!
commented Aug 7 by miles (18,230 points)
Great! Ok thanks again Jin.
commented Aug 7 by JonSpalding (380 points)
I fixed my code as follows.

I have an if() statement that enables "sites" to be read in from a file if such a file exists. If it does not exist, I create "sites" by setting it equal to "Hubbard(N_sites)". Defining "sites1" and "sites2" as type Hubbard before this if statement fixed the problem. In other words,

Instead of

    Hubbard sites
    if( sitesfile exists)
       {   
       readFromFile(sitesfile,sites);
       }
    else
      {
       sites = Hubbard(N_sites);
       auto sites1 = sites;
       auto sites2 = sites;
       }


I used

    Hubbard sites, sites1, sites2;
    if( sitesfile exists)
      {
      readfromfile(sitesfile,sites);
      }
     else
      {
       sites = Hubbard(N);
       sites1 = sites;
       sites2 = sites;
      }
commented Aug 7 by miles (18,230 points)
Yes, I hadn't noticed before that you had two different "sites" variables sites1 and sites2. I would discourage doing this because the main idea of a site set is to ensure that various MPS all have the same site indices. So the intended use of a site set is that you have a single site set in your program that you use to initialize all of your MPS and your InitState objects. In your code above things work ok because sites1 and sites2 are just copies of the same original site set. But ideally you would just use a single site set throughout.
commented Aug 7 by JonSpalding (380 points)
Ok thanks for the reminder, I will try it that way to stick with the intended use of sites variables.
commented Aug 23 by hermit0308 (760 points)
Hi Miles,

Thanks for reminding me. When I normalized psi, I got 122...2 without "psi.position(j)" and 11...1 with "psi.position(j)".
Welcome to ITensor Support Q&A, where you can ask questions and receive answers from other members of the community.

Formatting Tips:
  • To format code, indent by four spaces
  • To format inline LaTeX, surround it by @@ on both sides
  • To format LaTeX on its own line, surround it by $$ above and below
  • For LaTeX, it may be necessary to backslash-escape underscore characters to obtain proper formatting. So for example writing \sum\_i to represent a sum over i.
If you cannot register due to firewall issues (e.g. you cannot see the capcha box) please email Miles Stoudenmire to ask for an account.

To report ITensor bugs, please use the issue tracker.
...