Fermionic PEPS with U(1) symmetry

This example shows how to set up a fermionic PEPS with U(1) symmetry at half-filling using symmray and quimb, then optimize using imaginary time simple update, then evaluate the energy using boundary contraction.

%config InlineBackend.figure_formats = ['svg']
import quimb as qu
import quimb.tensor as qtn

import symmray as sr
symmetry = "U1"

Lx = 4
Ly = 4
D = 6


def site_charge(site):
    # put one fermion per site
    return 1

    # put two fermions on odd sites -> half filling
    # return 2 * ((site[0] + site[1]) % 2)


peps = sr.PEPS_fermionic_rand(
    symmetry=symmetry,
    Lx=Lx,
    Ly=Ly,
    bond_dim=D,
    seed=42,
    phys_dim=4,
    site_charge=site_charge,
)

print(peps.arrays[0])
U1FermionicArray(ndim=3, charge=1, indices=[
    (6 = 1+1+1+1+1+1 : +[-2,-1,0,1,2,3])
    (6 = 1+1+1+1+1+1 : +[-2,-1,0,1,2,3])
    (4 = 1+2+1 : +[0,1,2])
], num_blocks=15, backend=numpy, dtype=float64)
# impose neel order (NOTE: only for U1 and 1 fermion per site!)
for i, j in peps.gen_site_coos():
    # get the tensor data at site (i, j)
    t = peps[i, j]
    # get the sector: 0s on bonds and 1 on physical leg
    key = (0,) * (t.ndim - 1) + (1,)
    # get the index within the block to assign
    selector = (0,) * (t.ndim - 1) + (0 if (i + j) % 2 == 0 else 1,)
    # assign a much larger weight than the current random ones
    t.data.blocks[key][selector] = 100
# verify the spin structure using a basic cluster expectation
Ospin = sr.fermi_spin_operator_local_array(symmetry)

peps.compute_local_expectation_cluster(
    {(site,): Ospin for site in peps.gen_site_coos()},
    return_all=True,
)
{((0, 0),): array(0.49940142),
 ((0, 1),): array(-0.49691275),
 ((0, 2),): array(0.49482876),
 ((0, 3),): array(-0.49724477),
 ((1, 0),): array(-0.49515941),
 ((1, 1),): array(0.47291074),
 ((1, 2),): array(-0.47007018),
 ((1, 3),): array(0.49493919),
 ((2, 0),): array(0.49295516),
 ((2, 1),): array(-0.47213635),
 ((2, 2),): array(0.47206349),
 ((2, 3),): array(-0.49375622),
 ((3, 0),): array(-0.49917827),
 ((3, 1),): array(0.49487848),
 ((3, 2),): array(-0.49572495),
 ((3, 3),): array(0.49923981)}
terms = sr.ham_fermi_hubbard_from_edges(
    symmetry=symmetry,
    edges=tuple(peps.gen_bond_coos()),
    t=1.0,
    U=8.0,
)
ham = qtn.LocalHam2D(Lx, Ly, terms)

print(next(iter(terms.values())))
U1FermionicArray(ndim=4, charge=0, indices=[
    (4 = 1+2+1 : +[0,1,2])
    (4 = 1+2+1 : +[0,1,2])
    (4 = 1+2+1 : -[0,1,2])
    (4 = 1+2+1 : -[0,1,2])
], num_blocks=19, backend=numpy, dtype=float64)
su = qtn.SimpleUpdateGen(
    peps,
    ham,
    # setting a cutoff is important to turn on dynamic charge sectors
    cutoff=1e-12,
    second_order_reflect=True,
    # SimpleUpdateGen computes cluster energies by default
    # which might not be accurate
    compute_energy_every=10,
    compute_energy_opts=dict(max_distance=1),
    compute_energy_per_site=True,
    # use a fixed trotterization order
    ordering="sort",
    # if the gauge difference drops below this, we consider the PEPS converged
    tol=1e-9,
)
# run the evolution, these are reasonable defaults
tau = 0.5 * D ** (-3 / 2)
steps = round(50 / tau)

su.evolve(steps, tau=tau)
n=590, D=6, tau=0.034, max|dS|=9.85e-10, energy≈-0.397602:  40%|#######################6                                   | 590/1470 [02:04<03:05,  4.75it/s]
su.plot();
../_images/000fd3e97c1658efb82dddbd3215c64c635937f1a42710fa5756b91fbc9ce1a3.svg
gs = su.get_state()

Check energy properly with boundary contraction and increasing \(\chi\).

full_energies = {}

for chi in [16, 24, 32, 48, 64]:
    en = (
        gs.compute_local_expectation(
            ham.terms,
            normalized=True,
            max_bond=chi,
        )
        / gs.nsites
    )
    print(f"chi={chi}: E/N = {en}")
    full_energies[chi] = en
chi=16: E/N = -0.41554634346584896
chi=24: E/N = -0.4154680424161003
chi=32: E/N = -0.4154185143648837
chi=48: E/N = -0.4153858937353008
chi=64: E/N = -0.4153842433839665
qu.plot(full_energies.keys(), full_energies.values(), marker=".");
../_images/a567d16804b2c46060ac9b3c1cae68eb15d39e9694fd9ab0edec992041892266.svg