Path Integral Quantum Monte Carlo
move.cpp
Go to the documentation of this file.
1 
8 #include "move.h"
9 #include "path.h"
10 #include "action.h"
11 #include "lookuptable.h"
12 #include "communicator.h"
13 #include "factory.h"
14 
17 
18 /**************************************************************************/
21 /* Factory<MoveBase* (Path &, ActionBase*, MTRand&)> MoveFactory; */
23 #define REGISTER_MOVE(NAME,TYPE) \
24  const string TYPE::name = NAME;\
25  bool reg ## TYPE = moveFactory()->Register<TYPE>(TYPE::name);
26 
27 /**************************************************************************/
33 REGISTER_MOVE("displace",DisplaceMove)
34 REGISTER_MOVE("end staging",EndStagingMove)
35 REGISTER_MOVE("mid staging",MidStagingMove)
36 REGISTER_MOVE("swap break",SwapBreakMove)
37 REGISTER_MOVE("center of mass",CenterOfMassMove)
38 REGISTER_MOVE("staging",StagingMove)
39 REGISTER_MOVE("bisection",BisectionMove)
40 REGISTER_MOVE("open",OpenMove)
41 REGISTER_MOVE("close",CloseMove)
42 REGISTER_MOVE("insert",InsertMove)
43 REGISTER_MOVE("remove",RemoveMove)
44 REGISTER_MOVE("advance head",AdvanceHeadMove)
45 REGISTER_MOVE("recede head",RecedeHeadMove)
46 REGISTER_MOVE("advance tail",AdvanceTailMove)
47 REGISTER_MOVE("recede tail",RecedeTailMove)
48 REGISTER_MOVE("swap head",SwapHeadMove)
49 REGISTER_MOVE("swap tail",SwapTailMove)
50 
51 // ---------------------------------------------------------------------------
52 // ---------------------------------------------------------------------------
53 // MOVE BASE CLASS -----------------------------------------------------------
54 // ---------------------------------------------------------------------------
55 // ---------------------------------------------------------------------------
56 
57 /*************************************************************************/
60 MoveBase::MoveBase (Path &_path, ActionBase *_actionPtr, MTRand &_random,
61  ensemble _operateOnConfig, bool _varLength) :
62  operateOnConfig(_operateOnConfig),
63  variableLength(_varLength),
64  path(_path),
65  actionPtr(_actionPtr),
66  random(_random) {
67 
68  /* Initialize private data to zero */
69  numAccepted = numAttempted = numToMove = 0;
70  success = false;
71 
72  /* Setup the move attempt/accept arrays */
73  int b = int (ceil(log(1.0*constants()->Mbar()) / log(2.0)-EPS));
74  numAcceptedLevel.resize(b+1);
75  numAttemptedLevel.resize(b+1);
76 
77  numAcceptedLevel = 0;
78  numAttemptedLevel = 0;
79 
80  sqrtLambdaTau = sqrt(constants()->lambda() * constants()->tau());
81  sqrt2LambdaTau = sqrt(2.0)*sqrtLambdaTau;
82 
83  /* Setup the free density matrix arrays for sampling different
84  * winding sectors. We will sample w = -maxWind ... maxWind */
85  maxWind = constants()->maxWind();
86  numWind = ipow(2*maxWind + 1,NDIM);
87 
88  /* initialize the cumulative probability distribution */
89  cumrho0.resize(numWind);
90 
91  /* For each integer labelling a winding sector, we construct the winding
92  * vector and append to a matrix */
93  iVec wind;
94  for (int n = 0; n < numWind; n++ ) {
95  for (int i = 0; i < NDIM; i++) {
96  int scale = 1;
97  for (int j = i+1; j < NDIM; j++)
98  scale *= (2*maxWind + 1);
99  wind[i] = (n/scale) % (2*maxWind + 1);
100 
101  /* Wrap into the appropriate winding sector */
102  wind[i] -= (wind[i] > maxWind)*(2*maxWind + 1);
103  }
104 
105  /* Adjust for any non-periodic boundary conditions */
106  for (int i = 0; i < NDIM; i++) {
107  if (!path.boxPtr->periodic[i])
108  wind[i] = 0;
109  }
110 
111  /* Store the winding number */
112  winding.push_back(wind);
113  }
114 
115  /* Now we would like to sort the winding number array for the effecient
116  * calculation of maximal probabilities. We sort based on the winding
117  * sector. */
118  std::stable_sort(winding.begin(), winding.end(), [](const iVec& w1, const iVec& w2) {
119  return blitz::max(abs(w1)) < blitz::max(abs(w2));
120  /* return (blitz::dot(w1,w1) < blitz::dot(w2,w2)); */
121  });
122 
123  /* Now we determine the indices of the different winding sectors. These
124  * are used for optimization purposes during tower sampling */
125  for (int n = 0; n < numWind-1; n++) {
126  /* if (abs(dot(winding(n),winding(n)) - dot(winding(n+1),winding(n+1))) > EPS) */
127  if ( abs( max(abs(winding[n+1])) - max(abs(winding[n])) ) > EPS)
128  windingSector.push_back(n);
129  }
130  /* Add the last index */
131  if (windingSector.back() != numWind-1)
132  windingSector.push_back(numWind-1);
133 }
134 
135 /*************************************************************************/
139  originalPos.free();
140 }
141 
143 /*************************************************************************/
147 inline void MoveBase::printMoveState(string state) {
148 #ifdef DEBUG_WORM
149 
150  /* We make a list of all the beads contained in the worm */
151  Array <beadLocator,1> wormBeads; // Used for debugging
152  wormBeads.resize(path.worm.length+1);
153  wormBeads = XXX;
154 
155  /* Output the worldline configuration */
156  communicate()->file("debug")->stream() << "Move State: " << state
157  << " (" << path.getTrueNumParticles() << ")" << endl;
158  communicate()->file("debug")->stream() << "head " << path.worm.head[0] << " " << path.worm.head[1]
159  << " tail " << path.worm.tail[0] << " " << path.worm.tail[1]
160  << " length " << path.worm.length
161  << " gap " << path.worm.gap << endl;
162 
163  if (!path.worm.isConfigDiagonal) {
164  beadLocator beadIndex;
165  beadIndex = path.worm.tail;
166  int n = 0;
167  do {
168  wormBeads(n) = beadIndex;
169  beadIndex = path.next(beadIndex);
170  ++n;
171  } while(!all(beadIndex==path.next(path.worm.head)));
172  }
173 
174  path.printWormConfig(wormBeads);
175  path.printLinks<fstream>(communicate()->file("debug")->stream());
176  wormBeads.free();
177 #endif
178 }
179 
180 /*************************************************************************/
188 inline void MoveBase::checkMove(int callNum, double diffA) {
189 #ifdef DEBUG_MOVE
190  /* The first time we call, we calculate the kinetic and potential action */
191  if (callNum == 0) {
194  }
195 
196  /* The second time, we compute the updated values and compare. This would
197  * be used after a keep move */
198  if (callNum == 1) {
199  newV = actionPtr->potentialAction();
200  newK = actionPtr->kineticAction();
201  double diffV = newV - oldV;
202  if (abs(diffV-diffA) > EPS) {
203  communicate()->file("debug")->stream() << format("%-16s%16.6e\t%16.6e\t%16.6e\n") % getName()
204  % diffV % diffA % (diffV - diffA);
205  // communicate()->file("debug")->stream() << path.worm.beads << endl;
206  // communicate()->file("debug")->stream() << path.prevLink << endl;
207  // communicate()->file("debug")->stream() << path.nextLink << endl;
208  cout << getName() << " PROBLEM WITH KEEP " << diffV << " " << diffA << endl;
209  exit(EXIT_FAILURE);
210  }
211  }
212 
213  /* The third time would be used after an undo move */
214  if (callNum == 2) {
215  newV = actionPtr->potentialAction();
216  newK = actionPtr->kineticAction();
217  double diffV = newV - oldV;
218  double diffK = newK - oldK;
219  if ( (abs(diffV) > EPS) || abs(diffK) > EPS) {
220  communicate()->file("debug")->stream() << format("%-16s%16.6e\t%16.6e\n") % getName()
221  % diffV % diffK;
222  // communicate()->file("debug")->stream() << path.worm.beads << endl;
223  // communicate()->file("debug")->stream() << path.prevLink << endl;
224  // communicate()->file("debug")->stream() << path.nextLink << endl;
225  cout << getName() << " PROBLEM WITH UNDO " << diffV << " " << diffK << endl;
226  exit(EXIT_FAILURE);
227  }
228  }
229 
230  /* This call is used to debug the distributions in the changes in potential
231  * and kinetic energy per particle. diffA is the number of beads touched
232  * in the move here.*/
233  if (callNum == -1) {
234  newV = actionPtr->potentialAction();
235  newK = actionPtr->kineticAction();
236  double diffV = newV - oldV;
237  communicate()->file("debug")->stream() << format("%-16s%16.6e\t%16.6e\n") % getName()
238  % ((newK-oldK)/diffA) % ((diffV)/diffA);
239  }
240 #endif
241 }
243 
244 /*************************************************************************/
249  numAccepted++;
250  totAccepted++;
251 
252  /* Restore the shift level for the time step to 1 */
253  actionPtr->setShift(1);
254 
255  success = true;
256 }
257 
258 /*************************************************************************/
268 dVec MoveBase::newStagingPosition(const beadLocator &neighborIndex, const beadLocator &endIndex,
269  const int stageLength, const int k) {
270 
271  PIMC_ASSERT(path.worm.beadOn(neighborIndex));
272 
273  /* The rescaled value of lambda used for staging */
274  double f1 = 1.0 * (stageLength - k - 1);
275  double f2 = 1.0 / (1.0*(stageLength - k));
276  double sqrtLambdaKTau = sqrt2LambdaTau * sqrt(f1 * f2);
277 
278  /* We find the new 'midpoint' position which exactly samples the kinetic
279  * density matrix */
280  neighborPos = path(neighborIndex);
281  newRanPos = path(endIndex) - neighborPos;
283  newRanPos *= f2;
285 
286  /* This is the random kick around that midpoint */
287  for (int i = 0; i < NDIM; i++)
288  newRanPos[i] = random.randNorm(newRanPos[i],sqrtLambdaKTau);
289 
291 
292  return newRanPos;
293 }
294 
295 /*************************************************************************/
305 dVec MoveBase::newStagingPosition(const beadLocator &neighborIndex, const beadLocator &endIndex,
306  const int stageLength, const int k, iVec &wind) {
307 
308  PIMC_ASSERT(path.worm.beadOn(neighborIndex));
309 
310  /* The rescaled value of lambda used for staging */
311  double f1 = 1.0 * (stageLength - k - 1);
312  double f2 = 1.0 / (1.0*(stageLength - k));
313  double sqrtLambdaKTau = sqrt2LambdaTau * sqrt(f1 * f2);
314 
315  /* We find the new 'midpoint' position which exactly samples the kinetic
316  * density matrix */
317  neighborPos = path(neighborIndex);
318  newRanPos = (path(endIndex)+path.boxPtr->side*wind)-neighborPos;
319  newRanPos *= f2;
321 
322  /* This is the random kick around that midpoint */
323  for (int i = 0; i < NDIM; i++)
324  newRanPos[i] = random.randNorm(newRanPos[i],sqrtLambdaKTau);
325 
326  /* Make sure we choose the correct winding trajectory */
327  for (int i = 0; i < NDIM; i++) {
328  while (newRanPos[i] < -0.5*path.boxPtr->side[i])
329  {
330  wind[i]++;
331  newRanPos[i] += path.boxPtr->side[i];
332  }
333  while (newRanPos[i] >= 0.5*path.boxPtr->side[i])
334  {
335  wind[i]--;
336  newRanPos[i] -= path.boxPtr->side[i];
337  }
338  }
339 
341  assert(newRanPos[0] < 0.5*path.boxPtr->side[0] || newRanPos[0] >= -0.5*path.boxPtr->side[0]);
342 
343  return newRanPos;
344 }
345 
346 /*************************************************************************/
357 iVec MoveBase::sampleWindingSector(const beadLocator &startBead, const beadLocator &endBead,
358  const int stageLength, double &totalrho0) {
359 
360  /* For now, we hard-code the tolerance at 0.001% */
361  /* double tolerance = 1.0E-6; */
362 
363  /* Get the w = 0 sector separation */
364  dVec vel,velW;
365  vel = path(endBead) - path(startBead);
366 
367  /* If we aren't sampling winding sectors we always
368  * get the min sector. */
369  /* path.boxPtr->putInBC(vecl); */
370 
371  /* Initialize the probability and cumulative probabilities */
372  /* fill(cumrho0.begin(), cumrho0.end(), 0); */
373  cumrho0[0] = actionPtr->rho0(vel,stageLength);
374  totalrho0 = cumrho0[0];
375 
376  /* Sample the free density matrix for different winding sectors */
377  for (int n = 1; n < numWind; n++) {
378  velW = vel + winding.at(n)*path.boxPtr->side;
379  double crho0 = actionPtr->rho0(velW,stageLength);
380  totalrho0 += crho0;
381  cumrho0[n] = cumrho0[n-1] + crho0;
382  }
383 
384  /* Normalize the cumulative probability */
385  for (auto& crho0 : cumrho0)
386  crho0 /= totalrho0;
387 
388  /* for (uint32 n = 0; n < cumrho0.size(); ++n) */
389  /* cumrho0[n] /= totalrho0; */
390 
391  /* Perform tower sampling to select the winding vector */
392  int index;
393  index = std::lower_bound(cumrho0.begin(),cumrho0.end(),random.rand())
394  - cumrho0.begin();
395 
396  return winding.at(index);
397 }
398 
399 /*************************************************************************/
409 iVec MoveBase::getWindingNumber(const beadLocator &startBead, const beadLocator &endBead) {
410 
411  iVec wind;
412  wind = 0;
413  beadLocator beadIndex;
414  beadIndex = startBead;
415  dVec vel;
416  do {
417  /* Get the vector separation */
418  vel = path(path.next(beadIndex)) - path(beadIndex);
419 
420  for (int i = 0; i < NDIM; i++) {
421 
422  /* Only worry about the winding number for PBC */
423  if (path.boxPtr->periodic[i]) {
424  if (vel[i] < -0.5*path.boxPtr->side[i])
425  ++wind[i];
426  if (vel[i] >= 0.5*path.boxPtr->side[i])
427  --wind[i];
428  }
429  }
430 
431  beadIndex = path.next(beadIndex);
432  } while (!all(beadIndex==endBead));
433 
434  return wind;
435 }
436 
437 /*************************************************************************/
449 
450  PIMC_ASSERT(path.worm.beadOn(neighborIndex));
451 
452  /* The Gaussian distributed random position */
453  for (int i = 0; i < NDIM; i++)
454  newRanPos[i] = random.randNorm(path(neighborIndex)[i],sqrt2LambdaTau);
455 
457 
458  return newRanPos;
459 }
460 
461 /*************************************************************************/
470  const int lshift) {
471 
472  /* The size of the move */
473  double delta = sqrtLambdaTau*sqrt(1.0*lshift);
474 
475  /* We first get the index and position of the 'previous' neighbor bead */
476  nBeadIndex = path.prev(beadIndex,lshift);
477 
478  /* We now get the midpoint between the previous and next beads */
479  newRanPos = path.getSeparation(path.next(beadIndex,lshift),nBeadIndex);
480  newRanPos *= 0.5;
482 
483  /* This is the gausian distributed random kick around that midpoint */
484  for (int i = 0; i < NDIM; i++)
485  newRanPos[i] = random.randNorm(newRanPos[i],delta);
486 
487  /* Put in PBC and return */
489  return newRanPos;
490 }
491 
492 // ---------------------------------------------------------------------------
493 // ---------------------------------------------------------------------------
494 // DISPLACE MOVE CLASS -------------------------------------------------------
495 // ---------------------------------------------------------------------------
496 // ---------------------------------------------------------------------------
497 
498 /*************************************************************************/
504  MTRand &_random, ensemble _operateOnConfig) :
505  MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
506 
507  /* Initialize private data to zera */
509 
510  /* For a simple displacement move, we will only move one particle
511  * at a time, and thus only need to store one original position at
512  * a time. */
513  originalPos.resize(1);
514 }
515 
516 DisplaceMove::~DisplaceMove() {
517 }
518 
519 
520 /*************************************************************************/
524 
525  success = false;
526  bool start = false;
527 
528  /* Only perform a move if we have beads */
529  if (path.worm.getNumBeadsOn() == 0)
530  return success;
531 
532  /* Randomly select the bead to be moved, either the head or tail */
533  if (random.rand() < 0.5) {
534  beadIndex[0] = 0;
535  start = true;
536  }
537  else {
538  beadIndex[0] = constants()->numTimeSlices()-1;
539  start = false;
540  }
541 
542  /* We now select the worldline that will be updated */
543  beadIndex[1] = random.randInt(path.numBeadsAtSlice(beadIndex[0])-1);
544 
545  /* If path is broken, select which end to move */
546  if ( (path.breakSlice > 0) && (random.rand() < 0.5) ){
547  /* Check if worldline is broken */
548  beadLocator brokenBead = beadIndex;
549  if ( beadIndex[0] == 0){
550  while( !all(path.next(brokenBead)==XXX) ){
551  brokenBead = path.next(brokenBead);
552  if ( brokenBead[0] == path.breakSlice ){
553  if ( all(path.next(brokenBead)==XXX ) ) {
554  beadIndex = brokenBead;
555  start = false;
556  }
557  }
558  }
559  }else{
560  while( !all(path.prev(brokenBead)==XXX) ){
561  brokenBead = path.prev(brokenBead);
562  if ( brokenBead[0] == path.breakSlice+1 ){
563  if ( all(path.prev(brokenBead)==XXX ) ) {
564  beadIndex = brokenBead;
565  start = true;
566  }
567  }
568  }
569  }
570  }
571 
572  /* Make sure the bead is turned on, otherwise skip the move */
573  if (path.worm.beadOn(beadIndex)) {
574 
575  /* Increment the number of displacement moves and the total number
576  * of moves */
577  numAttempted++;
578  totAttempted++;
579 
580  checkMove(0,0);
581 
582  /* We need to distinguish between local and non-local actions for
583  * effeciency */
584 
585  /* Compute the total action, a single bead is involved in two
586  * pieces of the kinetic action */
587  oldAction = actionPtr->kineticAction(beadIndex);
588  if (actionPtr->local)
589  oldAction += actionPtr->potentialAction(beadIndex);
590  else {
591  /* Determine if we are starting from or finishing at a path end */
592  if (start)
593  oldAction += actionPtr->potentialAction(beadIndex,path.next(beadIndex));
594  else
595  oldAction += actionPtr->potentialAction(path.prev(beadIndex),beadIndex);
596  }
597 
598  /* Save the old position of the particle */
599  originalPos(0) = path(beadIndex);
600 
601  /* Generate a new random position for our particle */
603 
604  /* Compute the new part of the potential action */
605  newAction = actionPtr->kineticAction(beadIndex);
606 
607  /* We need to make the same distinction between local and non-local
608  * actions */
609  if (actionPtr->local)
610  newAction += actionPtr->potentialAction(beadIndex);
611  else {
612  /* Determine if we are starting from or finishing at a path end */
613  if (start)
614  newAction += actionPtr->potentialAction(beadIndex,path.next(beadIndex));
615  else
616  newAction += actionPtr->potentialAction(path.prev(beadIndex),beadIndex);
617  }
618 
619  /* The metropolis acceptance step */
620  if (random.rand() < exp(-(newAction - oldAction))) {
621  keepMove();
622  checkMove(1,newAction-oldAction);
623  }
624  else {
625  undoMove();
626  checkMove(2,0);
627  }
628 
629  } // if beadOn
630  else
631  success = false;
632 
633  return success;
634 }
635 
636 /*************************************************************************/
639 void DisplaceMove::undoMove() {
640  path.updateBead(beadIndex,originalPos(0));
641  success = false;
642 }
643 
644 
645 // ---------------------------------------------------------------------------
646 // ---------------------------------------------------------------------------
647 // END STAGING MOVE CLASS -------------------------------------------------------
648 // ---------------------------------------------------------------------------
649 // ---------------------------------------------------------------------------
650 
651 /*************************************************************************/
657  MTRand &_random, ensemble _operateOnConfig) :
658 MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
659 
660  /* Initialize private data to zera */
662 
663  /* We will perform staging moves of length Mbar/2 on the ends */
664  originalPos.resize(constants()->Mbar()/2);
665 }
666 
667 EndStagingMove::~EndStagingMove() {
668 }
669 
670 
671 /*************************************************************************/
675 
676  beadLocator beadIndex;
677  beadLocator pivotIndex; // The bead adjacent to the update that is fixed
678  beadLocator neighborIndex;
679  success = false;
680  bool movedIntoSubregionB;
681 
682  /* Randomly select the bead to be moved, either the head or tail */
683  if (random.rand() < 0.5) {
684  beadIndex[0] = 0;
685  beadIndex[1] = random.randInt(path.numBeadsAtSlice(beadIndex[0])-1);
686  leftMoving = true;
687  leftBead = beadIndex;
688 
689  }
690  else {
691  beadIndex[0] = constants()->numTimeSlices()-1;
692  beadIndex[1] = random.randInt(path.numBeadsAtSlice(beadIndex[0])-1);
693  leftMoving = false;
694  rightBead = beadIndex;
695  }
696 
697  /* If path is broken, select which end to move */
698  if ( (path.breakSlice > 0 ) && (random.rand() < 0.5) ){
699  /* Check if worldline is broken */
700  beadLocator brokenBead = beadIndex;
701 
702  if ( beadIndex[0] == 0){
703  while( !all(path.next(brokenBead)==XXX) ){
704  brokenBead = path.next(brokenBead);
705  if ( brokenBead[0] == path.breakSlice ){
706  if ( all(path.next(brokenBead)==XXX ) ){
707  leftMoving = false;
708  rightBead = brokenBead;
709  }
710  }
711  }
712  }
713  else {
714  while( !all(path.prev(brokenBead)==XXX) ){
715  brokenBead = path.prev(brokenBead);
716  if ( brokenBead[0] == path.breakSlice+1 ){
717  if ( all(path.prev(brokenBead)==XXX ) ){
718  leftMoving = true;
719  leftBead = brokenBead;
720  }
721  }
722  }
723  }
724  }
725 
726  /* Now we have to make sure that we are moving an active trajectory,
727  * otherwise we exit immediatly */
728  if (leftMoving){
729  /* For a left moving update, rightBead is prev(pivotIndex) */
730  beadIndex = leftBead;
731  for (int k = 0; k < (constants()->Mbar()/2); k++) {
732  if (!path.worm.beadOn(beadIndex) || all(path.next(beadIndex)==XXX))
733  return false;
734  beadIndex = path.next(beadIndex);
735  }
736  pivotIndex = beadIndex;
737  rightBead = path.prev(pivotIndex);
738  }else{
739  /* For a right moving update, leftBead is next(pivotIndex) */
740  beadIndex = rightBead;
741  for (int k = 0; k < (constants()->Mbar()/2); k++) {
742  if (!path.worm.beadOn(beadIndex) || all(path.prev(beadIndex)==XXX))
743  return false;
744  beadIndex = path.prev(beadIndex);
745  }
746  pivotIndex = beadIndex;
747  leftBead = path.next(pivotIndex);
748  }
749 
750  /* If we haven't found the worm head, and all beads are on, try to perform the move */
751 
752  /* Increment the attempted counters */
753  numAttempted++;
754  totAttempted++;
755 
756  /* Get the current action for the path segment to be updated */
757  oldAction = actionPtr->potentialAction(leftBead,rightBead);
758 
759  /* Perorm the staging update, generating the new path and updating bead
760  * positions, while storing the old one */
761  movedIntoSubregionB = false;
762  if (leftMoving){
763  neighborIndex = pivotIndex;
764  int k = originalPos.size()-1;
765  dVec pos;
766  do {
767  beadIndex = path.prev(neighborIndex);
768  originalPos(k) = path(beadIndex);
769  path.updateBead(beadIndex,newFreeParticlePosition(neighborIndex));
770  movedIntoSubregionB = path.inSubregionB(beadIndex);
771  --k;
772  neighborIndex = beadIndex;
773  } while (!all(path.prev(neighborIndex)==XXX));
774  }else{
775  neighborIndex = pivotIndex;
776  int k = 0;
777  dVec pos;
778  do {
779  beadIndex = path.next(neighborIndex);
780  originalPos(k) = path(beadIndex);
781  path.updateBead(beadIndex,newFreeParticlePosition(neighborIndex));
782  movedIntoSubregionB = path.inSubregionB(beadIndex);
783  ++k;
784  neighborIndex = beadIndex;
785  } while (!all(path.next(neighborIndex)==XXX));
786 
787  }
788 
789  /* Continue with update only if end has not moved into subRegionB */
790  if (!movedIntoSubregionB){
791 
792  /* Get the new action for the updated path segment */
793  newAction = actionPtr->potentialAction(leftBead,rightBead);
794 
795  /* The metropolis acceptance step */
796  if (random.rand() < exp(-(newAction - oldAction))) {
797  keepMove();
798  }
799  else {
800  undoMove();
801  }
802  }else {
803  undoMove();
804  }
805 
806  return success;
807 }
808 
809 /*************************************************************************/
812 void EndStagingMove::undoMove() {
813  int k = 0;
814  beadLocator beadIndex;
815  beadIndex = leftBead;
816  path.updateBead(beadIndex,originalPos(k));
817  while (!all(beadIndex==rightBead)){
818  beadIndex = path.next(beadIndex);
819  ++k;
820  path.updateBead(beadIndex,originalPos(k));
821  }
822 
823  success = false;
824 }
825 
826 // ---------------------------------------------------------------------------
827 // ---------------------------------------------------------------------------
828 // MID-STAGING MOVE CLASS -------------------------------------------------------
829 // ---------------------------------------------------------------------------
830 // ---------------------------------------------------------------------------
831 
832 /*************************************************************************/
838  MTRand &_random, ensemble _operateOnConfig) :
839 MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
840 
841  /* Initialize private data to zera */
843 
844  /* We will perform staging moves of length Mbar in the middle of the path */
845  originalPos.resize(constants()->Mbar());
846 }
847 
848 MidStagingMove::~MidStagingMove() {
849 }
850 
851 /*************************************************************************/
855 
856  beadLocator beadIndex;
857  beadLocator pivotIndex; // The bead adjacent to the update that is fixed
858  beadLocator neighborIndex;
859 
860  success = false;
861  bool startBreak; // Whether the update path starts broken
862  bool endBreak; // Whether the update path end broken
863  double centerWeightInit; // Initial weight of center slice
864  double centerWeightFinal; // Final weight of center slice after update
865 
866  /* Randomly select the bead to be moved on the left */
867  beadIndex[0] = path.breakSlice-constants()->Mbar()/2+1;
868  beadIndex[1] = random.randInt(path.numBeadsAtSlice(beadIndex[0])-1);
869  leftBead = beadIndex;
870 
871  /* Check if worldline is broken */
872  while( (!all(path.next(beadIndex)==XXX)) && (beadIndex[0] != path.breakSlice) ){
873  beadIndex = path.next(beadIndex);
874  }
875  midBeadL = beadIndex;
876  startBreak = all(path.next(midBeadL)==XXX);
877 
878  double totalrho0;
879  iVec wind;
880  /* Choose right path to update */
881  if( startBreak){
882  midBeadR[0] = path.breakSlice + 1;
883  midBeadR[1] = path.brokenWorldlinesR[random.randInt(path.brokenWorldlinesR.size()-1)];
884  wind = sampleWindingSector(midBeadL,midBeadR,1,totalrho0);
885  centerWeightInit = 1.0/totalrho0;
886  } else {
887  midBeadR = path.next(beadIndex);
888  centerWeightInit = 1.0;
889  }
890 
891  /* Move Mbar/2-1 stepts to rightBead */
892  beadIndex = midBeadR;
893  while( (!all(path.next(beadIndex)==XXX))
894  &&(beadIndex[0] != path.breakSlice+constants()->Mbar()/2) ){
895  beadIndex = path.next(beadIndex);
896  }
897  rightBead = beadIndex;
898 
899  /* Increment the attempted counters */
900  numAttempted++;
901  totAttempted++;
902 
903  /* Get the winding sector to sample */
904  wind = sampleWindingSector(path.prev(leftBead),path.next(rightBead),constants()->Mbar()+1,totalrho0);
905 
906  /* Get the current action for the path segment to be updated */
907  oldAction = actionPtr->potentialAction(leftBead,midBeadL);
908  oldAction += actionPtr->potentialAction(midBeadR,rightBead);
909 
910  /* Perform the staging update, generating the new path and updating bead
911  * positions, while storing the old one */
912  beadIndex = path.prev(leftBead);
913  int k = 0;
914  dVec pos;
915  do {
916  beadIndex = path.next(beadIndex);
917  originalPos(k) = path(beadIndex);
918  path.updateBead(beadIndex,
919  newStagingPosition(path.prev(beadIndex),path.next(rightBead),constants()->Mbar()+1,k,wind));
920  ++k;
921  } while (!all(beadIndex==midBeadL));
922 
923  beadIndex = midBeadR;
924  originalPos(k) = path(beadIndex);
925  path.updateBead(beadIndex,
926  newStagingPosition(midBeadL,path.next(rightBead),constants()->Mbar()+1,k,wind));
927 
928  k++;
929 
930  while (!all(beadIndex==rightBead)){
931  beadIndex = path.next(beadIndex);
932  originalPos(k) = path(beadIndex);
933 
934  path.updateBead(beadIndex,
935  newStagingPosition(path.prev(beadIndex),path.next(rightBead),constants()->Mbar()+1,k,wind));
936  ++k;
937  };
938 
939  /* check if midBead R in A*/
940  endBreak = path.inSubregionA(midBeadR);
941 
942  if (endBreak){
943  wind = sampleWindingSector(midBeadL,midBeadR,1,totalrho0);
944  centerWeightFinal = 1.0/totalrho0;
945  }else{
946  centerWeightFinal = 1.0;
947  }
948 
949  /* Get the new action for the updated path segment */
950  newAction = actionPtr->potentialAction(leftBead,midBeadL);
951  newAction += actionPtr->potentialAction(midBeadR,rightBead);
952 
953  /* The metropolis acceptance step */
954  if (random.rand() < (centerWeightFinal/centerWeightInit)*exp(-(newAction - oldAction))) {
955  keepMove();
956 
957  /* Update broken bead lists, make/break links */
958  if (startBreak && (!endBreak)){
959  path.addCenterLink(midBeadL,midBeadR);
960  }else if((!startBreak) && endBreak){
961  path.removeCenterLink(midBeadL);
962  }
963  }
964  else
965  undoMove();
966 
967  return success;
968 }
969 
970 
971 /*************************************************************************/
974 void MidStagingMove::undoMove() {
975  int k = 0;
976  beadLocator beadIndex;
977  beadIndex = leftBead;
978  path.updateBead(beadIndex,originalPos(k));
979  while (!all(beadIndex==midBeadL)){
980  beadIndex = path.next(beadIndex);
981  ++k;
982  path.updateBead(beadIndex,originalPos(k));
983  }
984  beadIndex = midBeadR;
985  k++;
986  path.updateBead(beadIndex,originalPos(k));
987  while (!all(beadIndex==rightBead)){
988  beadIndex = path.next(beadIndex);
989  ++k;
990  path.updateBead(beadIndex,originalPos(k));
991  }
992 
993  success = false;
994 }
995 
996 // ---------------------------------------------------------------------------
997 // ---------------------------------------------------------------------------
998 // SWAPBREAK MOVE CLASS -------------------------------------------------------
999 // ---------------------------------------------------------------------------
1000 // ---------------------------------------------------------------------------
1001 
1002 /*************************************************************************/
1008  MTRand &_random, ensemble _operateOnConfig) :
1009 MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
1010 
1011  /* Initialize private data to zera */
1013 
1014 }
1015 
1016 SwapBreakMove::~SwapBreakMove() {
1017 }
1018 
1019 /*************************************************************************/
1024 
1025  success = false;
1026 
1027  beadLocator brokenBeadL,brokenBeadR,closedBeadL,closedBeadR;
1028 
1029  /* Make sure we have at least one broken slice */
1030  if (path.breakSlice > 0) {
1031 
1032  /* Increment the number of displacement moves and the total number
1033  * of moves */
1034  numAttempted++;
1035  totAttempted++;
1036 
1037  /* Set time slices to broken slice */
1038  brokenBeadL[0] = path.breakSlice;
1039  brokenBeadR[0] = path.breakSlice+1;
1040  closedBeadL[0] = path.breakSlice;
1041 
1042  /* Select broken bead on left/right to swap */
1043  int brokenListIndexL = random.randInt(path.brokenWorldlinesL.size()-1);
1044  int brokenListIndexR = random.randInt(path.brokenWorldlinesR.size()-1);
1045 
1046  brokenBeadL[1] = path.brokenWorldlinesL[brokenListIndexL];
1047  brokenBeadR[1] = path.brokenWorldlinesR[brokenListIndexR];
1048 
1049  /* Select closed world line to swap */
1050  int closedListIndex = random.randInt(path.closedWorldlines.size()-1);
1051  closedBeadL[1] = path.closedWorldlines[closedListIndex];
1052  closedBeadR = path.next(closedBeadL);
1053 
1054  /* Compute the action for original path */
1055  double rho0Old;
1056  iVec wind;
1057  wind = sampleWindingSector(closedBeadL,closedBeadR,1,rho0Old);
1058 
1059  /* Close open worldline */
1060  path.makeLink(brokenBeadL,brokenBeadR);
1061 
1062  /* Open closed worldline */
1063  path.breakLink(closedBeadL);
1064 
1065  /* Compute the action for new path */
1066  double rho0New;
1067  wind = sampleWindingSector(brokenBeadL,brokenBeadR,1,rho0New);
1068 
1069  /* The metropolis acceptance step */
1070  if (random.rand() < rho0New/rho0Old ) {
1071 
1072  /* Update broken/closed wordline lists */
1073  path.closedWorldlines[closedListIndex] = brokenBeadL[1];
1074  path.brokenWorldlinesL[brokenListIndexL] = closedBeadL[1];
1075  path.brokenWorldlinesR[brokenListIndexR] = closedBeadR[1];
1076 
1077  keepMove();
1078  }
1079  else {
1080  /* Undo changes */
1081  path.makeLink(closedBeadL,closedBeadR);
1082  path.breakLink(brokenBeadL);
1083  success = false;
1084  }
1085 
1086  } // if breaklink > 0
1087  else
1088  success = false;
1089 
1090  return success;
1091 }
1092 
1093 // ---------------------------------------------------------------------------
1094 // ---------------------------------------------------------------------------
1095 // CENTEROFMASS MOVE CLASS ---------------------------------------------------
1096 // ---------------------------------------------------------------------------
1097 // ---------------------------------------------------------------------------
1098 
1099 /*************************************************************************/
1103  MTRand &_random, ensemble _operateOnConfig) :
1104  MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
1105 
1106  /* Initialize private data to zera */
1108 
1109  /* We setup the original position array which will store the shift
1110  * of a single particle at a time so it can be undone later */
1111  originalPos.resize(1);
1112 }
1113 
1114 /*************************************************************************/
1118 }
1119 
1120 /*************************************************************************/
1127 
1128  success = false;
1129 
1130  /* Only perform a move if we have beads */
1131  if (path.worm.getNumBeadsOn() == 0)
1132  return success;
1133 
1134  int startSlice = 0;
1135  /* If there are broken wordlines, choose between starting and ending bead*/
1136  if( (path.breakSlice > 0) && (random.rand() < 0.5) )
1137  startSlice = path.numTimeSlices-1;
1138 
1139  /* We don't bother performing a center of mass move, unless we have at
1140  * least one bead on startSlice */
1141  if (path.numBeadsAtSlice(startSlice) == 0)
1142  return false;
1143 
1144  checkMove(0,0.0);
1145 
1146  /* The initial bead */
1147  beadLocator firstBead;
1148  firstBead = startSlice,random.randInt(path.numBeadsAtSlice(startSlice)-1);
1149 
1150  bool startSubregionA,startSubregionB,endSubregionA,endSubregionB;
1151 
1152  /* Now we traverse the path backwards, until we find 1 of two
1153  * possibilities, either we reach a null bead, or we wrap around */
1154  startBead = firstBead;
1155  if (!all(path.prev(startBead)==XXX)) {
1156  do {
1157  startBead = path.prev(startBead);
1158  } while (!all(path.prev(startBead)==firstBead) && !all(path.prev(startBead)==XXX));
1159  }
1160 
1161  /* Get a closed worldline */
1162  if (all(path.prev(startBead)==firstBead)) {
1163  startBead = firstBead;
1164  endBead = path.prev(startBead);
1165  }
1166  /* Otherwise, find the end bead */
1167  else {
1168  endBead = firstBead;
1169  if (!all(path.next(endBead)==XXX)) {
1170  do {
1171  endBead = path.next(endBead);
1172  } while(!all(path.next(endBead)==XXX));
1173  }
1174  }
1175 
1176  int wlLength = 0;
1177  beadLocator beadIndex;
1178 
1179  /* Make sure the worldline to be moved is shorter than the number of time
1180  * slices */
1181  beadIndex = startBead;
1182  do {
1183  ++wlLength;
1184  beadIndex = path.next(beadIndex);
1185  } while (!all(beadIndex==path.next(endBead)));
1186 
1187  if (wlLength > constants()->numTimeSlices())
1188  return false;
1189 
1190  /* Increment the number of center of mass moves and the total number
1191  * of moves */
1192  numAttempted++;
1193  totAttempted++;
1194 
1195  /* The random shift that will be applied to the center of mass*/
1196  for (int i = 0; i < NDIM; i++)
1197  originalPos(0)[i] = constants()->comDelta()*(-0.5 + random.rand());
1198 
1199  /* Here we test to see if any beads are placed outside the box (if we
1200  * don't have periodic boundary conditions). If that is the case,
1201  * we don't continue */
1202  dVec pos;
1203  if (int(sum(path.boxPtr->periodic)) != NDIM) {
1204  beadIndex = startBead;
1205  do {
1206  pos = path(beadIndex) + originalPos(0);
1207  path.boxPtr->putInBC(pos);
1208  for (int i = 0; i < NDIM; i++) {
1209  if ((pos[i] < -0.5*path.boxPtr->side[i]) || (pos[i] >= 0.5*path.boxPtr->side[i]))
1210  return false;
1211  }
1212  beadIndex = path.next(beadIndex);
1213  } while (!all(beadIndex==path.next(endBead)));
1214  }
1215 
1216  /* Determine the old potential action of the path */
1217  oldAction = actionPtr->potentialAction(startBead,endBead);
1218 
1219  /* Go through the worldline and update the position of all the beads */
1220  beadIndex = startBead;
1221  startSubregionA = false;
1222  startSubregionB = false;
1223  endSubregionA = false;
1224  endSubregionB = false;
1225  do {
1226  /* Check if bead is in subregion A or B */
1227  if ((constants()->spatialSubregionOn())&&(!(startSubregionA||startSubregionB))){
1228  startSubregionA = path.inSubregionA(beadIndex);
1229  startSubregionB = path.inSubregionB(beadIndex);
1230  }
1231  pos = path(beadIndex) + originalPos(0);
1232  path.boxPtr->putInBC(pos);
1233  path.updateBead(beadIndex,pos);
1234  if ((constants()->spatialSubregionOn())&&(!(endSubregionA||endSubregionB))){
1235  endSubregionA = path.inSubregionA(beadIndex);
1236  endSubregionB = path.inSubregionB(beadIndex);
1237  }
1238  beadIndex = path.next(beadIndex);
1239  } while (!all(beadIndex==path.next(endBead)));
1240 
1241  if ( (startSubregionA && endSubregionB)|| (startSubregionB && endSubregionA) ){
1242  undoMove();
1243  checkMove(2,0.0);
1244  } else{
1245  /* Get the new potential action of the path */
1246  newAction = actionPtr->potentialAction(startBead,endBead);
1247 
1248  /* The metropolis acceptance step */
1249  if (random.rand() < exp(-(newAction - oldAction))) {
1250  keepMove();
1251  checkMove(1,newAction-oldAction);
1252  }
1253  else {
1254  undoMove();
1255  checkMove(2,0.0);
1256  }
1257  }
1258 
1259  return success;
1260 }
1261 
1262 /*************************************************************************/
1265 void CenterOfMassMove::undoMove() {
1266 
1267  dVec pos;
1268  beadLocator beadIndex;
1269  beadIndex = startBead;
1270  do {
1271  pos = path(beadIndex) - originalPos(0);
1272  path.boxPtr->putInBC(pos);
1273  path.updateBead(beadIndex,pos);
1274  beadIndex = path.next(beadIndex);
1275  } while (!all(beadIndex==path.next(endBead)));
1276 
1277  success = false;
1278 }
1279 
1280 // ---------------------------------------------------------------------------
1281 // ---------------------------------------------------------------------------
1282 // STAGING MOVE CLASS --------------------------------------------------------
1283 // ---------------------------------------------------------------------------
1284 // ---------------------------------------------------------------------------
1285 
1286 /*************************************************************************/
1290  MTRand &_random, ensemble _operateOnConfig) :
1291  MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
1292 
1293  /* Initialize private data to zera */
1295 
1296  /* Resize the original position array */
1297  originalPos.resize(constants()->Mbar()-1);
1298 
1299  /* The maximum length of a staging move */
1300  stageLength = constants()->Mbar();
1301 }
1302 
1303 /*************************************************************************/
1307  // empty destructor
1308 }
1309 
1310 /*************************************************************************/
1317 
1318  success = false;
1319 
1320  /* Only perform a move if we have beads */
1321  if (path.worm.getNumBeadsOn() == 0)
1322  return success;
1323 
1324  checkMove(0,0.0);
1325 
1326  /* We don't bother staging if we only have a worm, as this will be taken care
1327  * of with other moves. It is also possible that we could get stuck in an
1328  * infinite loop here.*/
1329  if (path.getTrueNumParticles()==0)
1330  return false;
1331 
1332  /* Randomly select the start bead of the stage */
1333 #if PIGS
1334  startBead[0] = random.randInt((path.numTimeSlices-1)-constants()->Mbar());
1335 #else
1336  startBead[0] = random.randInt(path.numTimeSlices-1);
1337 #endif
1338 
1339  /* We need to worry about the possibility of an empty slice for small
1340  * numbers of particles. */
1341  if (path.numBeadsAtSlice(startBead[0]) == 0)
1342  return false;
1343  startBead[1] = random.randInt(path.numBeadsAtSlice(startBead[0])-1);
1344 
1345  /* Do we perform varialble length staging updates? */
1346  if (constants()->varUpdates())
1347  stageLength = 2 + random.randInt(constants()->Mbar()-2);
1348 
1349  /* Now we have to make sure that we are moving an active trajectory,
1350  * otherwise we exit immediatly */
1351  beadLocator beadIndex;
1352  beadIndex = startBead;
1353  for (int k = 0; k < (stageLength); k++) {
1354  if (!path.worm.beadOn(beadIndex) || all(path.next(beadIndex)==XXX))
1355  return false;
1356  beadIndex = path.next(beadIndex);
1357  }
1358  endBead = beadIndex;
1359 
1360  /* If we haven't found the worm head, and all beads are on, try to perform the move */
1361 
1362  /* Increment the attempted counters */
1363  numAttempted++;
1364  totAttempted++;
1365 
1366  double totalrho0;
1367  iVec wind;
1368  wind = sampleWindingSector(startBead,endBead,stageLength,totalrho0);
1369 
1370  /* Get the current action for the path segment to be updated */
1371  oldAction = actionPtr->potentialAction(startBead,path.prev(endBead));
1372 
1373  /* Perform the staging update, generating the new path and updating bead
1374  * positions, while storing the old one */
1375  beadIndex = startBead;
1376  int k = 0;
1377  dVec pos;
1378  bool movedIntoSubRegionA = false;
1379  do {
1380  beadIndex = path.next(beadIndex);
1381  originalPos(k) = path(beadIndex);
1382  path.updateBead(beadIndex,
1383  newStagingPosition(path.prev(beadIndex),endBead,stageLength,k,wind));
1384  if (!movedIntoSubRegionA){
1385  movedIntoSubRegionA = path.inSubregionA(beadIndex);
1386  }
1387  ++k;
1388  } while (!all(beadIndex==path.prev(endBead)));
1389 
1390  if ( !movedIntoSubRegionA ) {
1391  /* Get the new action for the updated path segment */
1392  newAction = actionPtr->potentialAction(startBead,path.prev(endBead));
1393 
1394  /* The actual Metropolis test */
1395  if ( random.rand() < exp(-(newAction-oldAction)) ) {
1396  keepMove();
1397  checkMove(1,newAction-oldAction);
1398  }
1399  else {
1400  undoMove();
1401  checkMove(2,0.0);
1402  }
1403  }
1404  else {
1405  undoMove();
1406  }
1407 
1408  return success;
1409 }
1410 
1411 /*************************************************************************/
1415 void StagingMove::undoMove() {
1416 
1417  int k = 0;
1418  beadLocator beadIndex;
1419  beadIndex = startBead;
1420  do {
1421  beadIndex = path.next(beadIndex);
1422  path.updateBead(beadIndex,originalPos(k));
1423  ++k;
1424  } while (!all(beadIndex==path.prev(endBead)));
1425 
1426  success = false;
1427 }
1428 
1429 // ---------------------------------------------------------------------------
1430 // ---------------------------------------------------------------------------
1431 // BISECTION MOVE CLASS ------------------------------------------------------
1432 // ---------------------------------------------------------------------------
1433 // ---------------------------------------------------------------------------
1434 
1435 /*************************************************************************/
1441  MTRand &_random, ensemble _operateOnConfig) :
1442  MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
1443 
1444  /* Initialize private data to zera */
1446 
1447  /* Initialize the acceptance by level counters */
1448  /* These need to use the *actual* value of b */
1449  numAcceptedLevel.resize(constants()->b()+1);
1450  numAttemptedLevel.resize(constants()->b()+1);
1451  numAcceptedLevel = 0;
1452  numAttemptedLevel = 0;
1453 
1454  /* The number of levels used in bisection */
1455  numLevels = constants()->b();
1456 
1457  /* We setup the original and new positions as well as the include array
1458  * which stores updates to the beads involved in the bisection */
1459  numActiveBeads = ipow(2,numLevels)-1;
1460  include.resize(numActiveBeads);
1461  originalPos.resize(numActiveBeads);
1462  newPos.resize(numActiveBeads);
1463 }
1464 
1465 /*************************************************************************/
1469  include.free();
1470 }
1471 
1472 
1473 /*****************************************************************************/
1485 /*****************************************************************************/
1487 
1488  success = false;
1489 
1490  /* Only perform a move if we have beads */
1491  if (path.worm.getNumBeadsOn() == 0)
1492  return success;
1493 
1494  /* We cannot perform this move at present when using a pair product action */
1495  if (constants()->actionType() == "pair_product")
1496  return false;
1497 
1498  /* Do we perform varialble length bisection updates? */
1499  if (constants()->varUpdates()) {
1500  numLevels = 1+random.randInt(constants()->b()-1);
1501  numActiveBeads = ipow(2,numLevels)-1;
1502  }
1503 
1504  /* Only do bisections when we have at least one particle */
1505  if (path.getTrueNumParticles()==0)
1506  return false;
1507 
1508  /* Randomly select the start bead of the bisection */
1509  startBead[0] = random.randInt(path.numTimeSlices-1);
1510 
1511  /* We need to worry about the possibility of an empty slice for small
1512  * numbers of particles. */
1513  if (path.numBeadsAtSlice(startBead[0]) == 0)
1514  return false;
1515  startBead[1] = random.randInt(path.numBeadsAtSlice(startBead[0])-1);
1516 
1517  /* Now we have to make sure that we are moving an active trajectory,
1518  * otherwise we exit immediatly */
1519  beadLocator beadIndex;
1520  beadIndex = startBead;
1521  for (int k = 0; k < (numActiveBeads+1); k++) {
1522  if (!path.worm.beadOn(beadIndex) || all(path.next(beadIndex)==XXX))
1523  return false;
1524  beadIndex = path.next(beadIndex);
1525  }
1526  endBead = beadIndex;
1527 
1528  checkMove(0,0.0);
1529 
1530  /* Increment the number of displacement moves and the total number
1531  * of moves */
1532  numAttempted++;
1533  totAttempted++;
1534  numAttemptedLevel(numLevels)++;
1535  include = true;
1536 
1537  /* Now we perform the actual bisection down to level 1 */
1538  oldDeltaAction = 0.0;
1539  for (level = numLevels; level > 0; level--) {
1540 
1541  /* Compute the distance between time slices and set the tau
1542  * shift for the action */
1543  shift = ipow(2,level-1);
1544  actionPtr->setShift(shift);
1545 
1546  /* Reset the actions for this level*/
1547  oldAction = newAction = 0.0;
1548 
1549  beadIndex = path.next(startBead,shift);
1550  int k = 1;
1551  do {
1552  int n = k*shift-1;
1553 
1554  if (include(n)) {
1555  originalPos(n) = path(beadIndex);
1556  oldAction += actionPtr->potentialAction(beadIndex);
1557 
1558  /* Generate the new position and compute the action */
1559  newPos(n) = newBisectionPosition(beadIndex,shift);
1560  path.updateBead(beadIndex,newPos(n));
1561  newAction += actionPtr->potentialAction(beadIndex);
1562 
1563  /* Set the include bit */
1564  include(n) = false;
1565  }
1566  /* At level 1 we need to compute the full action */
1567  else if (level==1) {
1568  newAction += actionPtr->potentialAction(beadIndex);
1569  path.updateBead(beadIndex,originalPos(n));
1570  oldAction += actionPtr->potentialAction(beadIndex);
1571  path.updateBead(beadIndex,newPos(n));
1572  }
1573 
1574  ++k;
1575  beadIndex = path.next(beadIndex,shift);
1576  } while (!all(beadIndex==endBead));
1577 
1578  /* Record the total action difference at this level */
1580 
1581  /* Now we do the metropolis step, if we accept the move, we
1582  * keep going to the next level, however, if we reject it,
1583  * we return all slices that have already been moved back
1584  * to their original positions and break out of the level
1585  * loop. */
1586 
1587  /* The actual Metropolis test */
1588  if (random.rand() < exp(-deltaAction + oldDeltaAction)) {
1589  if (level == 1) {
1590  keepMove();
1591  checkMove(1,deltaAction);
1592  }
1593  }
1594  else {
1595  undoMove();
1596  checkMove(2,0.0);
1597  break;
1598  }
1599 
1600  oldDeltaAction = deltaAction;
1601 
1602  } // end over level
1603 
1604  return success;
1605 }
1606 
1607 /*****************************************************************************/
1611 /*****************************************************************************/
1612 void BisectionMove::keepMove() {
1613 
1614  numAccepted++;
1615  numAcceptedLevel(numLevels)++;
1616  totAccepted++;
1617 
1618  /* Restore the shift level for the time step to 1 */
1619  actionPtr->setShift(1);
1620 
1621  success = true;
1622 }
1623 
1624 /*****************************************************************************/
1629 /*****************************************************************************/
1630 void BisectionMove::undoMove() {
1631 
1632  /* Go through the list of updated beads and return them to their original
1633  * positions */
1634  int k = 0;
1635  beadLocator beadIndex;
1636  beadIndex = startBead;
1637  do {
1638  beadIndex = path.next(beadIndex);
1639  if (!include(k)) {
1640  path.updateBead(beadIndex,originalPos(k));
1641  }
1642  ++k;
1643  } while (!all(beadIndex==path.prev(endBead)));
1644 
1645  actionPtr->setShift(1);
1646  success = false;
1647 }
1648 
1649 // ---------------------------------------------------------------------------
1650 // ---------------------------------------------------------------------------
1651 // OPEN MOVE CLASS -----------------------------------------------------------
1652 // ---------------------------------------------------------------------------
1653 // ---------------------------------------------------------------------------
1654 
1655 /*************************************************************************/
1658 OpenMove::OpenMove (Path &_path, ActionBase *_actionPtr, MTRand &_random,
1659  ensemble _operateOnConfig, bool _varLength) :
1660  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
1661 
1662  /* Initialize private data to zero */
1664 }
1665 
1666 /*************************************************************************/
1670 }
1671 
1672 /*************************************************************************/
1681 
1682  success = false;
1683 
1684  /* Only perform a move if we have beads */
1685  if (path.worm.getNumBeadsOn() == 0)
1686  return success;
1687 
1688  /* Only do an open move when we have at least one particle */
1689  if (path.getTrueNumParticles()==0)
1690  return false;
1691 
1692  /* Get the length of the proposed gap to open up. We only allow even
1693  * gaps. */
1694  gapLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
1695  numLevels = int (ceil(log(1.0*gapLength) / log(2.0)-EPS));
1696 
1697  /* Randomly select the head bead, and make sure it is turned on, we only
1698  * allow the head or tail to live on even slices */
1699  /* THIS IS EXTREMELY IMPORTANT FOR DETAILED BALANCE */
1700  headBead[0] = 2*random.randInt(path.numTimeSlices/2-1);
1701  headBead[1] = random.randInt(path.numBeadsAtSlice(headBead[0])-1);
1702 
1703  /* Find the tail bead */
1704  tailBead = path.next(headBead,gapLength);
1705 
1706  /* Get the current winding number of the chosen trajectory */
1707  double totalrho0;
1708  iVec wind;
1709  wind = sampleWindingSector(headBead,tailBead,gapLength,totalrho0);
1710 
1711  /* Determine the separation in this winding sector */
1712  dVec sep;
1713  sep = path(tailBead) - path(headBead) + wind*path.boxPtr->side;
1714 
1715  /* We make sure that the proposed worm is not too costly */
1716  if ( !path.worm.tooCostly(sep,gapLength) )
1717  {
1718 
1719  checkMove(0,0.0);
1720 
1721  /* We use the 'true' number of particles here because we are still diagonal,
1722  * so it corresponds to the number of worldlines*/
1723  double norm = (constants()->C() * constants()->Mbar() * path.worm.getNumBeadsOn())
1724  / totalrho0;
1726 
1727  /* We rescale to take into account different attempt probabilities */
1728  norm *= constants()->attemptProb("close")/constants()->attemptProb("open");
1729 
1730  /* Weight for ensemble */
1731  norm *= actionPtr->ensembleWeight(-gapLength+1);
1732  double muShift = gapLength*constants()->mu()*constants()->tau();
1733 
1734  /* Increment the number of open moves and the total number of moves */
1735  numAttempted++;
1736  totAttempted++;
1737  numAttemptedLevel(numLevels)++;
1738 
1739  /* The temporary head and tail are special beads */
1740  path.worm.special1 = headBead;
1741  path.worm.special2 = tailBead;
1742 
1743  /* If we have a local action, perform a single slice rejection move */
1744  if (actionPtr->local) {
1745 
1746  double actionShift = (-log(norm) + muShift)/gapLength;
1747 
1748  /* We now compute the potential energy of the beads that would be
1749  * removed if the worm is inserted */
1750  deltaAction = 0.0;
1751  double factor = 0.5;
1752 
1753  beadLocator beadIndex;
1754  beadIndex = headBead;
1755  do {
1756  deltaAction = -(actionPtr->barePotentialAction(beadIndex) - factor*actionShift);
1757 
1758  /* We do a single slice Metropolis test and exit the move if we
1759  * wouldn't remove the single bead */
1760  if ( random.rand() >= exp(-deltaAction) ) {
1761  undoMove();
1762  return success;
1763  }
1764 
1765  factor = 1.0;
1766  beadIndex = path.next(beadIndex);
1767  } while (!all(beadIndex==tailBead));
1768 
1769  /* Add the part from the tail */
1770  deltaAction = -(actionPtr->barePotentialAction(tailBead) - 0.5*actionShift);
1771  deltaAction -= actionPtr->potentialActionCorrection(headBead,tailBead);
1772 
1773  /* Now perform the final metropolis acceptance test based on removing a
1774  * chunk of worldline. */
1775  if ( random.rand() < (exp(-deltaAction)) ) {
1776  keepMove();
1777  checkMove(1,deltaAction - gapLength*actionShift);
1778  }
1779  else {
1780  undoMove();
1781  checkMove(2,0.0);
1782  }
1783  }
1784  /* otherwise, perform a full trajctory update */
1785  else {
1786 
1787  /* We now compute the potential energy of the beads that would be
1788  * removed if the worm is inserted */
1789  oldAction = actionPtr->potentialAction(headBead,tailBead);
1790 
1791  /* Now perform the metropolis acceptance test based on removing a chunk of
1792  * worldline. */
1793  if ( random.rand() < norm*exp(oldAction - muShift) ) {
1794  keepMove();
1795  checkMove(1,-oldAction);
1796  }
1797  else {
1798  undoMove();
1799  checkMove(2,0.0);
1800  }
1801  }
1802 
1803  } // too costly
1804 
1805  return success;
1806 }
1807 
1808 /*************************************************************************/
1812 void OpenMove::keepMove() {
1813 
1814  /* update the acceptance counters */
1815  numAccepted++;
1816  totAccepted++;
1817  numAcceptedLevel(numLevels)++;
1818 
1819  /* Remove the beads and links from the gap */
1820  beadLocator beadIndex;
1821  beadIndex = path.next(headBead);
1822  while (!all(beadIndex==tailBead)) {
1823  beadIndex = path.delBeadGetNext(beadIndex);
1824  }
1825 
1826  /* Update all the properties of the worm */
1827  path.worm.update(path,headBead,tailBead);
1828 
1829  /* The configuration with a worm is not diagonal */
1830  path.worm.isConfigDiagonal = false;
1831 
1832  printMoveState("Opened up a worm.");
1833  success = true;
1834 }
1835 
1836 /*************************************************************************/
1839 void OpenMove::undoMove() {
1840 
1841  /* Reset the worm parameters */
1842  path.worm.reset();
1843  path.worm.isConfigDiagonal = true;
1844 
1845  printMoveState("Failed to open up a worm.");
1846  success = false;
1847 }
1848 
1849 // ---------------------------------------------------------------------------
1850 // ---------------------------------------------------------------------------
1851 // CLOSE MOVE CLASS ----------------------------------------------------------
1852 // ---------------------------------------------------------------------------
1853 // ---------------------------------------------------------------------------
1854 
1855 /*************************************************************************/
1858 CloseMove::CloseMove (Path &_path, ActionBase *_actionPtr,
1859  MTRand &_random, ensemble _operateOnConfig, bool _varLength) :
1860  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
1861 
1862  /* Initialize private data to zero */
1864 }
1865 
1866 /*************************************************************************/
1870  oldBeadOn.free();
1871 }
1872 
1873 /*************************************************************************/
1882 
1883  success = false;
1884 
1885  /* Only perform a move if we have beads */
1886  if (path.worm.getNumBeadsOn() == 0)
1887  return success;
1888 
1889  /* We first make sure we are in an off-diagonal configuration, and that that
1890  * gap is neither too large or too small and that the worm cost is reasonable.
1891  * Otherwise, we simply exit the move */
1892  if ( (path.worm.gap > constants()->Mbar()) || (path.worm.gap == 0)
1893  || path.worm.tooCostly() )
1894  return false;
1895 
1896  checkMove(0,0.0);
1897 
1898  /* Otherwise, proceed with the close move */
1899  numLevels = int (ceil(log(1.0*path.worm.gap) / log(2.0)-EPS));
1900 
1901  /* Increment the number of close moves and the total number of moves */
1902  numAttempted++;
1903  numAttemptedLevel(numLevels)++;
1904  totAttempted++;
1905 
1906  /* Get the head and new 'tail' slices for the worldline length
1907  * to be closed. These beads are left untouched */
1908  headBead = path.worm.head;
1909  tailBead = path.worm.tail;
1910 
1911  /* Sample the winding sector */
1912  double totalrho0;
1913  iVec wind;
1914  wind = sampleWindingSector(headBead,tailBead,path.worm.gap,totalrho0);
1915 
1916  /* Compute the part of the acceptance probability that does not
1917  * depend on the change in potential energy */
1918  double norm = totalrho0 /
1919  (constants()->C() * constants()->Mbar() *
1920  (path.worm.getNumBeadsOn() + path.worm.gap - 1));
1921 
1922  /* We rescale to take into account different attempt probabilities */
1923  norm *= constants()->attemptProb("open")/constants()->attemptProb("close");
1924 
1925  /* Weight for ensemble */
1926  norm *= actionPtr->ensembleWeight(path.worm.gap-1);
1927 
1928  /* The change in the number sector */
1929  double muShift = path.worm.gap*constants()->mu()*constants()->tau();
1930 
1931  /* If we have a local action, perform single slice updates */
1932  if (actionPtr->local) {
1933 
1934  double actionShift = (log(norm) + muShift)/path.worm.gap;
1935 
1936  /* Compute the potential action for the new trajectory, inclucing a piece
1937  * coming from the head and tail. */
1938  beadLocator beadIndex;
1939  beadIndex = path.worm.head;
1940 
1941  deltaAction = actionPtr->barePotentialAction(beadIndex) - 0.5*actionShift;
1942 
1943  /* We perform a metropolis test on the tail bead */
1944  if ( random.rand() >= exp(-deltaAction) ) {
1945  undoMove();
1946  return success;
1947  }
1948 
1949  for (int k = 0; k < (path.worm.gap-1); k++) {
1950  beadIndex = path.addNextBead(beadIndex,
1951  newStagingPosition(beadIndex,path.worm.tail,path.worm.gap,k,wind));
1952  deltaAction = actionPtr->barePotentialAction(beadIndex) - actionShift;
1953 
1954  /* We perform a metropolis test on the single bead */
1955  if ( random.rand() >= exp(-deltaAction) ) {
1956  undoMove();
1957  return success;
1958  }
1959  }
1960  path.next(beadIndex) = path.worm.tail;
1961  path.prev(path.worm.tail) = beadIndex;
1962 
1963  /* If we have made it this far, we compute the total action as well as the
1964  * action correction */
1965  deltaAction = actionPtr->barePotentialAction(path.worm.tail) - 0.5*actionShift;
1966  deltaAction += actionPtr->potentialActionCorrection(path.worm.head,path.worm.tail);
1967 
1968  /* Perform the metropolis test */
1969  if ( random.rand() < (exp(-deltaAction)) ) {
1970  keepMove();
1971  checkMove(1,deltaAction + log(norm) + muShift);
1972  }
1973  else {
1974  undoMove();
1975  checkMove(2,0);
1976  }
1977  }
1978  /* Otherwise, perform a full trajectory update */
1979  else
1980  {
1981  /* Generate a new new trajectory */
1982  beadLocator beadIndex;
1983  beadIndex = path.worm.head;
1984  for (int k = 0; k < (path.worm.gap-1); k++) {
1985  beadIndex = path.addNextBead(beadIndex,
1986  newStagingPosition(beadIndex,path.worm.tail,path.worm.gap,k,wind));
1987  }
1988  path.next(beadIndex) = path.worm.tail;
1989  path.prev(path.worm.tail) = beadIndex;
1990 
1991  /* Compute the action for the new trajectory */
1992  newAction = actionPtr->potentialAction(headBead,tailBead);
1993 
1994  /* Perform the metropolis test */
1995  if ( random.rand() < norm*exp(-newAction + muShift) ) {
1996  keepMove();
1997  checkMove(1,newAction);
1998  }
1999  else {
2000  undoMove();
2001  checkMove(2,0.0);
2002  }
2003  }
2004 
2005  return success;
2006 }
2007 
2008 /*************************************************************************/
2012 void CloseMove::keepMove() {
2013 
2014  /* update the acceptance counters */
2015  numAccepted++;
2016  numAcceptedLevel(numLevels)++;
2017  totAccepted++;
2018 
2019  /* Update all the properties of the closed worm and our newly
2020  * diagonal configuration. */
2021  path.worm.reset();
2022  path.worm.isConfigDiagonal = true;
2023 
2024  printMoveState("Closed up a worm.");
2025  success = true;
2026 }
2027 
2028 /*************************************************************************/
2031 void CloseMove::undoMove() {
2032 
2033  /* Delete all the beads that were added. */
2034  beadLocator beadIndex;
2035  beadIndex = path.next(path.worm.head);
2036  while (!all(beadIndex==path.worm.tail) && (!all(beadIndex==XXX)))
2037  beadIndex = path.delBeadGetNext(beadIndex);
2038 
2039  path.next(path.worm.head) = XXX;
2040  path.prev(path.worm.tail) = XXX;
2041 
2042  /* Make sure we register the off-diagonal configuration */
2043  path.worm.isConfigDiagonal = false;
2044 
2045  printMoveState("Failed to close up a worm.");
2046  success = false;
2047 }
2048 
2049 // ---------------------------------------------------------------------------
2050 // ---------------------------------------------------------------------------
2051 // INSERT MOVE CLASS ---------------------------------------------------------
2052 // ---------------------------------------------------------------------------
2053 // ---------------------------------------------------------------------------
2054 
2055 /*************************************************************************/
2058 InsertMove::InsertMove (Path &_path, ActionBase *_actionPtr, MTRand &_random,
2059  ensemble _operateOnConfig, bool _varLength) :
2060  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2061 
2062  /* Initialize private data to zero */
2064 }
2065 
2066 /*************************************************************************/
2070 }
2071 
2072 /*************************************************************************/
2082 
2083  /* Get the length of the proposed worm to insert */
2084  wormLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
2085  numLevels = int(ceil(log(1.0*wormLength) / log(2.0)-EPS));
2086 
2087  checkMove(0,0.0);
2088 
2089  /* Increment the number of insert moves and the total number of moves */
2090  numAttempted++;
2091  totAttempted++;
2092  numAttemptedLevel(numLevels)++;
2093 
2094  /* Move normalization factor */
2095  double norm = constants()->C() * constants()->Mbar() * path.numTimeSlices
2096  * path.boxPtr->volume;
2097  double muShift = wormLength*constants()->tau()*constants()->mu();
2098 
2099  /* We rescale to take into account different attempt probabilities */
2100  norm *= constants()->attemptProb("remove") / constants()->attemptProb("insert");
2101 
2102  /* Weight for ensemble */
2103  norm *= actionPtr->ensembleWeight(wormLength);
2104 
2105  /* If we are trying to insert a worm when it is not possible due to a
2106  * canonical constraint don't perform the update */
2107  if (norm < DBL_EPS)
2108  return false;
2109 
2110  /* We pick a random tail slice, and add a new bead */
2111  int slice = 2*(random.randInt(constants()->numTimeSlices()/2-1));
2112 
2113  /* Choose a random position inside the box for the proposed tail */
2114  tailBead = path.addBead(slice,path.boxPtr->randPosition(random));
2115  path.worm.special2 = tailBead;
2116 
2117  /* If we have a local action, perform a single slice rejection move */
2118  if (actionPtr->local) {
2119 
2120  double actionShift = (log(norm) + muShift)/wormLength;
2121 
2122  /* Generate the action for the proposed worm */
2123  beadLocator beadIndex;
2124  beadIndex = tailBead;
2125  deltaAction = actionPtr->barePotentialAction(beadIndex) - 0.5*actionShift;
2126 
2127  /* We perform a metropolis test on the tail bead */
2128  if ( random.rand() >= exp(-deltaAction) ) {
2129  undoMove();
2130  return success;
2131  }
2132 
2133  /* Now go through the non head/tail beads */
2134  for (int k = 1; k < wormLength; k++) {
2135 
2136  beadIndex = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2137  deltaAction = actionPtr->barePotentialAction(beadIndex) - actionShift;
2138 
2139  /* We perform a metropolis test on the single bead */
2140  if ( random.rand() >= exp(-deltaAction) ) {
2141  undoMove();
2142  return success;
2143  }
2144  }
2145  headBead = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2146  path.worm.special1 = headBead;
2147 
2148  /* If we have made it this far, we compute the total action as well as the
2149  * action correction */
2150  deltaAction = actionPtr->barePotentialAction(headBead) - 0.5*actionShift;
2151  deltaAction += actionPtr->potentialActionCorrection(tailBead,headBead);
2152 
2153  /* Perform a final Metropolis test for inserting the full worm*/
2154  if ( random.rand() < (exp(-deltaAction)) ) {
2155  keepMove();
2156  checkMove(1,deltaAction + actionShift*wormLength);
2157  }
2158  else {
2159  undoMove();
2160  checkMove(2,0.0);
2161  }
2162  }
2163  /* Otherwise, perform a full trajectory move */
2164  else {
2165 
2166  /* Generate the path for the proposed worm, setting the new head as special */
2167  beadLocator beadIndex;
2168  beadIndex = tailBead;
2169  for (int k = 0; k < wormLength; k++)
2170  beadIndex = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2171  headBead = beadIndex;
2172  path.worm.special1 = headBead;
2173 
2174  /* Compute the new path action */
2175  newAction = actionPtr->potentialAction(tailBead,headBead);
2176 
2177  /* Perform the metropolis test */
2178  if ( random.rand() < norm*exp(-newAction + muShift) ) {
2179  keepMove();
2180  checkMove(1,newAction);
2181  }
2182  else {
2183  undoMove();
2184  checkMove(2,0.0);
2185  }
2186  }
2187 
2188  return success;
2189 }
2190 
2191 /*************************************************************************/
2195 void InsertMove::keepMove() {
2196 
2197  /* update the acceptance counters */
2198  numAccepted++;
2199  totAccepted++;
2200  numAcceptedLevel(numLevels)++;
2201 
2202  /* Update all the properties of the inserted worm */
2203  path.worm.update(path,headBead,tailBead);
2204 
2205  /* The configuration with a worm is off-diagonal */
2206  path.worm.isConfigDiagonal = false;
2207 
2208  printMoveState("Inserted a worm.");
2209  success = true;
2210 }
2211 
2212 /*************************************************************************/
2215 void InsertMove::undoMove() {
2216 
2217  /* To undo an insert, we simply remove all the beads that we have
2218  * added and reset the worm state.*/
2219  beadLocator beadIndex;
2220  beadIndex = tailBead;
2221  do {
2222  beadIndex = path.delBeadGetNext(beadIndex);
2223  } while (!all(beadIndex==XXX));
2224 
2225  path.worm.reset();
2226 
2227  /* Reset the configuration to diagonal */
2228  path.worm.isConfigDiagonal = true;
2229 
2230  printMoveState("Failed to insert a worm.");
2231  success = false;
2232 }
2233 
2234 // ---------------------------------------------------------------------------
2235 // ---------------------------------------------------------------------------
2236 // REMOVE MOVE CLASS ---------------------------------------------------------
2237 // ---------------------------------------------------------------------------
2238 // ---------------------------------------------------------------------------
2239 
2240 /*************************************************************************/
2243 RemoveMove::RemoveMove (Path &_path, ActionBase *_actionPtr, MTRand &_random,
2244  ensemble _operateOnConfig, bool _varLength) :
2245  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2246 
2247  /* Initialize private data to zero */
2249 }
2250 
2251 /*************************************************************************/
2255 }
2256 
2257 /*************************************************************************/
2267 
2268  /* We first make sure we are in an off-diagonal configuration, and the worm isn't
2269  * too short or long */
2270  if ( (path.worm.length > constants()->Mbar()) || (path.worm.length < 1))
2271  return false;
2272 
2273  numLevels = int(ceil(log(1.0*path.worm.length) / log(2.0)-EPS));
2274 
2275  checkMove(0,0.0);
2276 
2277  /* Increment the number of insert moves and the total number of moves */
2278  numAttempted++;
2279  numAttemptedLevel(numLevels)++;
2280  totAttempted++;
2281 
2282  /* The normalization constant and action shift due to the chemical potential */
2283  double norm = 1.0 / (constants()->C() * constants()->Mbar() * path.numTimeSlices
2284  * path.boxPtr->volume);
2285  double muShift = path.worm.length * constants()->mu() * constants()->tau();
2286 
2287  /* We rescale to take into account different attempt probabilities */
2288  norm *= constants()->attemptProb("insert") / constants()->attemptProb("remove");
2289 
2290  /* Weight for ensemble */
2292 
2293  /* If we are trying to remove a worm when it is not possible due to a
2294  * canonical constraint don't perform the update */
2295  if (norm < DBL_EPS)
2296  return false;
2297 
2298  /* If we have a local action, perform a single slice rejection move */
2299  if (actionPtr->local) {
2300 
2301  double actionShift = (-log(norm) + muShift)/path.worm.length;
2302  deltaAction = 0.0;
2303 
2304  /* First do the head */
2305  beadLocator beadIndex;
2306  beadIndex = path.worm.head;
2307  double factor = 0.5;
2308  do {
2309  deltaAction = -(actionPtr->barePotentialAction(beadIndex) - factor*actionShift);
2310 
2311  /* We do a single slice Metropolis test and exit the move if we
2312  * wouldn't remove the single bead */
2313  if ( random.rand() >= exp(-deltaAction) ) {
2314  undoMove();
2315  return success;
2316  }
2317 
2318  factor = 1.0;
2319  beadIndex = path.prev(beadIndex);
2320  } while (!all(beadIndex==path.worm.tail));
2321 
2322  /* Add the part from the tail */
2323  deltaAction = -(actionPtr->barePotentialAction(path.worm.tail) - 0.5*actionShift);
2324  deltaAction -= actionPtr->potentialActionCorrection(path.worm.tail,path.worm.head);
2325 
2326  /* Perform final metropolis test */
2327  if ( random.rand() < (exp(-deltaAction)) ) {
2328  keepMove();
2329  checkMove(1,deltaAction + log(norm) - muShift);
2330  }
2331  else {
2332  undoMove();
2333  checkMove(2,0.0);
2334  }
2335  }
2336  /* otherwise, perform a full trajectory update */
2337  else {
2338  /* Compute the potential action of the path */
2339  oldAction = actionPtr->potentialAction(path.worm.tail,path.worm.head);
2340 
2341  /* Perform the metropolis test */
2342  if ( random.rand() < norm*exp(oldAction - muShift) ) {
2343  keepMove();
2344  checkMove(1,-oldAction);
2345  }
2346 
2347  else {
2348  undoMove();
2349  checkMove(2,0.0);
2350  }
2351  }
2352 
2353  return success;
2354 }
2355 
2356 /*************************************************************************/
2360 void RemoveMove::keepMove() {
2361 
2362  /* update the acceptance counters */
2363  numAccepted++;
2364  numAcceptedLevel(numLevels)++;
2365  totAccepted++;
2366 
2367  printMoveState("About to remove a worm.");
2368 
2369  /* We delete the worm from our data sets and reset all
2370  * worm properties. */
2371  beadLocator beadIndex;
2372  beadIndex = path.worm.head;
2373  do {
2374  beadIndex = path.delBeadGetPrev(beadIndex);
2375  } while (!all(beadIndex==XXX));
2376 
2377  path.worm.reset();
2378 
2379  /* The configuration without a worm is diagonal */
2380  path.worm.isConfigDiagonal = true;
2381 
2382  printMoveState("Removed a worm.");
2383  success = true;
2384 }
2385 
2386 /*************************************************************************/
2390 void RemoveMove::undoMove() {
2391 
2392  /* Reset the configuration to off-diagonal */
2393  path.worm.isConfigDiagonal = false;
2394 
2395  printMoveState("Failed to remove a worm.");
2396  success = false;
2397 }
2398 
2399 // ---------------------------------------------------------------------------
2400 // ---------------------------------------------------------------------------
2401 // ADVANCE HEAD MOVE CLASS ---------------------------------------------------
2402 // ---------------------------------------------------------------------------
2403 // ---------------------------------------------------------------------------
2404 
2405 /*************************************************************************/
2409  MTRand &_random, ensemble _operateOnConfig, bool _varLength) :
2410  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2411 
2412  /* Initialize private data to zero */
2414 }
2415 
2416 /*************************************************************************/
2420 }
2421 
2422 /*************************************************************************/
2431 
2432  success = false;
2433 
2434  /* Only perform a move if we have beads */
2435  if (path.worm.getNumBeadsOn() == 0)
2436  return success;
2437 
2438  /* Get the length of the proposed advancement by computing
2439  * a random number of levels to be used in the bisection algorithm. */
2440  advanceLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
2441  numLevels = int (ceil(log(1.0*advanceLength) / log(2.0)-EPS));
2442 
2443  checkMove(0,0.0);
2444 
2445  /* Increment the number of advance moves and the total number of moves */
2446  numAttempted++;
2447  numAttemptedLevel(numLevels)++;
2448  totAttempted++;
2449 
2450  double muShift = advanceLength*constants()->tau()*constants()->mu();
2451  double norm = constants()->attemptProb("recede head") /
2452  constants()->attemptProb("advance head");
2453 
2454  /* Weight for ensemble */
2455  norm *= actionPtr->ensembleWeight(advanceLength);
2456 
2457  /* Make the old head a special bead, and undefine the head */
2459  path.worm.head = XXX;
2460 
2461  /* If we have a local action, perform a single slice rejection move */
2462  if (actionPtr->local) {
2463 
2464  double actionShift = (log(norm) + muShift)/advanceLength;
2465 
2466  /* Generate the new path, and compute its action, assigning the new head */
2467  beadLocator beadIndex;
2468  beadIndex = path.worm.special1;
2469  deltaAction = actionPtr->barePotentialAction(beadIndex) - 0.5*actionShift;
2470 
2471  if ( random.rand() >= exp(-deltaAction) ) {
2472  undoMove();
2473  return success;
2474  }
2475 
2476  for (int k = 0; k < (advanceLength-1); k++) {
2477  beadIndex = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2478  deltaAction = actionPtr->barePotentialAction(beadIndex) - actionShift;
2479 
2480  /* We perform a metropolis test on the single bead */
2481  if ( random.rand() >= exp(-deltaAction) ) {
2482  undoMove();
2483  return success;
2484  }
2485  }
2486  headBead = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2487 
2488  /* Assign the new head and compute its action */
2489  path.worm.head = headBead;
2490  deltaAction = actionPtr->potentialAction(headBead) - 0.5*actionShift;
2491  deltaAction += actionPtr->potentialActionCorrection(path.worm.special1,path.worm.head);
2492 
2493  /* Perform the metropolis test */
2494  if ( random.rand() < (exp(-deltaAction))) {
2495  keepMove();
2496  checkMove(1,deltaAction + advanceLength*actionShift);
2497  }
2498  else {
2499  undoMove();
2500  checkMove(2,0.0);
2501  }
2502  }
2503  /* Otherwise, perform a full trajctory update */
2504  else {
2505 
2506  /* Generate the new path, assigning the new head */
2507  beadLocator beadIndex;
2508  beadIndex = path.worm.special1;
2509  for (int k = 0; k < advanceLength; k++)
2510  beadIndex = path.addNextBead(beadIndex,newFreeParticlePosition(beadIndex));
2511  headBead = beadIndex;
2512  path.worm.head = headBead;
2513 
2514  /* Compute the action for the updated path */
2516 
2517  /* Perform the metropolis test */
2518  if ( random.rand() < norm*exp(-newAction + muShift) ) {
2519  keepMove();
2520  checkMove(1,newAction);
2521  }
2522  else {
2523  undoMove();
2524  checkMove(2,0.0);
2525  }
2526  }
2527 
2528  return success;
2529 }
2530 
2531 /*************************************************************************/
2535 void AdvanceHeadMove::keepMove() {
2536 
2537  /* update the acceptance counters */
2538  numAccepted++;
2539  totAccepted++;
2540  numAcceptedLevel(numLevels)++;
2541 
2542  /* Update all the properties of the inserted worm */
2543  path.worm.update(path,headBead,path.worm.tail);
2544 
2545  /* The configuration with a worm is off-diagonal */
2546  path.worm.isConfigDiagonal = false;
2547 
2548  printMoveState("Advanced a worm.");
2549  success = true;
2550 }
2551 
2552 /*************************************************************************/
2556 void AdvanceHeadMove::undoMove() {
2557 
2558  /* Copy back the head bead */
2560 
2561  /* We remove all the beads and links that have been added. */
2562  beadLocator beadIndex;
2563  beadIndex = path.next(path.worm.head);
2564  while (!all(beadIndex==XXX))
2565  beadIndex = path.delBeadGetNext(beadIndex);
2566  path.next(path.worm.head) = XXX;
2567 
2568  /* Reset the configuration to off-diagonal */
2569  path.worm.isConfigDiagonal = false;
2570 
2571  /* Unset the special marker */
2572  path.worm.special1 = XXX;
2573 
2574  printMoveState("Failed to advance a worm.");
2575  success = false;
2576 }
2577 
2578 // ---------------------------------------------------------------------------
2579 // ---------------------------------------------------------------------------
2580 // ADVANCE TAIL MOVE CLASS ---------------------------------------------------
2581 // ---------------------------------------------------------------------------
2582 // ---------------------------------------------------------------------------
2583 
2584 /*************************************************************************/
2588  MTRand &_random, ensemble _operateOnConfig, bool _varLength) :
2589  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2590 
2591  /* Initialize private data to zero */
2593 }
2594 
2595 /*************************************************************************/
2599 }
2600 
2601 /*************************************************************************/
2610 
2611  success = false;
2612 
2613  /* Only perform a move if we have beads */
2614  if (path.worm.getNumBeadsOn() == 0)
2615  return success;
2616 
2617  /* Get the number of time slices we will try to shrink the worm by */
2618  advanceLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
2619  numLevels = int (ceil(log(1.0*advanceLength) / log(2.0)-EPS));
2620 
2621  /* We now make sure that this is shorter than the length of the worm,
2622  * otherewise we reject the move immediatly */
2623  if (advanceLength < path.worm.length) {
2624 
2625  /* The proposed new tail */
2626  tailBead = path.next(path.worm.tail,advanceLength);
2627 
2628  /* The action shift due to the chemical potential */
2629  double muShift = advanceLength*constants()->tau()*constants()->mu();
2630 
2631  double norm = constants()->attemptProb("recede tail") /
2632  constants()->attemptProb("advance tail");
2633 
2634  /* Weight for ensemble */
2635  norm *= actionPtr->ensembleWeight(-advanceLength);
2636 
2637  checkMove(0,0.0);
2638 
2639  /* Increment the number of recede moves and the total number of moves */
2640  numAttempted++;
2641  numAttemptedLevel(numLevels)++;
2642  totAttempted++;
2643 
2644  /* Mark the proposed tail as special */
2645  path.worm.special1 = tailBead;
2646 
2647  /* If we have a local action, perform a single slice rejection move */
2648  if (actionPtr->local) {
2649 
2650  double actionShift = (-log(norm) + muShift)/advanceLength;
2651 
2652  deltaAction = 0.0;
2653  double factor = 0.5;
2654 
2655  beadLocator beadIndex;
2656  beadIndex = path.worm.tail;
2657  do {
2658  deltaAction = -(actionPtr->barePotentialAction(beadIndex) - factor*actionShift);
2659 
2660  /* We do a single slice Metropolis test and exit the move if we
2661  * wouldn't remove the single bead */
2662  if ( random.rand() >= exp(-deltaAction) ) {
2663  undoMove();
2664  return success;
2665  }
2666 
2667  factor = 1.0;
2668  beadIndex = path.next(beadIndex);
2669  } while (!all(beadIndex==tailBead));
2670 
2671  /* Add the part from the tail */
2672  deltaAction = -(actionPtr->barePotentialAction(beadIndex) - 0.5*actionShift);
2673  deltaAction -= actionPtr->potentialActionCorrection(path.worm.tail,tailBead);
2674 
2675  /* Perform final metropolis test */
2676  if ( random.rand() < (exp(-deltaAction)) ) {
2677  keepMove();
2678  checkMove(1,deltaAction - advanceLength*actionShift);
2679  }
2680  else {
2681  undoMove();
2682  checkMove(2,0.0);
2683  }
2684  }
2685  /* Otherwise, perform a full trajectory update */
2686  else {
2687  /* Compute the old action for the path to be removed */
2689 
2690  /* Perform the metropolis test */
2691  if ( random.rand() < norm*exp(oldAction - muShift) ) {
2692  keepMove();
2693  checkMove(1,-oldAction);
2694  }
2695  else {
2696  undoMove();
2697  checkMove(2,0.0);
2698  }
2699  }
2700 
2701  } // advanceLength
2702 
2703  return success;
2704 }
2705 
2706 /*************************************************************************/
2710 void AdvanceTailMove::keepMove() {
2711 
2712  /* update the acceptance counters */
2713  numAccepted++;
2714  totAccepted++;
2715  numAcceptedLevel(numLevels)++;
2716 
2717  /* Delete beads and links */
2718  beadLocator beadIndex;
2719  beadIndex = path.prev(tailBead);
2720  do {
2721  beadIndex = path.delBeadGetPrev(beadIndex);
2722  } while (!all(beadIndex==XXX));
2723 
2724  /* Update all the changed properties of the inserted worm */
2725  path.worm.update(path,path.worm.head,tailBead);
2726 
2727  /* The configuration is still off-diagonal */
2728  path.worm.isConfigDiagonal = false;
2729 
2730  printMoveState("Advanced a worm tail.");
2731  success = true;
2732 }
2733 
2734 /*************************************************************************/
2738 void AdvanceTailMove::undoMove() {
2739 
2740  /* Make sure the configuration is still off-diagonal */
2741  path.worm.isConfigDiagonal = false;
2742 
2743  /* Unset the special marker */
2744  path.worm.special1 = XXX;
2745 
2746  printMoveState("Failed to advance a worm tail.");
2747  success = false;
2748 }
2749 
2750 // ---------------------------------------------------------------------------
2751 // ---------------------------------------------------------------------------
2752 // RECEDE HEAD MOVE CLASS ----------------------------------------------------
2753 // ---------------------------------------------------------------------------
2754 // ---------------------------------------------------------------------------
2755 
2756 /*************************************************************************/
2760  MTRand &_random, ensemble _operateOnConfig, bool _varLength) :
2761  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2762 
2763  /* Initialize private data to zero */
2765 }
2766 
2767 /*************************************************************************/
2771 }
2772 
2773 /*************************************************************************/
2781 
2782  success = false;
2783 
2784  /* Only perform a move if we have beads */
2785  if (path.worm.getNumBeadsOn() == 0)
2786  return success;
2787 
2788  /* Get the number of time slices we will try to shrink the worm by */
2789  recedeLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
2790  numLevels = int (ceil(log(1.0*recedeLength) / log(2.0)-EPS));
2791 
2792  /* We now make sure that this is shorter than the length of the worm,
2793  * otherewise we reject the move immediatly */
2794  if (recedeLength < path.worm.length) {
2795 
2796  /* The proposed new head */
2797  headBead = path.prev(path.worm.head,recedeLength);
2798 
2799  /* The action shift due to the chemical potential */
2800  double muShift = recedeLength*constants()->tau()*constants()->mu();
2801 
2802  double norm = constants()->attemptProb("advance head") /
2803  constants()->attemptProb("recede head");
2804 
2805  /* Weight for ensemble */
2806  norm *= actionPtr->ensembleWeight(-recedeLength);
2807 
2808  checkMove(0,0.0);
2809 
2810  /* Increment the number of recede moves and the total number of moves */
2811  numAttempted++;
2812  numAttemptedLevel(numLevels)++;
2813  totAttempted++;
2814 
2815  /* Set the proposed head as special */
2816  path.worm.special1 = headBead;
2817 
2818  /* If we have a local action, perform a single slice rejection move */
2819  if (actionPtr->local) {
2820 
2821  double actionShift = (-log(norm) + muShift)/recedeLength;
2822 
2823  deltaAction = 0.0;
2824  double factor = 0.5;
2825 
2826  beadLocator beadIndex;
2827  beadIndex = path.worm.head;
2828  do {
2829  deltaAction = -(actionPtr->barePotentialAction(beadIndex) - factor*actionShift);
2830  if ( random.rand() >= exp(-deltaAction) ) {
2831  undoMove();
2832  return success;
2833  }
2834 
2835  factor = 1.0;
2836  beadIndex = path.prev(beadIndex);
2837  } while (!all(beadIndex==headBead));
2838 
2839  deltaAction = -(actionPtr->barePotentialAction(headBead) - 0.5*actionShift);
2840  deltaAction -= actionPtr->potentialActionCorrection(path.worm.special1,path.worm.head);
2841 
2842  /* Perform final metropolis test */
2843  if ( random.rand() < (exp(-deltaAction)) ) {
2844  keepMove();
2845  checkMove(1,deltaAction - recedeLength*actionShift);
2846  }
2847  else {
2848  undoMove();
2849  checkMove(2,0.0);
2850  }
2851  }
2852  /* Otherwise, perform a full trajectory update */
2853  else {
2854  /* Get the original action for the path */
2856 
2857  /* Perform the metropolis test */
2858  if ( random.rand() < norm*exp(oldAction - muShift) ) {
2859  keepMove();
2860  checkMove(1,-oldAction);
2861  }
2862  else {
2863  undoMove();
2864  checkMove(2,0.0);
2865  }
2866  }
2867 
2868  } // recedeLength
2869 
2870  return success;
2871 }
2872 
2873 /*************************************************************************/
2877 void RecedeHeadMove::keepMove() {
2878 
2879  /* update the acceptance counters */
2880  numAccepted++;
2881  totAccepted++;
2882  numAcceptedLevel(numLevels)++;
2883 
2884  /* Delete beads and links */
2885  beadLocator beadIndex;
2886  beadIndex = path.next(headBead);
2887  do {
2888  beadIndex = path.delBeadGetNext(beadIndex);
2889  } while (!all(beadIndex==XXX));
2890 
2891  /* Update all the changed properties of the inserted worm */
2892  path.worm.update(path,headBead,path.worm.tail);
2893 
2894  /* The configuration is still off-diagonal */
2895  path.worm.isConfigDiagonal = false;
2896 
2897  printMoveState("Receded a worm head.");
2898  success = true;
2899 }
2900 
2901 /*************************************************************************/
2905 void RecedeHeadMove::undoMove() {
2906 
2907  /* Make sure the configuration is still off-diagonal */
2908  path.worm.isConfigDiagonal = false;
2909 
2910  /* Unset the special mark */
2911  path.worm.special1 = XXX;
2912 
2913  printMoveState("Failed to recede a worm head.");
2914  success = false;
2915 }
2916 
2917 // ---------------------------------------------------------------------------
2918 // ---------------------------------------------------------------------------
2919 // RECEDE TAIL MOVE CLASS ----------------------------------------------------
2920 // ---------------------------------------------------------------------------
2921 // ---------------------------------------------------------------------------
2922 
2923 /*************************************************************************/
2927  MTRand &_random, ensemble _operateOnConfig, bool _varLength) :
2928  MoveBase(_path,_actionPtr,_random,_operateOnConfig,_varLength) {
2929 
2930  /* Initialize private data to zero */
2932 }
2933 
2934 /*************************************************************************/
2938 }
2939 
2940 /*************************************************************************/
2948 
2949  success = false;
2950 
2951  /* Only perform a move if we have beads */
2952  if (path.worm.getNumBeadsOn() == 0)
2953  return success;
2954 
2955  /* Get the length of the proposed advancement by computing
2956  * a random number of levels to be used in the bisection algorithm. */
2957  recedeLength = 2*(1 + random.randInt(constants()->Mbar()/2-1));
2958  numLevels = int (ceil(log(1.0*recedeLength) / log(2.0)-EPS));
2959 
2960  checkMove(0,0.0);
2961 
2962  /* Increment the number of advance moves and the total number of moves */
2963  numAttempted++;
2964  numAttemptedLevel(numLevels)++;
2965  totAttempted++;
2966 
2967  double muShift = recedeLength*constants()->tau()*constants()->mu();
2968  double norm = constants()->attemptProb("advance tail") /
2969  constants()->attemptProb("recede tail");
2970 
2971  /* Weight for ensemble */
2972  norm *= actionPtr->ensembleWeight(recedeLength);
2973 
2974  /* Make the current tail special, and undefine the tail */
2976  path.worm.tail = XXX;
2977 
2978  /* If we have a local action, perform a single slice rejection move */
2979  if (actionPtr->local) {
2980 
2981  double actionShift = (log(norm) + muShift)/recedeLength;
2982 
2983  /* Compute the action for the proposed path, and assign the new tail */
2984  beadLocator beadIndex;
2985  beadIndex = path.worm.special1;
2986 
2987  deltaAction = actionPtr->barePotentialAction(beadIndex) - 0.5*actionShift;
2988 
2989  /* We perform a metropolis test on the tail bead */
2990  if ( random.rand() >= exp(-deltaAction) ) {
2991  undoMove();
2992  return success;
2993  }
2994 
2995  for (int k = 0; k < (recedeLength-1); k++) {
2996  beadIndex = path.addPrevBead(beadIndex,newFreeParticlePosition(beadIndex));
2997  deltaAction = actionPtr->barePotentialAction(beadIndex) - actionShift;
2998 
2999  /* We perform a metropolis test on the single bead */
3000  if ( random.rand() >= exp(-deltaAction) ) {
3001  undoMove();
3002  return success;
3003  }
3004  }
3005  tailBead = path.addPrevBead(beadIndex,newFreeParticlePosition(beadIndex));
3006 
3007  /* Assign the new tail bead and compute its action */
3008  path.worm.tail = tailBead;
3009  deltaAction = actionPtr->barePotentialAction(tailBead) - 0.5*actionShift;
3010  deltaAction += actionPtr->potentialActionCorrection(tailBead,path.worm.special1);
3011 
3012  /* Perform the metropolis test */
3013  if ( random.rand() < (exp(-deltaAction))) {
3014  keepMove();
3015  checkMove(1,deltaAction + recedeLength*actionShift);
3016  }
3017  else {
3018  undoMove();
3019  checkMove(2,0.0);
3020  }
3021  }
3022  /* Otherwise, we perform a full trajectory updates */
3023  else {
3024  /* Generate the new path, assigning the new tail */
3025  beadLocator beadIndex;
3026  beadIndex = path.worm.special1;
3027  for (int k = 0; k < recedeLength; k++)
3028  beadIndex = path.addPrevBead(beadIndex,newFreeParticlePosition(beadIndex));
3029  tailBead = beadIndex;
3030  path.worm.tail = tailBead;
3031 
3032  /* Get the action for the proposed path */
3034 
3035  /* Perform the metropolis test */
3036  if ( random.rand() < norm*exp(-newAction + muShift)) {
3037  keepMove();
3038  checkMove(1,newAction);
3039  }
3040  else {
3041  undoMove();
3042  checkMove(2,0.0);
3043  }
3044  }
3045 
3046  return success;
3047 }
3048 
3049 /*************************************************************************/
3053 void RecedeTailMove::keepMove() {
3054 
3055  /* update the acceptance counters */
3056  numAccepted++;
3057  totAccepted++;
3058  numAcceptedLevel(numLevels)++;
3059 
3060  /* Update all the properties of the inserted worm */
3061  path.worm.update(path,path.worm.head,tailBead);
3062 
3063  /* The configuration with a worm is off-diagonal */
3064  path.worm.isConfigDiagonal = false;
3065 
3066  printMoveState("Receded a worm tail.");
3067  success = true;
3068 }
3069 
3070 /*************************************************************************/
3074 void RecedeTailMove::undoMove() {
3075 
3076  /* Copy back the tail bead */
3078 
3079  /* We remove all the beads and links that have been added. */
3080  beadLocator beadIndex;
3081  beadIndex = path.prev(path.worm.tail);
3082  while (!all(beadIndex==XXX))
3083  beadIndex = path.delBeadGetPrev(beadIndex);
3084  path.prev(path.worm.tail) = XXX;
3085 
3086  /* Reset the configuration to off-diagonal */
3087  path.worm.isConfigDiagonal = false;
3088 
3089  /* Unset the special mark */
3090  path.worm.special1 = XXX;
3091 
3092  printMoveState("Failed to recede a worm tail.");
3093  success = false;
3094 }
3095 
3096 // ---------------------------------------------------------------------------
3097 // ---------------------------------------------------------------------------
3098 // SWAP MOVE BASE CLASS ------------------------------------------------------
3099 // ---------------------------------------------------------------------------
3100 // ---------------------------------------------------------------------------
3101 
3102 /*************************************************************************/
3105 SwapMoveBase::SwapMoveBase (Path &_path, ActionBase *_actionPtr, MTRand &_random,
3106  ensemble _operateOnConfig) :
3107  MoveBase(_path,_actionPtr,_random,_operateOnConfig) {
3108 }
3109 
3110 /*************************************************************************/
3114 }
3115 
3116 #include<numeric>
3117 template <typename T>
3118 vector<size_t> sort_indexes(const vector<T> &v) {
3119 
3120  // initialize original index locations
3121  vector<size_t> idx(v.size());
3122  std::iota(idx.begin(), idx.end(), 0);
3123 
3124  // sort indexes based on comparing values in v
3125  stable_sort(idx.begin(), idx.end(),
3126  [&v](size_t i1, size_t i2) {return v[i1] < v[i2];});
3127 
3128  return idx;
3129 }
3130 
3131 /*************************************************************************/
3141 double SwapMoveBase::getNorm(const beadLocator &beadIndex, const int sign) {
3142 
3143  double Sigma = 0.0;
3144  double crho0;
3145  dVec sep;
3146  int index = 0;
3147 
3149 
3150  /* Check if we need to resisize our cumulative distribution funciton */
3151  if (cumulant.size() < sizeCDF)
3152  cumulant.assign(sizeCDF,0.0);
3153 
3154  /* For each particle, we find the free particle weight for all winding
3155  * sectors. We start with W = 0. */
3156 
3157  /* We sum up the free particle density matrices for each bead
3158  * in the list */
3159  sep = path(path.lookup.fullBeadList(0)) - path(beadIndex);
3160  Sigma = actionPtr->rho0(sep,swapLength);
3161  cumulant.at(index) = Sigma;
3162  ++index;
3163  for (int n = 1; n < path.lookup.fullNumBeads; n++) {
3164  sep = path(path.lookup.fullBeadList(n)) - path(beadIndex);
3165  crho0 = actionPtr->rho0(sep,swapLength);
3166  Sigma += crho0;
3167  cumulant.at(index) = cumulant.at(index-1) + crho0;
3168  ++index;
3169  }
3170 
3171  /* Now we repeat for all winding sectors */
3172  for (int w = 1; w < numWind; w++) {
3173 
3174  /* Go through every particle in the lookup table. */
3175  for (int n = 0; n < path.lookup.fullNumBeads; n++) {
3176  sep = path(path.lookup.fullBeadList(n)) - path(beadIndex)
3177  + sign*winding.at(w)*path.boxPtr->side;
3178  crho0 = actionPtr->rho0(sep,swapLength);
3179  Sigma += crho0;
3180  cumulant.at(index) = cumulant.at(index-1) + crho0;
3181  ++index;
3182  }
3183  }
3184 
3185  /* Normalize the cumulant */
3186  for (unsigned int n = 0; n < sizeCDF; n++)
3187  cumulant.at(n) /= Sigma;
3188 
3189  return Sigma;
3190 }
3191 
3193 // * Get the normalization constant for a swap move.
3194 // *
3195 // * We compute the normalization constant used in both the pivot selection
3196 // * probability as well as the overall acceptance probabilty.
3197 // * @see Eq. (2.23) of PRE 74, 036701 (2006).
3198 //******************************************************************************/
3199 //double SwapMoveBase::getNorm(const beadLocator &beadIndex) {
3200 //
3201 // double Sigma = 0.0;
3202 // double crho0;
3203 //
3204 // /* We sum up the free particle density matrices for each bead
3205 // * in the list */
3206 // Sigma = actionPtr->rho0(beadIndex,path.lookup.fullBeadList(0),swapLength);
3207 // cumulant.at(0) = Sigma;
3208 // for (int n = 1; n < path.lookup.fullNumBeads; n++) {
3209 // crho0 = actionPtr->rho0(beadIndex,path.lookup.fullBeadList(n),swapLength);
3210 // Sigma += crho0;
3211 // cumulant.at(n) = cumulant.at(n-1) + crho0;
3212 // }
3213 //
3214 // /* Normalize the cumulant */
3215 // for (int n = 0; n < path.lookup.fullNumBeads; n++)
3216 // cumulant.at(n) /= Sigma;
3217 //
3218 //
3219 // return Sigma;
3220 //}
3221 
3222 /*************************************************************************/
3234 
3235  /* Generate a uniform deviate, and figure out where it fits in our cumulant
3236  * array using a binary search. This is basic tower sampling */
3237 
3238  double x = random.rand();
3239 
3240  int index = std::lower_bound(cumulant.begin(),cumulant.begin()+sizeCDF, x) - cumulant.begin();
3241  /* We need to determine the pivot index and winding sector */
3242 
3243  /* row index */
3244  int w = (index/path.lookup.fullNumBeads) % numWind;
3245 
3246  /* column index */
3247  int p = index % path.lookup.fullNumBeads;
3248 
3249  /* Copy over the pivot bead and return it */
3250  beadLocator pivotBead;
3251  pivotBead = path.lookup.fullBeadList(p);
3252 
3253  /* Get the winding number */
3254  wind = winding.at(w);
3255 
3256 
3257  return pivotBead;
3258 }
3259 
3260 /*************************************************************************/
3270 
3271  /* Generate a uniform deviate, and figure out where it fits in our cumulant
3272  * array using a binary search. This is basic tower sampling */
3273  int index = std::lower_bound(cumulant.begin(),cumulant.end(),random.rand())
3274  - cumulant.begin();
3275 
3276  /* Copy over the pivot bead and return it */
3277  beadLocator pivotBead;
3278  pivotBead = path.lookup.fullBeadList(index);
3279 
3280  return pivotBead;
3281 }
3282 
3283 // ---------------------------------------------------------------------------
3284 // ---------------------------------------------------------------------------
3285 // SWAP HEAD MOVE CLASS ------------------------------------------------------
3286 // ---------------------------------------------------------------------------
3287 // ---------------------------------------------------------------------------
3288 
3289 /*************************************************************************/
3293  MTRand &_random, ensemble _operateOnConfig) :
3294  SwapMoveBase(_path,_actionPtr,_random,_operateOnConfig) {
3295 
3296  /* Initialize private data to zero */
3298 
3299  /* Update the sizes of the original position array */
3300  originalPos.resize(constants()->Mbar()-1);
3301  originalPos = 0.0;
3302 }
3303 
3304 /*************************************************************************/
3308 }
3309 
3310 /*************************************************************************/
3318 
3319  success = false;
3320 
3321  /* Only perform a move if we have beads */
3322  if (path.worm.getNumBeadsOn() == 0)
3323  return success;
3324 
3325  /* We first make sure we are in an off-diagonal configuration */
3326  if (!path.worm.isConfigDiagonal) {
3327 
3328  /* Initialize */
3329  pivot = XXX;
3330  swap = XXX;
3331 
3332  /* Now we figure out how many beads will be involved with the swap bisection. */
3333  swapLength = constants()->Mbar();
3334  numLevels = int (ceil(log(1.0*swapLength) / log(2.0)-EPS));
3335 
3336  /* Now form the list of beads which are in the neighbourhood of
3337  * the head, but at the advanced time slice */
3338  int pivotSlice = path.worm.head[0] + swapLength;
3339  if (pivotSlice >= constants()->numTimeSlices())
3340  pivotSlice -= constants()->numTimeSlices();
3341 
3342  /* Update the full interaction list */
3344 
3345  /* We can only try to make a move if we have at least one bead to swap with */
3346  if (path.lookup.fullNumBeads > 0) {
3347 
3348  /* We compute the normalization factors using the head bead */
3349  SigmaHead = getNorm(path.worm.head);
3350 
3351  iVec wind;
3352  wind = 0;
3353  /* Get the pivot bead and winding number sector */
3354  pivot = selectPivotBead(wind);
3355 
3356  /* Now we try to find the swap bead. If we find the worm tail, we immediatly
3357  * exit the move */
3358  beadLocator beadIndex;
3359  beadIndex = pivot;
3360  for (int k = 0; k < swapLength; k++) {
3361  if (all(beadIndex==path.worm.tail))
3362  return false;
3363  beadIndex = path.prev(beadIndex);
3364  }
3365  swap = beadIndex;
3366 
3367  /* We only continue if the swap is not the tail, and the swap and pivot
3368  * grid boxes coincide. */
3369  if ( !all(path.worm.tail==swap) && path.lookup.gridNeighbors(pivot,swap) ) {
3370 
3371  checkMove(0,0.0);
3372 
3373  /* Increment the number of swap moves and the total number of moves */
3374  numAttempted++;
3375  totAttempted++;
3377 
3378  /* Now we create a new list of beads (using the same beadList)
3379  * which contains all beads in neighborhood of the swap bead
3380  * grid box, but at a time slice advanced by Mbar. We only need to
3381  * do this if head and swap are in different grid boxes. */
3384 
3385  /* Get the normalization factor for the new list */
3386  SigmaSwap = getNorm(swap);
3387 
3388  /* We now perform a pre-metropolis step on the selected bead. If this
3389  * is not accepted, it is extremely likely that the potential change
3390  * will not have any effect, so we don't bother with it. */
3391  double PNorm = min(SigmaHead/SigmaSwap,1.0);
3392  if (random.rand() < PNorm) {
3393 
3394  /* Mark the special beads */
3395  path.worm.special1 = swap;
3396  path.worm.special2 = pivot;
3397 
3398  /* Store the original positions */
3399  int k = 0;
3400  beadIndex = swap;
3401  do {
3402  /* Store the original positions */
3403  if (!all(beadIndex==swap) && !all(beadIndex==pivot)) {
3404  originalPos(k) = path(beadIndex);
3405  ++k;
3406  }
3407  beadIndex = path.next(beadIndex);
3408  } while (!all(beadIndex==path.next(pivot)));
3409 
3410  /* now compute the original action for the path to be
3411  * updated */
3413 
3414  /* Because the staging algorithm requires that we move foward
3415  * and backward in imaginary time (for periodic boundary conditions)
3416  * we perform the relinking now, and change back to the original
3417  * linking only if we reject the move */
3418 
3419  /* Store temporary bead locators for all the linkages that
3420  * will be changed */
3421  nextSwap = path.next(swap);
3422 
3423  /* Update the links. Here we exploit the non-constant return reference
3424  * semantics of the next/prev methods */
3425  path.next(path.worm.head) = nextSwap;
3426  path.next(swap) = XXX;
3427  path.prev(nextSwap) = path.worm.head;
3428 
3429  /* Change the former head to a special bead, and assign the new head */
3431  path.worm.head = swap;
3432 
3433  /* Propose a new trajectory */
3434  beadIndex = path.worm.special1;
3435  k = 0;
3436  do {
3437  if (!all(beadIndex==path.worm.special1) && !all(beadIndex==pivot)) {
3438  path.updateBead(beadIndex,
3439  newStagingPosition(path.prev(beadIndex),pivot,swapLength,k,wind));
3440  ++k;
3441  }
3442  beadIndex = path.next(beadIndex);
3443  } while (!all(beadIndex==path.next(pivot)));
3444 
3445  /* Compute the potential action for the updated path */
3447 
3448  if ( random.rand() < exp(-(newAction - oldAction))) {
3449  keepMove();
3450  checkMove(1,newAction-oldAction);
3451  }
3452  else {
3453  undoMove();
3454  checkMove(2,0.0);
3455  }
3456 
3457  } // PNorm
3458 
3459  } // if we didn't find the tail and grid boxes coincide
3460 
3461  } // numListBeads = 0
3462 
3463  } // isConfigDiagonal
3464 
3465  return success;
3466 }
3467 
3468 /*************************************************************************/
3471 void SwapHeadMove::keepMove() {
3472 
3473  /* update the acceptance counters */
3474  numAccepted++;
3475  totAccepted++;
3477 
3478  /* Now we update the properties of our worm. Head is replaced with
3479  * swap and we must update the length and gap */
3481 
3482  printMoveState("Performed a head swap.");
3483  success = true;
3484 }
3485 
3486 /*************************************************************************/
3490 void SwapHeadMove::undoMove() {
3491 
3492  /* Reassign the head bead */
3494 
3495  /* Return all links to their un-swapped values */
3496  path.next(path.worm.head) = XXX;
3497  path.next(swap) = nextSwap;
3498  path.prev(nextSwap) = swap;
3499 
3500  /* Return the path to its original coordinates */
3501  beadLocator beadIndex;
3502  beadIndex = path.next(swap);
3503  int k = 0;
3504  do {
3505  path.updateBead(beadIndex,originalPos(k));
3506  ++k;
3507  beadIndex = path.next(beadIndex);
3508  } while (!all(beadIndex==pivot));
3509 
3510  /* Make sure the configuration is still off-diagonal */
3511  path.worm.isConfigDiagonal = false;
3512 
3513  /* Unset the special beads */
3514  path.worm.special1 = XXX;
3515  path.worm.special2 = XXX;
3516 
3517  printMoveState("Failed to perform a head swap.");
3518  success = false;
3519 }
3520 
3521 // ---------------------------------------------------------------------------
3522 // ---------------------------------------------------------------------------
3523 // SWAP TAIL MOVE CLASS ------------------------------------------------------
3524 // ---------------------------------------------------------------------------
3525 // ---------------------------------------------------------------------------
3526 
3527 /*************************************************************************/
3531  MTRand &_random, ensemble _operateOnConfig) :
3532  SwapMoveBase(_path,_actionPtr,_random,_operateOnConfig) {
3533 
3534  /* Initialize private data to zero */
3536 
3537  /* Update the sizes of the original position array */
3538  originalPos.resize(constants()->Mbar()-1);
3539  originalPos = 0.0;
3540 }
3541 
3542 /*************************************************************************/
3546 }
3547 
3548 /*************************************************************************/
3555 
3556  success = false;
3557 
3558  /* Only perform a move if we have beads */
3559  if (path.worm.getNumBeadsOn() == 0)
3560  return success;
3561 
3562  /* We first make sure we are in an off-diagonal configuration */
3563  if (!path.worm.isConfigDiagonal) {
3564 
3565  /* Initialize */
3566  pivot = XXX;
3567  swap = XXX;
3568 
3569  /* Now we figure out how many beads will be involved with the swap bisection. */
3570  swapLength = constants()->Mbar();
3571  numLevels = int (ceil(log(1.0*swapLength) / log(2.0)-EPS));
3572 
3573  /* Now form the list of beads which are in the neighbourhood of
3574  * the tail, but at the regressed time slice */
3575  int pivotSlice = path.worm.tail[0] - swapLength;
3576  if (pivotSlice < 0)
3577  pivotSlice += constants()->numTimeSlices();
3578 
3580 
3581  /* We can only try to make a move if we have at least one bead to swap with */
3582  if (path.lookup.fullNumBeads > 0) {
3583 
3584  /* We compute the normalization factors using the tail bead */
3585  /* We have a factor of -1 here due to the tail */
3586  SigmaTail = getNorm(path.worm.tail,-1);
3587 
3588  /* Get the pivot bead and winding sector */
3589  iVec wind;
3590  wind = 0;
3591  pivot = selectPivotBead(wind);
3592 
3593  /* Now we try to find the swap bead. If we find the worm head, we immediatly
3594  * exit the move */
3595  beadLocator beadIndex;
3596  beadIndex = pivot;
3597  for (int k = 0; k < swapLength; k++) {
3598  if (all(beadIndex==path.worm.head))
3599  return false;
3600  beadIndex = path.next(beadIndex);
3601  }
3602  swap = beadIndex;
3603 
3604  /* We only continue if we don't find the head, and the pivot and swap grid
3605  * boxes coincide, otherwise we reject the move. */
3606  if ( !all(path.worm.head==swap) && path.lookup.gridNeighbors(pivot,swap) ) {
3607 
3608  checkMove(0,0.0);
3609 
3610  /* Increment the number of swap moves and the total number of moves */
3611  numAttempted++;
3612  totAttempted++;
3614 
3615  /* Now we create a new list of beads (using the same beadList)
3616  * which contains all beads in neighborhood of the swap bead
3617  * grid box, but at a time slice advanced by Mbar. We only
3618  * do this if tail and swap are in different grid boxes. */
3621 
3622  /* Get the normalization factor for the new list */
3623  SigmaSwap = getNorm(swap);
3624 
3625  /* We now perform a pre-metropolis step on the selected bead. If this
3626  * is not accepted, it is extremely unlikely that the potential change
3627  * will have any effect, so we don't bother with it. */
3628  double PNorm = min(SigmaTail/SigmaSwap,1.0);
3629  if (random.rand() < PNorm) {
3630 
3631  /* Mark the swap and pivot as special */
3632  path.worm.special1 = swap;
3633  path.worm.special2 = pivot;
3634 
3635  int k = 0;
3636  oldAction = newAction = 0.0;
3637 
3638  /* Store the old trajectory and compute its action */
3639  beadIndex = pivot;
3640  do {
3641  if (!all(beadIndex==swap) && !all(beadIndex==pivot)) {
3642  originalPos(k) = path(beadIndex);
3643  ++k;
3644  }
3645  beadIndex = path.next(beadIndex);
3646  } while (!all(beadIndex==path.next(swap)));
3647 
3649 
3650  /* Because the staging algorithm requires that we move foward
3651  * and backward in imaginary time (for periodic boundary conditions)
3652  * we perform the relinking now, and change back to the original
3653  * linking only if we reject the move */
3654 
3655  /* Store temporary bead locators for all the linkages that
3656  * will be changed */
3657  prevSwap = path.prev(swap);
3658 
3659  /* Update the links. Here we exploit the non-constant return reference
3660  * semantics of the next/prev methods */
3661  path.prev(path.worm.tail) = prevSwap;
3662  path.prev(swap) = XXX;
3663  path.next(prevSwap) = path.worm.tail;
3664 
3665  /* Change the former tail to a special bead, and assign the new tail */
3667  path.worm.tail = swap;
3668 
3669  /* Propose a new path trajectory and compute its action */
3670  k = 0;
3671  beadIndex = pivot;
3672  do {
3673  if (!all(beadIndex==path.worm.special1) && !all(beadIndex==pivot)) {
3674  path.updateBead(beadIndex,
3675  newStagingPosition(path.prev(beadIndex),path.worm.special1,swapLength,k,wind));
3676  ++k;
3677  }
3678  beadIndex = path.next(beadIndex);
3679  } while (!all(beadIndex==path.next(path.worm.special1)));
3680 
3682 
3683  /* Perform the Metropolis test */
3684  if ( random.rand() < exp(-(newAction - oldAction))) {
3685  keepMove();
3686  checkMove(1,newAction-oldAction);
3687  }
3688  else {
3689  undoMove();
3690  checkMove(2,0.0);
3691  }
3692 
3693  } // PNorm
3694 
3695  } // if we didn't find the tail and the grid boxes coincide
3696 
3697  } // numListBeads = 0
3698 
3699  } // isConfigDiagonal
3700 
3701  return success;
3702 }
3703 
3704 /*************************************************************************/
3707 void SwapTailMove::keepMove() {
3708 
3709  /* update the acceptance counters */
3710  numAccepted++;
3711  totAccepted++;
3713 
3714  /* Now we update the properties of our worm. Tail is replaced with
3715  * swap and we must update the length and gap */
3717 
3718  /* Restore the shift level for the time step to 1 */
3719  actionPtr->setShift(1);
3720 
3721  printMoveState("Performed a tail swap.");
3722  success = true;
3723 }
3724 
3725 /*************************************************************************/
3729 void SwapTailMove::undoMove() {
3730 
3731  /* Copy back the tail bead */
3733 
3734  /* Return all links to their un-swapped values */
3735  path.prev(path.worm.tail) = XXX;
3736  path.prev(swap) = prevSwap;
3737  path.next(prevSwap) = swap;
3738 
3739  beadLocator beadIndex;
3740  beadIndex = path.next(pivot);
3741  int k = 0;
3742  do {
3743  path.updateBead(beadIndex,originalPos(k));
3744  ++k;
3745  beadIndex = path.next(beadIndex);
3746  } while (!all(beadIndex==swap));
3747 
3748  /* Unset the special beads */
3749  path.worm.special1 = XXX;
3750  path.worm.special2 = XXX;
3751 
3752  /* Make sure the configuration is still off-diagonal */
3753  path.worm.isConfigDiagonal = false;
3754 
3755  printMoveState("Failed to perform a tail swap.");
3756  success = false;
3757 }
Action class definitions.
Holds a base class that all action classes will be derived from.
Definition: action.h:29
const bool local
Is the action local in imaginary time?
Definition: action.h:103
virtual double potentialAction()
The effective potential inter-ACTION for various pass conditions.
Definition: action.h:48
double ensembleWeight(const int)
The ensemble particle number weighting factor.
Definition: action.cpp:122
double kineticAction()
The full kinetic Action
Definition: action.cpp:205
void setShift(int _shift)
The public method that sets the tau scaling factor.
Definition: action.h:89
double rho0(const dVec &, const dVec &, int)
The free-particle density matrix.
Definition: action.cpp:83
A derived class which performs an advance head move, causing the head of a worm in a off-diagonal con...
Definition: move.h:438
~AdvanceHeadMove()
Destructor.
Definition: move.cpp:2419
AdvanceHeadMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2408
bool attemptMove()
Perform an advance head move.
Definition: move.cpp:2430
A derived class which performs an advance tail move, causing the tail of a worm in a off-diagonal con...
Definition: move.h:472
~AdvanceTailMove()
Destructor.
Definition: move.cpp:2598
bool attemptMove()
Perform an advance tail move.
Definition: move.cpp:2609
AdvanceTailMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2587
A derived class which performs a bisection move, which exactly samples the kinetic action.
Definition: move.h:296
BisectionMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:1440
bool attemptMove()
Bisection Move : attempt Move.
Definition: move.cpp:1486
~BisectionMove()
Destructor.
Definition: move.cpp:1468
A derived class which performs a simple displacement of the center of mass of the entire wordline for...
Definition: move.h:247
CenterOfMassMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:1102
bool attemptMove()
Performs a Center of Mass move.
Definition: move.cpp:1126
~CenterOfMassMove()
Destructor.
Definition: move.cpp:1117
A derived class which performs a close move, creating a diagonal world line configuration.
Definition: move.h:357
bool attemptMove()
Perform a close move.
Definition: move.cpp:1881
~CloseMove()
Destructor.
Definition: move.cpp:1869
CloseMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:1858
File * file(string type)
Get method returning file object.
Definition: communicator.h:85
int numTimeSlices()
Get number of time slices.
Definition: constants.h:99
int maxWind()
Get the maximum winding number sampled.
Definition: constants.h:101
double mu() const
Get chemical potential.
Definition: constants.h:43
int Mbar()
Get Mbar.
Definition: constants.h:97
double tau() const
Get imaginary time step.
Definition: constants.h:44
int b()
Get bisection level.
Definition: constants.h:98
double comDelta() const
Get center of mass shift.
Definition: constants.h:53
double C() const
Get full worm constant.
Definition: constants.h:50
virtual dVec randPosition(MTRand &) const =0
Random position inside a box.
double volume
The volume of the container in A^3.
Definition: container.h:35
TinyVector< unsigned int, NDIM > periodic
Determines which dimensions have periodic bc.
Definition: container.h:29
virtual dVec randUpdate(MTRand &, const dVec &) const =0
Random updated position inside a box.
void putInBC(dVec &r) const
Place a vector in boundary conditions.
Definition: container.h:50
virtual void putInside(dVec &) const =0
Place a vector inside the simulation cell.
dVec side
The linear dimensions of the box.
Definition: container.h:31
A derived class which performs a simple single slice displacement move.
Definition: move.h:153
bool attemptMove()
Perform a single slice update on the head or tail.
Definition: move.cpp:523
DisplaceMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:503
EndStagingMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:656
bool attemptMove()
Perform a single slice update on the head or tail.
Definition: move.cpp:674
A derived class which performs an insert move, creating an off-diagonal world line configuration with...
Definition: move.h:385
bool attemptMove()
Perform an insert move.
Definition: move.cpp:2081
InsertMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=DIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2058
~InsertMove()
Destructor.
Definition: move.cpp:2069
int fullNumBeads
The full number of active beads in beadList;.
Definition: lookuptable.h:44
void updateFullInteractionList(const beadLocator &, const int)
Fill up the fullBeadList array with a list of beads in the same grid box as the supplied beadIndex an...
bool gridNeighbors(const beadLocator &, const beadLocator &)
Given two beadIndices, determine if the beads lie in neighboring grid boxes.
Array< beadLocator, 1 > fullBeadList
The full dynamic list of interacting beads.
Definition: lookuptable.h:41
bool gridShare(const beadLocator &bead1, const beadLocator &bead2)
Determine if two beads are in the same grid box.
Definition: lookuptable.h:90
MidStagingMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:837
bool attemptMove()
CMH: Add a description for this update.
Definition: move.cpp:854
The base class that all moves will be derived from.
Definition: move.h:30
double sqrtLambdaTau
sqrt(Lambda * tau)
Definition: move.h:112
virtual ~MoveBase()
Destructor.
Definition: move.cpp:138
dVec neighborPos
Staging neighbor position.
Definition: move.h:115
uint32 numAttempted
The number of attempted moves.
Definition: move.h:87
Array< dVec, 1 > originalPos
The original particle positions.
Definition: move.h:97
vector< iVec > winding
The winding vectors
Definition: move.h:100
Array< dVec, 1 > newPos
New particle positions.
Definition: move.h:98
iVec getWindingNumber(const beadLocator &, const beadLocator &)
Find the winding number for a path between two beads.
Definition: move.cpp:409
double oldV
The old and new potential action.
Definition: move.h:140
Path & path
A reference to the paths.
Definition: move.h:80
dVec newFreeParticlePosition(const beadLocator &)
Generates a new position, which exactly samples the free particle density matrix.
Definition: move.cpp:448
int numWind
The total number of winding vectors.
Definition: move.h:105
dVec newStagingPosition(const beadLocator &, const beadLocator &, const int, const int)
Returns a new staging position which will exactly sample the kinetic action.
Definition: move.cpp:268
iVec sampleWindingSector(const beadLocator &, const beadLocator &, const int, double &)
Obtain a winding sector for a stage-like move.
Definition: move.cpp:357
dVec newBisectionPosition(const beadLocator &, const int)
Returns a new bisection position which will exactly sample the kinetic action.
Definition: move.cpp:469
MTRand & random
A reference to the RNG.
Definition: move.h:82
beadLocator nBeadIndex
Neighbor bead index.
Definition: move.h:114
double deltaAction
The action difference.
Definition: move.h:109
ActionBase * actionPtr
A base pointer to the action.
Definition: move.h:81
int numToMove
The number of particles moved.
Definition: move.h:88
virtual string getName()
return the move name
Definition: move.h:42
uint32 numAccepted
The number of accepted moves.
Definition: move.h:86
dVec newRanPos
Staing random position.
Definition: move.h:116
static uint32 totAccepted
The total number of moves accepted.
Definition: move.h:91
virtual void keepMove()
Keep the move.
Definition: move.cpp:248
double newAction
The new potential action.
Definition: move.h:108
Array< uint32, 1 > numAttemptedLevel
The number of moves attempted at each level.
Definition: move.h:95
bool success
Did we sucessfully perform a move?
Definition: move.h:84
double sqrt2LambdaTau
sqrt(2 * Lambda * tau)
Definition: move.h:111
double oldAction
The original potential action.
Definition: move.h:107
static uint32 totAttempted
The total number of moves attempted.
Definition: move.h:92
Array< uint32, 1 > numAcceptedLevel
The number of moves accepted at each level.
Definition: move.h:94
vector< double > cumrho0
Used for tower-sampling winding sectors.
Definition: move.h:102
double oldK
The old and new kinetic action.
Definition: move.h:139
A derived class which performs an open move, creating a worm with a well defined head and tail.
Definition: move.h:329
OpenMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=DIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:1658
bool attemptMove()
Perform an open move.
Definition: move.cpp:1680
~OpenMove()
Destructor.
Definition: move.cpp:1669
The space-time trajectories.
Definition: path.h:29
bool inSubregionA(const beadLocator &) const
Checks to see if bead is in subregion A/B at break slice + 1.
Definition: path.cpp:518
beadLocator delBeadGetNext(const beadLocator &)
Delete a bead and move forwards.
Definition: path.cpp:326
beadLocator delBeadGetPrev(const beadLocator &)
Delete a bead and move backwards.
Definition: path.cpp:309
vector< int > closedWorldlines
A list of particles with closed worldlines on left of break.
Definition: path.h:41
vector< int > brokenWorldlinesR
A list of particles with broken worldlines on right of break.
Definition: path.h:40
void printWormConfig(Array< beadLocator, 1 > &)
Used when debugging worm configurations.
Definition: path.cpp:743
void makeLink(const beadLocator &, const beadLocator &)
Make a link between beads.
Definition: path.cpp:415
dVec getSeparation(const beadLocator &, const beadLocator &) const
Return the separation vector between two particles in the same timeslice.
Definition: path.h:173
vector< int > brokenWorldlinesL
A list of particles with broken worldlines on left of break.
Definition: path.h:39
void removeCenterLink(const beadLocator &)
Break the link to right of bead t center slice AND update lists.
Definition: path.cpp:423
const int numTimeSlices
A local constant copy of the number of time slices.
Definition: path.h:37
beadLocator addPrevBead(const beadLocator &, const dVec &)
Add a bead at the previous time slice.
Definition: path.cpp:221
Array< int, 1 > numBeadsAtSlice
The number of active beads at a given time slice.
Definition: path.h:48
int breakSlice
The location of the break in the path (0=>no break)
Definition: path.h:38
beadLocator addBead(const int, const dVec &)
Add a bead to the worldline configuration at a given slice.
Definition: path.cpp:250
void addCenterLink(const beadLocator &, const beadLocator &)
Make a link between beads at center slice AND update lists.
Definition: path.cpp:441
bool inSubregionB(const beadLocator &) const
Check if bead is in subregion B.
Definition: path.cpp:533
void printLinks(Tstream &)
Output bead-link info, used for debugging.
Definition: path.h:250
void updateBead(const beadLocator &, const dVec &)
Update the position of a bead in the worldine configuration.
Definition: path.cpp:182
beadLocator & next(int slice, int ptcl)
Move one link forward in imaginary time.
Definition: path.h:86
const Container * boxPtr
A constant reference to the container class.
Definition: path.h:43
Worm worm
Details on the worm.
Definition: path.h:44
beadLocator & prev(int slice, int ptcl)
Move one link backward in imaginary time.
Definition: path.h:95
beadLocator addNextBead(const beadLocator &, const dVec &)
Add a bead at the next time slice.
Definition: path.cpp:194
LookupTable & lookup
A reference to the nearest neighbor lookup table.
Definition: path.h:46
void breakLink(const beadLocator &)
Break the link to right of bead.
Definition: path.cpp:406
int getTrueNumParticles() const
The number of active particles.
Definition: path.h:54
A derived class which performs a recede move on the head, causing a worm head to propagate backwards ...
Definition: move.h:500
bool attemptMove()
Perform a recede head move.
Definition: move.cpp:2780
~RecedeHeadMove()
Destructor.
Definition: move.cpp:2770
RecedeHeadMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2759
A derived class which performs a recede move on the tail, causing a worm tail to propagate backwards ...
Definition: move.h:527
RecedeTailMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2926
bool attemptMove()
Perform a recede tail move.
Definition: move.cpp:2947
~RecedeTailMove()
Destructor.
Definition: move.cpp:2937
A derived class which performs a remove move, creating a diagonal world line configuration by destroy...
Definition: move.h:413
bool attemptMove()
Perform a remove move.
Definition: move.cpp:2266
RemoveMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL, bool _varLength=true)
Constructor.
Definition: move.cpp:2243
~RemoveMove()
Destructor.
Definition: move.cpp:2254
A derived class which performs a staging move, which exactly samples the kinetic action.
Definition: move.h:271
bool attemptMove()
Perform the staging move.
Definition: move.cpp:1316
StagingMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:1289
~StagingMove()
Destructor.
Definition: move.cpp:1306
SwapBreakMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=ANY)
Constructor.
Definition: move.cpp:1007
bool attemptMove()
CMH: Please add a method description for this move.
Definition: move.cpp:1023
A derived class which performs a swap head move, which mixes up worldlines by reconnecting the worm h...
Definition: move.h:591
~SwapHeadMove()
Destructor.
Definition: move.cpp:3307
SwapHeadMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL)
Constructor.
Definition: move.cpp:3292
bool attemptMove()
Perform a swap head move.
Definition: move.cpp:3317
A derived class which forms the base of a swap head and swap tail move class.
Definition: move.h:554
beadLocator pivot
The pivot bead.
Definition: move.h:568
SwapMoveBase(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL)
Constructor.
Definition: move.cpp:3105
vector< double > cumulant
The cumulant array used in selecting a pivot.
Definition: move.h:566
beadLocator selectPivotBead()
Select the pivot bead for a swap move.
Definition: move.cpp:3269
double SigmaSwap
Probability normalization factor.
Definition: move.h:571
~SwapMoveBase()
Destructor.
Definition: move.cpp:3113
double getNorm(const beadLocator &, const int sign=1)
Get the normalization constant for a swap move.
Definition: move.cpp:3141
unsigned int sizeCDF
The size of the cumulative distribution function.
Definition: move.h:564
beadLocator swap
The swap bead.
Definition: move.h:569
int swapLength
The length of worldLine to be moved.
Definition: move.h:562
int numLevels
The number of bisection levels.
Definition: move.h:563
A derived class which performs a swap tail move, which mixes up worldlines by reconnecting the worm t...
Definition: move.h:619
~SwapTailMove()
Destructor.
Definition: move.cpp:3545
bool attemptMove()
Perform a swap tail move.
Definition: move.cpp:3554
SwapTailMove(Path &, ActionBase *, MTRand &, ensemble _operateOnConfig=OFFDIAGONAL)
Constructor.
Definition: move.cpp:3530
bool isConfigDiagonal
Stores the diagonality of the configuration.
Definition: worm.h:39
int gap
numTimeSlices - length
Definition: worm.h:38
beadLocator tail
The coordinates of the worm tail.
Definition: worm.h:32
beadLocator head
The coordinates of the worm head.
Definition: worm.h:31
beadLocator special2
Special bead, used in move updates.
Definition: worm.h:34
void update(Path &, const beadLocator &, const beadLocator &)
We update all worm properties for a new head and tail.
Definition: worm.cpp:69
int beadOn(int, int) const
Safely get a bead (int indexed)
Definition: worm.h:148
bool tooCostly()
Return true if the worm is too costly.
Definition: worm.h:68
void reset()
Reset the worm to a null state.
Definition: worm.cpp:53
int getNumBeadsOn() const
Return the number of active beads.
Definition: worm.h:88
beadLocator special1
Special bead, used in move updates.
Definition: worm.h:33
int length
The length of the worm.
Definition: worm.h:37
Ttype & max(Ttype &x, Ttype &y)
Maximum of two inputs.
Definition: common.h:146
#define NDIM
Number of spatial dimnsions.
Definition: common.h:71
int ipow(int base, int power)
Return the integer value of a number raised to a power.
Definition: common.h:136
unsigned long uint32
Unsigned integer type, at least 32 bits.
Definition: common.h:105
TinyVector< int, 2 > beadLocator
time-slice,bead-number world line index
Definition: common.h:117
ensemble
Each move can operate on only the digaonal ensemble, only the off-diagonal ensemble,...
Definition: common.h:133
#define EPS
A small number.
Definition: common.h:94
Ttype & min(Ttype &x, Ttype &y)
Minimum of two inputs.
Definition: common.h:142
TinyVector< double, NDIM > dVec
A NDIM-vector of type double.
Definition: common.h:111
#define PIMC_ASSERT(X)
Rename assert method.
Definition: common.h:64
TinyVector< int, NDIM > iVec
A NDIM-vector of type integer.
Definition: common.h:114
#define XXX
Used to refer to a nonsense beadIndex.
Definition: common.h:98
Class definitions for all file input/output.
Communicator * communicate()
Global public access to the communcator singleton.
Definition: communicator.h:121
ConstantParameters * constants()
Global public access to the constants.
Definition: constants.h:201
Factory class definitions.
LookupTable class definition.
MoveFactory moveFactory
Setup the move factory.
Definition: move.cpp:22
Move class definitions.
Path class definition.