jcmgray / symmray

A minimal block sparse symmetric and fermionic tensor python library
Apache License 2.0
7 stars 2 forks source link

Oddpos issue when creating random fermionic TNS #8

Open sjdu10 opened 3 hours ago

sjdu10 commented 3 hours ago

Code reproduction for fMPS:

import symmray as sr
sr.TN_fermionic_from_edges_rand('U1', [(0,1), (1,0)], bond_dim=4, phys_dim=4)

Get: ValueError: oddpos required for calculating global phase of contractions with odd parity fermionic arrays.

Might need to manually specify the oddpos for each tensor? In my own random TNS generation function, I attribute the oddpos to each odd-parity tensor according to their tid..

sjdu10 commented 2 hours ago

By using

def site_charge(site):
    # put two fermions on odd sites -> half filling
    return 2 * (site % 2)

I seem to be able to bypass this construction problem, but I ran into another problem in running SU:

1. MPS

import quimb.tensor as qtn
import symmray as sr
# Define the lattice shape
L = 4 # length of the chain
edges = qtn.edges_1d_chain(L, cyclic=False)

# Random spnful fMPS
D = 4
symmetry = 'U1'

def site_charge(site):
    # put two fermions on odd sites -> half filling
    return 2 * (site % 2)

fmps = sr.TN_fermionic_from_edges_rand(
    symmetry, 
    edges, 
    bond_dim=D, 
    phys_dim=4,
    seed=42,
    site_charge=site_charge
)
site_info = sr.parse_edges_to_site_info(
    edges,
    D,
    phys_dim=4,
    site_ind_id="k{}",
    site_tag_id="I{}",
)
# Hamiltonian
terms = sr.ham_fermi_hubbard_from_edges(
    symmetry=symmetry,
    edges=tuple(fmps.gen_bond_coos()),
    t=1.0,
    U=8.0,
    mu=0.0,
)
ham = qtn.LocalHam1D(L, terms, cyclic=False)
su = qtn.SimpleUpdateGen(fmps, ham, D=2, gate_opts={'cutoff':1e-12})
# cluster energies may not be accuracte yet
su.evolve(50, tau=0.3)

This gives: ValueError: Shape mismatch. as it tried to go from (16, 16) to (3, 4, 3, 4) during SU. The error persists when I change the value of D.

2. PEPS

import quimb.tensor as qtn
import symmray as sr

symmetry = "U1"

Lx = 4
Ly = 2
D = 2

def site_charge(site):
    # 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,
)

terms = sr.ham_fermi_hubbard_from_edges(
    symmetry=symmetry,
    edges=tuple(peps.gen_bond_coos()),
    t=1.0,
    U=8.0,
    mu=0.0,
)
ham = qtn.LocalHam2D(Lx, Ly, terms)

su = qtn.SimpleUpdateGen(
    peps,
    ham,
    # setting a cutoff is important to turn on dynamic charge sectors
    gate_opts=dict(cutoff=1e-12),
    second_order_reflect=True,
    # SimpleUpdateGen compute 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,
)
su.evolve(50, tau=0.3)

For D=2, the code gives error: ValueError: Shape mismatch. as it tries to go from (16, 16) to (1, 3, 1, 3) in the middle of SU. For D=4, the code can run properly.

jcmgray commented 34 minutes ago

I think I have various changes that fix these things locally, sorry I haven't pushed them yet, will do soon. For the first problem, I don't know if it has an effect here, but the edges are assumed to be non-directed, i.e. (0, 1) and (1, 0) are the same edge specified twice.