-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathising.cpp
164 lines (142 loc) · 3.78 KB
/
ising.cpp
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include "ising.h"
/* Constructor */
Ising2D::Ising2D(const int &nrow, const int &ncol)
: nrow(nrow), ncol(ncol), area(nrow * ncol),
engine(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
rand_col(0, static_cast<int>(ncol - 1)),
rand_row(0, static_cast<int>(nrow - 1)),
dice(0, static_cast<double>(1)) {
// Default values
prob = 0.5;
kT = 1;
init_lattice();
init_spins();
}
/* Destructor */
Ising2D::~Ising2D() {
lattice.reset();
}
/* Initialize 2D lattice */
void Ising2D::init_lattice() {
lattice.set_size(nrow, ncol);
}
/* Initialize random spins */
void Ising2D::init_spins() {
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
(dice(engine) > prob) ? lattice(i, j) = 1 : lattice(i, j) = -1;
}
}
}
void Ising2D::resize(int &width, int &height) {
/* Resize lattice and re-init spins */
nrow = width;
ncol = height;
area = width * height;
lattice.reset();
init_lattice();
reset();
}
void Ising2D::reset() {
/* Resets RNG variables and re-initializes spins*/
rand_col = std::uniform_int_distribution<int>(0, static_cast<int>(ncol - 1));
rand_row = std::uniform_int_distribution<int>(0, static_cast<int>(nrow - 1));
dice.reset();
init_spins();
}
/* PBC check */
int Ising2D::pbc(int index, int Length) {
if (index < 0) {
return Length - 1;
} else if (index == Length) {
return 0;
}
return index;
}
/* Get total sum of nearest-neighbours */
int Ising2D::get_neighbor_sum() {
return lattice(pbc(I + 1, nrow), J)
+ lattice(pbc(I - 1, nrow), J)
+ lattice(I, pbc(J + 1, ncol))
+ lattice(I, pbc(J - 1, ncol));
}
/* Get total energy of system */
float Ising2D::get_total_energy() {
TotalE = 0.0;
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
TotalE += static_cast<float>(get_neighbor_sum()) * lattice(i, j);
}
}
return TotalE / 2.0 / area;
}
/* Get total magnetism of system */
float Ising2D::get_total_spin() {
TotalM = 0.0;
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
TotalM += lattice(i, j);
}
}
return TotalM / area;
}
/* Generate random site in cell */
void Ising2D::pick_random_site() {
I = rand_row(engine);
J = rand_col(engine);
}
/* Calculate change in energy */
void Ising2D::calculate_energy() {
dE = 2 * lattice(I, J) * get_neighbor_sum();
}
/* Flip spin */
void Ising2D::flip_spin() {
// Flip spin
(lattice(I, J) == 1) ? lattice(I, J) = -1 : lattice(I, J) = 1;
// Update energy and magnet
Mn += static_cast<float>(-2) * lattice(I, J);
En += static_cast<float>(dE);
}
/* Sweep across lattice */
void Ising2D::sweep() {
for (int i = 0; i < area; i++) {
pick_random_site();
calculate_energy();
if (dE < 0) {
flip_spin();
} else {
if (dice(engine) < std::exp(-static_cast<float>(dE) / kT)) {
flip_spin();
}
}
}
}
bool Ising2D::finish() {
/* Check if system is converged */
float total_spin = get_total_spin();
return total_spin == 1.0 || total_spin == -1.0;
}
void Ising2D::increase_temp() {
kT += 0.1;
if (kT > 3.0) {
kT = 3.0;
}
}
void Ising2D::decrease_temp() {
kT -= 0.1;
if (kT < 0.1) {
kT = 0.1;
}
}
void Ising2D::increase_prob() {
prob += 0.1;
if (prob > 0.9) {
prob = 0.9;
}
}
void Ising2D::decrease_prob() {
prob -= 0.1;
if (prob < 0.1) {
prob = 0.1;
}
}