Examples#
Heisenberg model on a 4×4 lattice#
Compute the ground state energy of the antiferromagnetic Heisenberg model and compare to the known value E₀/N ≈ −0.7018 (Sandvik, 1997).
import numpy as np
import jax.numpy as jnp
from tachys.lattice.spins.spin_state import SpinState
from tachys.lattice.spins.hamiltonians.heisenberg import heisenberg_square_pbc
from tachys.lattice.exact_diag import spins_hilbert_space, exact_diag
L, N = 4, 16
H = heisenberg_square_pbc(L=L, J=1.0)
all_configs = spins_hilbert_space(N)
state_full = SpinState(spins=jnp.array(all_configs, dtype=jnp.int8), Ns=N)
def pack(state):
bits = (np.asarray(state.spins) + 1) // 2
return (bits * 2 ** np.arange(bits.shape[-1])).sum(axis=-1)
eigenvalues, _ = exact_diag(state_full, H, pack, k=1)
print(f"E₀ = {eigenvalues[0]:.8f}") # -11.22845248
print(f"E₀ / N = {eigenvalues[0] / N:.8f}") # -0.70177828
Hubbard model at quarter filling#
4×4 lattice, N_e = 4 electrons, benchmarked against Dagotto et al. (1992) at U/t = 4 and U/t = 8.
import numpy as np
import jax.numpy as jnp
from tachys.lattice.fermions.fermion_state import FermionState
from tachys.lattice.fermions.hamiltonians.hubbard import hubbard_square_pbc
from tachys.lattice.exact_diag import fermions_hilbert_space, exact_diag
L, Ns, Ne = 4, 16, 4
all_configs = fermions_hilbert_space(Ns, Ne) # C(32, 4) = 35 960 states
state_full = FermionState(
occupations=jnp.array(all_configs, dtype=jnp.int8),
Ns=Ns,
Ne=Ne,
)
def pack(state):
occ = np.asarray(state.occupations)
return (occ * 2 ** np.arange(occ.shape[-1])).sum(axis=-1)
for U in (4.0, 8.0):
H = hubbard_square_pbc(L=L, t=1.0, U=U)
eigenvalues, _ = exact_diag(state_full, H, pack, k=1)
print(f"U={U:.0f}: E₀ = {eigenvalues[0]:.5f}")
# U=4: E₀ = -11.53029 (Dagotto 1992: -11.5303)
# U=8: E₀ = -11.32150 (Dagotto 1992: -11.3215)
Adding a perturbation#
Because operators compose via ordinary arithmetic, adding a perturbation to any existing Hamiltonian is a single line:
from tachys.lattice.spins.spin_operators import Sz
from tachys.lattice.spins.hamiltonians.heisenberg import heisenberg_square_pbc
H = heisenberg_square_pbc(L=4, J=1.0)
H_field = H + 0.1 * Sz(site=0) # uniform field on site 0
# H_field is itself a callable — use it exactly like H
eigenvalues, _ = exact_diag(state_full, H_field, pack, k=1)