Path Integral Quantum Monte Carlo
action.cpp
Go to the documentation of this file.
1 
8 #include "action.h"
9 #include "path.h"
10 #include "potential.h"
11 #include "lookuptable.h"
12 #include "wavefunction.h"
13 
14 // ---------------------------------------------------------------------------
15 // ---------------------------------------------------------------------------
16 // ACTION BASE CLASS --------------------------------------------------------
17 // ---------------------------------------------------------------------------
18 // ---------------------------------------------------------------------------
19 
20 /**************************************************************************/
23 ActionBase::ActionBase (const Path &_path, LookupTable &_lookup,
24  PotentialBase *_externalPtr, PotentialBase *_interactionPtr,
25  WaveFunctionBase *_waveFunctionPtr, bool _local, string _name,
26  double _endFactor, int _period) :
27  local(_local),
28  period(_period),
29  externalPtr(_externalPtr),
30  interactionPtr(_interactionPtr),
31  name(_name),
32  lookup(_lookup),
33  path(_path),
34  waveFunctionPtr(_waveFunctionPtr),
35  endFactor(_endFactor)
36 {
37 
38  /* The default tau scale is 1 */
39  shift = 1;
40 
41  /* Initialize the separation histogram */
42  sepHist.resize(NPCFSEP);
43  sepHist = 0;
44  cylSepHist.resize(NPCFSEP);
45  cylSepHist = 0;
46  dSep = 0.5*sqrt(sum(path.boxPtr->periodic))*path.boxPtr->side[NDIM-1] / (1.0*NPCFSEP);
47 
48  /* Needed for canonical ensemble weighting */
51  window = constants()->window();
52  windowWidth = constants()->windowWidth();
53  gaussianEnsemble = constants()->gaussianEnsemble();
54  gaussianEnsembleSD = constants()->gaussianEnsembleSD();
55 }
56 
57 /**************************************************************************/
61  sepHist.free();
62  cylSepHist.free();
63 }
64 
65 /*************************************************************************/
71 inline void ActionBase::updateSepHist(const dVec &_sep) {
72  dVec psep;
73  psep = path.boxPtr->periodic*_sep;
74  int nR = int(sqrt(dot(psep,psep))/dSep);
75  if (nR < NPCFSEP)
76  ++sepHist(nR);
77 }
78 
79 /**************************************************************************/
83 double ActionBase::rho0(const dVec &r1, const dVec &r2, int M) {
84  dVec vel;
85  vel = r2 - r1;
86  path.boxPtr->putInBC(vel);
87  double rho0Norm = pow(4.0*M_PI*constants()->lambda()*M*constants()->tau(),-0.5*NDIM);
88  return ( rho0Norm * exp(-dot(vel,vel) / (4.0*constants()->lambda()*M*constants()->tau()) ) );
89 }
90 
91 /**************************************************************************/
95 double ActionBase::rho0(const beadLocator &bead1, const beadLocator &bead4, int M) {
96  dVec vel;
97  vel = path.getSeparation(bead1,bead4);
98  double rho0Norm = pow(4.0*M_PI*constants()->lambda()*M*constants()->tau(),-0.5*NDIM);
99  return ( rho0Norm * exp(-dot(vel,vel) / (4.0*constants()->lambda()*M*constants()->tau()) ) );
100 }
101 
102 /**************************************************************************/
110 double ActionBase::rho0(const dVec &vel, const int M) {
111  double rho0Norm = pow(4.0*M_PI*constants()->lambda()*M*constants()->tau(),-0.5*NDIM);
112  return ( rho0Norm * exp(-dot(vel,vel) / (4.0*constants()->lambda()*M*constants()->tau()) ) );
113 }
114 
115 /**************************************************************************/
122 double ActionBase::ensembleWeight(const int deltaNumBeads) {
123 
124  // ensembleWieght returns 1.0 unless window or ensemble weight is used
125  if ( window || gaussianEnsemble ){
126  int numBeads = path.worm.getNumBeadsOn();
127  int numBeadsP = numBeads + deltaNumBeads;
128 
129  // Check if we are within bead window
130  if (window){
131  int beadWindowWidth = path.numTimeSlices*windowWidth;
132  if ( ( numBeadsP > (numBeads0+beadWindowWidth) )||
133  (numBeadsP < (numBeads0-beadWindowWidth)) )
134  return 0.0;
135  }
136  // If we are within window check gaussian weight
137  if (gaussianEnsemble){
138  double sigmaBeads = path.numTimeSlices*gaussianEnsembleSD;
139  double xp = 1.0*(numBeadsP-numBeads0)*(numBeadsP-numBeads0)/
140  (2.0*sigmaBeads*sigmaBeads);
141  double x = 1.0*(numBeads-numBeads0)*(numBeads-numBeads0)/
142  (2.0*sigmaBeads*sigmaBeads);
143  return exp(-xp+x);
144  }
145  else
146  return 1.0;
147  }
148  else
149  return 1.0; // Return 1.0 if no enembleWeight is used
150 
151 }
152 
153 /**************************************************************************/
159 double ActionBase::kineticAction (const beadLocator &beadIndex) {
160 
161  double totK = 0.0;
162  /* We get the Kinetic action for a single slice, which connects
163  * to two other slices */
164  dVec vel;
165  vel = path.getVelocity(path.prev(beadIndex));
166  totK += dot(vel,vel);
167  vel = path.getVelocity(beadIndex);
168  totK += dot(vel,vel);
169 
170  return totK / (4.0*constants()->lambda()*tau());
171 }
172 
173 /**************************************************************************/
180 double ActionBase::kineticAction (const beadLocator &beadIndex, int wlLength) {
181 
182  double totK = 0.0;
183 
184  /* Make a local copy of beadIndex */
185  beadLocator beadID;
186  beadID = beadIndex;
187 
188  /* Starting from the initial bead, move wlLength slices in imaginary time
189  * and accumulate the kinetic action */
190  dVec vel;
191  for (int n = 0; n < wlLength; n++) {
192  vel = path.getVelocity(beadID);
193  totK += dot(vel, vel);
194  beadID = path.next(beadID);
195  }
196 
197  return totK / (4.0*constants()->lambda()*tau());
198 }
199 
200 /**************************************************************************/
206 
207  double totK = 0.0;
208 
209  /* Calculate the kinetic energy. Even though there
210  * may be multiple mixing and swaps, it doesn't matter as we always
211  * just advance one time step at a time, as taken care of through the
212  * linking arrays. This has been checked! */
213  beadLocator beadIndex;
214  for (int slice = 0; slice < path.numTimeSlices; slice++) {
215  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
216  beadIndex = slice,ptcl;
217  totK += kineticAction(beadIndex);
218  }
219  }
220 
221  return totK;
222 }
223 
224 /**************************************************************************/
237 double ActionBase::potentialAction (const beadLocator &startBead,
238  const beadLocator &endBead) {
239 
240  double totU = 0.0;
241  beadLocator beadIndex;
242  beadIndex = startBead;
243  do {
244  totU += potentialAction(beadIndex);
245  beadIndex = path.next(beadIndex);
246  } while (!all(beadIndex==path.next(endBead)));
247  return totU;
248 }
249 
250 // ---------------------------------------------------------------------------
251 // ---------------------------------------------------------------------------
252 // LOCAL ACTION BASE CLASS ---------------------------------------------------
253 // ---------------------------------------------------------------------------
254 // ---------------------------------------------------------------------------
255 
256 /**************************************************************************/
259 LocalAction::LocalAction (const Path &_path, LookupTable &_lookup,
260  PotentialBase *_externalPtr, PotentialBase *_interactionPtr,
261  WaveFunctionBase *_waveFunctionPtr, const TinyVector<double,2> &_VFactor,
262  const TinyVector<double,2> & _gradVFactor, bool _local, string _name,
263  double _endFactor, int _period) :
264  ActionBase(_path,_lookup,_externalPtr,_interactionPtr,_waveFunctionPtr,
265  _local,_name,_endFactor,_period),
266  VFactor(_VFactor),
267  gradVFactor(_gradVFactor)
268 {
269  shift = 1;
270 }
271 
272 /**************************************************************************/
276 }
277 
278 /**************************************************************************/
290 
291  double totU = 0.0;
292 
293  /* Combine the potential and a possible correction */
294  for (int slice = 0; slice < path.numTimeSlices; slice++) {
295  eo = (slice % 2);
296  totU += VFactor[eo]*tau()*sum(V(slice));
297 
298  /* We only add the correction if it is finite */
299  if ( gradVFactor[eo] > EPS )
300  totU += gradVFactor[eo] * tau() * tau() * tau() * constants()->lambda()
301  * gradVSquared(slice);
302  }
303 
304  return ( totU );
305 }
306 
307 /**************************************************************************/
320 double LocalAction::potentialAction (const beadLocator &beadIndex) {
321 
322  double bareU = 0.0;
323  double corU = 0.0;
324  eo = (beadIndex[0] % 2);
325 
326  /* We first compute the base potential action piece */
327  bareU = VFactor[eo]*tau()*Vnn(beadIndex);
328 
329  /* If we have a finite correction and are not at the base level
330  * of bisection (shift=1) we compute the full correction */
331  if ( (shift == 1) && (gradVFactor[eo] > EPS) )
332  corU = gradVFactor[eo] * tau() * tau() * tau() * constants()->lambda()
333  * gradVnnSquared(beadIndex);
334 
335 #if PIGS
336  /* We tack on a trial wave function and boundary piece if necessary */
337  if ( (beadIndex[0] == 0) || (beadIndex[0] == (constants()->numTimeSlices()-1)) ) {
338  bareU *= 0.5*endFactor;
339  bareU -= log(waveFunctionPtr->PsiTrial(beadIndex[0]));
340  }
341 #endif
342 
343  return (bareU + corU);
344 }
345 
346 /**************************************************************************/
353 
354  double bareU = VFactor[beadIndex[0]%2]*tau()*Vnn(beadIndex);
355 
356 #if PIGS
357  /* We tack on a trial wave function and boundary piece if necessary */
358  if ( (beadIndex[0] == 0) || (beadIndex[0]== (constants()->numTimeSlices()-1)) ) {
359  bareU *= 0.5*endFactor;
360  bareU -= log(waveFunctionPtr->PsiTrial(beadIndex[0]));
361  }
362 #endif
363 
364  return bareU;
365 }
366 
367 /**************************************************************************/
373 
374  eo = (beadIndex[0] % 2);
375  /* If we have a finite correction */
376  if (gradVFactor[eo] > EPS) {
377 
378  /* We need to update the lookup table here */
379  lookup.updateInteractionList(path,beadIndex);
380 
381  /* Compute the correction */
382  return (gradVFactor[eo] * tau() * tau() * tau() * constants()->lambda()
383  * gradVnnSquared(beadIndex));
384  }
385  else
386  return 0.0;
387 
388 }
389 
390 /**************************************************************************/
400  const beadLocator &endBead) {
401 
402  double corU = 0.0;
403  beadLocator beadIndex;
404  beadIndex = startBead;
405  do {
406  corU += potentialActionCorrection(beadIndex);
407  beadIndex = path.next(beadIndex);
408  } while (!all(beadIndex==path.next(endBead)));
409 
410  return corU;
411 }
412 
413 /**************************************************************************/
423 
424  double dU = 0.0;
425  eo = (slice % 2);
426 
427  /* We first compute the base potential action piece */
428  dU = VFactor[eo]*sum(V(slice));
429 
430  /* As long as there is a finite correction, we include it */
431  if ( gradVFactor[eo] > EPS )
432  dU += 3.0 * gradVFactor[eo] * tau() * tau() * constants()->lambda()
433  * gradVSquared(slice);
434  return (dU);
435 
436 }
437 
438 /**************************************************************************/
448 
449  double d2U = 0.0;
450  eo = (slice % 2);
451 
452  /* As long as there is a finite correction, we include it */
453  if ( gradVFactor[eo] > EPS )
454  d2U += 6.0 * gradVFactor[eo] * tau() * constants()->lambda()
455  * gradVSquared(slice);
456  return (d2U);
457 
458 }
459 
460 /**************************************************************************/
470  eo = (slice % 2);
471 
472  /* As long as thers is a finite correction, we include it */
473  if ( gradVFactor[eo] > EPS )
474  return gradVFactor[eo] * tau() * tau() * tau() * gradVSquared(slice);
475  else
476  return 0.0;
477 }
478 
479 /**************************************************************************/
489 double LocalAction::derivPotentialActionTau (int slice, double maxR) {
490 
491  double dU = 0.0;
492  eo = (slice % 2);
493 
494  /* We first compute the base potential action piece */
495  dU = VFactor[eo]*V(slice,maxR);
496 
497  /* As long as there is a finite correction, we include it */
498  if ( gradVFactor[eo] > EPS )
499  dU += 3.0 * gradVFactor[eo] * tau() * tau() * constants()->lambda()
500  * gradVSquared(slice,maxR);
501  return (dU);
502 
503 }
504 
505 /**************************************************************************/
515 double LocalAction::derivPotentialActionLambda (int slice, double maxR) {
516  eo = (slice % 2);
517 
518  /* As long as there is a finite correction, we include it */
519  if ( gradVFactor[eo] > EPS )
520  return gradVFactor[eo] * tau() * tau() * tau() * gradVSquared(slice,maxR);
521  else
522  return 0.0;
523 }
524 
525 /*************************************************************************/
529 double LocalAction::V(const beadLocator &bead1) {
530 
531  /* We only need to calculate the potential if the bead is on */
532  if (path.worm.beadOn(bead1)) {
533 
534  bead2[0] = bead1[0];
535 
536  /* Get the state of bead 1 */
537  beadState state1 = path.worm.getState(bead1);
538 
539  /* Calculate the total external potential */
540  double totVext = path.worm.factor(state1)*externalPtr->V(path(bead1));
541 
542  /* Now calculate the total interation potential, neglecting self-interactions */
543  double totVint = 0.0;
544 
545 
546  for (bead2[1]= 0; bead2[1] < path.numBeadsAtSlice(bead1[0]); bead2[1]++) {
547 
548  /* Skip self interactions */
549  if ( bead2[1] != bead1[1] ) {
550 
551  /* get the separation between the two particles */
552  sep = path.getSeparation(bead2,bead1);
553 
554  /* Now add the interaction potential */
555  totVint += path.worm.factor(state1,bead2) * interactionPtr->V(sep);
556  } // bead2 != bead1
557 
558  } // for bead2
559  return ( totVext + totVint );
560 
561  } // if bead1On
562  else
563  return 0.0;
564 }
565 
566 /*************************************************************************/
573 TinyVector<double,2> LocalAction::V(const int slice) {
574 
575  double totVint = 0.0;
576  double totVext = 0.0;
577 
578  beadLocator bead1;
579  bead1[0] = bead2[0] = slice;
580 
581  int numParticles = path.numBeadsAtSlice(slice);
582 
583  /* Initialize the separation histogram */
584  sepHist = 0;
585 
586  /* Calculate the total potential, including external and interaction
587  * effects*/
588  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
589 
590  /* Get the state of bead 1 */
591  beadState state1 = path.worm.getState(bead1);
592 
593  /* Evaluate the external potential */
594  totVext += path.worm.factor(state1)*externalPtr->V(path(bead1));
595 
596  /* The loop over all other particles, to find the total interaction
597  * potential */
598  for (bead2[1] = bead1[1]+1; bead2[1] < numParticles; bead2[1]++) {
599  sep = path.getSeparation(bead2,bead1);
600  updateSepHist(sep);
601  totVint += path.worm.factor(state1,bead2) * interactionPtr->V(sep);
602  } // bead2
603 
604  } // bead1
605 
606  /* Separate the external and interaction parts */
607  return TinyVector<double,2>(totVext,totVint);
608 }
609 
610 /*************************************************************************/
619 double LocalAction::V(const int slice, const double maxR) {
620 
621  double totVint = 0.0;
622  double totVext = 0.0;
623  dVec r1,r2;
624 
625  double r1sq,r2sq;
626 
627  beadLocator bead1;
628  bead1[0] = bead2[0] = slice;
629 
630  int numParticles = path.numBeadsAtSlice(slice);
631 
632  /* Initialize the separation histogram */
633  cylSepHist = 0;
634 
635  /* Calculate the total potential, including external and interaction
636  * effects*/
637  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
638 
639  r1 = path(bead1);
640 
641  r1sq = 0.0;
642  for (int i = 0; i < NDIM-1; i++)
643  r1sq += r1[i]*r1[i];
644 
645  if (r1sq < maxR*maxR) {
646 
647  /* Evaluate the external potential */
648  totVext += externalPtr->V(path(bead1));
649 
650  /* The loop over all other particles, to find the total interaction
651  * potential */
652  for (bead2[1] = bead1[1]+1; bead2[1] < numParticles; bead2[1]++) {
653  r2 = path(bead2);
654 
655  r2sq = 0.0;
656  for (int i = 0; i < NDIM-1; i++)
657  r2sq += r2[i]*r2[i];
658 
659  sep = path.getSeparation(bead2,bead1);
660  if (r2sq < maxR*maxR) {
661  int nR = int(abs(sep[2])/dSep);
662  if (nR < NPCFSEP)
663  ++cylSepHist(nR);
664  }
665  totVint += interactionPtr->V(sep);
666  } // bead2
667 
668  } // maxR
669  } // bead1
670 
671  return ( totVext + totVint );
672 }
673 
674 /*************************************************************************/
680 double LocalAction::Vnn(const beadLocator &bead1) {
681 
682  double totVint = 0.0;
683  double totVext = 0.0;
684 
685  /* We only continue if bead1 is turned on */
686  if (path.worm.beadOn(bead1)) {
687 
688  /* Fill up th nearest neighbor list */
690 
691  /* Get the state of bead 1 */
692  beadState state1 = path.worm.getState(bead1);
693 
694  /* Evaluate the external potential */
695  totVext = path.worm.factor(state1)*externalPtr->V(path(bead1));
696 
697  /* Sum the interaction potential over all NN beads */
698  for (int n = 0; n < lookup.numBeads; n++) {
699  totVint += path.worm.factor(state1,lookup.beadList(n))
701  }
702  }
703  return ( totVext + totVint );
704 }
705 
706 
707 /*************************************************************************/
713 double LocalAction::Vnn(const int slice) {
714 
715  Array <bool,1> doParticles(path.numBeadsAtSlice(slice));
716  doParticles = true;
717 
718  double totVint = 0.0;
719  double totVext = 0.0;
720 
721  iVec gIndex,nngIndex; // The grid box of a particle
722  TinyVector<int,NDIM+1> nnIndex; // The nearest neighbor boxes of a particle
723  TinyVector<int,NDIM+2> hI1,hI2; // The hash indices
724 
725  dVec pos; // The position of a particle
726 
727  beadLocator bead1; // Interacting beads
728  bead1[0] = slice;
729 
730  for (bead1[1] = 0; bead1[1] < path.numBeadsAtSlice(slice); bead1[1]++) {
731 
732  doParticles(bead1[1]) = false;
733 
734  /* Get the state of bead 1 */
735  beadState state1 = path.worm.getState(bead1);
736 
737  /* Accumulate the external potential */
738  pos = path(bead1);
739  totVext += path.worm.factor(state1)*externalPtr->V(pos);
740 
741  /* Get the interaction list */
743 
744  /* Sum the interaction potential over all NN beads */
745  for (int n = 0; n < lookup.numBeads; n++) {
746  bead2 = lookup.beadList(n);
747  if (doParticles(bead2[1])) {
748  sep = path.getSeparation(bead2,bead1);
749  totVint += path.worm.factor(state1,bead2) * interactionPtr->V(sep);
750  }
751  } // n
752 
753  } // bead1
754 
755  return ( totVext + totVint );
756 }
757 
758 /**************************************************************************/
763 
764  double totF2 = 0.0; // The total force squared
765 
766  if (path.worm.beadOn(bead1)) {
767 
768  /* All interacting beads are on the same slice. */
769  bead2[0] = bead3[0] = bead1[0];
770 
771  /* The 'forces' and particle separation */
772  dVec Fext1,Fext2;
773  dVec Fint1,Fint2,Fint3;
774 
775  int numParticles = path.numBeadsAtSlice(bead1[0]);
776 
777  /* Get the gradient squared part for the external potential*/
778  Fext1 = externalPtr->gradV(path(bead1));
779 
780  /* We loop through all beads and compute the forces between beads
781  * 1 and 2 */
782  Fint1 = 0.0;
783  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
784 
785  if (!all(bead1==bead2)) {
786 
787  sep = path.getSeparation(bead2,bead1);
788  Fint2 = interactionPtr->gradV(sep);
789  Fint1 -= Fint2;
790  Fext2 = externalPtr->gradV(path(bead2));
791 
792  /* There is a single term that depends on this additional interaction
793  * between beads 2 and 3. This is where all the time is taken */
794  Fint3 = 0.0;
795  for (bead3[1] = 0; bead3[1] < numParticles; bead3[1]++) {
796  if ( !all(bead3==bead2) && !all(bead3==bead1) ) {
797  sep = path.getSeparation(bead2,bead3);
798  Fint3 += interactionPtr->gradV(sep);
799  }
800  } // for bead3
801 
802  totF2 += dot(Fint2,Fint2) + 2.0*dot(Fext2,Fint2) + 2.0*dot(Fint2,Fint3);
803 
804  } //bead1 != bead2
805 
806  } // for bead2
807 
808  totF2 += dot(Fext1,Fext1) + 2.0 * dot(Fext1,Fint1) + dot(Fint1,Fint1);
809 
810  } // bead1 On
811 
812  return totF2;
813 }
814 
815 /**************************************************************************/
821 double LocalAction::gradVSquared(const int slice) {
822 
823  double totF2 = 0.0;
824 
825  int numParticles = path.numBeadsAtSlice(slice);
826 
827  /* The two interacting particles */
828  beadLocator bead1;
829  bead1[0] = bead2[0] = slice;
830 
831  dVec F; // The 'force'
832 
833  /* We loop over the first bead */
834  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
835 
836  F = 0.0;
837  /* Sum up potential for all other active beads in the system */
838  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
839 
840  /* Avoid self interactions */
841  if (!all(bead1==bead2)) {
842 
843  /* The interaction component of the force */
844  F += interactionPtr->gradV(path.getSeparation(bead1,bead2));
845  }
846 
847  } // end bead2
848 
849  /* Now add the external component */
850  F += externalPtr->gradV(path(bead1));
851 
852  totF2 += dot(F,F);
853  } // end bead1
854 
855  return totF2;
856 }
857 
858 /**************************************************************************/
864 double LocalAction::gradVSquared(const int slice, const double maxR) {
865 
866  double totF2 = 0.0;
867 
868  int numParticles = path.numBeadsAtSlice(slice);
869 
870  /* The two interacting particles */
871  beadLocator bead1;
872  bead1[0] = bead2[0] = slice;
873  dVec r1;
874  double r1sq;
875 
876  dVec F; // The 'force'
877 
878  /* We loop over the first bead */
879  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
880 
881  r1 = path(bead1);
882  r1sq = 0.0;
883  for (int i = 0; i < NDIM-1; i++)
884  r1sq += r1[i]*r1[i];
885 
886  if (r1sq < maxR*maxR) {
887 
888  F = 0.0;
889  /* Sum up potential for all other active beads in the system */
890  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
891  /* Avoid self interactions */
892  if (!all(bead1==bead2)) {
893 
894  /* The interaction component of the force */
895  F += interactionPtr->gradV(path.getSeparation(bead1,bead2));
896  }
897  } // end bead2
898 
899  /* Now add the external component */
900  F += externalPtr->gradV(path(bead1));
901 
902  totF2 += dot(F,F);
903  } // maxR
904  } // end bead1
905 
906  return totF2;
907 }
908 
909 /**************************************************************************/
916 
917  /* This should always be called after Vnn, such that the lookup table
918  * interaction list has been updated!!! */
919 
920  double totF2 = 0.0; // The total force squared
921 
922  if (path.worm.beadOn(bead1)) {
923 
924  /* The 'forces' and particle separation */
925  dVec Fext1,Fext2;
926  dVec Fint1,Fint2,Fint3;
927 
928  /* Get the gradient squared part for the external potential*/
929  Fext1 = externalPtr->gradV(path(bead1));
930 
931  /* We first loop over bead2's interacting with bead1 via the nn lookup table */
932  Fint1 = 0.0;
933  for (int n = 0; n < lookup.numBeads; n++) {
934  bead2 = lookup.beadList(n);
935 
936  /* Eliminate self and null interactions */
937  if ( !all(bead1 == bead2) ) {
938 
939  /* Get the separation between beads 1 and 2 and compute the terms in the
940  * gradient squared */
941  sep = lookup.beadSep(n);
942  Fint2 = interactionPtr->gradV(sep);
943  Fint1 -= Fint2;
944  Fext2 = externalPtr->gradV(path(bead2));
945 
946  /* We now loop over bead3, this is the time-intensive part of the calculation */
947  Fint3 = 0.0;
948  for (int m = 0; m < lookup.numBeads; m++) {
949  bead3 = lookup.beadList(m);
950 
951  /* Eliminate self-interactions */
952  if ( !all(bead3==bead2) && !all(bead3==bead1) ) {
953  sep = path.getSeparation(bead2,bead3);
954  Fint3 += interactionPtr->gradV(sep);
955  }
956 
957  } // end bead3
958 
959  totF2 += dot(Fint2,Fint2) + 2.0*dot(Fext2,Fint2) + 2.0*dot(Fint2,Fint3);
960 
961  } // bead2 != bead1
962 
963  } // end bead2
964 
965  totF2 += dot(Fext1,Fext1) + 2.0 * dot(Fext1,Fint1) + dot(Fint1,Fint1);
966 
967  } // bead1 on
968 
969  return totF2;
970 }
971 
972 /**************************************************************************/
978 dVec LocalAction::gradientV(const int slice) {
979 
980  int numParticles = path.numBeadsAtSlice(slice);
981 
982  /* The two interacting particles */
983  beadLocator bead1;
984  bead1[0] = bead2[0] = slice;
985 
986  dVec gV; // The 'force'
987 
988  /* We loop over the first bead */
989  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
990  gV = 0.0;
991  /* Sum up potential for all other active beads in the system */
992  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
993 
994  /* Avoid self interactions */
995  if (!all(bead1==bead2)) {
996 
997  /* The interaction component of the force */
998  gV += interactionPtr->gradV(path.getSeparation(bead1,bead2));
999  }
1000  } // end bead2
1001 
1002  /* Now add the external component */
1003  gV += externalPtr->gradV(path(bead1));
1004  } // end bead1
1005 
1006  return gV;
1007 }
1008 
1009 /*************************************************************************/
1015 dMat LocalAction::tMatrix(const int slice) {
1016 
1017  int numParticles = path.numBeadsAtSlice(slice);
1018 
1019  dMat tMat = 0.0; // tMat(row, col)
1020 
1021  dVec rDiff = 0.0;
1022  double rmag = 0.0;
1023  double d2V = 0.0;
1024  double dV = 0.0;
1025 
1026  /* two interacting particles */
1027  beadLocator bead1;
1028  bead1[0] = bead2[0] = slice;
1029 
1030  for (int a=0; a<NDIM; a++){
1031  for (int b=0; b<NDIM; b++){
1032 
1033  /* loop over first bead */
1034  for (bead1[1]=0; bead1[1]<numParticles; bead1[1]++){
1035 
1036  /* loop over all other beads */
1037  for (bead2[1]=0; bead2[1]<numParticles; bead2[1]++){
1038 
1039  /* avoid self-interactions */
1040  if (!all(bead1==bead2)) {
1041 
1042  rDiff = path.getSeparation(bead1, bead2);
1043  rmag = sqrt(dot(rDiff,rDiff));
1044  d2V = interactionPtr->grad2V(rDiff);
1045  d2V += externalPtr->grad2V(path(bead1));
1046  dV = sqrt(dot(interactionPtr->gradV(rDiff)
1047  ,interactionPtr->gradV(rDiff)));
1048  dV += sqrt(dot(externalPtr->gradV(path(bead1))
1049  ,externalPtr->gradV(path(bead1))));
1050 
1051  tMat(a,b) += rDiff(a)*rDiff(b)*d2V/(rmag*rmag);
1052  if (a != b)
1053  tMat(a,b) -= (rDiff(a)*rDiff(b)/pow(rmag,3))*dV;
1054  else
1055  tMat(a,b) += (1.0/rmag - rDiff(a)*rDiff(b)/pow(rmag,3))*dV;
1056  }
1057  } // end bead2
1058  } // end bead1
1059  }
1060  }
1061 
1062  tMat /= 2.0; // don't want to double count interactions
1063 
1064  return ( tMat );
1065 }
1066 
1067 /**************************************************************************/
1079 double LocalAction::rDOTgradUterm1(const int slice) {
1080 
1081  eo = slice % 2;
1082  int numParticles = path.numBeadsAtSlice(slice);
1083 
1084  /* The two interacting particles */
1085  beadLocator bead1;
1086  bead1[0] = bead2[0] = slice;
1087 
1088  dVec gVi, gV;
1089  double rDotgV = 0.0;
1090 
1091  /* We loop over the first bead */
1092  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1093  gVi = 0.0;
1094  /* Sum potential of bead1 interacting with all other beads at
1095  * a given time slice.*/
1096  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
1097 
1098  /* Avoid self interactions */
1099  if (!all(bead1==bead2)) {
1100 
1101  /* The interaction component of the force */
1102  gVi += interactionPtr->gradV(path.getSeparation(bead1,bead2));
1103  }
1104  } // end bead2
1105 
1106  /* Now add the external component */
1107  gV = (externalPtr->gradV(path(bead1)) + gVi);
1108 
1109  rDotgV += dot(gV, path(bead1));
1110 
1111  } // end bead1
1112 
1113  return (VFactor[eo]*constants()->tau()*rDotgV);
1114 }
1115 
1116 /**************************************************************************/
1126 double LocalAction::rDOTgradUterm2(const int slice) {
1127 
1128  eo = slice % 2;
1129  int numParticles = path.numBeadsAtSlice(slice);
1130 
1131  /* The two interacting particles */
1132  beadLocator bead1;
1133  bead1[0] = bead2[0] = slice;
1134 
1135  dVec gVi, gVe, gV, g2V;
1136 
1137  double term2 = 0.0;
1138  if (gradVFactor[eo] > EPS){
1139 
1140  /* constants for tMatrix */
1141  dVec rDiff = 0.0;
1142  double rmag = 0.0;
1143  double d2V = 0.0;
1144  double dV = 0.0;
1145  double dVe = 0.0;
1146  double dVi = 0.0;
1147  double g2Vi = 0.0;
1148  double g2Ve = 0.0;
1149 
1150  /* We loop over the first bead */
1151  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1152  gV = 0.0;
1153  g2V = 0.0;
1154  dMat tMat = 0.0; // tMat(row, col)
1155  dVec gVdotT = 0.0;
1156 
1157  /* compute external potential derivatives */
1158  gVe = externalPtr->gradV(path(bead1));
1159  dVe = sqrt(dot(gVe,gVe));
1160  g2Ve = externalPtr->grad2V(path(bead1));
1161 
1162  gV += gVe; // update full slice gradient at bead1
1163 
1164  /* Sum potential of bead1 interacting with all other beads at
1165  * a given time slice.*/
1166  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
1167 
1168  /* separation vector */
1169  rDiff = path.getSeparation(bead1, bead2);
1170  rmag = sqrt(dot(rDiff,rDiff));
1171 
1172  /* Avoid self interactions */
1173  if (!all(bead1==bead2)) {
1174 
1175  /* Compute interaction potential derivatives */
1176  gVi = interactionPtr->gradV(rDiff);
1177  dVi = sqrt(dot(gVi,gVi));
1178  g2Vi = interactionPtr->grad2V(rDiff);
1179 
1180  /* total derivatives between bead1 and bead2 at bead1 */
1181  dV = dVi + dVe;
1182  d2V = g2Vi + g2Ve;
1183 
1184  /* compute the T-matrix for bead1 interacting with bead2 */
1185  for (int a=0; a<NDIM; a++){
1186  for (int b=0; b<NDIM; b++){
1187  tMat(a,b) += rDiff(a)*rDiff(b)*d2V/(rmag*rmag)
1188  - rDiff(a)*rDiff(b)*dV/pow(rmag,3);
1189  if (a == b)
1190  tMat(a,b) += dV/rmag;
1191  }
1192  } // end T-matrix
1193 
1194  gV += gVi; // update full slice gradient at bead1
1195 
1196  }
1197  } // end bead2
1198 
1199  /* blitz++ product function seems broken in my current
1200  * version, so this performs matrix-vector mult.
1201  * Checked --MTG */
1202  for(int j=0; j<NDIM; j++){
1203  for(int i=0; i<NDIM; i++){
1204  gVdotT(j) += gV(i)*tMat(j,i);
1205  }
1206  }
1207  term2 += dot(gVdotT, path(bead1));
1208 
1209  } // end bead1
1210 
1211  term2 *= (2.0 * gradVFactor[eo] * pow(tau(),3) * constants()->lambda());
1212  }
1213 
1214  return (term2);
1215 }
1216 
1217 /**************************************************************************/
1228 double LocalAction::deltadotgradUterm1(const int slice) {
1229 
1230  eo = slice % 2;
1231  int numParticles = path.numBeadsAtSlice(slice);
1232  int virialWindow = constants()->virialWindow();
1233 
1234  /* The two interacting particles */
1235  beadLocator bead1, beadNext, beadPrev, beadNextOld, beadPrevOld;
1236  bead1[0] = bead2[0] = slice;
1237 
1238  dVec gVi, gVe, gV, delta;
1239  double rDotgV = 0.0;
1240 
1241  /* We loop over the first bead */
1242  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1243  gVi = 0.0;
1244  gVe = 0.0;
1245  gV = 0.0;
1246  delta = 0.0;
1247  /* Sum potential of bead1 interacting with all other beads at
1248  * a given time slice.*/
1249  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
1250 
1251  /* Avoid self interactions */
1252  if (!all(bead1==bead2)) {
1253 
1254  /* The interaction component of the force */
1255  gVi += interactionPtr->gradV(path.getSeparation(bead1,bead2));
1256  }
1257  } // end bead2
1258 
1259  /* Now add the external component */
1260  gVe += externalPtr->gradV(path(bead1));
1261 
1262  /* Compute deviation of bead from COM of worldline,
1263  * WITHOUT mirror image conv. */
1264  dVec runTotMore = 0.0;
1265  dVec runTotLess = 0.0;
1266  dVec COM = 0.0;
1267  dVec pos1 = path(bead1);
1268  beadNextOld = bead1;
1269  beadPrevOld = bead1;
1270  for (int gamma = 0; gamma < virialWindow; gamma++) {
1271  // move along worldline to next (previous) bead
1272  beadNext = path.next(bead1, gamma);
1273  beadPrev = path.prev(bead1, gamma);
1274  // keep running total of distance from first bead
1275  // to the current beads of interest
1276  runTotMore += path.getSeparation(beadNext, beadNextOld);
1277  runTotLess += path.getSeparation(beadPrev, beadPrevOld);
1278  // update center of mass of WL
1279  COM += (pos1 + runTotMore) + (pos1 + runTotLess);
1280  // store current bead locations
1281  beadNextOld = beadNext;
1282  beadPrevOld = beadPrev;
1283  }
1284  COM /= (2.0*virialWindow);
1285 
1286  delta = pos1 - COM; // end delta computation.
1287  path.boxPtr->putInBC(delta);
1288 
1289  gV += (gVe + gVi);
1290 
1291  rDotgV += dot(gV, delta);
1292 
1293  } // end bead1
1294 
1295  return (VFactor[eo]*constants()->tau()*rDotgV);
1296 }
1297 
1298 /**************************************************************************/
1307 double LocalAction::deltadotgradUterm2(const int slice) {
1308 
1309  eo = slice % 2;
1310  int numParticles = path.numBeadsAtSlice(slice);
1311  int virialWindow = constants()->virialWindow();
1312 
1313  /* The two interacting particles */
1314  beadLocator bead1, beadNext, beadPrev, beadNextOld, beadPrevOld;
1315  bead1[0] = bead2[0] = slice;
1316 
1317  dVec gVi, gVe, gV, g2V, delta;
1318 
1319  double term2 = 0.0;
1320  if (gradVFactor[eo] > EPS){
1321 
1322  /* constants for tMatrix */
1323  dVec rDiff = 0.0;
1324  double rmag = 0.0;
1325  double d2V = 0.0;
1326  double dV = 0.0;
1327  double dVe = 0.0;
1328  double dVi = 0.0;
1329  double g2Vi = 0.0;
1330  double g2Ve = 0.0;
1331 
1332  /* We loop over the first bead */
1333  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1334  gV = 0.0;
1335  g2V = 0.0;
1336  delta = 0.0;
1337  dMat tMat = 0.0; // tMat(row, col)
1338  dVec gVdotT = 0.0;
1339 
1340  /* compute external potential derivatives */
1341  gVe = externalPtr->gradV(path(bead1));
1342  dVe = sqrt(dot(gVe,gVe));
1343  g2Ve = externalPtr->grad2V(path(bead1));
1344 
1345  gV += gVe; // update full slice gradient at bead1
1346 
1347  /* Sum potential of bead1 interacting with all other beads at
1348  * a given time slice.*/
1349  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
1350 
1351  /* separation vector */
1352  rDiff = path.getSeparation(bead1, bead2);
1353  rmag = sqrt(dot(rDiff,rDiff));
1354 
1355  /* Avoid self interactions */
1356  if (!all(bead1==bead2)) {
1357 
1358  /* Compute interaction potential derivatives */
1359  gVi = interactionPtr->gradV(rDiff);
1360  dVi = sqrt(dot(gVi,gVi));
1361  g2Vi = interactionPtr->grad2V(rDiff);
1362 
1363  /* total derivatives between bead1 and bead2 at bead1 */
1364  dV = dVi + dVe;
1365  d2V = g2Vi + g2Ve;
1366 
1367  /* compute the T-matrix for bead1 interacting with bead2 */
1368  for (int a=0; a<NDIM; a++){
1369  for (int b=0; b<NDIM; b++){
1370  tMat(a,b) += rDiff(a)*rDiff(b)*d2V/(rmag*rmag)
1371  - rDiff(a)*rDiff(b)*dV/pow(rmag,3);
1372  if (a == b)
1373  tMat(a,b) += dV/rmag;
1374  }
1375  } // end T-matrix
1376 
1377  gV += gVi; // update full slice gradient at bead1
1378 
1379  }
1380  } // end bead2
1381 
1382  /* blitz++ product function seems broken in my current
1383  * version, so this performs matrix-vector mult.
1384  * Checked --MTG */
1385  for(int j=0; j<NDIM; j++){
1386  for(int i=0; i<NDIM; i++){
1387  gVdotT(j) += gV(i)*tMat(j,i);
1388  }
1389  }
1390 
1391  /* Compute deviation of bead from COM of worldline,
1392  * WITHOUT mirror image conv.*/
1393  dVec runTotMore = 0.0;
1394  dVec runTotLess = 0.0;
1395  dVec COM = 0.0;
1396  dVec pos1 = path(bead1);
1397  beadNextOld = bead1;
1398  beadPrevOld = bead1;
1399  for (int gamma = 0; gamma < virialWindow; gamma++) {
1400  // move along worldline to next (previous) bead
1401  beadNext = path.next(bead1, gamma);
1402  beadPrev = path.prev(bead1, gamma);
1403  // keep running total of distance from first bead
1404  // to the current beads of interest
1405  runTotMore += path.getSeparation(beadNext, beadNextOld);
1406  runTotLess += path.getSeparation(beadPrev, beadPrevOld);
1407  // update center of mass of WL
1408  COM += (pos1 + runTotMore) + (pos1 + runTotLess);
1409  // store current bead locations
1410  beadNextOld = beadNext;
1411  beadPrevOld = beadPrev;
1412  }
1413  COM /= (2.0*virialWindow);
1414  delta = pos1 - COM; // end delta computation.
1415 
1416  path.boxPtr->putInBC(delta);
1417 
1418  term2 += dot(gVdotT, delta);
1419 
1420  } // end bead1
1421 
1422  term2 *= (2.0 * gradVFactor[eo] * pow(tau(),3) * constants()->lambda());
1423  }
1424 
1425  return (term2);
1426 }
1427 
1428 /*************************************************************************/
1433 double LocalAction::virialKinCorrection(const int slice) {
1434 
1435  double vKC = 0.0;
1436 
1437  /* Combine the potential and a possible correction */
1438  eo = (slice % 2);
1439 
1440  /* We only add the correction if it is finite */
1441  if ( gradVFactor[eo] > EPS ) {
1442 
1443  vKC += gradVSquared(slice);
1444 
1445  /* scale by constants */
1446  vKC *= gradVFactor[eo] * pow(tau(),3) * constants()->lambda();
1447  }
1448 
1449  return ( vKC );
1450 }
1451 
1452 /*************************************************************************/
1458 dVec LocalAction::gradU(const int slice) {
1459 
1460  dVec gU2 = 0.0;
1461  dMat tM = tMatrix(slice);
1462  dVec gV = gradientV(slice);
1463 
1464  /* Combine the potential and a possible correction */
1465  eo = (slice % 2);
1466  dVec gU1 = VFactor[eo]*tau()*gradientV(slice);
1467 
1468  /* We only add the correction if it is finite */
1469  if ( gradVFactor[eo] > EPS ) {
1470  /* blitz++ product function seems broken in my current
1471  * version, so this performs matrix-vector mult. */
1472  for(int j=0; j<NDIM; j++){
1473  for(int i=0; i<NDIM; i++){
1474  gU2(i) += gV(j)*tM(i,j);
1475  }
1476  }
1477  /* now scale by constants */
1478  gU2 *= 2.0 * gradVFactor[eo] * pow(tau(),3) * constants()->lambda();
1479  }
1480 
1481  return ( gU1+gU2 );
1482 }
1483 // ---------------------------------------------------------------------------
1484 // ---------------------------------------------------------------------------
1485 // NON LOCAL ACTION BASE CLASS -----------------------------------------------
1486 // ---------------------------------------------------------------------------
1487 // ---------------------------------------------------------------------------
1488 
1489 /**************************************************************************/
1493  PotentialBase *_externalPtr, PotentialBase *_interactionPtr,
1494  WaveFunctionBase *_waveFunctionPtr, bool _local, string _name) :
1495  ActionBase(_path,_lookup,_externalPtr,_interactionPtr,_waveFunctionPtr,
1496  _local,_name)
1497 {
1498  NNbead.resize(constants()->initialNumParticles(),false);
1499 }
1500 
1501 /**************************************************************************/
1505 }
1506 
1507 /**************************************************************************/
1515 
1516  double totU = 0.0;
1517  for (int slice = 0; slice < path.numTimeSlices; slice++)
1518  totU += sum(U(slice));
1519 
1520  return ( totU );
1521 }
1522 
1523 /**************************************************************************/
1529 
1530  /* We only need to calculate the potential action if the two neighboring
1531  * beads are on */
1532  if (!path.worm.beadOn(bead1))
1533  return 0.0;
1534 
1535  /* Since the non-local action lives on a link, both bead1 and nextBead1
1536  * must exist */
1537  beadLocator nextBead1,nextBead2;
1538  nextBead1 = path.next(bead1);
1539 
1540  double totU = 0.0;
1541 
1542 #if PIGS
1543  /* We tack on a trial wave function and boundary piece if necessary */
1544  if ( (bead1[0] == 0) || (bead1[0] == (constants()->numTimeSlices()-1)) )
1545  totU -= log(waveFunctionPtr->PsiTrial(bead1));
1546 #endif
1547 
1548  /* Make sure nextBead1 is a real bead and that it is active */
1549  if ( (all(nextBead1==XXX)) || (!path.worm.beadOn(nextBead1)) )
1550  return totU;
1551 
1552  /* Evaluate the external potential */
1553  double totVext = externalPtr->V(path(bead1))+externalPtr->V(path(nextBead1));
1554 
1555  /* Get the interaction list */
1557  for (int n = 0; n < lookup.numBeads; n++) {
1558  bead2 = lookup.beadList(n);
1559  if(!all(path.next(bead2)==XXX))
1560  NNbead[bead2[1]] = true;
1561  }
1562 
1563  /* Get the next interaction list */
1564  lookup.updateInteractionList(path,nextBead1);
1565  for (int n = 0; n < lookup.numBeads; n++) {
1566  bead2 = path.prev(lookup.beadList(n));
1567  if(!all(bead2==XXX))
1568  NNbead[bead2[1]] = true;
1569  }
1570 
1571  bead2[0] = bead1[0];
1572  for (bead2[1]= 0; bead2[1] < path.numBeadsAtSlice(bead1[0]); bead2[1]++) {
1573  if(NNbead[bead2[1]]){
1574  nextBead2 = path.next(bead2);
1575  sep = path.getSeparation(bead1,bead2);
1576  sep2 = path.getSeparation(nextBead1,nextBead2);
1577  totU += interactionPtr->V(sep,sep2);
1578  NNbead[bead2[1]] = false;
1579  }
1580  }
1581 
1582  double totUext = tau()*totVext/(2.0);
1583 
1584  /* bead2[0] = bead1[0]; */
1585 
1586  /* /1* Now calculate the total effective interation potential, neglecting self-interactions *1/ */
1587  /* for (bead2[1]= 0; bead2[1] < path.numBeadsAtSlice(bead1[0]); bead2[1]++) { */
1588 
1589  /* /1* Skip self interactions *1/ */
1590  /* if ( bead2[1] != bead1[1] ) { */
1591 
1592  /* /1* get the separation between the two particles at the first time */
1593  /* * slice *1/ */
1594  /* sep = path.getSeparation(bead1,bead2); */
1595 
1596  /* /1* Now we find the separation at the advanced time step *1/ */
1597  /* nextBead2 = path.next(bead2); */
1598 
1599  /* /1* If the imaginary time neighbor exists, compute the effective */
1600  /* * potential *1/ */
1601  /* if ( (!all(nextBead2==XXX)) && (path.worm.beadOn(nextBead2)) ) { */
1602  /* sep2 = path.getSeparation(nextBead1,nextBead2); */
1603  /* totU += interactionPtr->V(sep,sep2,constants()->lambda(),constants()->tau()); */
1604  /* } */
1605  /* } // bead2 != bead1 */
1606 
1607 
1608  /* } // for bead2 */
1609 
1610  return (totU + totUext);
1611 }
1612 
1613 /**************************************************************************/
1619 TinyVector<double,2> NonLocalAction::U(int slice) {
1620 
1621  double totUint = 0.0;
1622  double totUext = 0.0;
1623 
1624  beadLocator bead1;
1625  bead1[0] = bead2[0] = slice;
1626 
1627  beadLocator nextBead1,nextBead2;
1628 
1629  int numParticles = path.numBeadsAtSlice(slice);
1630 
1631  /* Initialize the separation histogram */
1632  sepHist = 0;
1633 
1634  /* Calculate the total potential, including external and interaction
1635  * effects*/
1636  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1637 
1638  /* Get the advanced neightbor of bead1 */
1639  nextBead1 = path.next(bead1);
1640 
1641  for (bead2[1] = bead1[1]+1; bead2[1] < numParticles; bead2[1]++) {
1642  sep = path.getSeparation(bead1,bead2);
1643 
1644  /* Get the advanced neighbor of the second bead */
1645  nextBead2 = path.next(bead2);
1646 
1647  sep2 = path.getSeparation(nextBead1,nextBead2);
1648  totUint += interactionPtr->V(sep,sep2);
1649  } // bead2
1650 
1651  } // bead1
1652  return TinyVector<double,2>(totUext,totUint);
1653 }
1654 
1655 /**************************************************************************/
1665 
1666  double totU = 0.0;
1667 
1668  beadLocator bead1;
1669  bead1[0] = bead2[0] = slice;
1670 
1671  beadLocator nextBead1,nextBead2;
1672 
1673  int numParticles = path.numBeadsAtSlice(slice);
1674 
1675  /* Initialize the separation histogram */
1676  sepHist = 0;
1677 
1678  /* Calculate the total potential, including external and interaction
1679  * effects*/
1680  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1681 
1682  /* Get the advanced neightbor of bead1 */
1683  nextBead1 = path.next(bead1);
1684 
1685  for (bead2[1] = bead1[1]+1; bead2[1] < numParticles; bead2[1]++) {
1686  sep = path.getSeparation(bead1,bead2);
1687  updateSepHist(sep);
1688 
1689  /* Get the advanced neighbor of the second bead */
1690  nextBead2 = path.next(bead2);
1691 
1692  sep2 = path.getSeparation(nextBead1,nextBead2);
1693  totU += interactionPtr->dVdtau(sep,sep2);
1694  } // bead2
1695 
1696  } // bead1
1697  return ( totU );
1698 }
1699 
1700 /**************************************************************************/
1710 
1711  double totU = 0.0;
1712 
1713  beadLocator bead1;
1714  bead1[0] = bead2[0] = slice;
1715 
1716  beadLocator nextBead1,nextBead2;
1717 
1718  int numParticles = path.numBeadsAtSlice(slice);
1719 
1720  /* Calculate the total potential, including external and interaction
1721  * effects*/
1722  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
1723 
1724  /* Get the advanced neightbor of bead1 */
1725  nextBead1 = path.next(bead1);
1726 
1727  for (bead2[1] = bead1[1]+1; bead2[1] < numParticles; bead2[1]++) {
1728  sep = path.getSeparation(bead1,bead2);
1729 
1730  /* Get the advanced neighbor of the second bead */
1731  nextBead2 = path.next(bead2);
1732 
1733  sep2 = path.getSeparation(nextBead1,nextBead2);
1734  totU += interactionPtr->dVdlambda(sep,sep2);
1735  } // bead2
1736 
1737  } // bead1
1738  return ( totU );
1739 }
Action class definitions.
Holds a base class that all action classes will be derived from.
Definition: action.h:29
WaveFunctionBase * waveFunctionPtr
A pointer to a trial wave function object.
Definition: action.h:119
Array< int, 1 > cylSepHist
A histogram of separations for a cylinder.
Definition: action.h:112
virtual double potentialAction()
The effective potential inter-ACTION for various pass conditions.
Definition: action.h:48
ActionBase(const Path &, LookupTable &, PotentialBase *, PotentialBase *, WaveFunctionBase *, bool _local=true, string _name="Base", double _endFactor=1.0, int _period=1)
Setup the path data members and canonical re-weighting factors.
Definition: action.cpp:23
double endFactor
Mutiplictive factor of the potential action on ends.
Definition: action.h:120
Array< int, 1 > sepHist
A histogram of separations.
Definition: action.h:111
int numBeads0
The target number of beads.
Definition: action.h:126
PotentialBase * interactionPtr
The interaction potential.
Definition: action.h:109
bool canonical
Are we in the canonical ensemble?
Definition: action.h:125
LookupTable & lookup
We need a non-constant reference for updates.
Definition: action.h:117
double tau()
The local shifted value of tau.
Definition: action.h:133
PotentialBase * externalPtr
The external potential.
Definition: action.h:108
double ensembleWeight(const int)
The ensemble particle number weighting factor.
Definition: action.cpp:122
double kineticAction()
The full kinetic Action
Definition: action.cpp:205
virtual ~ActionBase()
Empty base constructor.
Definition: action.cpp:60
void updateSepHist(const dVec &)
Update the separation histogram.
Definition: action.cpp:71
int shift
The scaling factor for tau.
Definition: action.h:122
const Path & path
A reference to the paths.
Definition: action.h:118
double rho0(const dVec &, const dVec &, int)
The free-particle density matrix.
Definition: action.cpp:83
int windowWidth() const
Get window 1/2 width.
Definition: constants.h:92
int numTimeSlices()
Get number of time slices.
Definition: constants.h:99
double lambda() const
Get lambda = hbar^2/(2mk_B)
Definition: constants.h:46
bool window() const
Get window on/off.
Definition: constants.h:90
double gaussianEnsembleSD() const
Get enesemble weight standard dev.
Definition: constants.h:94
int virialWindow() const
Get centroid virial window size.
Definition: constants.h:55
bool canonical() const
Get ensemble.
Definition: constants.h:89
bool gaussianEnsemble() const
Get enesemble weight on/off.
Definition: constants.h:93
int initialNumParticles()
Get initial number of particles.
Definition: constants.h:100
TinyVector< unsigned int, NDIM > periodic
Determines which dimensions have periodic bc.
Definition: container.h:29
void putInBC(dVec &r) const
Place a vector in boundary conditions.
Definition: container.h:50
dVec side
The linear dimensions of the box.
Definition: container.h:31
double potentialAction()
Return the potential action for all time slices and all particles.
Definition: action.cpp:289
double deltadotgradUterm1(const int)
Return the sum over particles at a given time slice of the gradient of the action potential for a sin...
Definition: action.cpp:1228
double potentialActionCorrection(const beadLocator &)
Return the potential action correction for a single bead.
Definition: action.cpp:372
virtual ~LocalAction()
Empty base constructor.
Definition: action.cpp:275
double rDOTgradUterm2(int)
Return the sum over particles at a given time slice of the gradient of the action potential for a sin...
Definition: action.cpp:1126
double secondderivPotentialActionTau(int)
The second derivative of the potential action wrt tau on all links starting on slice.
Definition: action.cpp:447
dMat tMatrix(const int)
Returns the T-matrix needed to compute gradU.
Definition: action.cpp:1015
double gradVSquared(const beadLocator &)
Return the gradient of the full potential squared for a single bead.
Definition: action.cpp:762
double virialKinCorrection(const int)
Returns the value of the virial kinetic energy correction term.
Definition: action.cpp:1433
double derivPotentialActionLambda(int)
The derivative of the potential action wrt lambda for all links starting on slice.
Definition: action.cpp:469
double rDOTgradUterm1(int)
Return the sum over particles at a given time slice of the gradient of the action potential for a sin...
Definition: action.cpp:1079
TinyVector< double, 2 > VFactor
The even/odd slice potential factor.
Definition: action.h:196
dVec gradU(const int)
Returns the value of the gradient of the potential action for all beads at a given time slice.
Definition: action.cpp:1458
TinyVector< double, 2 > gradVFactor
The even/odd slice correction factor.
Definition: action.h:197
dVec gradientV(const int)
Return the gradient of the full potential for all beads at a single time slice.
Definition: action.cpp:978
LocalAction(const Path &, LookupTable &, PotentialBase *, PotentialBase *, WaveFunctionBase *, const TinyVector< double, 2 > &, const TinyVector< double, 2 > &, bool _local=true, string _name="Local", double _endFactor=1.0, int _period=1)
Setup the path data members and local action factors.
Definition: action.cpp:259
double derivPotentialActionTau(int)
The derivative of the potential action wrt tau on all links starting on slice.
Definition: action.cpp:422
double deltadotgradUterm2(const int)
Return the sum over particles at a given time slice of the gradient of the action potential for a sin...
Definition: action.cpp:1307
int eo
Is a slice even or odd?
Definition: action.h:194
double barePotentialAction(const beadLocator &)
Return the bare potential action for a single bead indexed with beadIndex.
Definition: action.cpp:352
double V(const beadLocator &)
Returns the total value of the potential energy, including both the external potential,...
Definition: action.cpp:529
double Vnn(const beadLocator &)
Returns the total value of the potential energy, including both the external potential,...
Definition: action.cpp:680
double gradVnnSquared(const beadLocator &)
Return the gradient of the full potential squared for a single bead.
Definition: action.cpp:915
The particle (bead) lookup table.
Definition: lookuptable.h:29
Array< beadLocator, 1 > beadList
The cutoff dynamic list of interacting beads.
Definition: lookuptable.h:40
void updateInteractionList(const Path &, const beadLocator &)
Update the NN lookup table and the array of beadLocators containing all beads which 'interact' with t...
Array< dVec, 1 > beadSep
The separation between beads.
Definition: lookuptable.h:42
int numBeads
The cutoff number of active beads in beadList;.
Definition: lookuptable.h:43
double derivPotentialActionLambda(int)
The derivative of the potential action wrt lambda on all links starting on slice.
Definition: action.cpp:1709
double potentialAction()
Return the potential action for all time slices and all particles.
Definition: action.cpp:1514
NonLocalAction(const Path &, LookupTable &, PotentialBase *, PotentialBase *, WaveFunctionBase *, bool _local=false, string _name="Non-local")
Setup the path data members for non-local actions.
Definition: action.cpp:1492
TinyVector< double, 2 > U(int)
Return the potential action for all time slices and all particles.
Definition: action.cpp:1619
double derivPotentialActionTau(int)
The derivative of the potential action wrt tau on all links starting on slice.
Definition: action.cpp:1664
virtual ~NonLocalAction()
Empty constructor.
Definition: action.cpp:1504
The space-time trajectories.
Definition: path.h:29
dVec getVelocity(const beadLocator &) const
Return the velocity between two time slices of a given particle as a ndim-vector.
Definition: path.h:183
dVec getSeparation(const beadLocator &, const beadLocator &) const
Return the separation vector between two particles in the same timeslice.
Definition: path.h:173
const int numTimeSlices
A local constant copy of the number of time slices.
Definition: path.h:37
Array< int, 1 > numBeadsAtSlice
The number of active beads at a given time slice.
Definition: path.h:48
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
The base class from which all specific potentials are derived from.
Definition: potential.h:32
virtual double grad2V(const dVec &)
Grad^2 of the potential.
Definition: potential.h:48
virtual dVec gradV(const dVec &)
The gradient of the potential.
Definition: potential.h:45
virtual double dVdlambda(const dVec &, const dVec &)
The derivative of the effective potential with respect to lambda and tau.
Definition: potential.h:52
virtual double V(const dVec &)
The potential.
Definition: potential.h:39
Holds a base class that all trial wave function classes will be derived from.
Definition: wavefunction.h:26
virtual double PsiTrial(const int)
The Constant Trial Wave Function.
Definition: wavefunction.h:36
int beadOn(int, int) const
Safely get a bead (int indexed)
Definition: worm.h:148
beadState getState(const beadLocator &) const
Get the state of the supplied bead?
Definition: worm.h:110
double factor(const beadState, const beadLocator &) const
Compute the value of the potential action trajectory factor.
Definition: worm.cpp:109
int getNumBeadsOn() const
Return the number of active beads.
Definition: worm.h:88
#define NDIM
Number of spatial dimnsions.
Definition: common.h:71
TinyMatrix< double, NDIM, NDIM > dMat
A NDIM x NDIM matrix of type double.
Definition: common.h:108
TinyVector< int, 2 > beadLocator
time-slice,bead-number world line index
Definition: common.h:117
#define EPS
A small number.
Definition: common.h:94
#define NPCFSEP
Spatial separations to be used in the pair correlation function.
Definition: common.h:90
beadState
Each bead can have three possible states.
Definition: common.h:129
TinyVector< double, NDIM > dVec
A NDIM-vector of type double.
Definition: common.h:111
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
ConstantParameters * constants()
Global public access to the constants.
Definition: constants.h:201
LookupTable class definition.
Path class definition.
All possible potential classes.
Action class definitions.