-
Notifications
You must be signed in to change notification settings - Fork 0
/
model.go
101 lines (88 loc) · 1.76 KB
/
model.go
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package main
import (
"errors"
"math"
"math/rand"
"sync"
"time"
)
// Model is an Ising model
type Model struct {
sync.Mutex
Alpha float64
Beta float64
de [][]int // Delta Energy for a flip at each site
l [][]int // Lattice
n int // Lattice size (n x n)
}
// NewModel returns a NxN Ising model
func NewModel(N int) (*Model, error) {
if !powerOfTwo(N) {
return nil, errors.New("Model must have dimension power of 2")
}
m := Model{Alpha: 0.3, Beta: 6.0}
m.n = N
m.de = make([][]int, N)
m.l = make([][]int, N)
for i := 0; i < N; i++ {
m.de[i] = make([]int, N)
m.l[i] = make([]int, N)
for j := 0; j < N; j++ {
m.l[i][j] = (rand.Intn(2) * 2) - 1 // +1 or -1
}
}
return &m, nil
}
// Step advances the Ising Model by one Metropolis step.
func (m *Model) Step() {
m.Lock()
defer m.Unlock()
// Compute the change in energy from a flip at each site
for i := 0; i < m.n; i++ {
for j := 0; j < m.n; j++ {
m.de[i][j] = 2 * m.l[i][j] * (m.l[(i+1)&(m.n-1)][j] +
m.l[(i-1)&(m.n-1)][j] +
m.l[i][(j+1)&(m.n-1)] +
m.l[i][(j-1)&(m.n-1)])
}
}
// Flipping loop
for i := 0; i < m.n; i++ {
go func(i int) {
for j := 0; j < m.n; j++ {
if m.de[i][j] < 0 {
if rand.Float64() < m.Alpha {
m.l[i][j] = -m.l[i][j]
}
} else {
if rand.Float64() < m.Alpha*math.Exp(-m.Beta*float64(m.de[i][j])) {
m.l[i][j] = -m.l[i][j]
}
}
}
}(i)
}
return
}
// Run steps the model once per 100 ms for ever.
func (m *Model) Run() {
go func() {
for {
time.Sleep(100 * time.Millisecond)
m.Step()
}
}()
}
// powerOfTwo checks if a number is a power of two or not.
func powerOfTwo(n int) bool {
if n <= 0 {
return false
}
for n > 1 {
if (n & 1) == 1 {
return false
}
n = n >> 1
}
return true
}