-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathising.py
63 lines (47 loc) · 1.76 KB
/
ising.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import numpy as np
def initialize_state(grid_size, rng):
"""Initialize Ising model with an aligned spin grid.
Input:
grid_size:
Length of the side of a square lattice.
rng:
numpy Random Generator (or compatible) object.
Output:
Two dimensional array of [grid_size x grid_size] size filled with
all values either 1 or -1.
"""
#if rng.random() < 0.5:
# return -np.ones((grid_size, grid_size))
return np.ones((grid_size, grid_size))
def _get_neighborhood(state, pos):
"""Get total spin of a four neighboring spins."""
grid_size = state.shape[0]
# boundaries continue on opposite side
return (
state[(pos[0] + 1) % grid_size, pos[1]]
+ state[(pos[0] - 1) % grid_size, pos[1]]
+ state[pos[0], (pos[1] + 1) % grid_size]
+ state[pos[0], (pos[1] - 1) % grid_size]
)
def update_state_ising(state, beta, rng):
"""Update state according to Glauber Ising model.
Input:
state:
Square [N x N] array encoding the state of the Ising model.
beta:
Inverse temperature (1/kT).
rng:
numpy Random Generator (or compatible) object.
Output:
Updated state of the model ([N x N] square array) after N**2 MC
steps.
"""
exponent = np.exp(-np.arange(1, 3) * 4 * beta)
grid_size = state.shape[0]
n_steps = grid_size**2
for _ in range(n_steps):
pos = rng.integers(0, grid_size, size=2)
dE = 2 * state[pos[0], pos[1]] * _get_neighborhood(state, pos)
if (dE <= 0) or (rng.random() < exponent[int(dE / 4 - 1)]):
state[pos[0], pos[1]] = -state[pos[0], pos[1]]
return state