| name | statistical-mechanics |
| description | Statistical mechanics fundamentals including ensembles, partition functions, phase transitions, Monte Carlo methods, and non-equilibrium dynamics for physics applications. |
| category | physics |
| tags | ["physics","statistical-mechanics","ensembles","partition-functions","phase-transitions","monte-carlo","non-equilibrium","thermodynamics"] |
| difficulty | advanced |
| author | neuralblitz |
Statistical Mechanics
What I do
I provide comprehensive expertise in statistical mechanics, the bridge between microscopic physics and thermodynamics. I enable you to apply ensemble theory, calculate partition functions, analyze phase transitions, implement Monte Carlo simulations, and model non-equilibrium dynamics. My knowledge spans from foundational statistical foundations to modern computational methods essential for condensed matter physics, soft matter, biological physics, and materials science.
When to use me
Use statistical mechanics when you need to: derive thermodynamic properties from microscopic models, analyze critical phenomena and phase transitions, simulate many-body systems using Monte Carlo, calculate equation of state for gases and materials, understand transport phenomena and fluctuations, model magnetic systems and spin models, or connect molecular dynamics to macroscopic observables.
Core Concepts
- Microstates and Macrostates: Microscopic configurations and their macroscopic aggregations with entropy S = k_B ln Ω.
- Phase Space: Complete specification of particle positions and momenta for classical systems.
- Ensembles: Collections of microstates with different constraints (microcanonical, canonical, grand canonical).
- Partition Functions: Z = Σ exp(-βE) encoding all thermodynamic information.
- Thermodynamic Relations: Connecting partition functions to free energy, entropy, and equations of state.
- Phase Transitions: Qualitative changes in system behavior with singularities in derivatives of free energy.
- Mean-Field Theory: Approximate treatment replacing interactions with effective fields.
- Critical Phenomena: Universal behavior near phase transitions characterized by critical exponents.
- Fluctuation-Dissipation: Connecting response functions to equilibrium fluctuations.
- Non-Equilibrium Dynamics: Time evolution toward equilibrium and current flows.
Code Examples
Ensembles and Partition Functions
import numpy as np
def boltzmann_factor(E, T):
"""exp(-E/k_B T)"""
kB = 1.38e-23
return np.exp(-E / (kB * T))
def canonical_partition_function(energies, T):
"""Z = Σ exp(-βE_i)"""
beta = 1 / (1.38e-23 * T)
return np.sum(np.exp(-beta * np.array(energies)))
def canonical_expectation(E, Z, T):
"""⟨E⟩ = (1/Z) Σ E_i exp(-βE_i)"""
beta = 1 / (1.38e-23 * T)
weights = np.exp(-beta * np.array(E))
return np.sum(E * weights) / Z
def heat_capacity(energies, T, Cv):
"""Cv = (⟨E²⟩ - ⟨E⟩²) / (k_B T²)"""
beta = 1 / (1.38e-23 * T)
Z = canonical_partition_function(energies, T)
E_avg = canonical_expectation(energies, Z, T)
E2_avg = canonical_expectation([E**2 for E in energies], Z, T)
return (E2_avg - E_avg**2) / ((1.38e-23) * T**2)
E0, E1 = 0, 0.001
energies = [E0, E1]
print("Two-level system:")
for T in [10, , , , ]:
Z = canonical_partition_function(energies, T)
E_avg = canonical_expectation(energies, Z, T)
()
():
hbar =
beta = / ( * T)
omega * hbar * beta > :
np.exp(-omega * hbar * beta / )
np.exp(-omega * hbar * beta / ) / ( - np.exp(-omega * hbar * beta))
():
h =
kB =
lam = h / np.sqrt( * np.pi * m * kB * T)
V / lam**
():
kB =
N * kB * T / V
N_A =
V =
T =
P = ideal_gas_pressure(N_A, T, V)
()
():
beta = / ( * T)
Xi =
eps single_particle_states:
Xi *= ( + np.exp(-beta * (eps - grand_mu)))
Xi
():
kB =
/ (np.exp((eps - mu) / (kB * T)) + )
():
kB =
mu >= eps:
np.inf
/ (np.exp((eps - mu) / (kB * T)) - )
()
delta_E = *
f = fermi_dirac_occupation(delta_E, , )
()
Ising Model and Phase Transitions
import numpy as np
class IsingModel:
def __init__(self, L, J=1, h=0):
"""2D Ising model on L×L lattice."""
self.L = L
self.J = J
self.h = h
self.N = L * L
self.spins = np.random.choice([-1, 1], size=(L, L))
def energy(self):
"""Calculate total energy."""
E = 0
for i in range(self.L):
for j in range(self.L):
right = self.spins[(i+1) % self.L, j]
down = self.spins[i, (j+1) % self.L]
E -= self.J * self.spins[i, j] * (right + down)
E -= self.h * self.spins[i, j]
return E / 2
def magnetization(self):
np.(.spins)
():
kB =
_ (.N):
i = np.random.randint(.L)
j = np.random.randint(.L)
neighbors = (.spins[(i-) % .L, j] +
.spins[(i+) % .L, j] +
.spins[i, (j-) % .L] +
.spins[i, (j+) % .L])
dE = * .spins[i, j] * (.J * neighbors + .h)
dE < np.random.random() < np.exp(-dE / (kB * T)):
.spins[i, j] *= -
():
_ (n_sweeps):
.metropolis_step(T)
():
.equilibrate(T, n_sweeps)
mags = []
eners = []
_ (n_sweeps):
.metropolis_step(T)
mags.append(.magnetization())
eners.append(.energy())
np.mean(mags)/.N, np.std(mags)/.N, np.mean(eners)/.N, np.std(eners)/.N
L =
ising = IsingModel(L)
()
temperatures = [, , , , , , ]
T temperatures:
m, dm, E, dE = ising.simulate(T, n_sweeps=)
()
():
m2 = np.mean(np.array(mags)**)
m4 = np.mean(np.array(mags)**)
- m4 / ( * m2**)
()
T [, , ]:
ising2 = IsingModel()
ising2.equilibrate(T, )
mags = [ising2.magnetization() _ ()]
U = binder_cumulant(mags)
()
Mean-Field Theory
import numpy as np
def mean_field_ising(T, J, h=0, max_iter=100, tol=1e-6):
"""Mean-field solution of Ising model."""
kB = 1.0
beta = 1 / T
m = 0.1
for iteration in range(max_iter):
m_new = np.tanh(beta * (J * 6 * m + h))
if abs(m_new - m) < tol:
break
m = m_new
return m
def solve_self_consistent(T, J):
"""Solve MF equations numerically."""
from scipy.optimize import brentq
def equation(m):
kB = 1.0
return m - np.tanh(m * J * 6 / (kB * T))
Tc_mf = J * 6
if T > Tc_mf:
return 0
try:
m = brentq(equation, 1e-6, 1.0)
return m
except:
return
Tc_mf =
()
()
T [, , , , , , , ]:
m = solve_self_consistent(T, )
T < Tc_mf:
beta_mf = np.log(m) / np.log((Tc_mf - T) / Tc_mf)
()
:
()
():
a * (T - Tc_mf) * m** + b * m**
():
T > Tc:
chi0 / (T - Tc)
chi0 / (T_c - T)
()
T [, , , ]:
chi = susceptibility(T, )
()
Monte Carlo Methods
import numpy as np
def metropolis_sampling(pdf, proposal_std, n_samples, x0):
"""Metropolis-Hastings sampling from arbitrary PDF."""
samples = [x0]
x = x0
for _ in range(n_samples):
x_proposed = x + np.random.normal(0, proposal_std)
alpha = pdf(x_proposed) / pdf(x)
if np.random.random() < alpha:
x = x_proposed
samples.append(x)
return np.array(samples)
def wolff_cluster_update(spins, J, T):
"""Wolff single-cluster Monte Carlo update."""
L = len(spins)
visited = np.zeros(L, dtype=bool)
site = np.random.randint(L)
cluster = [site]
visited[site] = True
S_cluster = spins[site]
i = 0
while i < len(cluster):
current = cluster[i]
P_add = 1 - np.exp(-2 * J / T)
neighbors = [(current - 1) % L, (current + 1) % L]
for n in neighbors:
if not visited[n] and spins[n] == S_cluster:
if np.random.random() < P_add:
visited[n] = True
cluster.append(n)
i += 1
for site in cluster:
spins[site] *= -1
spins
():
L = (spins)
bonds = np.zeros(L, dtype=)
i (L):
spins[i] == spins[(i+) % L]:
P_bond = - np.exp(- * J / T)
bonds[i] = np.random.random() < P_bond
clusters = []
visited = np.zeros(L, dtype=)
i (L):
visited[i]:
cluster = [i]
visited[i] =
j = i
bonds[j]:
j = (j + ) % L
visited[j]:
visited[j] =
cluster.append(j)
clusters.append(cluster)
cluster clusters:
np.random.random() < :
site cluster:
spins[site] *= -
spins
():
n = (samples)
mean = np.mean(samples)
var = np.var(samples)
acf = np.correlate(samples - mean, samples - mean, mode=)
acf = acf[n-:] / (acf[n-] * np.arange(n, , -))
tau = + np.(acf[:])
tau
N =
J, T = ,
spins = np.random.choice([-, ], size=N)
()
()
()
Non-Equilibrium Dynamics
import numpy as np
class MasterEquation:
def __init__(self, transition_matrix):
"""dP/dt = W·P for Markov process."""
self.W = transition_matrix
def propagate(self, P0, dt, n_steps):
"""Forward Euler integration of master equation."""
P = P0.copy()
t = 0
results = [P.copy()]
for _ in range(n_steps):
dP = self.W @ P
P = P + dt * dP
t += dt
results.append(P.copy())
return np.array(results)
def langevin_dynamics(x0, v0, gamma, kT, m, dt, n_steps):
"""Langevin dynamics: m dv/dt = -γv - dU/dx + √(2γkT)ξ(t)"""
x, v = x0, v0
results = [(x, v)]
for _ in range(n_steps):
xi = np.random.normal(0, 1)
noise = np.sqrt(2 * gamma * kT / dt)
v += dt / m * (-gamma * v + noise * xi)
x += dt * v
results.append((x, v))
return np.array(results)
def green_kubo_relation(velocity_correlation):
"""Diffusion coefficient from velocity autocorrelation."""
return np.trapz(velocity_correlation, dx=dt)
def ():
x =
positions = [x]
_ (n_steps):
dx = np.random.normal(, np.sqrt( * D * dt))
x += dx
positions.append(x)
np.array(positions)
():
np.array([np.mean((positions[t:] - positions[:-t])**)
t ((positions)//)])
D =
dt =
n_steps =
positions = brownian_motion_1D(D, dt, n_steps)
msd = mean_squared_displacement(positions)
()
()
()
():
():
kT =
np.mean(np.exp(-np.array(work_samples) / kT))
():
Best Practices
- Verify equilibrium properties by checking that observables don't drift over time in long simulations.
- Use multiple independent runs with different random seeds to estimate statistical errors.
- For critical phenomena, simulate large systems near Tc to minimize finite-size effects.
- Use cluster algorithms (Wolff, Swendsen-Wang) to overcome critical slowing down near phase transitions.
- Distinguish between different ensemble averages and ensure proper equilibration before measurement.
- Use block averaging to estimate statistical errors and autocorrelation times.
- For non-equilibrium simulations, verify that fluctuations satisfy fluctuation-dissipation relations.
- When applying mean-field theory, check self-consistency of the mean-field approximation.
- Use histogram reweighting to efficiently sample across phase transitions.
- Consider conservation laws and select appropriate dynamics (microcanonical vs canonical) for your system.