Simulation¶
Simulation(config)
¶
High-level interface to Ising model Monte Carlo simulation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
SimulationConfig
|
Complete simulation configuration. |
required |
Examples:
>>> from mcising import Simulation, SimulationConfig, LatticeConfig
>>> config = SimulationConfig(
... lattice=LatticeConfig(size=16, j1=1.0),
... temperatures=(3.0, 2.269, 1.5),
... n_sweeps=500,
... )
>>> sim = Simulation(config)
>>> results = sim.run(show_progress=False)
>>> sorted(results.energy) == [1.5, 2.269, 3.0]
True
num_sites
property
¶
Total number of spins N in the simulated lattice.
spins
property
writable
¶
Current spin configuration as a 2D NumPy array.
energy
property
¶
Current energy per site.
magnetization
property
¶
Current magnetization per site.
reset()
¶
Discard all evolved state and return to the initial condition.
The spin configuration and RNG stream are restored to exactly
what a fresh Simulation(config) starts with; manual
sweep() calls and spins assignments are forgotten.
run(*, reset=True, show_progress=True, on_temperature_complete=None, skip_temperatures=None)
¶
Execute the full simulation across all temperatures.
run() first resets the simulation to its deterministic
initial condition (see reset()), so repeated calls on the
same object return identical results, and any prior manual
sweep() or spins assignment has no effect on the run.
Pass reset=False to continue from the current core state
instead (checkpoint resume uses this).
Behavior depends on config.mode:
- COOLDOWN (default): Temperatures processed sequentially in descending order. Spins carried from high T to low T.
- INDEPENDENT: Each temperature runs in parallel from random initialization. Uses all CPU cores via Rayon.
- PARALLEL_TEMPERING: All temperatures run as one coupled replica-exchange ensemble with periodic swap attempts.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
reset
|
bool
|
When True (default), rebuild the core from the configuration before running. When False, keep the current spins and RNG state (only meaningful in cooldown mode — the parallel modes build fresh Rust replicas per call regardless). |
True
|
show_progress
|
bool
|
Whether to display a Rich progress bar. |
True
|
on_temperature_complete
|
callable
|
Called once per completed temperature. In cooldown mode it fires as each temperature finishes; in the parallel modes the batch computes every temperature first and the callback then fires once per temperature. |
None
|
skip_temperatures
|
frozenset[float]
|
Temperatures to leave out of this run (e.g. already completed in a checkpoint). In independent mode the remaining temperatures keep the RNG streams they would have had in a full run. In parallel tempering only skipping every temperature (or none) is allowed — the replicas form one coupled ensemble. |
None
|
Returns:
| Type | Description |
|---|---|
SimulationResults
|
Collected measurements across all temperatures. |
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
In parallel tempering, when |
sweep(n_sweeps=1, *, temperature)
¶
Perform sweeps at a given temperature and return observables.
One sweep is num_sites attempted-flip equivalents for
Metropolis and Swendsen-Wang, but ONE cluster update for Wolff
— measuring at a per-sweep flip-budget boundary is size-biased
(P10 exact-enumeration rejection), so Wolff callers scale
n_sweeps by roughly num_sites over the expected cluster
size instead. The returned counters report the work honestly.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_sweeps
|
int
|
Number of MC sweeps to perform. |
1
|
temperature
|
float
|
Simulation temperature (must be > 0). Keyword-only, so a
pre-1.0 positional |
required |
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary with keys 'energy', 'magnetization', 'acceptance_rate', and 'n_cluster_flips' (0.0 for Metropolis). 'acceptance_rate' is the classic acceptance fraction for Metropolis, the flipped-spin fraction for Swendsen-Wang, and identically 1.0 for Wolff (rejection-free). |
SimulationResults(temperatures=list(), energy=dict(), magnetization=dict(), configurations=dict(), correlation_function=None, correlation_length=None, n_cluster_flips=dict(), adaptive_diagnostics=None, metadata=dict(), _statistics_cache=dict())
dataclass
¶
Container for simulation results across temperatures.
Attributes:
| Name | Type | Description |
|---|---|---|
temperatures |
list[float]
|
Temperature values that were simulated. |
energy |
dict[float, NDArray[float64]]
|
Energy per site measurements at each temperature. |
magnetization |
dict[float, NDArray[float64]]
|
Magnetization per site measurements at each temperature. |
configurations |
dict[float, NDArray[int8]]
|
Spin configurations at each temperature, shape |
correlation_function |
dict[float, tuple[NDArray, NDArray]] | None
|
(distances, correlations) at each temperature, or None if not computed. |
correlation_length |
dict[float, NDArray[float64]] | None
|
Correlation length measurements at each temperature, or None. |
n_cluster_flips |
dict[float, int]
|
Cluster flips during the measurement sweeps at each temperature
(thermalization excluded). 0 for Metropolis; for Wolff this is
the number of cluster updates (one per sweep), the honest work
record behind the |
metadata |
dict[str, object]
|
Provenance and timing: the |
num_sites
cached
property
¶
Total number of spins N, resolved from provenance.
Prefers the restored :class:~mcising.config.SimulationConfig
(present for every run and every loaded file with provenance);
falls back to the shape of stored spin configurations for
config-less legacy files. Never guesses: a wrong N silently
mis-scales specific heat and susceptibility (B11).
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If neither the config metadata nor stored configurations can supply the site count. |
statistics(temperature)
¶
Observable estimates with standard errors at one temperature.
Computed lazily from the stored measurement series and memoized.
Means (E, M, |M|) carry blocking standard errors; specific heat,
susceptibility, and the Binder cumulant carry delete-one-block
jackknife errors (see :mod:mcising.statistics). Total: a
temperature with no or degenerate data yields nan estimates
rather than an exception.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
temperature
|
float
|
Temperature to compute statistics at. |
required |
Returns:
| Type | Description |
|---|---|
ObservableStatistics
|
Per-temperature estimates; errors are |
specific_heat(temperature)
¶
Specific heat per site: Cv = N * Var(E) / T^2.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
temperature
|
float
|
Temperature to compute Cv at. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Specific heat per site. For the standard error use
|
susceptibility(temperature, *, kind='connected')
¶
Magnetic susceptibility per site.
The default connected convention is
chi = N * (<m**2> - <|m|>**2) / T (standard for finite-size
scaling; breaking default since P10, #39). kind="signed"
selects the pre-1.0 N * Var(m) / T form — see
:func:mcising.statistics.susceptibility.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
temperature
|
float
|
Temperature to compute chi at. |
required |
kind
|
('connected', 'signed')
|
Susceptibility convention. |
"connected"
|
Returns:
| Type | Description |
|---|---|
float
|
Susceptibility per site. For the standard error (connected
convention) use |
binder_cumulant(temperature)
¶
Binder cumulant U4 = 1 -
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
temperature
|
float
|
Temperature to compute U4 at. |
required |
Returns:
| Type | Description |
|---|---|
float
|
Binder cumulant (dimensionless; no site count needed). For
the standard error use
|
summary()
¶
Print a Rich table summarizing results per temperature.
Shows mean energy, magnetization, specific heat,
susceptibility, and Binder cumulant with standard errors
(value ± error; n/a where the series is too short to
quote one).
to_dataframe()
¶
Convert results to a pandas DataFrame.
Returns a DataFrame with columns: T, E_mean, E_err, E_std,
M_mean, M_err, M_std, Cv, Cv_err, chi, chi_err, U4, U4_err,
tau_int, samples. The *_err columns are standard errors of
the mean/estimator (blocking for means, jackknife for derived
quantities); E_std/M_std remain the sample spread of
the series (not an uncertainty). Errors are nan where the
series is too short to quote one.
Returns:
| Type | Description |
|---|---|
DataFrame
|
Summary statistics per temperature. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If pandas is not installed. |
AdaptiveDiagnostics(thermalization_sweeps=0, truncation_point=0, is_thermalized=True, tau_int=0.5, measurement_interval=1, production_sweeps=0, n_samples=0, stationary_sweeps=0)
dataclass
¶
Per-temperature diagnostics from the adaptive measurement scheme.
Attributes:
| Name | Type | Description |
|---|---|---|
thermalization_sweeps |
int
|
Total thermalization sweeps used (annealing ramp + all fixed-temperature diagnostic sweeps). |
stationary_sweeps |
int
|
Fixed-temperature sweeps analyzed for stationarity and tau_int. Never includes the cool-down ramp: the ramp's energy trace is non-stationary by construction and is excluded from all estimation (B9, #20). |
truncation_point |
int
|
MSER truncation point within the fixed-temperature series. |
is_thermalized |
bool
|
Whether the fixed-temperature series was detected as stationary. |
tau_int |
float
|
Integrated autocorrelation time, estimated on the stationary tail of the fixed-temperature series only. |
measurement_interval |
int
|
Measurement interval used for production (tau_multiplier * tau_int). |
production_sweeps |
int
|
Total production sweeps used. |
n_samples |
int
|
Number of measurement samples collected. |
IsingSimulation
¶
Core Ising model simulation engine (Rust/PyO3).
One lattice, one coupling set, one update algorithm and one
random-number stream. :class:mcising.Simulation drives it for the
high-level API; use it directly for sweep-level control — custom
temperature schedules, per-sweep observables, or exact state
round-trips through :meth:get_spins / :meth:get_rng_state.
The Hamiltonian is H = -J1 Σ s_i s_j - J2 Σ s_i s_j - J3 Σ s_i s_j
- h Σ s_i over nearest, next-nearest and third-nearest neighbour
pairs (each bond once); positive couplings are ferromagnetic.
Constructor arguments (positional, in this order):
lattice_size— linear sizeL: sites per side (the honeycomb has two sites per cell, the chainLsites in total).j1,j2,j3— nearest-, next-nearest- and third-nearest-neighbour couplings; the cluster algorithms requirej1 > 0andj2 = j3 = h = 0.h— external field.seed— seed of the Xoshiro256** generator that draws the initial configuration and every update.algorithm—"metropolis"(default),"wolff"or"swendsen_wang".lattice_type—"square"(default),"triangular","honeycomb","cubic"or"chain"; periodic boundaries in every direction.
lattice_size
property
¶
Linear lattice size L passed at construction.
num_sites
property
¶
Number of spins.
L² (square, triangular), 2L² (honeycomb), L³ (cubic) or
L (chain).
j1
property
¶
Nearest-neighbour coupling J1.
j2
property
¶
Next-nearest-neighbour coupling J2.
j3
property
¶
Third-nearest-neighbour coupling J3.
h
property
¶
External field h.
algorithm_name
property
¶
"metropolis", "wolff" or "swendsen_wang".
__new__(lattice_size, j1, j2, j3, h, seed, algorithm='metropolis', lattice_type='square')
¶
Construct a simulation; the parameters are documented on the class.
sweep(n_sweeps=1, *, temperature)
¶
Run n_sweeps Monte Carlo sweeps at temperature.
One Metropolis sweep attempts every site once in a sequential scan; one Wolff sweep grows and flips a single cluster; one Swendsen-Wang sweep rebuilds every bond and gives every cluster an independent flip decision.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_sweeps
|
int
|
Number of sweeps. |
1
|
temperature
|
float
|
Temperature |
required |
Returns:
| Type | Description |
|---|---|
tuple[int, int, int]
|
|
energy()
¶
Energy per site of the current configuration, H / num_sites.
magnetization()
¶
Signed magnetization per site, Σ s_i / num_sites.
get_spins()
¶
Copy of the spin configuration as an int8 array in the lattice's shape.
(L, L) for the square and triangular lattices, (L, L, 2)
for the honeycomb, (L, L, L) for the cubic lattice and (L,)
for the chain.
set_spins(spins)
¶
Replace the configuration.
The array must hold exactly num_sites values, each +1 or
-1; it is read in row-major order, so any shape with the right
size is accepted. Raises ValueError otherwise.
flip_spin(site)
¶
Flip one spin, addressed by its flat row-major site index.
Flat indexing is the one scheme every lattice shares (a
(row, col) pair cannot address cubic or honeycomb sites).
Raises ValueError for an index outside range(num_sites).
spin_energy(site)
¶
Local energy of one spin, by flat site index.
-s_i (J1 Σ_nn s_j + J2 Σ_nnn s_j + J3 Σ_tnn s_j + h) — flipping
the spin changes the total energy by -2 * spin_energy(site).
correlation_function()
¶
Spin-spin correlation C(r) = <s_0 s_r> of the current configuration.
A full O(N²) pair sum binned by distance; returns
(distances, correlations) as two float arrays.
correlation_length()
¶
Second-moment correlation length of the current configuration.
Derived from the same C(r) as :meth:correlation_function.
anneal(temp_schedule)
¶
Thermalization ramp: one sweep at each positive entry of temp_schedule.
Nothing is recorded; non-positive entries are skipped.
extend_thermalization(n_sweeps, *, temperature)
¶
Sweep n_sweeps times at temperature, recording the energy.
Returns the energy per site after every sweep — the series that
adaptive thermalization analyses with
:meth:analyze_thermalization_series.
analyze_thermalization_series(series, c_window, tau_multiplier)
staticmethod
¶
Stationarity and autocorrelation analysis of an energy series.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
series
|
NDArray[float64]
|
Energy per site after each sweep. |
required |
c_window
|
float
|
Automatic-windowing constant for the integrated autocorrelation
time (Sokal's |
required |
tau_multiplier
|
float
|
Measurement interval recommended as |
required |
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
|
production_sweeps(n_measurements, interval, *, temperature, store_configs, compute_correlation=False, correlation_interval=1)
¶
Run a production block of n_measurements measurements.
One FFI crossing for the whole block, with the GIL released while
sweeping. Energy and magnetization are measured after each block of
interval sweeps, a configuration snapshot is stored when
store_configs and the correlation observables are evaluated at
every correlation_interval-th measurement when
compute_correlation. The random-number stream is consumed
exactly as n_measurements separate sweep(interval) calls
would consume it.
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
The per-temperature dict the parallel runners return:
|
get_rng_state()
¶
Serialized generator state (JSON bytes as ints).
Lets a checkpoint continue the exact random-number stream through
:meth:set_rng_state.
set_rng_state(state)
¶
Restore a state returned by :meth:get_rng_state.
Malformed input raises ValueError.