Other Methods for sampling Ising models#
Wolf Algorithm (cluster methods):
Near the critical point \(T_c\) where the system develops a magnetization, any single-spin-flip dynamics becomes very slow (the correlation time diverges). Wolff came up with a clever method to flip whole clusters of spins!
Pick a spin at random, remember its direction \(s = \pm 1\), and flip it.
For each of the four neighboring spins, if it is in the direction \(s\), flip it with probability \(p = 1 - e^{\beta 2J}\).
For each of the new flipped spins, recursively flip their neighbors as in step 2
from numba import njit
import numpy as np
@njit
def run_wolf_mc(spins=np.random.choice([-1, 1], size=(20, 20)),
J=1,
T=1,
nsteps = 10000):
'''Sampling 2D ising lattice with Wolff algorithm.
Returns:
- S: trajectory of lattice
- M: Magnetization'''
N = len(spins)
n = N**2
S, M = [], []
for step in range(nsteps):
# Pick random spin
i, j = np.random.randint(N), np.random.randint(N)
#Initial pocket and cluster lists
Pocket, Cluster = [(i,j)], [(i,j)]
#Start looking for pockets of spins pointing in same direction
while len(Pocket)>0:
i, j = Pocket.pop(0)
# interogate neighbours of spin[i,j]
for m, n in [((j+1)%N, j), ((i-1)%N, j), (i, (j+1)%N), (i, (j-1)%N)]:
#If neighbouring spin is in same direction and not already in the Cluster
if spins[m, n] == spins[i, j] and (m, n) not in Cluster:
#Accept/reject move according to Wolff criteria
if np.random.random() < 1.0 - math.exp(- J / T):
Pocket.append((m,n))
Cluster.append((m,n))
#Update cluster move and save data
for c in Cluster:
spins[c] *= -1
S.append(spins.copy())
M.append(np.mean(spins))
return S, M