Source code for utils.evolution_helpers

"""
Shared infrastructure for ordering evolution visualisation scripts.

Provides the snapshot loop and figure generation shared by the Ising, XY,
and Clock ordering-evolution scripts.
"""
from __future__ import annotations

import logging
from typing import Any

import numpy as np

from utils.plotting import ensure_results_dir, plot_ordering_evolution


[docs] def run_ordering_evolution( *, model_cls: type, model_kwargs: dict[str, Any], capture_vorticity: bool, title: str, size: int, temp: float, step_targets: list[int], output_dir: str, logger: logging.Logger | None = None, ) -> None: """Run an ordering evolution simulation and save the multi-panel figure. Quenches the model to ``temp``, advances to each step in ``step_targets``, captures spin configurations and correlation functions, optionally captures vorticity maps, and writes the figure to ``output_dir``. Parameters ---------- model_cls : type Simulation class to instantiate (e.g. ``XYSimulation``). model_kwargs : dict[str, Any] Extra keyword arguments forwarded to the constructor beyond ``size``, ``temp``, and ``update='random'``. capture_vorticity : bool Whether to record vorticity maps at each snapshot. Pass ``True`` for vector-spin models (XY, Clock) and ``False`` for scalar models (Ising). Controls ``is_vector`` in the output figure. title : str Figure-level suptitle. size : int Linear lattice size L. temp : float Quench temperature T. step_targets : list[int] MC step counts at which to capture snapshots. Need not be sorted; the function sorts them internally. output_dir : str Directory in which to write the output figure. logger : logging.Logger, optional Logger to use; creates a module-level logger if not provided. """ _log = logger or logging.getLogger(__name__) sim = model_cls(size=size, temp=temp, update='random', **model_kwargs) targets = sorted(step_targets) n_targets: int = len(targets) snapshots: list[np.ndarray] = [] snapshots_vort: list[np.ndarray] = [] snapshots_gr: list[tuple[np.ndarray, np.ndarray]] = [] current_step: int = 0 for target in targets: steps_to_run = target - current_step for _ in range(steps_to_run): sim.step() current_step = target if sim.spins is not None: snapshots.append(sim.spins.copy()) snapshots_gr.append(sim._calculate_correlation_function()) if capture_vorticity: snapshots_vort.append(sim._calculate_vorticity()) _log.debug( f'Captured snapshot at step {target}' f' (n_v={sim._get_vortex_density():.4f})' ) else: _log.debug(f'Captured snapshot at step {target}') _log.info(f'Collected {n_targets} snapshots. Saving figure ...') plot_ordering_evolution( targets=targets, snapshots=snapshots, gr_data=snapshots_gr, vorticity_data=snapshots_vort if capture_vorticity else None, title=title, filename='ordering_evolution.png', directory=ensure_results_dir(directory=output_dir), is_vector=capture_vorticity, )