-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimulation.cpp
147 lines (134 loc) · 4.44 KB
/
simulation.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
#include "simulation.h"
#include <math.h>
Simulation::Simulation(int systemLength, double Tmin, double Tmax, int seed):
systemLength(systemLength)
{
rng = gsl_rng_alloc(gsl_rng_mt19937);
gsl_rng_set(rng,seed);
// Open OUTFILE for writing.
#ifdef SAMPLE_TO_FILE
sprintf(filename,"Q%i_L_%i_SEED_%i_Tmin_%f_Tmax_%f%s.dat", Q, DIMENSION, seed, Tmin, Tmax, SUFFIX);
filedescriptor = fopen(filename, "w");
#endif
for( int i=0; i<systemLength*systemLength; i++ ) {
/* GSL generates an integer in the range [0,Q-1] with uniform probability */
unsigned long spin = gsl_rng_uniform_int(rng,Q);
lattice1[i] = spin;
lattice2[i] = spin;
}
for( int row=0; row<systemLength; row++ ) {
for( int column=0; column<systemLength; column++ ) {
unsigned int pos = row*systemLength+column+1;
/* Precalculate indices needed for periodic boundary conditions */
indices[pos].up = ( row == (systemLength-1) ? pos - systemLength*(systemLength-1) : pos + systemLength);
indices[pos].down = ( row == 0 ? pos + systemLength*(systemLength-1) : pos - systemLength);
}
}
for( int i=0; i<systemLength; i++ ) {
int j=0;
#ifdef PREFILL
for( j=0; j<systemLength/4; j++ ) {
#endif
lattice1[i*systemLength+j] = 0;
lattice2[i*systemLength+j] = 1;
#ifdef PREFILL
}
#endif
}
for( int i=0; i<systemLength; i++ ) {
double gradient = (Tmax-Tmin)/(systemLength-1);
temperature[i] = Tmin + gradient*i;
}
}
Simulation::~Simulation()
{
printf("--> Aborted. Cleaning up");
gsl_rng_free(rng);
#ifdef SAMPLE_TO_FILE
fclose(filedescriptor);
#endif
}
void Simulation::sample()
{
// Update difference map d(i,j)
for ( int i=0; i<systemLength*systemLength; i++ ) {
difference[i] = (lattice1[i] == lattice2[i]);
}
// Update interface I(i)
Sample sample;
sample.I = 0;
sample.Wsquared = 0;
sample.iteration = iteration;
for ( int row=0; row<systemLength; row++ ) {
int column;
for (column=systemLength-1; column; column-- ) {
if (!difference[row*systemLength+column]) break;
}
interface[row] = column;
sample.I += column;
}
sample.I /= systemLength;
for ( int i=0; i<systemLength; i++ ) {
sample.Wsquared += pow(interface[i] - sample.I,2.0d);
}
sample.Wsquared /= systemLength;
// Write sample point to OUTFILE or STDOUT
#ifdef SAMPLE_TO_FILE
fprintf(filedescriptor,"%f %f %i\n", sample.I, sample.Wsquared, sample.iteration);
fflush(filedescriptor);
#endif
printf("%f %f %u\n", sample.I, sample.Wsquared, sample.iteration);
}
void Simulation::truncate()
{
// Close filehandle and open for writing
#ifdef SAMPLE_TO_FILE
fclose(filedescriptor);
filedescriptor = fopen(filename, "w");
#endif
}
void Simulation::evolve(int numberOfIterations)
{
for (int iter=0; iter<numberOfIterations; iter++ ) {
unsigned long row = gsl_rng_uniform_int(rng, systemLength);
unsigned long column = gsl_rng_uniform_int(rng, systemLength-2)+1; // Edges not to be updated
double r = gsl_rng_uniform(rng);
heatBath(lattice1,row,column,r);
heatBath(lattice2,row,column,r);
}
iteration++;
}
void Simulation::heatBath(unsigned char lattice[DIMENSION], unsigned long row, unsigned long column, double r)
{
double weight[Q];
int position = row*systemLength+column;
// Work out spin weights for nodes
double cummWeight = 0;
for (int qValue=0; qValue<Q; qValue++ ) {
int neighbours = 0;
if (lattice[position-1] == qValue) neighbours++;
if (lattice[position+1] == qValue) neighbours++;
if (lattice[indices[position].up] == qValue) neighbours++;
if (lattice[indices[position].down] == qValue) neighbours++;
weight[qValue] = exp((double)neighbours/temperature[column]);
cummWeight += weight[qValue];
}
#ifdef DEBUG
printf(" Probabilities \n");
#endif
// Normalize weights
for (int qValue=0; qValue<Q; qValue++ ) {
weight[qValue] /= cummWeight;
#ifdef DEBUG
printf("%f\n", weight[qValue]);
#endif
}
/* Find apropriate new spin based on given random uniform r */
double cumm = weight[0];
int qValue;
for( qValue=1; r>cumm; qValue++ ) cumm += weight[qValue];
#ifdef DEBUG
printf("r == %f , Picked value %i\n", r, qValue);
#endif
lattice[position] = qValue-1;
}