CI PyPI crates.io docs.rs docs License: MIT arXiv
A Python library for simulating Ising spin systems with modern Monte Carlo methods. The core simulation loop is written in Rust (via PyO3) for performance, with a thin Python wrapper for ease of use. Currently focused on spin glass simulation, where the combination of parallel tempering, replica cluster moves, and overlap statistics is of particular interest.
- Ising ferromagnets and spin glasses on periodic Bravais lattices (hypercubic, triangular, or any custom neighbor offsets)
- Arbitrary, bimodal (±J), or Gaussian coupling distributions
- Multiple replicas with overlap statistics for spin glass order parameters
The following algorithms are currently supported:
- Single-spin flips (Metropolis and Gibbs sampling)
- Swendsen-Wang cluster updates
- Wolff cluster updates
- Parallel tempering
- Houdayer isoenergetic cluster move (replica cluster move for spin glasses)
- Jörg move (stochastic overlap cluster move)
- CMR move (Chayes-Machta-Redner blue-bond overlap cluster move)
- Passive full-graph FK and overlap-cluster observations with per-disorder statistics
- Full-ladder parallel tempering diagnostics and reproducible optional seeds
Run simulations directly from the terminal:
# 2D ferromagnet with cluster updates and parallel tempering peapods simulate --shape 32 32 --temp-min 1.5 --temp-max 3.0 \ --n-sweeps 5000 --cluster-interval 1 --pt-interval 1 --n-replicas 2 # 3D spin glass with Houdayer ICM peapods simulate --shape 8 8 8 --couplings bimodal \ --temp-min 0.8 --temp-max 1.4 --n-temps 24 --n-sweeps 10000 \ --pt-interval 1 --overlap-cluster-update-interval 1 --n-replicas 4 # Save full results to .npz peapods simulate --shape 16 16 --temp-min 1.5 --temp-max 3.0 \ --n-sweeps 5000 --pt-interval 1 --n-replicas 2 -o results.npz
For full control over geometry and parameters, use the Python API directly:
import numpy as np from peapods import Ising # Triangular lattice ferromagnet (T_c = 4/ln(3) ≈ 3.641) tri = Ising((32, 32), temperatures=np.linspace(3.0, 4.2, 32), n_replicas=2, neighbor_offsets=[[1, 0], [0, 1], [1, -1]]) tri.sample(n_sweeps=5000, sweep_mode="metropolis", cluster_update_interval=1, pt_interval=1) print(tri.binder_cumulant)
Pass an explicit seed for deterministic couplings and dynamics. Full SW-style graphs can be measured without acting on spins:
model = Ising((32, 32), couplings="bimodal", temperatures=np.linspace(1, 3, 16), n_replicas=2, seed=42) result = model.sample(n_sweeps=5000, cluster_update_interval=10, cluster_mode="sw", cluster_action="observe", pt_interval=1, pt_schedule="full_ladder") fk = result["per_disorder"]["cluster_observations"]["fk"]
Autocorrelation diagnostics use the exact bounded-memory ring backend by
default. Set autocorrelation_backend="fft" together with
autocorrelation_max_lag for faster evaluation when retaining the full
measurement history and its higher memory use are acceptable.
For a more complete example, check out examples/energy_vs_temperature.py.
We recommend uv for package management. Bare pip works too (if you don't mind using a worse management tool).
uv venv
source .venv/bin/activate
uv pip install peapodsPre-built wheels are available for Linux (x86_64, aarch64), macOS (Intel, Apple Silicon), and Windows (x86_64).
Requires a Rust toolchain and maturin:
uv pip install maturin numpy maturin develop --release