montecarlo.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13 ***************************************************************************/
14 #include "montecarlo.h"
15 #include "rand.h"
16 
17 #include <pthread.h>
18 
19 MonteCarlo::Vector3<double> MonteCarlo::s_ASiteIsingVector[16];
20 volatile bool MonteCarlo::s_bAborting = false;
21 
22 using namespace std;
23 
24 int MonteCarlo::s_L;
26 double MonteCarlo::s_alpha;
29 double MonteCarlo::s_cutoff_real_radius;
30 MonteCarlo::FieldRealArray MonteCarlo::s_fields_real[16][16];
31 MonteCarlo::FieldRealArray MonteCarlo::s_fields_real_B[16][16][3];
32 MonteCarlo::FieldRealArray MonteCarlo::s_fields_real_8a[8][16][3];
33 MonteCarlo::FieldRealArray MonteCarlo::s_fields_real_48f[48][16][3];
35 double MonteCarlo::s_cutoff_rec_radius;
36 std::vector<MonteCarlo::Spin> MonteCarlo::s_fields_rec[16][16];
37 std::vector<MonteCarlo::Vector3<MonteCarlo::Spin> > MonteCarlo::s_fields_rec_generic[16];
39 std::vector<std::complex<MonteCarlo::Spin> > MonteCarlo::s_exp_ph[16];
40 std::vector<int> MonteCarlo::s_4r2_neighbor;
41 
42 MonteCarlo::MonteCarlo(int num_threads)
43  :
44  m_bTerminated(false),
45  m_sec_cache_enabled(false),
46  m_third_cache_enabled(false),
47  m_sec_cache_firsttime(true),
48  m_third_cache_firsttime(true)
49 {
50  int lsize = s_num_spins/16;
51 
52  for(int site1 = 0; site1 < 16; site1++) {
53  #ifdef PACK_4FLOAT
54  m_spins_real[site1].resize(spins_real_index(0,0,s_L)/4);
55  #else
56  m_spins_real[site1].resize(3*lsize);
57  #endif
58 
59  m_field_pri_cached[site1].resize(lsize, 0.0);
60  m_field_pri_cached_sane.resize(lsize, 0);
61  for(int site2 = 0; site2 < 16; site2++) {
62  m_field_sec_cached[site2][site1].resize(lsize, 0.0);
63  m_field_sec_cached_sane[site2].resize(lsize, 0);
64  m_field_third_cached[site2][site1].resize(lsize, 0.0);
65  m_field_third_cached_sane[site2].resize(lsize, 0);
66  }
67  m_probability_buffers[0][site1].resize(lsize, 0.0);
68  m_probability_buffers[1][site1].resize(lsize, 0.0);
69  }
70 
71  fprintf(stderr, "# of spins = %d\n", 16*lsize);
72  randomize();
73 
74  for(int i = 0; i < num_threads - 1; i++) {
75  pthread_t tid;
76  int ret =
77  pthread_create(&tid, NULL, xthread_start_routine, this);
78  assert(!ret);
79  m_threads.push_back(tid);
80  }
81 }
82 MonteCarlo::~MonteCarlo()
83 {
84  {
85  XScopedLock<XCondition> lock(m_thread_pool_cond);
86  m_bTerminated = true;
87  m_thread_pool_cond.broadcast();
88  }
89  for(deque<pthread_t>::iterator it = m_threads.begin(); it != m_threads.end(); it++)
90  {
91  void *retv;
92  int ret = pthread_join(*it, &retv);
93  assert(!ret);
94  }
95 }
96 void
97 MonteCarlo::read(istream &is)
98 {
99  if(!is.good()) throw "input io error\n";
100  string str;
101  do {
102  getline(is, str);
103  } while(str[0] != '#');
104  while(str[0] == '#') {
105  getline(is, str);
106  }
107  int size;
108  sscanf(str.c_str(), "size=%d", &size);
109  if(size != s_L) throw "size mismatch\n";
110  is >> str;
111  if(str != "[") throw "ill format\n";
112  for(int site1 = 0; site1 < 16; site1++) {
113  is >> str;
114  if(str != "[") throw "ill format\n";
115  for(int k1 = 0; k1 < s_L; k1++) {
116  is >> str;
117  if(str != "[") throw "ill format\n";
118  for(int j1 = 0; j1 < s_L; j1++) {
119  is >> str;
120  if(str != "[") throw "ill format\n";
121  for(int i1 = 0; i1 < s_L; i1++) {
122  is >> str;
123  if(str != "[") throw "ill format\n";
124  is >> str;
125  int x = atoi(str.c_str());
126  if(abs(x) != 1) throw "value be +-1\n";
127  int sidx = spins_real_index(i1,j1,k1);
128  writeSpin(x, site1, sidx);
129  is >> str;
130  if(str != "?") {
131  int lidx = lattice_index(i1,j1,k1);
132  m_field_pri_cached[site1][lidx] = atof(str.c_str());
133  m_field_pri_cached_sane[lidx] |= 1u << site1;
134  }
135  is >> str;
136  if(str != "]") throw "ill format\n";
137  }
138  is >> str;
139  if(str != "]") throw "ill format\n";
140  }
141  is >> str;
142  if(str != "]") throw "ill format\n";
143  }
144  is >> str;
145  if(str != "]") throw "ill format\n";
146  }
147  is >> str;
148  if(str != "]") throw "ill format\n";
149 
150  makeReciprocalImage();
151 }
152 
153 void
154 MonteCarlo::write(ostream &os)
155 {
156  if(!os.good()) throw "output io error\n";
157  os << "# MonteCarlo calculation for pyrochlore. Kentaro Kitagawa." << endl;
158  os << "# ver. 1.0." << endl;
159  os << "# Spin configuration below." << endl;
160  os << "size=" << s_L << endl;
161  os << "[ ";
162  for(int site1 = 0; site1 < 16; site1++) {
163  os << "[ ";
164  for(int k1 = 0; k1 < s_L; k1++) {
165  os << "[ ";
166  for(int j1 = 0; j1 < s_L; j1++) {
167  os << "[ ";
168  for(int i1 = 0; i1 < s_L; i1++) {
169  os << "[ ";
170  int lidx = lattice_index(i1,j1,k1);
171  os << readSpin(site1, spins_real_index(lidx));
172  if(m_field_pri_cached_sane[lidx] & (1u << site1)) {
173  char buf[31];
174  snprintf(buf, 30, "%.16g", m_field_pri_cached[site1][lidx]);
175  os << " " << buf;
176  }
177  else
178  {
179  os << " ?";
180  }
181  os << " ] " ;
182  }
183  os << "]" << endl;
184  }
185  os << "]" << endl;
186  }
187  os << "]" << endl;
188  }
189  os << "]" << endl;
190 }
191 
192 void
194 {
195  fprintf(stderr, "Randomize spins\n");
196  for(int site1 = 0; site1 < 16; site1++) {
197  m_ext_field[site1] = 0.0;
198  }
199  for(int site1 = 0; site1 < 16; site1++) {
200  for(int k1 = 0; k1 < s_L; k1++) {
201  for(int j1 = 0; j1 < s_L; j1++) {
202  for(int i1 = 0; i1 < s_L; i1++) {
203  int sidx = spins_real_index(i1,j1,k1);
204  int val = (randMT19937() < 0.5) ? 1 : -1;
205  writeSpin(val, site1, sidx);
206  }
207  }
208  }
209  }
210  makeReciprocalImage();
211 }
213 MonteCarlo::siteMagnetization()
214 {
215  Quartet quartet;
216  for(int k1 = 0; k1 < s_L; k1++) {
217  for(int j1 = 0; j1 < s_L; j1++) {
218  for(int i1 = 0; i1 < s_L; i1++) {
219  int sidx = spins_real_index(i1,j1,k1);
220  for(int trans = 0; trans < 4; trans++) {
221  int in = 0;
222  for(int site_wo_trans = 0; site_wo_trans < 4; site_wo_trans++) {
223  int site1 = site_wo_trans + 4*trans;
224  Spin spin = readSpin(site1, sidx);
225  quartet.sites[site1 % 4] += spin;
226  in += (spin == 1) ? 1 : 0;
227  }
228  quartet.twotwo += (in == 2) ? 1 : 0;
229  quartet.onethree += ((in == 1) || (in == 3)) ? 1 : 0;
230  }
231  }
232  }
233  }
234  quartet.twotwo /= (s_num_spins/4);
235  quartet.onethree /= (s_num_spins/4);
236  for(int site1 = 0; site1 < 4; site1++) {
237  quartet.sites[site1] /= (s_num_spins/4);
238  quartet.sites[site1] *= A_MOMENT;
239  }
240  return quartet;
241 }
244 {
245  Vector3<double> m;
246  Quartet quartet = siteMagnetization();
247  for(int site1 = 0; site1 < 4; site1++) {
248  Vector3<double> v(s_ASiteIsingVector[site1]);
249  v *= quartet.sites[site1];
250  m += v;
251  }
252  m *= 1.0/4; // per one spin.
253  return m;
254 }
255 void
256 MonteCarlo::takeThermalAverage(long double tests_after_check)
257 {
258  m_SumDeltaU += m_DeltaU * tests_after_check;
259 
260  for(int site = 0; site < 16; site++) {
261  m_SumSpin[site] += real(m_spins_rec[site][reciprocal_index(0,0,0)]) * tests_after_check;
262  }
263 
264  m_SumTests += tests_after_check;
265 }
266 
267 double
268 MonteCarlo::exec(double temp, Vector3<double> field, int *flips,
269  long double *tests, double *DUav, Vector3<double> *Mav)
270 {
271  m_beta = 1.0/K_B/temp;
272 
273  for(int site1 = 0; site1 < 16; site1++) {
274  m_ext_field[site1] = field.innerProduct(s_ASiteIsingVector[site1]);
275  }
276 
277  m_DeltaU = 0.0;
278  m_SumDeltaU = 0.0;
279  for(int site = 0; site < 16; site++) {
280  m_SumSpin[site] = 0.0;
281  }
282  m_SumTests = 0.0;
283  m_SumTestsAtLastFlip = 0.0;
284 
285  m_flipHistory.clear();
286 
287  doTests(flips, *tests);
288 
289  *DUav = m_SumDeltaU / s_num_spins / m_SumTests;
290  Vector3<double> m;
291  for(int site1 = 0; site1 < 16; site1++) {
292  Vector3<double> v(s_ASiteIsingVector[site1]);
293  v *= (double)(m_SumSpin[site1]);
294  m += v;
295  }
296  m *= A_MOMENT / s_num_spins / m_SumTests;
297  *Mav = m;
298  *tests = m_SumTests;
299  return m_DeltaU/s_num_spins;
300 }
301 inline double
302 MonteCarlo::flippingProbability(int site, int lidx, double h, double *pdu)
303 {
304  int sidx = spins_real_index(lidx);
305  double du = 2 * readSpin(site, sidx) * A_MOMENT * MU_B * (
306  h + m_ext_field[site]);
307  *pdu = du;
308 
309  if(du <= 0.0) return 1.0;
310 
311  // probability.
312  return exp(-m_beta*du);
313 }
314 long double
316 {
317  //calculate probabilities.
318  m_sec_cache_enabled = true;
319 
320  double sum_p = 0.0;
321 
322  int current_buffer;
323  if(m_last_flipped_lattice_index >= 0) {
324  // swap buffers.
325  current_buffer = 1 - m_last_probability_buffer;
326  }
327  else {
328  current_buffer = 0;
329  m_play_back_buffer = false;
330  }
331  if(m_play_back_buffer) {
332  for(int site1 = 0; site1 < 16; site1++) {
333  double *pprob = &m_probability_buffers[current_buffer][site1][0];
334  for(int i = 0; i < s_num_spins/16; i++) {
335  sum_p += *(pprob++);
336  }
337  }
338  }
339  else {
340  // iterate target site.
341  for(int site1 = 0; site1 < 16; site1++) {
342  double *pprob = &m_probability_buffers[current_buffer][site1][0];
343  int cnt = s_num_spins/16;
344  for(int lidx = 0; lidx < cnt; lidx++) {
345  double h = hinteraction(site1, lidx);
346  double du = 0.0;
347  double probability = flippingProbability(site1, lidx, h, &du);
348  *pprob = probability;
349  pprob++;
350  sum_p += probability;
351  }
352  }
353  }
354  m_play_back_buffer = false;
355  m_last_probability_buffer = current_buffer;
356 
357  double p_av = sum_p / s_num_spins;
358  if(p_av <= 0.0) return -1;
359  // counts to next flip.
360  long double cnt_d = ceill(log2l(1.0 - randMT19937()) / log2l((long double)1.0 - p_av));
361  if(cnt_d <= 0.0) return -1;
362 // if(cnt_d > 1e4 * m_spins.size()) return -1;
363 // long long int cnt = llrintl(cnt_d);
364 // if(cnt == 0) return 0;
365  // choose target site
366  double p = randMT19937()*sum_p;
367  int lidx = s_num_spins/16 - 1;
368  int site1 = 16;
369  double pit = 0.0;
370  for(int site = 0; site < 16; site++) {
371  double *pprob = &m_probability_buffers[current_buffer][site][0];
372  for(int i = 0; i < s_num_spins/16; i++) {
373  pit += *(pprob++);
374  if(pit >= p) {
375  lidx = i;
376  site1 = site;
377  break;
378  }
379  }
380  if(pit >= p) break;
381  }
382  assert(pit < sum_p * 1.00001);
383  assert(site1 != 16);
384  double du = 0.0;
385  flippingProbability(site1, lidx, hinteraction(site1, lidx), &du);
386  flipSpin(site1, lidx, du, cnt_d);
387 // fprintf(stderr, "Accelerate Flipping done. Skipped tests = %lld\n", cnt);
388 
389  if((m_last_flipped_lattice_index == lidx) && (m_last_flipped_site == site1)) {
390  m_play_back_buffer = true;
391  fprintf(stderr, "0");
392  }
393  else {
394  if(m_last_flipped_lattice_index >= 0) {
395  int size = s_L;
396  int n = lidx;
397  int i1 = n % size;
398  n /= size;
399  int j1 = n % size;
400  n /= size;
401  int k1 = n;
402  n = m_last_flipped_lattice_index;
403  int i2 = n % size;
404  n /= size;
405  int j2 = n % size;
406  n /= size;
407  int k2 = n;
408  VectorInt v = distance(site1, m_last_flipped_site,
409  (i1 - i2 + size) % size, (j1 - j2 + size) % size, (k1 - k2 + size) % size);
410  int d = v.x*v.x + v.y*v.y + v.z*v.z;
411  assert(d > 0);
412  for(int i = 0; i < 10; i++) {
413  if(i == 9) {
414  assert(d >= s_4r2_neighbor[i]);
415  fprintf(stderr, ".");
416  break;
417  }
418  if(s_4r2_neighbor[i] == d) {
419  fprintf(stderr, "%d", i + 1);
420  break;
421  }
422  }
423  if(sum_p > 3.0) {
424  // leave accel flipping mode.
425  m_last_probability_buffer = -1;
426  }
427  }
428  }
429  m_last_flipped_lattice_index = lidx;
430  m_last_flipped_site = site1;
431  return cnt_d;
432 }
433 double
435  bool abondon_cache = (randMT19937() < 0.05);
436  if(abondon_cache) {
437  fprintf(stderr, "Abondon cache.\n");
438  fill(m_field_pri_cached_sane.begin(), m_field_pri_cached_sane.end(), 0);
439  }
440  //internal energy. [J/A-site]
441  double U = 0.0;
442  // iterate target site.
443  for(int site1 = 0; site1 < 16; site1++) {
444  for(int lidx = 0; lidx < s_num_spins/16; lidx++) {
445  double h = 0.0;
446  h = hinteraction(site1, lidx);
447  // interacting field must be half.
448  h *= 0.5;
449  h += m_ext_field[site1];
450  U += -readSpin(site1, spins_real_index(lidx)) * A_MOMENT * MU_B * h;
451  }}
452 
453  U /= s_num_spins;
454  return U;
455 }
456 void
457 MonteCarlo::doTests(int *flips, long double tests)
458 {
459  int flipped = 0;
460  int flipped_checked = 0;
461  m_sec_cache_hit = 0;
462  m_third_cache_hit = 0;
463  m_hinteractions_called = 0;
464  long tested = 0;
465  long tests_after_check = 0;
466  long double tests_accel_flip = 0;
467  long double tests_accel_flip_started = 0;
468  int flipped_accel_flip_started = 0;
469  bool accel_flip = false;
470  for(;;) {
471  if((flipped >= *flips) && (m_SumTests + tests_after_check >= tests)) break;
472  if(s_bAborting) {
473  fprintf(stderr, "Signal caught! Aborting...\n");
474  break;
475  }
476 
477  if(accel_flip) {
478  takeThermalAverage(tests_after_check);
479  tests_after_check = 0;
480  long double adv = accelFlipping();
481  if(adv <= 0) {
482  fprintf(stderr, "Spins are completely freezed!.\n");
483  break;
484  }
485  tests_accel_flip += adv;
486  flipped++;
487  if(m_last_probability_buffer < 0) {
488  fprintf(stderr, "\nSkipped tests = %Lg. Flipped = %d\n",
489  (long double)(tests_accel_flip - tests_accel_flip_started), flipped - flipped_accel_flip_started);
490  accel_flip = false;
491 // activateThreading();
492  }
493  continue;
494  }
495 
496  // pick-up target spin.
497  int idx = (int)floor(randMT19937() * s_num_spins);
498 
499  int site = idx % 16;
500  int lidx = idx / 16;
501 
502  double h = hinteraction(site, lidx);
503 
504  double du = 0.0;
505  double probability = flippingProbability(site, lidx, h, &du);
506 
507  tested++;
508  tests_after_check++;
509 
510  if((probability >= 1) || (randMT19937() < probability)) {
511  flipSpin(site, lidx, du, tests_after_check);
512  tests_after_check = 0;
513  flipped++;
514  }
515 
516  if((tested % s_num_spins == 0) && (tested != 0)) {
517  int flips = flipped - flipped_checked;
518 
519  if(flips <= 0) {
520  fprintf(stderr, "Flipping Acceleration...");
521  accel_flip = true;
522  tests_accel_flip_started = tests_accel_flip;
523  flipped_accel_flip_started = flipped;
524  m_last_flipped_lattice_index = -1;
525  }
526 
527  if(m_third_cache_enabled) {
528  if(m_hinteractions_called > m_sec_cache_hit) {
529  double hit_prob = (double)m_third_cache_hit / (m_hinteractions_called - m_sec_cache_hit) / 16;
530  if(!m_third_cache_firsttime && (hit_prob < THIRD_CACHE_OFF_FACTOR)) {
531  m_third_cache_enabled = false;
532  for(int i = 0; i < 16; i++) {
533  fill(m_field_third_cached_sane[i].begin(), m_field_third_cached_sane[i].end(), 0);
534  }
535  fprintf(stderr, "Flip = %f %%\n", (double)100.0*flips / m_hinteractions_called);
536  fprintf(stderr, "Disable 3rd cache. hit = %f%%\n", 100.0*hit_prob);
537  }
538  m_third_cache_firsttime = false;
539  }
540  }
541  else {
542  double hit_prob_estimate =
543  pow(1.0 - (double)flips / m_hinteractions_called /16 / (s_L*s_L*s_L)
544  * (4.0*M_PI/3.0*s_cutoff_real/2*s_cutoff_real/2*s_cutoff_real/2), (double)s_num_spins);
545  if(hit_prob_estimate > THIRD_CACHE_ON_FACTOR) {
546  m_third_cache_enabled = true;
547  m_third_cache_firsttime = true;
548  fprintf(stderr, "Flip = %f %%\n", (double)100.0*flips / m_hinteractions_called);
549  fprintf(stderr, "Enable 3rd cache. estimate = %f%%\n", 100.0*hit_prob_estimate);
550  }
551  }
552  m_third_cache_hit = 0;
553 
554  if(m_sec_cache_enabled) {
555  double hit_prob = (double)m_sec_cache_hit / (m_hinteractions_called) / 16;
556  if(!m_sec_cache_firsttime && (hit_prob < SEC_CACHE_OFF_FACTOR)) {
557  m_sec_cache_enabled = false;
558  for(int i = 0; i < 16; i++) {
559  fill(m_field_sec_cached_sane[i].begin(), m_field_sec_cached_sane[i].end(), 0);
560  }
561  fprintf(stderr, "Flip = %f %%\n", (double)100.0*flips / m_hinteractions_called);
562  fprintf(stderr, "Disable secondary cache. hit = %f%%\n", 100.0*hit_prob);
563  }
564 // fprintf(stderr, "Secondary cache hit = %f%%\n", 100.0*hit_prob);
565  m_sec_cache_firsttime = false;
566  }
567  else {
568  double hit_prob_estimate =
569  pow(1.0 - (double)flips / m_hinteractions_called /16, (double)s_num_spins);
570  if(hit_prob_estimate > SEC_CACHE_ON_FACTOR) {
571  m_sec_cache_enabled = true;
572  m_sec_cache_firsttime = true;
573  fprintf(stderr, "Flip = %f %%\n", (double)100.0*flips / m_hinteractions_called);
574  fprintf(stderr, "Enable secondary cache. estimate = %f%%\n", 100.0*hit_prob_estimate);
575  }
576  }
577  m_sec_cache_hit = 0;
578 
579  flipped_checked = flipped;
580  m_hinteractions_called = 0;
581  }
582  }
583  if(accel_flip) {
584  fprintf(stderr, "\nSkipped tests = %Lg. Flipped = %d\n",
585  (long double)(tests_accel_flip - tests_accel_flip_started), flipped - flipped_accel_flip_started);
586  }
587  *flips = flipped;
588  takeThermalAverage(tests_after_check);
589 }
590 
591 inline void
592 MonteCarlo::modifyReciprocalImage(Spin diff, int site1, int i, int j, int k)
593 {
594  int cutoff = s_cutoff_rec;
595  int cnt = 2*cutoff + 1;
596  complex<Spin> *pspin = &m_spins_rec[site1][0];
597 
598  Vector3<double> pos1(cg_ASitePositions[site1]);
599  pos1 *= LATTICE_CONST / 4.0;
600  double phx = -2*M_PI / (LATTICE_CONST * s_L) * (i * LATTICE_CONST + pos1.x);
601  double phy = -2*M_PI / (LATTICE_CONST * s_L) * (j * LATTICE_CONST + pos1.y);
602  double phz = -2*M_PI / (LATTICE_CONST * s_L) * (k * LATTICE_CONST + pos1.z);
603  complex<Spin> exp_i_rx = exp(complex<Spin>(0.0, phx));
604  complex<Spin> exp_i_ry = exp(complex<Spin>(0.0, phy));
605  complex<Spin> exp_i_rz = exp(complex<Spin>(0.0, phz));
606 
607  complex<Spin> exp_ikrz = ((Spin)diff)
608  * exp(complex<Spin>(0.0, -cutoff * (phx + phy)));
609  for(int kz = 0; kz <= cutoff; kz++) {
610  complex<Spin> exp_ikryz = exp_ikrz;
611  for(int ky = -cutoff; ky <= cutoff; ky++) {
612  complex<Spin> exp_ikr = exp_ikryz;
613  for(int n = 0; n < cnt; n++) {
614  pspin[n] += exp_ikr;
615  exp_ikr *= exp_i_rx;
616  }
617  pspin+=cnt;
618  exp_ikryz *= exp_i_ry;
619  }
620  exp_ikrz *= exp_i_rz;
621  }
622  assert(pspin == &*m_spins_rec[site1].end());
623 }
624 void
625 MonteCarlo::makeReciprocalImage()
626 {
627  int cutoff = s_cutoff_rec;
628  if(!cutoff) return;
629  for(int site = 0; site < 16; site++) {
630  m_spins_rec[site].clear();
631  m_spins_rec[site].resize((2*cutoff+1)*(2*cutoff+1)*(cutoff+1), 0.0);
632  for(int k = 0; k < s_L; k++) {
633  for(int j = 0; j < s_L; j++) {
634  for(int i = 0; i < s_L; i++) {
635  modifyReciprocalImage(readSpin(site, spins_real_index(i,j,k)), site, i, j, k);
636  }
637  }
638  }
639  }
640 }
641 void
642 MonteCarlo::flipSpin(int site1, int lidx, double du, long double tests_after_check)
643 {
644  takeThermalAverage(tests_after_check);
645 
646  m_DeltaU += du;
647 
648  int sidx = spins_real_index(lidx);
649  Spin oldv = readSpin(site1, sidx);
650  int n = lidx;
651  int i = n % s_L;
652  n /= s_L;
653  int j = n % s_L;
654  n /= s_L;
655  int k = n;
656  modifyReciprocalImage(-2*oldv, site1, i, j, k);
657  // flip spin. keep repeated image.
658  writeSpin(-oldv, site1, sidx);
659  assert(spins_real_index(i,j,k) == sidx);
660 
661  FlipHistory hist;
662  hist.lidx = lidx;
663  hist.site = site1;
664  hist.delta = -2*oldv;
665  hist.tests = (m_SumTests - m_SumTestsAtLastFlip);
666  m_flipHistory.push_back(hist);
667  m_SumTestsAtLastFlip = m_SumTests;
668 
669  //set dirty flags to caches.
670  fill(m_field_pri_cached_sane.begin(), m_field_pri_cached_sane.end(), 0);
671  if(m_sec_cache_enabled) {
672  fill(m_field_sec_cached_sane[site1].begin(), m_field_sec_cached_sane[site1].end(), 0);
673  }
674  if(m_third_cache_enabled) {
675  int size = s_L;
676  int dist = s_cutoff_real;
677  int r2bound = dist*dist;
678  uint16_t *p0 = &m_field_third_cached_sane[site1][0];
679  for(int dk = -dist; dk <= dist; dk++) {
680  int dk2 = abs(dk) - 1;
681  dk2 = dk2*dk2;
682  uint16_t *p_k = p0 + lattice_index(0, 0, (k + dk + size) % size);
683  for(int dj = -dist; dj <= dist; dj++) {
684  int dj2 = abs(dj) - 1;
685  dj2 = dk2 + dj2*dj2;
686  uint16_t *p_j = p_k + lattice_index(0, (j + dj + size) % size, 0);
687  for(int di = -dist; di <= dist; di++) {
688  int di2 = abs(di) - 1;
689  int r2 = dj2 + di2*di2;
690  if(r2 <= r2bound) {
691  p_j[lattice_index((i + di + size) % size, 0, 0)] = 0;
692  }
693  }
694  }
695  }
696  }
697 
698 }
699 void
700 MonteCarlo::write(char *data, double *fields, double *probabilities)
701 {
702  for(int site = 0; site < 16; site++) {
703  for(int k1 = 0; k1 < s_L; k1++) {
704  for(int j1 = 0; j1 < s_L; j1++) {
705  for(int i1 = 0; i1 < s_L; i1++) {
706  *(data++) = lrint(readSpin(site, spins_real_index(i1,j1,k1)));
707  if(fields) {
708  int lidx = lattice_index(i1,j1,k1);
709  double h = hinteraction(site, lidx);
710  *(fields++) = h;
711  if(probabilities) {
712  double du;
713  double probability = flippingProbability(site, lidx, h, &du);
714  *(probabilities++) = probability;
715  }
716  }
717  }
718  }
719  }
720  }
721 }
722 void
723 MonteCarlo::write_bsite(Vector3<double> *fields)
724 {
725  for(int site = 0; site < 16; site++) {
726  for(int k1 = 0; k1 < s_L; k1++) {
727  for(int j1 = 0; j1 < s_L; j1++) {
728  for(int i1 = 0; i1 < s_L; i1++) {
729  Vector3<double> h;
730  h += iterate_real_generic(s_fields_real_B[site], i1, j1, k1);
731  Vector3<double> pos(cg_BSitePositions[site]);
732  pos *= 1.0/4.0;
733  h += iterate_rec_generic(pos, i1, j1, k1);
734  *(fields++) = h;
735  }
736  }
737  }
738  }
739 }
740 void
741 MonteCarlo::write_8asite(Vector3<double> *fields)
742 {
743  for(int site = 0; site < 8; site++) {
744  for(int k1 = 0; k1 < s_L; k1++) {
745  for(int j1 = 0; j1 < s_L; j1++) {
746  for(int i1 = 0; i1 < s_L; i1++) {
747  Vector3<double> h;
748  h += iterate_real_generic(s_fields_real_8a[site], i1, j1, k1);
749  Vector3<double> pos(cg_8aSitePositions[site]);
750  pos *= 1.0/8.0;
751  h += iterate_rec_generic(pos, i1, j1, k1);
752  *(fields++) = h;
753  }
754  }
755  }
756  }
757 }
758 void
759 MonteCarlo::write_48fsite(Vector3<double> *fields)
760 {
761  for(int site = 0; site < 48; site++) {
762  for(int k1 = 0; k1 < s_L; k1++) {
763  for(int j1 = 0; j1 < s_L; j1++) {
764  for(int i1 = 0; i1 < s_L; i1++) {
765  Vector3<double> h;
766  h += iterate_real_generic(s_fields_real_48f[site], i1, j1, k1);
767  Vector3<double> pos(cg_48fSitePositions[site]);
768  pos *= 1.0/8.0;
769  h += iterate_rec_generic(pos, i1, j1, k1);
770  *(fields++) = h;
771  }
772  }
773  }
774  }
775 }
776 void
777 MonteCarlo::write_flips(std::deque<FlipHistory> &buf) {
778  buf.resize(m_flipHistory.size());
779  std::copy(m_flipHistory.begin(), m_flipHistory.end(), buf.begin());
780 }
781 
782 void
783 MonteCarlo::read(const char *data, double temp, Vector3<double> field)
784 {
785  m_beta = 1.0/K_B/temp;
786 
787  for(int site1 = 0; site1 < 16; site1++) {
788  m_ext_field[site1] = field.innerProduct(s_ASiteIsingVector[site1]);
789  }
790 
791  for(int site = 0; site < 16; site++) {
792  for(int k1 = 0; k1 < s_L; k1++) {
793  for(int j1 = 0; j1 < s_L; j1++) {
794  for(int i1 = 0; i1 < s_L; i1++) {
795  writeSpin(*(data++), site, spins_real_index(i1,j1,k1));
796  }
797  }
798  }
799  if(m_sec_cache_enabled)
800  fill(m_field_sec_cached_sane[site].begin(), m_field_sec_cached_sane[site].end(), 0);
801  if(m_third_cache_enabled)
802  fill(m_field_third_cached_sane[site].begin(), m_field_third_cached_sane[site].end(), 0);
803  }
804  fill(m_field_pri_cached_sane.begin(), m_field_pri_cached_sane.end(), 0);
805  makeReciprocalImage();
806 }

Generated for KAME4 by  doxygen 1.8.3