I'm trying to write a generalized parity for a double-wire model of Fermions that conserves global number and the parity of the number of fermions in a given wire. Namely the model proposed in https://arxiv.org/pdf/1705.01786.pdf (equations 1-3) with the g term set to 0. The model has the usual nearest-neighbor tunneling, a nearest-neighbor potential energy term, and a cooper pair exchance term between two coupled quanutm wires. To implement this, I've mapped the two 1-d chains into a single 1-d chain with odd numbered sites corresponding to chain a and even numbered sites corresponding to chain b. The parity that is conserved is the parity of the number of fermions on one of the chains, say the odd number of sites. So I need to keep track of that parity as well as enforce global number conservation. The number conservation works fine, but the global parity does not.
I've attempted to adapt the Fermion.h file to include this generalized parity. The adapting the fermion.h file is based on some of the comments here, http://www.itensor.org/support/2030/3-component-hubbard-model?show=2030#q2030, for a 3-component Fermi-hubbard model.
Here is my attempt to generalize the fermion.h file names have been changed to avoid an error that was being thrown about redefining things like Fermion and FermionSite.
#pragma once
#include "itensor/mps/siteset.h"
#include "itensor/util/str.h"
namespace itensor {
class FermionSiteAlt;
using FermionOddSitePar = BasicSiteSet<FermionSiteAlt>;
class FermionSiteAlt
{
Index s;
public:
FermionSiteAlt(Index I) : s(I) { }
FermionSiteAlt(Args const& args = Args::global())
{
auto ts = TagSet("Site,Fermion");
auto n = 1;
if(args.defined("SiteNumber"))
{
n = args.getInt("SiteNumber");
ts.addTags("n="+str(n));
}
auto conserveQNs = args.getBool("ConserveQNs",true);
auto conserve_Nf = args.getBool("ConserveNf",conserveQNs);
auto conserve_Pfodd = args.getBool("ConservePfodd",false);
auto oddevenupdown = args.getBool("OddEvenUpDown",false);
if(not conserveQNs)
{
s = Index(2,ts);
}
else if(not oddevenupdown) //usual case
{
if(conserve_Nf) //usual case
{
if(not conserve_Pfodd) //usual case
{
s = Index(QN({"Nf",0,-1}),1,
QN({"Nf",1,-1}),1,Out,ts);
}
else // conserve_Pfodd not usual case
{
if( n%2==1 ) {
s = Index(QN({"Nf",0,-1}),1,QN({"Pfodd",0,-2}),1,
QN({"Nf",1,-1}),1,QN({"Pfodd",1,-2}),1,
Out,ts);
}
if( n%2==0 ) {
s = Index(QN({"Nf",0,-1}),1,QN({"Pfodd",0,-2}),1,
QN({"Nf",1,-1}),1,QN({"Pfodd",0,-2}),1,
Out,ts);
}
}
}
else
{
s = Index(QN({"Pf",0,-2}),1,
QN({"Pf",1,-2}),1,Out,ts);
}
}
else
{
auto q_emp = QN({"Sz",0},{"Nf",0,-1});
QN q_occ;
if(n%2==1) q_occ = QN({"Sz",+1},{"Nf",1,-1});
else q_occ = QN({"Sz",-1},{"Nf",1,-1});
s = Index(q_emp,1,
q_occ,1,Out,ts);
}
}
Index
index() const { return s; }
IndexVal
state(std::string const& state)
{
if(state == "Emp" || state == "0")
{
return s(1);
}
else
if(state == "Occ" || state == "1")
{
return s(2);
}
else
{
throw ITError("State " + state + " not recognized");
}
return IndexVal{};
}
ITensor
op(std::string const& opname,
Args const& args) const
{
auto sP = prime(s);
auto Emp = s(1);
auto EmpP = sP(1);
auto Occ = s(2);
auto OccP = sP(2);
auto Op = ITensor(dag(s),sP);
if(opname == "N" || opname == "n")
{
Op.set(Occ,OccP,1);
}
else
if(opname == "C")
{
Op.set(Occ,EmpP,1);
}
else
if(opname == "Cdag")
{
Op.set(Emp,OccP,1);
}
else
if(opname == "A")
{
Op.set(Occ,EmpP,1);
}
else
if(opname == "Adag")
{
Op.set(Emp,OccP,1);
}
else
if(opname == "F" || opname == "FermiPhase")
{
Op.set(Emp,EmpP,1);
Op.set(Occ,OccP,-1);
}
else
if(opname == "projEmp")
{
Op.set(Emp,EmpP,1);
}
else
if(opname == "projOcc")
{
Op.set(Occ,OccP,1);
}
else
{
throw ITError("Operator \"" + opname + "\" name not recognized");
}
return Op;
}
//
// Deprecated, for backwards compatibility
//
FermionSiteAlt(int n, Args const& args = Args::global())
{
*this = FermionSiteAlt({args,"SiteNumber=",n});
}
};
//
// Deprecated, for backwards compatability
//
// Commented out
//// Rebels don't care about backwards compatability. Burn it down!
// using SpinlessSite = FermionSiteAlt;
// using Spinless = BasicSiteSet<SpinlessSite>;
} //namespace itensor
Continued in first comment below - character limit prevented posting both sets of code.