ubuntu2404
#!/usr/bin/env python31"""2Statistical Mechanics Monte Carlo Simulations3==============================================45This module implements Monte Carlo simulations for statistical mechanics systems:6- 2D Ising model with Metropolis algorithm7- Exact 1D Ising model solutions8- Thermodynamic property calculations9- Phase transition analysis1011Keywords: ising model monte carlo, statistical mechanics python, metropolis algorithm,12phase transition simulation, partition function calculation, magnetic susceptibility1314Author: CoCalc Scientific Templates15License: MIT16"""1718import numpy as np19import matplotlib.pyplot as plt20from numba import jit2122# Set reproducible random seed23np.random.seed(42)2425class IsingModel2D:26"""272D Ising model Monte Carlo simulation using Metropolis algorithm.2829Hamiltonian: H = -J Σ_{<i,j>} S_i S_j - h Σ_i S_i30where S_i = ±1 are spin variables.31"""3233def __init__(self, N, J=1.0, h=0.0):34"""35Parameters:36-----------37N : int38Linear lattice size (N×N total spins)39J : float40Nearest-neighbor coupling constant41h : float42External magnetic field43"""44self.N = N45self.J = J46self.h = h47self.spins = np.random.choice([-1, 1], size=(N, N))4849@staticmethod50@jit(nopython=True)51def total_energy(spins, J, h):52"""Calculate total energy of the configuration."""53N = spins.shape[0]54energy = 0.05556# Nearest neighbor interactions with periodic boundary conditions57for i in range(N):58for j in range(N):59right = spins[i, (j+1) % N]60down = spins[(i+1) % N, j]61energy -= J * spins[i, j] * (right + down)6263# External field term64energy -= h * np.sum(spins)65return energy6667@staticmethod68@jit(nopython=True)69def metropolis_step(spins, beta, J, h):70"""Perform one Metropolis Monte Carlo sweep."""71N = spins.shape[0]7273for _ in range(N * N):74# Choose random site75i, j = np.random.randint(0, N, 2)7677# Calculate energy change for spin flip78neighbors = (spins[i, (j+1) % N] + spins[i, (j-1) % N] +79spins[(i+1) % N, j] + spins[(i-1) % N, j])8081delta_E = 2 * J * spins[i, j] * neighbors + 2 * h * spins[i, j]8283# Metropolis acceptance criterion84if delta_E < 0 or np.random.random() < np.exp(-beta * delta_E):85spins[i, j] *= -18687@staticmethod88@jit(nopython=True)89def magnetization(spins):90"""Calculate magnetization per site."""91return np.mean(spins)9293def simulate(self, temperature, n_steps=5000, n_equilibration=1000, sample_interval=10):94"""95Run Monte Carlo simulation at given temperature.9697Parameters:98-----------99temperature : float100Temperature T101n_steps : int102Number of Monte Carlo steps after equilibration103n_equilibration : int104Number of equilibration steps105sample_interval : int106Sampling interval for measurements107108Returns:109--------110observables : dict111Dictionary containing measured observables112"""113beta = 1.0 / temperature114115# Equilibration116for step in range(n_equilibration):117self.metropolis_step(self.spins, beta, self.J, self.h)118119# Measurement phase120magnetizations = []121energies = []122123for step in range(n_steps):124self.metropolis_step(self.spins, beta, self.J, self.h)125126if step % sample_interval == 0:127mag = abs(self.magnetization(self.spins))128energy = self.total_energy(self.spins, self.J, self.h) / (self.N**2)129130magnetizations.append(mag)131energies.append(energy)132133# Calculate thermodynamic quantities134mag_mean = np.mean(magnetizations)135mag_var = np.var(magnetizations)136energy_mean = np.mean(energies)137energy_var = np.var(energies)138139observables = {140'magnetization': mag_mean,141'susceptibility': beta * mag_var * self.N**2,142'energy': energy_mean,143'heat_capacity': beta**2 * energy_var * self.N**2,144'final_configuration': self.spins.copy()145}146147return observables148149class IsingModel1D:150"""1511D Ising model exact solution using transfer matrix method.152153The transfer matrix approach provides exact thermodynamic properties154for comparison with Monte Carlo results and validation.155"""156157def __init__(self, J=1.0, h=0.0):158"""159Parameters:160-----------161J : float162Nearest-neighbor coupling constant163h : float164External magnetic field165"""166self.J = J167self.h = h168169def transfer_matrix(self, temperature):170"""171Construct transfer matrix for given temperature.172173Returns:174--------175T_matrix : ndarray1762×2 transfer matrix177"""178beta = 1.0 / temperature179180# Matrix elements181T11 = np.exp(beta * (self.J + self.h)) # ↑↑182T12 = np.exp(beta * (-self.J)) # ↑↓183T21 = np.exp(beta * (-self.J)) # ↓↑184T22 = np.exp(beta * (self.J - self.h)) # ↓↓185186return np.array([[T11, T12], [T21, T22]])187188def exact_properties(self, temperature, N=None):189"""190Calculate exact thermodynamic properties.191192Parameters:193-----------194temperature : float195Temperature T196N : int, optional197System size for finite-size calculations198199Returns:200--------201properties : dict202Exact thermodynamic properties203"""204T_matrix = self.transfer_matrix(temperature)205eigenvals = np.linalg.eigvals(T_matrix)206lambda_max = np.max(eigenvals)207208# Free energy per site (thermodynamic limit)209f_per_site = -temperature * np.log(lambda_max)210211properties = {212'free_energy_per_site': f_per_site,213'eigenvalues': eigenvals214}215216# Finite system properties217if N is not None:218Z = np.trace(np.linalg.matrix_power(T_matrix, N))219F_total = -temperature * np.log(Z)220properties['partition_function'] = Z221properties['free_energy_total'] = F_total222223return properties224225def critical_temperature_2d():226"""227Return the exact critical temperature for 2D Ising model.228229T_c = 2J / ln(1 + √2) ≈ 2.269 J230"""231return 2.0 / np.log(1 + np.sqrt(2))232233def phase_transition_study(lattice_size=64, T_min=1.0, T_max=4.0, n_temps=20):234"""235Study the magnetic phase transition in 2D Ising model.236237Parameters:238-----------239lattice_size : int240Linear size of the lattice241T_min, T_max : float242Temperature range243n_temps : int244Number of temperature points245246Returns:247--------248temperatures : array249Temperature points250results : list251List of simulation results at each temperature252"""253print(f"Phase transition study: {lattice_size}×{lattice_size} lattice")254255temperatures = np.linspace(T_min, T_max, n_temps)256T_c = critical_temperature_2d()257print(f"Theoretical critical temperature: T_c = {T_c:.3f}")258259ising = IsingModel2D(N=lattice_size, J=1.0, h=0.0)260results = []261262for i, T in enumerate(temperatures):263print(f" Temperature {i+1}/{n_temps}: T = {T:.2f}")264observables = ising.simulate(T, n_steps=5000, n_equilibration=1000)265results.append(observables)266267return temperatures, results, T_c268269def exact_vs_monte_carlo_comparison():270"""271Compare 1D Ising model exact solution with Monte Carlo simulation.272"""273print("=== 1D Ising Model: Exact vs Monte Carlo ===")274275# Parameters276J = 1.0277h = 0.1 # Small field to break symmetry278temperatures = np.linspace(0.5, 5.0, 20)279280# Exact solution281exact_model = IsingModel1D(J=J, h=h)282exact_results = []283284for T in temperatures:285props = exact_model.exact_properties(T, N=100)286exact_results.append(props)287288print(f"Exact 1D calculation completed: {len(temperatures)} temperatures")289return temperatures, exact_results290291def thermodynamic_integration_demo():292"""293Demonstrate calculation of thermodynamic properties.294"""295print("=== Thermodynamic Integration Demo ===")296297# Calculate free energy as function of temperature298temperatures = np.linspace(0.5, 5.0, 100)299model_1d = IsingModel1D(J=1.0, h=0.1)300301free_energies = []302partition_functions = []303304for T in temperatures:305props = model_1d.exact_properties(T, N=50)306free_energies.append(props['free_energy_per_site'])307partition_functions.append(props['partition_function'])308309return temperatures, free_energies, partition_functions310311def extract_critical_exponents(temperatures, magnetizations, T_c):312"""313Extract critical exponents from Monte Carlo data.314315Near T_c: m ∝ |T - T_c|^β where β ≈ 1/8 for 2D Ising model316"""317# Focus on temperatures near T_c318mask = np.abs(temperatures - T_c) < 0.5319T_fit = temperatures[mask]320m_fit = np.array(magnetizations)[mask]321322# Only use temperatures below T_c where magnetization is non-zero323below_Tc = T_fit < T_c324if np.sum(below_Tc) > 3:325reduced_temp = (T_c - T_fit[below_Tc]) / T_c326log_m = np.log(m_fit[below_Tc] + 1e-10) # Avoid log(0)327log_t = np.log(reduced_temp + 1e-10)328329# Linear fit in log-log space330coeffs = np.polyfit(log_t, log_m, 1)331beta_critical = coeffs[0]332333print(f"Estimated critical exponent β = {beta_critical:.3f}")334print(f"Theoretical value β = 0.125")335336return beta_critical337else:338print("Insufficient data points below T_c for critical exponent extraction")339return None340341if __name__ == "__main__":342# Run demonstrations343temperatures, results, T_c = phase_transition_study(lattice_size=32, n_temps=10)344345# Extract observables346magnetizations = [r['magnetization'] for r in results]347energies = [r['energy'] for r in results]348susceptibilities = [r['susceptibility'] for r in results]349350print(f"\nFinal results:")351print(f"Lowest T magnetization: {magnetizations[0]:.4f}")352print(f"Highest T magnetization: {magnetizations[-1]:.4f}")353354# Critical exponent analysis355extract_critical_exponents(temperatures, magnetizations, T_c)356357# Run other demonstrations358exact_vs_monte_carlo_comparison()359thermodynamic_integration_demo()360361