Source code for scripts.xy.bkt_transition

"""
Analysis of the Berezinskii-Kosterlitz-Thouless (BKT) transition in the 2D XY model.
Measures the average vortex density as a function of temperature.
"""
from __future__ import annotations

import argparse
import logging

import matplotlib.pyplot as plt
import numpy as np

from models.xy_model import XYSimulation
from utils.cli_helpers import parse_args_compat
from utils.system_helpers import (
    convergence_equilibrate,
    parallel_sweep,
    save_plot,
    setup_logging,
)


[docs] def simulate_bkt_point(params: tuple[float, int, int, int, int]) -> float: """ Worker function to simulate a single temperature and measure average vortex density. Parameters ---------- params: Tuple of (T, L, eq_probe_steps, eq_max_steps, meas_steps). Returns ------- Average vortex density n_v. """ T, L, eq_probe_steps, eq_max_steps, meas_steps = params sim_r = XYSimulation(size=L, temp=T, init_state='random') sim_o = XYSimulation(size=L, temp=T, init_state='ordered') convergence_equilibrate(sim_r, sim_o, chunk_size=eq_probe_steps, max_steps=eq_max_steps) total_vortex_density = 0.0 for _ in range(meas_steps): sim_r.step() total_vortex_density += sim_r._get_vortex_density() return total_vortex_density / meas_steps
[docs] def main() -> None: """Run temperature sweep to observe vortex-density growth near T_BKT.""" parser = argparse.ArgumentParser(description='2D XY Model BKT Transition Analysis') parser.add_argument('--size', type=int, default=40, help='Linear lattice size L') parser.add_argument( '--eq-probe-steps', type=int, default=1000, help='Chunk size for convergence check during equilibration (default: 1000)', ) parser.add_argument( '--eq-max-steps', type=int, default=200000, help='Hard cap on equilibration steps (default: 200000)', ) parser.add_argument('--meas-steps', type=int, default=100, help='Measurement steps') parser.add_argument('--t-min', type=float, default=0.5, help='Minimum temperature') parser.add_argument('--t-max', type=float, default=1.5, help='Maximum temperature') parser.add_argument('--t-points', type=int, default=21, help='Number of temperature points') parser.add_argument('--output-dir', type=str, default='results/xy', help='Output directory') parser.add_argument('--log-file', type=str, default=None, help='Optional log file path') parser.add_argument('--verbose', action='store_true', help='Enable verbose logging') args = parse_args_compat(parser) # Configure logging log_level = logging.DEBUG if args.verbose else logging.INFO logger = setup_logging(level=log_level, log_file=args.log_file) # Generate temperature points temperatures: np.ndarray = np.linspace(args.t_min, args.t_max, args.t_points) T_BKT_THEORETICAL: float = 0.893 logger.info(f'Starting BKT transition study (vortex density) for L={args.size}...') logger.info(f'Range: [{args.t_min}, {args.t_max}] with {args.t_points} points.') sweep_params = [ (T, args.size, args.eq_probe_steps, args.eq_max_steps, args.meas_steps) for T in temperatures ] vortex_densities: list[float] = parallel_sweep( worker_func=simulate_bkt_point, params=sweep_params ) # Plotting results plt.figure(figsize=(10, 6)) plt.plot(temperatures, vortex_densities, 'o-', markersize=5, label='Vortex Density $n_v$') plt.axvline( x=T_BKT_THEORETICAL, color='r', linestyle='--', alpha=0.7, label=f'Theoretical $T_{{BKT}} \\approx {T_BKT_THEORETICAL}$', ) plt.xlabel('Temperature (T)') plt.ylabel('Average Vortex Density $n_v$') plt.title(f'Vortex Density in 2D XY Model (L={args.size})') plt.grid(True) plt.legend() save_plot(filename='bkt_transition.png', directory=args.output_dir)
if __name__ == '__main__': main()