26 #include <gsl/gsl_sf_erf.h>
28 #define erfc_(x) gsl_sf_erfc(x)
34 #define MU_B 9.27410e-24
36 #define K_B 1.38062e-23
38 #define N_A 6.02217e23
43 #define LATTICE_CONST 10.12e-10
44 #define LATTICE_VOLUME (LATTICE_CONST*LATTICE_CONST*LATTICE_CONST)
46 #define SEC_CACHE_ON_FACTOR 0.02
47 #define SEC_CACHE_OFF_FACTOR 0.01
48 #define THIRD_CACHE_ON_FACTOR 0.05
49 #define THIRD_CACHE_OFF_FACTOR 0.02
58 #define AHF_DY_O1_DIPOLE (MU_B*1e-7/pow(sqrt(3.0)/8.0*LATTICE_CONST, 3.0)*2.0)
60 #define AHF_DY_O1 (AHF_DY_O1_DIPOLE + (-25.06e6+19.64e6)/5.7719e6/A_MOMENT/(4.0/sqrt(3.0)))
68 Vector3(T nx, T ny) : x(nx), y(ny), z(0) {}
69 Vector3(T nx, T ny, T nz) : x(nx), y(ny), z(nz) {}
73 Vector3(
const X n[3]) : x(n[0]), y(n[1]), z(n[2]) {}
76 bool operator==(
const Vector3 &s1)
const
77 {
return ((x == s1.x) && (y == s1.y) && (z == s1.z));}
80 x += s1.x; y += s1.y; z += s1.z;
85 x -= s1.x; y -= s1.y; z -= s1.z;
89 Vector3 &operator*=(
const X &k) {
90 x *= k; y *= k; z *= k;
98 return x1*x1 + y1*y1 + z1*z1;
108 T zbab = x1*x2 + y1*y2 + z1*z2;
109 T ab2 = x2*x2 + y2*y2 + z2*z2;
110 T zb2 = x1*x1 + y1*y1 + z1*z1;
111 return (zb2*ab2 - zbab*zbab) / ab2;
114 T ir = (T)1.0 / sqrt(x*x + y*y + z*z);
115 x *= ir; y *= ir; z *= ir;
117 Vector3 &vectorProduct(
const Vector3 &s1) {
119 s2.x = y * s1.z - z * s1.y;
120 s2.y = z * s1.x - x * s1.z;
121 s2.z = x * s1.y - y * s1.x;
125 T innerProduct(
const Vector3 &s1)
const {
126 return x * s1.x + y * s1.y + z * s1.z;
129 return sqrt(x*x+y*y+z*z);
139 double exec(
double temp, Vector3<double> field,
140 int *flips,
long double *tests,
double *DUav, Vector3<double> *Mav);
171 static int setupField(
int size,
double dfactor,
172 double cutoff_real,
double cutoff_rec,
double alpha);
174 void read(std::istream &);
177 void write(std::ostream &);
178 void write(
char *spins,
179 double *fields = 0,
double *probabilities = 0);
183 struct FlipHistory {
int lidx;
int site;
float delta;
double tests;};
184 void write_flips(std::deque<FlipHistory> &buf);
186 static int length() {
202 int m_hint_spin1_site;
203 int m_hint_spin1_lattice_index;
206 int m_hint_sec_cache_miss[16];
211 int m_last_probability_buffer;
212 int m_last_flipped_site;
213 int m_last_flipped_lattice_index;
214 bool m_play_back_buffer;
215 std::vector<double> m_probability_buffers[2][16];
222 bool m_sec_cache_enabled, m_third_cache_enabled;
223 bool m_sec_cache_firsttime, m_third_cache_firsttime;
242 void doTests(
int *flips,
long double tests);
243 void flipSpin(
int site,
int lidx,
double du,
long double tests_after_check);
244 inline double flippingProbability(
int site,
int lidx,
double field,
double *du);
251 static double s_cutoff_real_radius;
254 static double s_cutoff_rec_radius;
265 static inline int lattice_index(
int i,
int j,
int k);
273 for(
int i = 0; i < 4; i++) x[i] = 0.0;
276 for(
int i = 0; i < 4; i++) x[i] = v.x[i];
281 for(
int i = 0; i < 4; i++) h += x[i];
285 for(
int i = 0; i < 4; i++) x[i] += v.x[i];
289 for(
int i = 0; i < 4; i++) x[i] *= v.x[i];
293 #if defined __GNUC__ || defined __clang__
294 __attribute__((__aligned__(16)))
305 static void addFieldsReal(MonteCarlo::Spin v,
FieldRealArray& array,
int di,
int dj,
int dk);
308 static std::vector<Vector3<Spin> > s_fields_rec_generic[16];
311 static std::vector<std::complex<MonteCarlo::Spin> > s_exp_ph[16];
312 static inline int reciprocal_index(
int kx,
int ky,
int kz);
320 static inline int spins_real_index(
int i,
int j,
int k);
321 static inline int spins_real_index(
int lidx);
322 inline Spin readSpin(
int site,
int sidx);
323 inline void writeSpin(Spin v,
int site,
int sidx);
326 void makeReciprocalImage();
332 double hinteraction_miscache(
int sec_cache_miss_cnt,
int site,
int lidx);
333 inline double iterate_interactions(
int site1,
int lidx,
int site2);
335 inline double iterate_real_redirected(
int cnt,
const FieldRealArray &,
int i,
int j,
int k,
int site2);
336 double iterate_real(
int site1,
int i,
int j,
int k,
int site2);
339 inline double iterate_rec_redirected(
int cutoff,
int site1,
int i,
int j,
int k,
int site2);
340 double iterate_rec(
int site1,
int i,
int j,
int k,
int site2);
352 void takeThermalAverage(
long double tests_after_check);
357 long double m_SumTests;
358 long double m_SumTestsAtLastFlip;
362 std::deque<pthread_t> m_threads;
363 static void * xthread_start_routine(
void *);
367 std::deque<FlipHistory> m_flipHistory;
372 static const int cg_ASitePositions[16][3] = {
373 {0,0,0}, {1,1,0}, {1,0,1}, {0,1,1},
374 {2,2,0}, {3,3,0}, {3,2,1}, {2,3,1},
375 {0,2,2}, {1,3,2}, {1,2,3}, {0,3,3},
376 {2,0,2}, {3,1,2}, {3,0,3}, {2,1,3}
379 static const int cg_BSitePositions[16][3] = {
380 {2,2,2}, {1,3,0}, {3,0,1}, {0,1,3},
381 {0,0,2}, {3,1,0}, {1,2,1}, {2,3,3},
382 {2,0,0}, {1,1,2}, {3,2,3}, {0,3,1},
383 {0,2,0}, {3,3,2}, {1,0,3}, {2,1,1}
386 static const int cg_8aSitePositions[8][3] = {
387 {1,1,1}, {5,5,1}, {1,5,5}, {5,1,5},
388 {7,3,3}, {3,7,3}, {7,7,7}, {3,3,7}
390 #define OX (0.4201*8)
392 static const double cg_48fSitePositions[48][3] = {
393 {OX,1,1}, {OX+4,5,1}, {OX,5,5}, {OX+4,1,5},
394 {1,OX,1}, {5,OX+4,1}, {1,OX+4,5}, {5,OX,5},
395 {1,1,OX}, {5,5,OX}, {1,5,OX+4}, {5,1,OX+4},
396 {-OX+6,1,5}, {-OX+10,5,5}, {-OX+6,5,1}, {-OX+10,1,1},
397 {5,-OX+6,1}, {1,-OX+10,1}, {5,-OX+10,5}, {1,-OX+6,5},
398 {1,5,-OX+6}, {5,1,-OX+6}, {1,1,-OX+10}, {5,5,-OX+10},
399 {7,OX+2,3}, {3,OX-2,3}, {7,OX-2,7}, {3,OX+2,7},
400 {OX-2,3,3}, {OX+2,7,3}, {OX-2,7,7}, {OX+2,3,7},
401 {3,3,OX-2}, {7,7,OX-2}, {3,7,OX+2}, {7,3,OX+2},
402 {7,-OX+8,7}, {3,-OX+4,7}, {7,-OX+4,3}, {3,-OX+8,3},
403 {-OX+4,7,3}, {-OX+8,3,3}, {-OX+4,3,7}, {-OX+8,7,7},
404 {7,3,-OX+4}, {3,7,-OX+4}, {7,7,-OX+8}, {3,3,-OX+8}
408 static const int cg_ASiteIsingAxes[16][3] = {
409 {1,1,1}, {-1,-1,1}, {-1,1,-1}, {1,-1,-1},
410 {1,1,1}, {-1,-1,1}, {-1,1,-1}, {1,-1,-1},
411 {1,1,1}, {-1,-1,1}, {-1,1,-1}, {1,-1,-1},
412 {1,1,1}, {-1,-1,1}, {-1,1,-1}, {1,-1,-1}
415 MonteCarlo::reciprocal_index(
int kx,
int ky,
int kz) {
419 MonteCarlo::lattice_index(
int i,
int j,
int k) {
420 return s_L*(
s_L*k + j) + i;
424 MonteCarlo::spins_real_index(
int i,
int j,
int k) {
425 int l = ((3 *
s_L - 1) / 4 + 1) * 4;
426 return 3*l*(
s_L*k + j) +
s_L + i;
429 MonteCarlo::spins_real_index(
int lidx) {
430 int l = ((3 *
s_L - 1) / 4 + 1) * 4;
431 return 3*l*(lidx /
s_L) +
s_L + (lidx %
s_L);
433 inline MonteCarlo::Spin
434 MonteCarlo::readSpin(
int site,
int sidx) {
440 MonteCarlo::writeSpin(Spin v,
int site,
int sidx) {
447 MonteCarlo::spins_real_index(
int i,
int j,
int k) {
451 MonteCarlo::spins_real_index(
int lidx) {
452 return lidx * 3 - (lidx %
s_L) * 2 +
s_L;
454 inline MonteCarlo::Spin
455 MonteCarlo::readSpin(
int site,
int sidx) {
459 MonteCarlo::writeSpin(Spin v,
int site,
int sidx) {
470 v.x = 4*di + cg_ASitePositions[site2][0] - cg_ASitePositions[site1][0];
471 v.y = 4*dj + cg_ASitePositions[site2][1] - cg_ASitePositions[site1][1];
472 v.z = 4*dk + cg_ASitePositions[site2][2] - cg_ASitePositions[site1][2];
476 MonteCarlo::iterate_interactions(
int site1,
int lidx,
int site2)
485 double h = iterate_rec(site1, i, j, k, site2);
487 if(m_third_cache_enabled &&
493 double hreal = iterate_real(site1, i, j, k, site2);
494 if(m_third_cache_enabled) {
501 if(m_sec_cache_enabled) {
519 int sec_cache_miss_cnt = 0;
520 for(
int site2 = 0; site2 < 16; site2++) {
521 if(m_sec_cache_enabled &&
527 m_hint_sec_cache_miss[sec_cache_miss_cnt++] = site2;
531 if(sec_cache_miss_cnt <= 8) {
533 for(
int miss = 0; miss < sec_cache_miss_cnt; miss++) {
534 int site2 = m_hint_sec_cache_miss[miss];
535 h += iterate_interactions(site1, lidx, site2);
539 h += hinteraction_miscache(sec_cache_miss_cnt, site1, lidx);