Path Integral Quantum Monte Carlo
estimator.cpp
Go to the documentation of this file.
1 
8 #include "estimator.h"
9 #include "path.h"
10 #include "action.h"
11 #include "potential.h"
12 #include "communicator.h"
13 #include "factory.h"
14 
15 
16 /**************************************************************************/
20 #define REGISTER_ESTIMATOR(NAME,TYPE) \
21  const string TYPE::name = NAME;\
22  bool reg ## TYPE = estimatorFactory()->Register<TYPE>(TYPE::name);
23 
24 /**************************************************************************/
35 REGISTER_ESTIMATOR("number distribution",NumberDistributionEstimator);
38 REGISTER_ESTIMATOR("bipartition density",BipartitionDensityEstimator);
41 REGISTER_ESTIMATOR("planar density average rho",PlaneParticleAveragePositionEstimator);
42 REGISTER_ESTIMATOR("planar potential average Vext",PlaneAverageExternalPotentialEstimator);
43 REGISTER_ESTIMATOR("superfluid fraction",SuperfluidFractionEstimator);
53 REGISTER_ESTIMATOR("one body density matrix",OneBodyDensityMatrixEstimator);
54 REGISTER_ESTIMATOR("pair correlation function",PairCorrelationEstimator);
55 REGISTER_ESTIMATOR("static structure factor",StaticStructureFactorEstimator);
56 REGISTER_ESTIMATOR("intermediate scattering function",IntermediateScatteringFunctionEstimator);
59 REGISTER_ESTIMATOR("cylinder number particles",CylinderNumberParticlesEstimator);
60 REGISTER_ESTIMATOR("cylinder number distribution",CylinderNumberDistributionEstimator);
61 REGISTER_ESTIMATOR("cylinder linear density",CylinderLinearDensityEstimator);
62 REGISTER_ESTIMATOR("cylinder superfluid fraction",CylinderSuperfluidFractionEstimator);
63 REGISTER_ESTIMATOR("cylinder one body density matrix",CylinderOneBodyDensityMatrixEstimator);
64 REGISTER_ESTIMATOR("cylinder pair correlation function",CylinderPairCorrelationEstimator);
65 REGISTER_ESTIMATOR("cylinder radial potential",CylinderRadialPotentialEstimator);
66 REGISTER_ESTIMATOR("cylinder linear potential",CylinderLinearPotentialEstimator);
67 REGISTER_ESTIMATOR("cylinder potential energy",PotentialEnergyEstimator);
68 REGISTER_ESTIMATOR("pigs kinetic energy",KineticEnergyEstimator);
69 REGISTER_ESTIMATOR("pigs total energy",TotalEnergyEstimator);
70 REGISTER_ESTIMATOR("pigs thermodynamic potential energy",ThermoPotentialEnergyEstimator);
71 REGISTER_ESTIMATOR("pigs positions",PositionEstimator);
72 REGISTER_ESTIMATOR("pigs particle resolved positions",ParticleResolvedPositionEstimator);
73 REGISTER_ESTIMATOR("pigs particle correlations",ParticleCorrelationEstimator);
74 REGISTER_ESTIMATOR("pigs velocity",VelocityEstimator);
75 REGISTER_ESTIMATOR("pigs subregion occupation",SubregionOccupationEstimator);
76 REGISTER_ESTIMATOR("pigs one body density matrix",PIGSOneBodyDensityMatrixEstimator);
77 
78 /**************************************************************************/
82 const string SwapEstimator::name = "pigs multi swap";
83 bool regSwap = multiEstimatorFactory()->Register<SwapEstimator>(SwapEstimator::name);
84 
85 const string EntPartEstimator::name = "pigs multi entanglement of particles";
86 bool regEntPart = multiEstimatorFactory()->Register<EntPartEstimator>(EntPartEstimator::name);
87 
88 // ---------------------------------------------------------------------------
89 // ---------------------------------------------------------------------------
90 // ESTIMATOR BASE CLASS ------------------------------------------------------
91 // ---------------------------------------------------------------------------
92 // ---------------------------------------------------------------------------
93 
94 /**************************************************************************/
103 EstimatorBase::EstimatorBase(const Path &_path, ActionBase *_actionPtr,
104  const MTRand &_random, double _maxR, int _frequency, string _label) :
105  path(_path),
106  actionPtr(_actionPtr),
107  random(_random),
108  maxR(_maxR),
109  frequency(_frequency),
110  label(_label),
111  numSampled(0),
112  numAccumulated(0),
113  totNumAccumulated(0),
114  diagonal(true),
115  endLine(true)
116 {
117  /* Two handy local constants */
120 
121  /* A normalization factor for time slices used in estimators */
122  sliceFactor.resize(constants()->numTimeSlices(),1.0);
123 
124  /* The slices over which we average quantities PIGS vs. PIMC */
125 #if PIGS
126  int midSlice = (path.numTimeSlices-1)/2;
127  startSlice = midSlice - actionPtr->period;
128  endSlice = midSlice + actionPtr->period;
130 
131  if(actionPtr->local) {
132  endDiagSlice = endSlice + 1;
133  sliceFactor[startSlice] = 0.5;
134  sliceFactor[endSlice] = 0.5;
135  }
136 #else
137  startSlice = 0;
140 #endif
141 }
142 
143 /**************************************************************************/
147  estimator.free();
148  norm.free();
149 }
150 
151 /**************************************************************************/
162 
163  /* Increment the number of attempted samplings */
164  numSampled++;
165 
166  if (!frequency)
167  return false;
168  if ((numSampled % frequency) != 0)
169  return false;
171  return false;
172  if (!canonical)
173  return true;
174  if (path.worm.getNumBeadsOn() == numBeads0)
175  return true;
176 
177  return false;
178 }
179 
180 /**************************************************************************/
188 
189  if (baseSample()) {
191  numAccumulated++;
192  accumulate();
193  }
194 }
195 
196 /**************************************************************************/
201 void EstimatorBase::initialize(int _numEst) {
202 
203  numEst = _numEst;
204  estimator.resize(numEst);
205  norm.resize(numEst);
206  norm = 1.0;
207  reset();
208 }
209 
210 /**************************************************************************/
215 void EstimatorBase::initialize(vector<string> estLabel) {
216 
217  /* Initialize the map linking names to indices */
218  for(size_t i = 0; i < estLabel.size(); ++i)
219  estIndex[estLabel[i]] = i;
220 
221  /* write the header string */
222  estLabel.front() = str(format("#%15s") % estLabel.front());
223  header = "";
224  for (const auto& label : estLabel)
225  header += str(format("%16s") % label);
226 
227  numEst = estLabel.size();
228  estimator.resize(numEst);
229  norm.resize(numEst);
230  norm = 1.0;
231  reset();
232 }
233 
234 /**************************************************************************/
241 
242  /* Provided that we will perform at least one measurement, open an output
243  * file and possibly write a header */
244  if (frequency > 0) {
245  /* Assign the output file pointer */
246  outFilePtr = &(communicate()->file(label)->stream());
247 
248  /* Write the header to disk if we are not restarting or if this is
249  * a new estimator. */
250  if (!constants()->restart() || (!communicate()->file(label)->exists())) {
251  (*outFilePtr) << header;
252  if (endLine)
253  (*outFilePtr) << endl;
254  }
255  }
256 }
257 
258 /*************************************************************************/
262  numAccumulated = 0;
263  estimator = 0.0;
264 }
265 
266 /*************************************************************************/
269 void EstimatorBase::restart(const uint32 _numSampled, const uint32 _totNumAccumulated) {
270  numSampled = _numSampled;
271  totNumAccumulated = _totNumAccumulated;
272  reset();
273 }
274 
275 /*************************************************************************/
284 
285  /* Average */
286  estimator *= (norm/(1.0*numAccumulated));
287 
288  /* Now write the estimator values to disk */
289  for (int n = 0; n < numEst; n++)
290  (*outFilePtr) << format("%16.8E") % estimator(n);
291 
292  if (endLine)
293  (*outFilePtr) << endl;
294 
295  /* Reset all values */
296  reset();
297 }
298 
299 /*************************************************************************/
306 
307  /* Prepare the position file for writing over old data */
308  communicate()->file(label)->reset();
309 
310  (*outFilePtr) << header;
311  if (endLine)
312  (*outFilePtr) << endl;
313 
314  /* Now write the running average of the estimator to disk */
315  for (int n = 0; n < numEst; n++)
316  (*outFilePtr) << format("%16.8E\n") %
318 
319  communicate()->file(label)->rename();
320 }
321 
322 /*************************************************************************/
325 void EstimatorBase::appendLabel(string append) {
326  label = label + append;
327 }
328 
329 // ---------------------------------------------------------------------------
330 // ---------------------------------------------------------------------------
331 // TIME ESTIMATOR CLASS ------------------------------------------------------
332 // ---------------------------------------------------------------------------
333 // ---------------------------------------------------------------------------
334 
335 /*************************************************************************/
341  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
342  int _frequency, string _label) :
343  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
344 
345  /* Set estimator name and header */
346  header = str(format("%16s%16s") % "us" % "mcsteps");
347  endLine = false;
348  initialize(2);
349 }
350 
351 /*************************************************************************/
355 
356  numSampled++;
357 
358  if (frequency && ((numSampled % frequency) == 0)) {
360  numAccumulated++;
361  accumulate();
362  }
363 }
364 
365 /*************************************************************************/
368 void TimeEstimator::accumulate() {
369  if (totNumAccumulated == 1)
370  time_begin = std::chrono::high_resolution_clock::now();
371 }
372 
373 /*************************************************************************/
377  time_end = std::chrono::high_resolution_clock::now();
378  estimator(0) = 0.001*std::chrono::duration_cast<std::chrono::nanoseconds>(
379  time_end - time_begin).count()/numAccumulated;
380  estimator(1) = 1.0*numAccumulated;
381 
382  // close the loop
383  time_begin = time_end;
384 
385  /* Now write the estimator values to disk */
386  for (int n = 0; n < numEst; n++)
387  (*outFilePtr) << format("%16.8E") % estimator(n);
388 
389  if (endLine)
390  (*outFilePtr) << endl;
391 
392  /* Reset all values */
393  reset();
394 }
395 
396 // ---------------------------------------------------------------------------
397 // ---------------------------------------------------------------------------
398 // ENERGY ESTIMATOR CLASS ----------------------------------------------------
399 // ---------------------------------------------------------------------------
400 // ---------------------------------------------------------------------------
401 
402 /*************************************************************************/
410  const MTRand &_random, double _maxR, int _frequency, string _label) :
411  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
412 
413  endLine = false;
414  initialize({"K","V","V_ext","V_int","E","E_mu","K/N","V/N","E/N"});
415 }
416 
417 /*************************************************************************/
421 }
422 
423 /*************************************************************************/
430 void EnergyEstimator::accumulate() {
431 
432  double totK = 0.0;
433  double totV = 0.0;
434  TinyVector<double,2> totVop(0.0);
435 
436  int numParticles = path.getTrueNumParticles();
437  int numTimeSlices = endSlice - startSlice;
438 
439  /* The total tail correction */
440  double tailV = (1.0*numParticles*numParticles/path.boxPtr->volume)
442 
443  /* The kinetic normalization factor */
444  double kinNorm = constants()->fourLambdaTauInv() / (constants()->tau() * numTimeSlices);
445 
446  /* The classical contribution to the kinetic energy per particle
447  * including the chemical potential */
448  double classicalKinetic = (0.5 * NDIM / constants()->tau()) * numParticles;
449 
450  /* We first calculate the kinetic energy. Even though there
451  * may be multiple mixing and swaps, it doesn't matter as we always
452  * just advance one time step at a time, as taken care of through the
453  * linking arrays. This has been checked! */
454  beadLocator beadIndex;
455  dVec vel;
456  for (int slice = startSlice; slice < endSlice; slice++) {
457  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
458  beadIndex = slice,ptcl;
459  vel = path.getVelocity(beadIndex);
460  totK -= dot(vel,vel);
461  }
462  }
463  /* Normalize the accumulated link-action part */
464  totK *= kinNorm;
465 
466  /* Now we compute the potential and kinetic energy using the thermodynamic estimator.
467  * The operator estimator is also computed on physical time slices. */
468  double t1 = 0.0;
469  double t2 = 0.0;
470 
471  for (int slice = startSlice; slice < endDiagSlice; slice++) {
472  t1 += sliceFactor[slice]*actionPtr->derivPotentialActionLambda(slice);
473  t2 += sliceFactor[slice]*actionPtr->derivPotentialActionTau(slice);
474  if (!(slice % actionPtr->period))
475  totVop += sliceFactor[slice]*actionPtr->potential(slice);
476  }
477 
478  t1 *= constants()->lambda()/(constants()->tau()*numTimeSlices);
479  t2 /= 1.0*numTimeSlices;
480 
481  /* Normalize the action correction and the total potential*/
482  totVop /= (numTimeSlices/actionPtr->period);
483 
484  /* Perform all the normalizations and compute the individual energy terms */
485  totK += (classicalKinetic + t1);
486  totV = t2 - t1 + tailV;
487  totVop[1] += tailV;
488 
489  /* Now we accumulate the average total, kinetic and potential energy,
490  * as well as their values per particles. */
491  estimator(estIndex["K"]) += totK;
492  estimator(estIndex["V"]) += totV;
493  estimator(estIndex["V_ext"]) += totVop[0];
494  estimator(estIndex["V_int"]) += totVop[1];
495 
496  estimator(estIndex["E"]) += totK + totV;
497  estimator(estIndex["E_mu"]) += totK + totV - constants()->mu()*numParticles;
498 
499  /* ToDo: This is broken for the cases where numParticles == 0. Need to add
500  * a special accumulator and renormalize these measruements. To study this
501  * case, just divide separately by <N> (error bars may be too small). */
502  if (numParticles > 0) {
503  estimator(estIndex["K/N"]) += totK/(1.0*numParticles);
504  estimator(estIndex["V/N"]) += totV/(1.0*numParticles);
505  estimator(estIndex["E/N"]) += (totK + totV)/(1.0*numParticles);
506  }
507 }
508 
509 // ---------------------------------------------------------------------------
510 // ---------------------------------------------------------------------------
511 // VIRIAL ENERGY ESTIMATOR CLASS ---------------------------------------------
512 // ---------------------------------------------------------------------------
513 // ---------------------------------------------------------------------------
514 
515 /*************************************************************************/
524  const MTRand &_random, double _maxR, int _frequency, string _label) :
525  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
526 
527  /* Set estimator name and header, we will always report the energy
528  * first, hence the comment symbol*/
529  header = str(format("#%15s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s%16s")
530  % "K_op" % "K_cv" % "V_op" % "V_cv" % "E" % "E_mu" % "K_op/N" % "K_cv/N" % "V_op/N"
531  % " V_cv/N" % "E/N" % "EEcv*Beta^2"% "Ecv*Beta" % "dEdB" % "CvCov1"
532  % "CvCov2" % "CvCov3" % "E_th" % "P");
533  initialize(19);
534 }
535 
536 /*************************************************************************/
540 }
541 
542 /*************************************************************************/
558 void VirialEnergyEstimator::accumulate() {
559 
560  /* Set up potential operator energy, thermodynamic energy,
561  * centroid virial energy, centroid virial kinetic energy (see Jang Jang Voth),
562  * and terms that go into both energy estimators. */
563  double totVop = 0.0;
564  double thermE = 0.0; // = thermTerm1 + + T5 + tailV
565  double totEcv = 0.0; // = T1+T2+T3+T4+T5+tailV
566  double Kcv = 0.0; // = T1+T2+T3+T4+virKinTerm
567  double T2 = 0.0;
568  double T3 = 0.0;
569  double T4 = 0.0;
570  double virKinTerm = 0.0;
571 
572  int numParticles = path.getTrueNumParticles();
573  int numTimeSlices = path.numTimeSlices;
574  double beta = 1.0*numTimeSlices*constants()->tau();
575  int virialWindow = constants()->virialWindow();
576 
577  /* The total tail correction */
578  double tailV = (1.0*numParticles*numParticles/path.boxPtr->volume)
580 
581  /* The constant term from the thermodynamic energy. */
582  double thermTerm1 = (0.5 * NDIM / constants()->tau()) * numParticles;
583 
584  /* The constant term from the centroid virial energy. */
585  double T1 = 0.5 * NDIM * numParticles / (1.0*virialWindow*constants()->tau());
586 
587  /* Calculate the exchange energy for centroid virial energy.
588  * Also computes kinetic piece of thermodynamic energy which
589  * fluctuates wildly. */
590  double exchangeNorm = 1.0/(4.0*virialWindow*pow(constants()->tau(),2)
591  *constants()->lambda()*numTimeSlices);
592 
593  /* Compute the thermodynamic pressure */
594  double Pressure = NDIM*numParticles;
595  double P2,P3;
596  P2 = P3 = 0.0;
597 
598  beadLocator bead1, beadNext, beadNextOld;
599  dVec vel1, vel2;
600  for (int slice = 0; slice < numTimeSlices; slice++) {
601  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
602  bead1 = slice,ptcl; // current bead
603  vel2 = path.getVelocity(bead1);
604  beadNextOld = bead1;
605  vel1 = 0.0;
606  /* get r_{current + window} - r_{current} */
607  for (int gamma = 1; gamma <= virialWindow; gamma++) {
608  beadNext = path.next(bead1, gamma);
609  vel1 += path.getSeparation(beadNext, beadNextOld);
610  beadNextOld = beadNext;
611  }
612  T2 -= dot(vel1,vel2);
613 
614  /* compute second term of thermodynamic estimator */
615  thermE -= dot(vel2,vel2);
616  }
617  }
618  P2 = thermE;
619  T2 *= exchangeNorm;
620 
621  /* add second pressure term. */
622  P2 /= (2.0*constants()->lambda()*constants()->tau()*numTimeSlices);
623  Pressure += P2;
624 
625  /* Compute T3, T4, T5, operator potential energy,
626  * and the kinetic energy correction. */
627  int eo;
628  double T5 = 0.0;
629  for (int slice = 0; slice < numTimeSlices; slice++) {
630  eo = (slice % 2);
631  T3 += actionPtr->deltaDOTgradUterm1(slice);
632  T4 += actionPtr->deltaDOTgradUterm2(slice);
633  T5 += actionPtr->derivPotentialActionTau(slice);
634  virKinTerm += actionPtr->virKinCorr(slice);
635  if (eo==0)
636  totVop += sum(actionPtr->potential(slice));
637 
638  P3 += actionPtr->rDOTgradUterm1(slice)
639  + actionPtr->rDOTgradUterm2(slice);
640  }
641 
642  P3 *= (1.0/(2.0*numTimeSlices));
643  Pressure -= P3;
644 
645  /* end pressure calculation */
646  Pressure /= (NDIM*constants()->tau()*constants()->V());
647 
648  totVop /= (0.5 * numTimeSlices);
649  totVop += tailV;
650 
651  T3 /= (2.0*beta);
652  T4 /= (1.0*beta);
653  T5 /= (1.0*numTimeSlices);
654  virKinTerm /= (0.5*beta);
655 
656  /* Normalize second term of the thermodynamic energy then
657  * add the rest of the terms to it. */
658  thermE *= constants()->fourLambdaTauInv() / (constants()->tau() * numTimeSlices);
659  thermE += thermTerm1;
660  thermE += T5;
661  thermE += tailV;
662 
663  /* Compute total centroid virial energy */
664  totEcv = T1 + T2 + T3 + T4 + T5 + tailV;
665 
666  /* Compute centroid virial kinetic energy */
667  Kcv = T1 + T2 + T3 + T4 + virKinTerm;
668 
669  /* Compute dE/d(\beta) for centroid virial specific heat:
670  * C_V^{CV}/(k_B \beta^2) = <E^2> - <E>^2 - <dEdB> */
671  double dEdB = (-1.0*T1 - 2.0*T2 + 2.0*T4)/constants()->tau(); // checked
672 
673  for (int slice = 0; slice<numTimeSlices; slice++){
674  dEdB += actionPtr->secondderivPotentialActionTau(slice)/(1.0*numTimeSlices);
675  }
676  dEdB *= beta*beta/(1.0*numTimeSlices);
677 
678  /* accumulate all energy estimators. */
679  estimator(0) += totEcv - totVop; // operator kinetic energy
680  estimator(1) += Kcv; // centroid virial kinetic energy
681  estimator(2) += totVop; // operator potential energy
682  estimator(3) += totEcv - Kcv; //centroid virial potential energy
683  estimator(4) += totEcv; // total energy
684  estimator(5) += totEcv - constants()->mu()*numParticles;
685  estimator(6) += (totEcv - totVop)/(1.0*numParticles);
686  estimator(7) += Kcv/(1.0*numParticles);
687  estimator(8) += totVop/(1.0*numParticles);
688  estimator(9) += (totEcv - Kcv)/(1.0*numParticles);
689  estimator(10) += totEcv/(1.0*numParticles);
690 
691  /* accumulate specific heat estimators. */
692  estimator(11) += totEcv*thermE*beta*beta;
693  estimator(12) += totEcv*beta;
694  estimator(13) += dEdB;
695  estimator(14) += totEcv*thermE*beta*beta*totEcv*beta;
696  estimator(15) += totEcv*beta*dEdB;
697  estimator(16) += totEcv*thermE*beta*beta*dEdB;
698 
699  /* thermodynamic energy */
700  estimator(17) += thermE;
701 
702  /* Pressure */
703  estimator(18) += Pressure;
704 
705 }
706 
707 // ---------------------------------------------------------------------------
708 // ---------------------------------------------------------------------------
709 // NUM PARTICLES ESTIMATOR CLASS ---------------------------------------------
710 // ---------------------------------------------------------------------------
711 // ---------------------------------------------------------------------------
712 
713 /*************************************************************************/
720  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
721  int _frequency, string _label) :
722  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
723 
724  /* Set estimator name and header */
725  header = str(format("%16s%16s%16s") % "N" % "N^2" % "density");
726  endLine = false;
727  initialize(3);
728 }
729 
730 /*************************************************************************/
734 }
735 
736 /*************************************************************************/
739 void NumberParticlesEstimator::accumulate() {
740  int numParticles = path.getTrueNumParticles();
741  estimator(0) += 1.0*numParticles;
742  estimator(1) += 1.0*numParticles*numParticles;
743  estimator(2) += 1.0*numParticles/path.boxPtr->volume;
744 }
745 
746 // ---------------------------------------------------------------------------
747 // ---------------------------------------------------------------------------
748 // NUMBER DISTRIBUTION ESTIMATOR CLASS ---------------------------------------
749 // ---------------------------------------------------------------------------
750 // ---------------------------------------------------------------------------
751 
752 /*************************************************************************/
760  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
761  int _frequency, string _label) :
762  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
763 
764  /* For now, we assume 50 particles on each side of the mean */
765  particleShift = 50;
766  startParticleNumber = max(constants()->initialNumParticles()-particleShift,0);
767  if (startParticleNumber == 0)
768  endParticleNumber = 2*particleShift;
769  else
770  endParticleNumber = constants()->initialNumParticles() + particleShift;
771  maxNumParticles = endParticleNumber - startParticleNumber + 1;
772 
773  /* If our number of paticles is too small, we compensate */
774  if ((constants()->initialNumParticles() - particleShift) < 0)
775  particleShift = constants()->initialNumParticles();
776 
777  initialize(maxNumParticles);
778 
779  /* Set estimator name and header */
780  header = str(format("#%15d") % startParticleNumber);
781  for (int n = startParticleNumber+1; n <= endParticleNumber; n++)
782  header.append(str(format("%16d") % n));
783 }
784 
785 /*************************************************************************/
789 }
790 
791 /*************************************************************************/
794 void NumberDistributionEstimator::accumulate() {
795 
796  /* Get the correct particle Number index, and increment the corresponding bin */
798  + particleShift;
799  if (index >= 0 && index < maxNumParticles)
800  estimator(index) += 1.0;
801 }
802 
803 // ---------------------------------------------------------------------------
804 // ---------------------------------------------------------------------------
805 // PARTICLE DENSITY ESTIMATOR CLASS ---------------------------------------------
806 // ---------------------------------------------------------------------------
807 // ---------------------------------------------------------------------------
808 
809 /*************************************************************************/
817  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
818  int _frequency, string _label) :
819  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
820 
822 
823  /* Setup estimator name and header. We include the PIMCID as we
824  * replace the file on every output.*/
825  diffLabels = {"dx","dy","dz"};
826 
827  header = str(format("# PIMCID: %s\n") % constants()->id());
828  header += "# ESTINF:" ;
829  for (int i = 0; i < NDIM; i++)
830  header += str(format(" %s = %12.6E") % diffLabels[i] % path.boxPtr->gridSize[i]);
831  header += str(format(" NGRIDSEP = %d\n") % NGRIDSEP);
832  header += str(format("#%15s") % "density");
833 
834  /* The normalization: 1/(dV*M) */
835  for (int n = 0; n < numEst; n++)
836  norm(n) = 1.0/(1.0*(endSlice-startSlice)*(1.0/actionPtr->period) *
838 }
839 
840 /*************************************************************************/
844 }
845 
846 /*************************************************************************/
850 void ParticlePositionEstimator::accumulate() {
851 
852  beadLocator beadIndex;
853 
854  for (int slice = startSlice; slice < endDiagSlice; slice += actionPtr->period) {
855  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
856  beadIndex = slice,ptcl;
857 
858  /* update our particle position histogram */
859  int n = path.boxPtr->gridIndex(path(beadIndex));
860  estimator(n) += sliceFactor[slice];
861  }
862  }
863 }
864 
865 // ---------------------------------------------------------------------------
866 // ---------------------------------------------------------------------------
867 // BIPARTITION DENSITY ESTIMATOR CLASS ---------------------------------------
868 // ---------------------------------------------------------------------------
869 // ---------------------------------------------------------------------------
870 
871 /*************************************************************************/
879  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
880  int _frequency, string _label) :
881  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
882 
883  /* Set estimator name and header*/
884  header = str(format("#%15s%16s") % "film dens" % "bulk dens");
885  endLine = true;
886  initialize(2);
887  norm(0) = 1.0/(path.numTimeSlices);
888  norm(1) = 1.0/(path.numTimeSlices);
889 }
890 
891 /*************************************************************************/
895  // empty destructor
896 }
897 
898 /*************************************************************************/
903 void BipartitionDensityEstimator::accumulate() {
904 
905  /* label the lengths of the sides of the simulation cell */
906  dVec lside;
907  for (int i = 0; i < NDIM; i++)
908  lside[i] = path.boxPtr->side[i];
909 
910  /* read in the exclusion lengths */
911  Array<double,1> excLens (actionPtr->externalPtr->getExcLen());
912  double excZ = excLens(1);
913 
914  /* determine volume of film region and bulk region */
915  double bulkVol ((lside[2]-2.0*excZ)*lside[0]*lside[1]);
916  double filmArea (lside[0]*2.0*excZ);
917 
918  /* keep track of number of particles in bulk and film */
919  int filmNum (0);
920  int bulkNum (0);
921 
922  dVec pos;
923  beadLocator beadIndex;
924  for (int slice = 0; slice < path.numTimeSlices; slice++) {
925  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
926  beadIndex = slice,ptcl;
927 
928  pos = path(beadIndex);
929  if (pos[2] > excZ)
930  bulkNum += 1;
931  else if (pos[2] < -excZ)
932  bulkNum += 1;
933  else
934  filmNum += 1;
935  }
936  }
937  /* update estimator with density in both regions*/
938  estimator(0) += 1.0*filmNum/(1.0*filmArea);
939  estimator(1) += 1.0*bulkNum/(1.0*bulkVol);
940 }
941 
942 // ---------------------------------------------------------------------------
943 // ---------------------------------------------------------------------------
944 // LINEAR PARTICLE DENSITY ESTIMATOR CLASS ------------------------------------
945 // ---------------------------------------------------------------------------
946 // ---------------------------------------------------------------------------
947 
948 /*************************************************************************/
956  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
957  int _frequency, string _label) :
958  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
959 
960  /* Make sure we have a bin centered at 0.0 */
961  numGrid = 2*NGRIDSEP-1;
962  dz = path.boxPtr->side[NDIM-1] / numGrid;
963 
964  /* This is a diagonal estimator that gets its own file */
965  initialize(numGrid);
966 
967  /* A local copy of the box size */
968  side = path.boxPtr->side;
969 
970  /* The header contains information about the grid */
971  header = str(format("# ESTINF: dz = %12.6E NGRIDSEP = %d\n") % dz % numGrid);
972  header += str(format("#%15.6E") % (-0.5*side[NDIM-1]));
973  for (int n = 1; n < numGrid; n++)
974  header.append(str(format("%16.6E") % (n*dz - 0.5*side[NDIM-1])));
975 
976  double A = 1.0;
977  for (int i = 0; i < NDIM-1; i++)
978  A *= side[i];
979 
980  norm = 1.0/(1.0*(endSlice-startSlice)*(1.0/actionPtr->period)*A*dz);
981 }
982 
983 /*************************************************************************/
987 }
988 
989 
990 /*************************************************************************/
994 void LinearParticlePositionEstimator::accumulate() {
995 
996  beadLocator beadIndex;
997  dVec pos;
998  int index;
999 
1000  for (int slice = startSlice; slice < endDiagSlice; slice += actionPtr->period) {
1001  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1002  beadIndex = slice,ptcl;
1003  pos = path(beadIndex);
1004 
1005  /* Get the z-index */
1006  index = static_cast<int>(abs(pos[NDIM-1] + 0.5*side[NDIM-1] - EPS ) / (dz + EPS));
1007 
1008  /* update our particle position histogram */
1009  if (index < numGrid)
1010  estimator(index) += sliceFactor[slice];
1011  }
1012  }
1013 }
1014 
1015 
1016 // ---------------------------------------------------------------------------
1017 // ---------------------------------------------------------------------------
1018 // PLANE PARTICLE DENSITY ESTIMATOR CLASS ------------------------------------
1019 // ---------------------------------------------------------------------------
1020 // ---------------------------------------------------------------------------
1021 
1022 /*************************************************************************/
1030  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1031  int _frequency, string _label) :
1032  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1033 
1034 
1035  /* We choose an odd number to make sure (0,0) is the central
1036  * grid box. */
1037  numLinearGrid = 4*NGRIDSEP+1;
1038  numGrid = numLinearGrid*numLinearGrid;
1039 
1040  /* The spatial discretization */
1041  for (int i = 0; i < NDIM; i++)
1042  dl[i] = path.boxPtr->side[i] / numLinearGrid;
1043 
1044  /* This is a diagonal estimator that gets its own file */
1045  initialize(numGrid);
1046 
1047  /* The header contains information about the grid */
1048  header = str(format("# ESTINF: dx = %12.6E dy = %12.6E NGRIDSEP = %d\n")
1049  % dl[0] % dl[1] % numLinearGrid);
1050  header += str(format("#%15.3E") % 0.0);
1051  for (int n = 1; n < numGrid; n++)
1052  header.append(str(format("%16.3E") % (1.0*n)));
1053 
1054  /* Compute the area of a grid box */
1055  double A = 1.0;
1056  for (int i = 0; i < NDIM-1; i++)
1057  A *= dl[i];
1058 
1059  norm = 1.0/((endSlice-startSlice)*(1.0/actionPtr->period)*A*path.boxPtr->side[NDIM-1]);
1060  side = path.boxPtr->side;
1061 }
1062 
1063 /*************************************************************************/
1067 }
1068 
1069 
1070 /*************************************************************************/
1074 void PlaneParticlePositionEstimator::accumulate() {
1075 
1076  beadLocator beadIndex;
1077  dVec pos;
1078 
1079  for (int slice = startSlice; slice < endDiagSlice; slice += actionPtr->period) {
1080  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1081  beadIndex = slice,ptcl;
1082  pos = path(beadIndex);
1083 
1084  int index = 0;
1085  for (int i = 0; i < NDIM-1; i++) {
1086  int scale = 1;
1087  for (int j = i+1; j < NDIM-1; j++)
1088  scale *= numLinearGrid;
1089  index += scale*static_cast<int>(abs(pos[i] + 0.5*side[i] - EPS ) / (dl[i] + EPS));
1090  }
1091 
1092  /* update our particle position histogram */
1093  if (index < numGrid)
1094  estimator(index) += sliceFactor[slice];
1095  }
1096  }
1097 }
1098 
1099 // ---------------------------------------------------------------------------
1100 // ---------------------------------------------------------------------------
1101 // PLANE PARTICLE AVERAGE DENSITY ESTIMATOR CLASS ----------------------------
1102 // ---------------------------------------------------------------------------
1103 // ---------------------------------------------------------------------------
1104 
1105 /*************************************************************************/
1113  const Path &_path, ActionBase *_actionPtr, const MTRand &_random,
1114  double _maxR, int _frequency, string _label) :
1115  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1116 
1117  /* We choose an odd number to make sure (0,0) is the central
1118  * grid box. */
1119  numLinearGrid = 4*NGRIDSEP+1;
1120  numGrid = numLinearGrid*numLinearGrid;
1121 
1122  /* The spatial discretization */
1123  for (int i = 0; i < NDIM; i++)
1124  dl[i] = path.boxPtr->side[i] / numLinearGrid;
1125 
1126  /* This is a diagonal estimator that gets its own file */
1127  initialize(numGrid);
1128 
1129  /* The header contains information about the grid */
1130  header = str(format("# PIMCID: %s\n") % constants()->id());
1131  header = str(format("# ESTINF: dx = %12.6E dy = %12.6E NGRIDSEP = %d\n")
1132  % dl[0] % dl[1] % numLinearGrid);
1133  header += str(format("#%15s") % "plane density");
1134 
1135  /* Compute the area of a grid box */
1136  double A = 1.0;
1137  for (int i = 0; i < NDIM-1; i++)
1138  A *= dl[i];
1139 
1140  norm = 1.0/((endSlice-startSlice)*(1.0/actionPtr->period)*A*path.boxPtr->side[NDIM-1]);
1141  side = path.boxPtr->side;
1142 }
1143 
1144 /*************************************************************************/
1148 }
1149 
1150 /*************************************************************************/
1154 void PlaneParticleAveragePositionEstimator::accumulate() {
1155 
1156  beadLocator beadIndex;
1157  dVec pos;
1158 
1159  for (int slice = startSlice; slice < endDiagSlice; slice += actionPtr->period) {
1160  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1161  beadIndex = slice,ptcl;
1162  pos = path(beadIndex);
1163 
1164  int index = 0;
1165  for (int i = 0; i < NDIM-1; i++) {
1166  int scale = 1;
1167  for (int j = i+1; j < NDIM-1; j++)
1168  scale *= numLinearGrid;
1169  index += scale*static_cast<int>(abs(pos[i] + 0.5*side[i] - EPS ) / (dl[i] + EPS));
1170  }
1171 
1172  /* update our particle position histogram */
1173  if (index < numGrid)
1174  estimator(index) += sliceFactor[slice];
1175  }
1176  }
1177 }
1178 
1179 // ---------------------------------------------------------------------------
1180 // ---------------------------------------------------------------------------
1181 // PLANE AVERAGE EXTERNAL POTENTIAL ESTIMATOR
1182 // ---------------------------------------------------------------------------
1183 // ---------------------------------------------------------------------------
1184 
1185 /*************************************************************************/
1192  const Path &_path, ActionBase *_actionPtr, const MTRand &_random,
1193  double _maxR, int _frequency, string _label) :
1194  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1195 
1196  /* We choose an odd number to make sure (0,0) is the central
1197  * grid box. */
1198  numLinearGrid = 4*NGRIDSEP+1;
1199  numGrid = numLinearGrid*numLinearGrid;
1200 
1201  /* The spatial discretization */
1202  for (int i = 0; i < NDIM; i++)
1203  dl[i] = path.boxPtr->side[i] / numLinearGrid;
1204 
1205  /* This is a diagonal estimator that gets its own file */
1206  initialize(numGrid);
1207 
1208  /* The header contains information about the grid */
1209  header = str(format("# PIMCID: %s\n") % constants()->id());
1210  header = str(format("# ESTINF: dx = %12.6E dy = %12.6E NGRIDSEP = %d\n")
1211  % dl[0] % dl[1] % numLinearGrid);
1212  header += str(format("#%15s") % "plane external potential");
1213 
1214  side = path.boxPtr->side;
1215 }
1216 
1217 /*************************************************************************/
1221 }
1222 
1223 /*************************************************************************/
1227 void PlaneAverageExternalPotentialEstimator::accumulate() {
1228 
1229  beadLocator beadIndex;
1230  dVec pos;
1231 
1232  for (int slice = startSlice; slice < endDiagSlice; slice += actionPtr->period) {
1233  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1234  beadIndex = slice,ptcl;
1235  pos = path(beadIndex);
1236 
1237  /* Obtain the index of the particle position */
1238  int index = 0;
1239  for (int i = 0; i < NDIM-1; i++) {
1240  int scale = 1;
1241  for (int j = i+1; j < NDIM-1; j++)
1242  scale *= numLinearGrid;
1243  index += scale*static_cast<int>(abs(pos[i] + 0.5*side[i] - EPS ) / (dl[i] + EPS));
1244  }
1245 
1246  /* update the external potential in each grid box */
1247  if (index < numGrid) {
1248  norm(index) += sliceFactor[slice];
1249  estimator(index) += sliceFactor[slice]*actionPtr->externalPtr->V(pos);
1250  }
1251  } //ptcl
1252  } //slice
1253 }
1254 
1255 /*************************************************************************/
1262 
1263  /* Prepare the position file for writing over old data */
1264  communicate()->file(label)->reset();
1265 
1266  (*outFilePtr) << header;
1267  if (endLine)
1268  (*outFilePtr) << endl;
1269 
1270  /* Now write the running average of the estimator to disk */
1271  double Vext = 0.0;
1272  for (int n = 0; n < numEst; n++) {
1273  if (abs(norm(n)) > 0.0)
1274  Vext = estimator(n)/norm(n);
1275  else
1276  Vext = 0.0;
1277  (*outFilePtr) << format("%16.8E\n") % Vext;
1278  }
1279 
1280  communicate()->file(label)->rename();
1281 }
1282 
1283 // ---------------------------------------------------------------------------
1284 // ---------------------------------------------------------------------------
1285 // SUPERFLUID FRACTION ESTIMATOR CLASS ---------------------------------------
1286 // ---------------------------------------------------------------------------
1287 // ---------------------------------------------------------------------------
1288 
1289 /*************************************************************************/
1298  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1299  int _frequency, string _label) :
1300  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1301 
1302  windMax = 10;
1303  /* We compute a bunch of estimators here, the superfluid fraction, the winding
1304  * number in all possible dimensions, and the winding number histograms up to
1305  * windMax windings. These are all diagonal estimators and we have our own
1306  * output file.*/
1307  initialize(4 + 2*windMax + 1 + 1);
1308 
1309  header = str(format("#%15s%16s%16s%16s") % "rho_s/rho" % "W^2(x)" % "W^2(y)" % "W^2(z)");
1310  for (int w = -windMax; w <= windMax; w++)
1311  header += str(format("%11sP(%+1d)") % " " % w);
1312  header += str(format("%16s") % "Area_rho_s");
1313 
1314  /* The pre-factor for the superfluid density is always the same */
1315  norm(0) = constants()->T() / (2.0 * sum(path.boxPtr->periodic) * constants()->lambda());
1316 
1317  /* The pre-factor for the area esimator */
1318  norm(5+2*windMax) = 0.5*constants()->T()*constants()->numTimeSlices()/constants()->lambda();
1319 }
1320 
1321 /*************************************************************************/
1325 }
1326 
1327 /*************************************************************************/
1334 void SuperfluidFractionEstimator::accumulate() {
1335 
1336  int numTimeSlices= path.numTimeSlices;
1337  double locW2oN = 0.0;
1338 
1339  /* Sum up the winding number over all particles */
1340  beadLocator beadIndex;
1341  double Az, I;
1342  dVec pos1,pos2;
1343 
1344  Az = I = 0.0;
1345  dVec W,vel;
1346  W = 0.0;
1347  for (int slice = 0; slice < numTimeSlices; slice++) {
1348  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1349 
1350  /* The winding number estimator */
1351  beadIndex = slice,ptcl;
1352  vel = path.getVelocity(beadIndex);
1353  W += vel;
1354 
1355  /* The area estimator */
1356  pos1 = path(beadIndex);
1357  pos2 = path(path.next(beadIndex));
1358  Az += pos1[0]*pos2[1]-pos2[0]*pos1[1];
1359  I += pos1[0]*pos2[0] + pos1[1]*pos2[1];
1360 
1361  }
1362  }
1363 
1364  /* Scale by the periodicity of the boundary conditions */
1365  W *= path.boxPtr->periodic;
1366 
1367  /* Compute the locally scaled W^2/N */
1368  locW2oN = dot(W,W)/(1.0*path.getTrueNumParticles());
1369 
1370  /* The average winding number squared */
1371  estimator(0) += locW2oN;
1372 
1373  /* Scale by the length of the system in each dimension*/
1374  W *= path.boxPtr->sideInv;
1375 
1376  /* The individual winding numbers, we always store 3 values regardless
1377  * of the dimensionality to ensure output file consistency */
1378  int i;
1379  for (i = 0; i < NDIM; i++)
1380  estimator(1+i) += W[i]*W[i];
1381  for (int j = i; j < 3; j++)
1382  estimator(1+j) += 0.0;
1383 
1384  /* Calcluate the winding number probablity in the NDIM^th dimension */
1385  int n = 0;
1386  for (int p = -windMax; p <= windMax; p++) {
1387  if (abs(W[NDIM-1]-1.0*p) < 0.2)
1388  estimator(4+n) += 1.0;
1389  ++n;
1390  }
1391 
1392  /* The Area Estimator */
1393  estimator(5+2*windMax) += Az*Az/I;
1394 }
1395 
1396 // ---------------------------------------------------------------------------
1397 // ---------------------------------------------------------------------------
1398 // PLANE WINDING SUPERFLUID DENSITY ESTIMATOR CLASS --------------------------
1399 // ---------------------------------------------------------------------------
1400 // ---------------------------------------------------------------------------
1401 
1402 /*************************************************************************/
1411 (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1412  int _frequency, string _label) :
1413  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1414 
1415  numGrid = (2*NGRIDSEP)*(2*NGRIDSEP);
1416 
1417  /* The spatial discretization */
1418  dx = path.boxPtr->side[0] / (2.0*NGRIDSEP);
1419  dy = path.boxPtr->side[1] / (2.0*NGRIDSEP);
1420 
1421  /* This is a diagonal estimator that gets its own file */
1422  initialize(numGrid);
1423 
1424  /* The header is the first line which contains the spatial separations */
1425  header = str(format("#%15.3E") % 0.0);
1426  for (int n = 1; n < numGrid; n++)
1427  header.append(str(format("%16.3E") % (1.0*n)));
1428 
1429  norm = 0.5 * constants()->T()/(dx*dy*path.boxPtr->side[NDIM-1]*constants()->lambda());
1430 
1431  /* Initialize the local arrays */
1432  locWz.resize(numGrid);
1433  locWz = 0.0;
1434 
1435  side = path.boxPtr->side;
1436 }
1437 
1438 /*************************************************************************/
1442  locWz.free();
1443 }
1444 
1445 /*************************************************************************/
1450 void PlaneWindingSuperfluidDensityEstimator::accumulate() {
1451 
1452  int numTimeSlices = path.numTimeSlices;
1453 
1454  beadLocator beadIndex;
1455  double Wz;
1456  dVec pos1,pos2;
1457  dVec vel;
1458 
1459  Wz = 0.0;
1460  locWz = 0.0;
1461  for (int slice = 0; slice < numTimeSlices; slice++) {
1462  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1463 
1464  beadIndex = slice,ptcl;
1465  pos1 = path(beadIndex);
1466  pos2 = path(path.next(beadIndex));
1467 
1468  int i = static_cast<int>(abs(pos1[0] + 0.5*side[0] - EPS ) / (dx + EPS));
1469  int j = static_cast<int>(abs(pos1[1] + 0.5*side[1] - EPS ) / (dy + EPS));
1470  int k = 2*NGRIDSEP*j + i;
1471 
1472  /* The winding number estimator */
1473  vel = path.getVelocity(beadIndex)*path.boxPtr->periodic;
1474  Wz += vel[NDIM-1];
1475 
1476  /* The local part of the winding number */
1477  if (k < numGrid)
1478  locWz(k) += vel[NDIM-1];
1479  }
1480  }
1481 
1482  estimator += locWz*Wz;
1483 }
1484 
1485 // ---------------------------------------------------------------------------
1486 // ---------------------------------------------------------------------------
1487 // PLANE AREA SUPERFLUID DENSITY ESTIMATOR CLASS -----------------------------
1488 // ---------------------------------------------------------------------------
1489 // ---------------------------------------------------------------------------
1490 
1491 /*************************************************************************/
1500 (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1501  int _frequency, string _label) :
1502  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1503 
1504  numGrid = (2*NGRIDSEP)*(2*NGRIDSEP);
1505 
1506  /* The spatial discretization */
1507  dx = path.boxPtr->side[0] / (2.0*NGRIDSEP);
1508  dy = path.boxPtr->side[1] / (2.0*NGRIDSEP);
1509 
1510  /* This is a diagonal estimator that gets its own file */
1511  initialize(numGrid);
1512 
1513  /* The header is the first line which contains the spatial separations */
1514  header = str(format("#%15.3E") % 0.0);
1515  for (int n = 1; n < numGrid; n++)
1516  header.append(str(format("%16.3E") % (1.0*n)));
1517 
1518  norm = 0.5 * constants()->T()/(dx*dy*path.boxPtr->side[NDIM-1]*constants()->lambda());
1519 
1520  /* Initialize the local arrays */
1521  locAz.resize(numGrid);
1522  locAz = 0.0;
1523 
1524  side = path.boxPtr->side;
1525 }
1526 
1527 /*************************************************************************/
1531  locAz.free();
1532 }
1533 
1534 /*************************************************************************/
1539 void PlaneAreaSuperfluidDensityEstimator::accumulate() {
1540 
1541  int numTimeSlices = path.numTimeSlices;
1542 
1543  beadLocator beadIndex;
1544  double tAz,Az,rp2;
1545  dVec pos1,pos2;
1546 
1547  Az = 0.0;
1548  locAz = 0.0;
1549  for (int slice = 0; slice < numTimeSlices; slice++) {
1550  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1551 
1552  beadIndex = slice,ptcl;
1553  pos1 = path(beadIndex);
1554  pos2 = path(path.next(beadIndex));
1555 
1556  int i = static_cast<int>(abs(pos1[0] + 0.5*side[0] - EPS ) / (dx + EPS));
1557  int j = static_cast<int>(abs(pos1[1] + 0.5*side[1] - EPS ) / (dy + EPS));
1558  int k = 2*NGRIDSEP*j + i;
1559 
1560  /* The distance from the z-axis squared */
1561  rp2 = pos1[0]*pos1[0] + pos1[1]*pos1[1];
1562  if (rp2 < dx*dx)
1563  rp2 = 0.25*dx*dx;
1564 
1565  /* The z-component of the area estimator */
1566  tAz = pos1[0]*pos2[1] - pos2[0]*pos1[1];
1567 
1568  /* The total area */
1569  Az += tAz;
1570 
1571  /* The local part of the area */
1572  if (k < numGrid)
1573  locAz(k) += tAz/rp2;
1574  }
1575  }
1576 
1577  estimator += locAz*Az;
1578 }
1579 
1580 // ---------------------------------------------------------------------------
1581 // ---------------------------------------------------------------------------
1582 // RADIAL WINDING SUPERFLUID DENSITY ESTIMATOR CLASS -------------------------
1583 // ---------------------------------------------------------------------------
1584 // ---------------------------------------------------------------------------
1585 
1586 /*************************************************************************/
1595 (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1596  int _frequency, string _label) :
1597  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1598 
1599  numGrid = NGRIDSEP;
1600 
1601  /* The spatial discretization */
1602  dR = 0.5*path.boxPtr->side[0] / (1.0*numGrid);
1603 
1604  /* This is a diagonal estimator that gets its own file */
1605  initialize(numGrid);
1606 
1607  /* The header is the first line which contains the spatial separations */
1608  header = str(format("#%15.3E") % 0.0);
1609  for (int n = 1; n < numGrid; n++)
1610  header.append(str(format("%16.3E") % ((n)*dR)));
1611 
1612  norm = 0.5 * constants()->T()/constants()->lambda();
1613  for (int n = 0; n < numGrid; n++)
1614  norm(n) /= (M_PI*(2*n+1)*dR*dR*path.boxPtr->side[NDIM-1]);
1615 
1616  /* Initialize the local arrays */
1617  locWz.resize(numGrid);
1618  locWz = 0.0;
1619 }
1620 
1621 /*************************************************************************/
1625  locWz.free();
1626 }
1627 
1628 /*************************************************************************/
1633 void RadialWindingSuperfluidDensityEstimator::accumulate() {
1634 
1635  int numTimeSlices = path.numTimeSlices;
1636 
1637  beadLocator beadIndex;
1638  double Wz;
1639  dVec pos1,pos2;
1640  dVec vel;
1641 
1642  Wz = 0.0;
1643  locWz = 0.0;
1644  for (int slice = 0; slice < numTimeSlices; slice++) {
1645  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1646 
1647  beadIndex = slice,ptcl;
1648  pos1 = path(beadIndex);
1649  pos2 = path(path.next(beadIndex));
1650 
1651  int k = int(sqrt(pos1[0]*pos1[0]+pos1[1]*pos1[1])/dR);
1652 
1653  /* The winding number estimator */
1654  vel = path.getVelocity(beadIndex)*path.boxPtr->periodic;
1655  Wz += vel[NDIM-1];
1656 
1657  /* The local part of the winding number */
1658  if (k < numGrid)
1659  locWz(k) += vel[NDIM-1];
1660  }
1661  }
1662 
1663  estimator += locWz*Wz;
1664 }
1665 
1666 // ---------------------------------------------------------------------------
1667 // ---------------------------------------------------------------------------
1668 // RADIAL AREA SUPERFLUID DENSITY ESTIMATOR CLASS ----------------------------
1669 // ---------------------------------------------------------------------------
1670 // ---------------------------------------------------------------------------
1671 
1672 /*************************************************************************/
1681 (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1682  int _frequency, string _label) :
1683  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1684 
1685  numGrid = NGRIDSEP;
1686 
1687  /* The spatial discretization */
1688  dR = 0.5*path.boxPtr->side[0] / (1.0*numGrid);
1689 
1690  /* This is a diagonal estimator that gets its own file */
1691  initialize(numGrid);
1692 
1693  /* The header is the first line which contains the spatial separations */
1694  header = str(format("#%15.3E") % 0.0);
1695  for (int n = 1; n < numGrid; n++)
1696  header.append(str(format("%16.3E") % ((n)*dR)));
1697 
1698  norm = 0.5 * constants()->T()/constants()->lambda();
1699  for (int n = 0; n < numGrid; n++)
1700  norm(n) /= (M_PI*(2*n+1)*dR*dR*path.boxPtr->side[NDIM-1]);
1701 
1702  /* Initialize the local arrays */
1703  locAz.resize(numGrid);
1704  locAz = 0.0;
1705 }
1706 
1707 /*************************************************************************/
1711  locAz.free();
1712 }
1713 
1714 /*************************************************************************/
1719 void RadialAreaSuperfluidDensityEstimator::accumulate() {
1720 
1721  int numTimeSlices = path.numTimeSlices;
1722 
1723  beadLocator beadIndex;
1724  double Az,rp2,tAz;
1725  dVec pos1,pos2;
1726 
1727  Az = 0.0;
1728  locAz = 0.0;
1729  for (int slice = 0; slice < numTimeSlices; slice++) {
1730  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1731 
1732  beadIndex = slice,ptcl;
1733  pos1 = path(beadIndex);
1734  pos2 = path(path.next(beadIndex));
1735  rp2 = pos1[0]*pos1[0] + pos1[1]*pos1[1];
1736 
1737  int k = int(sqrt(rp2)/dR);
1738 
1739  /* The z-component of the area estimator */
1740  tAz = pos1[0]*pos2[1] - pos2[0]*pos1[1];
1741 
1742  /* The total area */
1743  Az += tAz;
1744 
1745  /* The local part of the winding number */
1746  if (k < numGrid)
1747  locAz(k) += tAz/rp2;
1748  }
1749  }
1750 
1751  estimator += locAz*Az;
1752 }
1753 
1754 // ---------------------------------------------------------------------------
1755 // ---------------------------------------------------------------------------
1756 // LOCAL SUPERFLUID DENSITY ESTIMATOR CLASS ----------------------------------
1757 // ---------------------------------------------------------------------------
1758 // ---------------------------------------------------------------------------
1759 
1760 /*************************************************************************/
1769 (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1770  int _frequency, string _label):
1771  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1772 
1773  /* This is a 'local' histogram estimator so we use the defined grid */
1774  numGrid = path.boxPtr->numGrid;
1775  initialize(3*numGrid);
1776 
1777  /* The smallest allowed radius */
1778  dR = 0.5*path.boxPtr->side[0]/numGrid;
1779 
1780  header = str(format("#%15d\n") % NGRIDSEP);
1781  header += str(format("#%15s%16s%16s") % "W:rho_s" % "A:rho_s" % "A^2");
1782 
1783  double C = 0.5*constants()->T()/constants()->lambda();
1784 
1785  /* The normalization constant for the local winding and area estimators. */
1786  for (int n = 0; n < numGrid; n++) {
1787  double dV = path.boxPtr->gridBoxVolume(n);
1788  norm(n) = C/dV;
1789  norm(n+numGrid) = C/dV;
1790  norm(n+2*numGrid) = C/dV;
1791  }
1792 
1793  /* Initialize the local arrays */
1794  locWz.resize(numGrid);
1795  locWz = 0.0;
1796 
1797  locAz.resize(numGrid);
1798  locAz = 0.0;
1799 
1800  locA2.resize(numGrid);
1801  locA2 = 0.0;
1802 
1803 }
1804 
1805 /*************************************************************************/
1809  locWz.free();
1810  locAz.free();
1811  locA2.free();
1812 }
1813 
1814 /*************************************************************************/
1819 
1820  /* Prepare the position file for writing over old data */
1821  communicate()->file(label)->reset();
1822 
1823  (*outFilePtr) << header;
1824  if (endLine)
1825  (*outFilePtr) << endl;
1826 
1827  /* Now write the running average of the estimator to disk */
1828  for (int n = 0; n < numGrid; n++) {
1829  for (int i = 0; i < int(numEst/numGrid); i++)
1830  (*outFilePtr) << format("%16.8E") %
1831  (norm(n+i*numGrid)*estimator(n+i*numGrid)/totNumAccumulated);
1832  (*outFilePtr) << endl;
1833  }
1834 
1835  communicate()->file(label)->rename();
1836 }
1837 
1838 /*************************************************************************/
1845 void LocalSuperfluidDensityEstimator::accumulate() {
1846 
1847  int numTimeSlices = path.numTimeSlices;
1848  locAz = 0.0;
1849  locA2 = 0.0;
1850  locWz = 0.0;
1851 
1852  beadLocator beadIndex;
1853  double Az,rp2,Wz;
1854  double tAz;
1855  dVec pos1,pos2;
1856  dVec vel;
1857 
1858  Az = Wz = 0.0;
1859  for (int slice = 0; slice < numTimeSlices; slice++) {
1860  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
1861 
1862  beadIndex = slice,ptcl;
1863  pos1 = path(beadIndex);
1864  pos2 = path(path.next(beadIndex));
1865  int n = path.boxPtr->gridIndex(pos1);
1866 
1867  /* The distance from the z-axis squared */
1868  //rp2 = pos1[0]*pos1[0] + pos1[1]*pos1[1];
1869  rp2 = pos1[0]*pos2[0] + pos1[1]*pos2[1];
1870  if (abs(rp2) < dR*dR)
1871  rp2 = dR*dR;
1872 
1873  /* The winding number estimator */
1874  vel = path.getVelocity(beadIndex)*path.boxPtr->periodic;
1875  Wz += vel[NDIM-1];
1876 
1877  /* The local part of the winding number */
1878  locWz(n) += vel[NDIM-1];
1879 
1880  /* The z-component of the area estimator */
1881  tAz = pos1[0]*pos2[1] - pos2[0]*pos1[1];
1882 
1883  /* The total area */
1884  Az += tAz;
1885 
1886  /* The two local components */
1887  locA2(n) += tAz;
1888  locAz(n) += tAz/rp2;
1889  }
1890  }
1891 
1892  locWz *= Wz;
1893  locAz *= Az;
1894  locA2 *= Az;
1895 
1896  for (int n = 0; n < path.boxPtr->numGrid; n++) {
1897  estimator(n) += locWz(n);
1898  estimator(n+numGrid) += locAz(n);
1899  estimator(n+2*numGrid) += locA2(n);
1900  }
1901 }
1902 
1903 // ---------------------------------------------------------------------------
1904 // ---------------------------------------------------------------------------
1905 // DIAGONAL FRACTION ESTIMATOR CLASS -----------------------------------------
1906 // ---------------------------------------------------------------------------
1907 // ---------------------------------------------------------------------------
1908 
1909 /*************************************************************************/
1916  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1917  int _frequency, string _label) :
1918  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1919 
1920  initialize(1);
1921 
1922  header = str(format("%16s") % "diagonal");
1923  endLine = false;
1924 }
1925 
1926 /*************************************************************************/
1930 }
1931 
1932 /*************************************************************************/
1936 void DiagonalFractionEstimator::accumulate() {
1938  estimator(0) += 1.0;
1939 }
1940 
1941 /*************************************************************************/
1945 
1946  numSampled++;
1947 
1948  if (frequency && ((numSampled % frequency) == 0)) {
1950  numAccumulated++;
1951  accumulate();
1952  }
1953 }
1954 
1955 // ---------------------------------------------------------------------------
1956 // ---------------------------------------------------------------------------
1957 // WORM ESTIMATOR CLASS ------------------------------------------------------
1958 // ---------------------------------------------------------------------------
1959 // ---------------------------------------------------------------------------
1960 
1961 /*************************************************************************/
1969  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
1970  int _frequency, string _label) :
1971  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
1972 
1973  /* We measure the average worm length, gap and cost. It is an off-diagonal
1974  * estimator that is output to its own file */
1975  initialize(5);
1976  diagonal = false;
1977 
1978  header = str(format("#%15s%16s%16s%16s%16s") % "rel-worm-len" %
1979  "rel-worm-gap" % "worm-cost" % "head-tail-sep" % "particles");
1980 }
1981 
1982 /*************************************************************************/
1986 }
1987 
1988 /*************************************************************************/
1991 void WormPropertiesEstimator::accumulate() {
1992  estimator(0) += 1.0*path.worm.length / (1.0*path.numTimeSlices);
1993  estimator(1) += 1.0*path.worm.gap / (1.0*path.numTimeSlices);
1994  double r = dot(path.worm.sep,path.worm.sep);
1995  if (path.worm.gap == 0)
1996  estimator(2) += 0.0;
1997  else
1998  estimator(2) += 1.0*r*constants()->fourLambdaTauInv()/(1.0*path.worm.gap);
1999  estimator(3) += 1.0*sqrt(r);
2000  estimator(4) += 1.0*path.worm.getNumBeadsOn()/(1.0*constants()->numTimeSlices());
2001 }
2002 
2003 // ---------------------------------------------------------------------------
2004 // ---------------------------------------------------------------------------
2005 // PERMUTATION CYCLE ESTIMATOR CLASS -----------------------------------------
2006 // ---------------------------------------------------------------------------
2007 // ---------------------------------------------------------------------------
2008 
2009 /*************************************************************************/
2016  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2017  int _frequency, string _label) :
2018  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
2019 
2020  /* We just choose arbitrarily to only count cycles including up to 40 particles */
2021  maxNumCycles = 40;
2022 
2023  /* The permutatoin cycle estimator has its own file, and consists of
2024  * maxNumCycles permutation cycles */
2025  initialize(maxNumCycles);
2026 
2027  /* Set estimator name and header, which contains the permutation cycle
2028  * numbers */
2029  header = str(format("#%15d") % 1);
2030  for (int n = 2; n <= maxNumCycles; n++)
2031  header.append(str(format("%16d") % n));
2032 }
2033 
2034 /*************************************************************************/
2038  doBead.free();
2039 }
2040 
2041 /*************************************************************************/
2048 void PermutationCycleEstimator::accumulate() {
2049 
2050  /* The start bead for each world line, and the moving index */
2051  beadLocator startBead;
2052  beadLocator beadIndex;
2053 
2054  int numParticles = path.getTrueNumParticles();
2055  int numWorldlines = path.numBeadsAtSlice(0);
2056 
2057  double cycleNorm;
2058 
2059  if (numParticles > 0)
2060  cycleNorm = 1.0 / (1.0*numParticles);
2061  else
2062  cycleNorm = 0.0;
2063 
2064  /* We create a local vector, which determines whether or not we have
2065  * already included a bead at slice 0*/
2066  doBead.resize(numWorldlines);
2067  doBead = true;
2068 
2069  /* We go through each particle/worldline */
2070  for (int n = 0; n < numWorldlines; n++) {
2071 
2072  /* The initial bead to be moved */
2073  startBead = 0,n;
2074 
2075  /* We make sure we don't try to touch the same worldline twice */
2076  if (doBead(n)) {
2077 
2078  /* Mark the beads as touched and increment the number of worldlines */
2079  beadIndex = startBead;
2080 
2081  /* The world line length, we simply advance until we have looped back on
2082  * ourselves. */
2083  int wlLength = 0;
2084  do {
2085  wlLength++;
2086 
2087  /* We turn off any zero-slice beads we have touched */
2088  if (beadIndex[0]==0)
2089  doBead(beadIndex[1]) = false;
2090 
2091  beadIndex = path.next(beadIndex);
2092  } while (!all(beadIndex==startBead));
2093 
2094  /* Accumulte the cycle length counter */
2095  int cycleNum = int(wlLength / path.numTimeSlices);
2096  if ((cycleNum > 0) && (cycleNum <= maxNumCycles))
2097  estimator(cycleNum-1) += 1.0*cycleNum*cycleNorm;
2098  } // doBead
2099 
2100  } // n
2101 }
2102 
2103 // ---------------------------------------------------------------------------
2104 // ---------------------------------------------------------------------------
2105 // LOCAL PERMUTATION CYCLE ESTIMATOR CLASS -----------------------------------------
2106 // ---------------------------------------------------------------------------
2107 // ---------------------------------------------------------------------------
2108 
2109 /*************************************************************************/
2118  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2119  int _frequency, string _label) :
2120  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label) {
2121 
2122  /* We just choose arbitrarily to only count cycles including up to 40 particles */
2123  maxNumCycles = 40;
2124 
2125  /* The local permutation cycle estimator has its own file, and consists of
2126  * maxNumCycles permutation cycles */
2128 
2129  /* vector to hold number of worldlines put into a grid space */
2130  numBeadInGrid.resize(estimator.size());
2131 
2132  /* Set estimator header */
2133  header = str(format("#%15d") % NGRIDSEP);
2134 
2135 }
2136 
2137 /*************************************************************************/
2141  doBead.free();
2142 }
2143 
2144 /*************************************************************************/
2148 /* void LocalPermutationEstimator::output() { */
2149 
2150 /* /1* Prepare the position file for writing over old data *1/ */
2151 /* communicate()->file(label)->reset(); */
2152 
2153 /* (*outFilePtr) << header; */
2154 /* if (endLine) */
2155 /* (*outFilePtr) << endl; */
2156 
2157 /* /1* Now write the running average of the estimator to disk *1/ */
2158 /* for (int n = 0; n < numEst; n++) */
2159 /* (*outFilePtr) << format("%16.6E\n") % */
2160 /* (estimator(n)/totNumAccumulated); */
2161 
2162 /* communicate()->file(label)->rename(); */
2163 /* } */
2164 
2165 /*************************************************************************/
2175 void LocalPermutationEstimator::accumulate() {
2176 
2177  /* The start bead for each world line, and the moving index */
2178  beadLocator startBead;
2179  beadLocator beadIndex;
2180 
2181  int numWorldlines = path.numBeadsAtSlice(0);
2182 
2183  /* We create a local vector, which determines whether or not we have
2184  * already included a bead at slice 0*/
2185  doBead.resize(numWorldlines);
2186  doBead = true;
2187 
2188  /* We go through each particle/worldline */
2189  for (int n = 0; n < numWorldlines; n++) {
2190 
2191  /* The initial bead to be moved */
2192  startBead = 0,n;
2193 
2194  /* We make sure we don't try to touch the same worldline twice */
2195  if (doBead(n)) {
2196 
2197  /* Mark the beads as touched and increment the number of worldlines */
2198  beadIndex = startBead;
2199 
2200  /* The world line length, we simply advance until we have looped back on
2201  * ourselves. */
2202  int wlLength = 0;
2203  do {
2204  wlLength++;
2205 
2206  /* We turn off any zero-slice beads we have touched */
2207  if (beadIndex[0]==0)
2208  doBead(beadIndex[1]) = false;
2209 
2210  beadIndex = path.next(beadIndex);
2211  } while (!all(beadIndex==startBead)); // up to here, we have computed WL length only.
2212 
2213  /* Accumulate the cycle length counter */
2214  int cycleNum = int(wlLength / path.numTimeSlices);
2215 
2216  /* Loop through worldline again, this time binning the appropriate
2217  * permutation number (- 1) corresponding to its spatial coordinates.*/
2218  do {
2219  int nn = path.boxPtr->gridIndex(path(beadIndex));
2220  if ((cycleNum > 0) && (cycleNum <= maxNumCycles)){
2221  estimator(nn) += (1.0*cycleNum - 1.0);
2222  numBeadInGrid(nn) += 1;
2223  }
2224 
2225  beadIndex = path.next(beadIndex);
2226  } while (!all(beadIndex==startBead));
2227  } // doBead
2228  } // n
2229 
2230  /* Correct for multiple worldlines being in the same gridpoint
2231  * and compute normalization factor. */
2232  for (int i(0); i<int(estimator.size()); i++){
2233  if ((estimator(i) > 0) && (numBeadInGrid(i) > 0)){
2234  estimator(i) /= numBeadInGrid(i);
2235  }
2236  }
2237 
2238  /* resize array to store number of beads per grid */
2239  numBeadInGrid.resize(0);
2240  numBeadInGrid.resize(estimator.size());
2241 
2242 }
2243 // ---------------------------------------------------------------------------
2244 // ---------------------------------------------------------------------------
2245 // ONE BODY DENSITY MATRIX ESTIMATOR CLASS -----------------------------------
2246 // ---------------------------------------------------------------------------
2247 // ---------------------------------------------------------------------------
2248 
2249 /*************************************************************************/
2257  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2258  int _frequency, string _label) :
2259  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label),
2260  lpath(_path)
2261 {
2262 
2263  sqrt2LambdaTau = sqrt(2.0 * constants()->lambda() * constants()->tau());
2264 
2265  /* We chooose the maximum separation to be sqrt(NDIM)*min(L)/2 */
2266  dR = 0.5*sqrt(sum(path.boxPtr->periodic))*(blitz::min(path.boxPtr->side)) / (1.0*NOBDMSEP);
2267 
2268  /* This is an off-diagonal estimator*/
2270  diagonal = false;
2271 
2272  /* The header is the first line which contains the spatial separations */
2273  header = str(format("#%15.3E") % 0.0);
2274  for (int n = 1; n < NOBDMSEP; n++)
2275  header.append(str(format("%16.3E") % (n*dR)));
2276 
2277  numReps = 5;
2278  norm = 1.0 / (1.0*numReps);
2279 }
2280 
2281 /*************************************************************************/
2285 }
2286 
2287 /*************************************************************************/
2297  numSampled++;
2298  if ( frequency &&
2299  ((numSampled % frequency) == 0) &&
2301  (path.worm.gap > 0) && (path.worm.gap <= constants()->Mbar()) &&
2302  ( (lpath.worm.tail[0] % 2) == 0) ) {
2303 
2304  /* If we are canonical, we want the closed configuration to be close
2305  * to our ideal one */
2306  if ( (!canonical) ||
2307  (abs(path.worm.getNumBeadsOn()+path.worm.gap-numBeads0) <= 2) ) {
2309  numAccumulated++;
2310  accumulate();
2311  }
2312  }
2313 }
2314 
2315 /*************************************************************************/
2322 inline dVec OneBodyDensityMatrixEstimator::getRandomVector(const double r) {
2323  dVec rVec;
2324  rVec = 0.0;
2325 #if NDIM==1
2326  if (random.rand() < 0.5)
2327  rVec = r;
2328  else
2329  rVec = -r;
2330 #elif NDIM==2
2331  double theta = 2.0*M_PI*random.rand();
2332  rVec[0] = r*cos(theta);
2333  rVec[1] = r*sin(theta);
2334 #elif NDIM==3
2335  if (lpath.boxPtr->name == "Prism") {
2336  double theta = 2.0*M_PI*random.rand();
2337  double phi = M_PI*random.rand();
2338  rVec[0] = r*cos(theta)*sin(phi);
2339  rVec[1] = r*sin(theta)*sin(phi);
2340  rVec[2] = r*cos(phi);
2341  }
2342  else {
2343  if (random.rand() < 0.5)
2344  rVec[NDIM-1] = r;
2345  else
2346  rVec[NDIM-1] = -r;
2347  }
2348 #endif
2349  return rVec;
2350 }
2351 
2352 /*************************************************************************/
2362 dVec OneBodyDensityMatrixEstimator::newStagingPosition(const beadLocator &neighborIndex,
2363  const beadLocator &endIndex, const int stageLength, const int k) {
2364 
2365  /* The rescaled value of lambda used for staging */
2366  double f1 = 1.0 * (stageLength - k - 1);
2367  double f2 = 1.0 / (1.0*(stageLength - k));
2368  double sqrtLambdaKTau = sqrt2LambdaTau * sqrt(f1 * f2);
2369 
2370  /* We find the new 'midpoint' position which exactly samples the kinetic
2371  * density matrix */
2372  neighborPos = lpath(neighborIndex);
2373  newRanPos = lpath(endIndex) - neighborPos;
2374  lpath.boxPtr->putInBC(newRanPos);
2375  newRanPos *= f2;
2376  newRanPos += neighborPos;
2377 
2378  /* This is the random kick around that midpoint */
2379  for (int i = 0; i < NDIM; i++)
2380  newRanPos[i] = random.randNorm(newRanPos[i],sqrtLambdaKTau);
2381 
2382  lpath.boxPtr->putInside(newRanPos);
2383 
2384  return newRanPos;
2385 }
2386 
2387 /*************************************************************************/
2395 void OneBodyDensityMatrixEstimator::accumulate() {
2396 
2397  oldTailPos = lpath(lpath.worm.tail);
2398  oldAction = actionPtr->potentialAction(lpath.worm.tail);
2399 
2400  /* We make a list of all the beads involved in the move, adding them
2401  * as we go. */
2402  beadLocator beadIndex;
2403  beadIndex = lpath.worm.head;
2404  dVec pos;
2405  pos = 0.0;
2406  for (int k = 0; k < (lpath.worm.gap-1); k++)
2407  beadIndex = lpath.addNextBead(beadIndex,pos);
2408 
2409  /* Perform the final connection to the tail*/
2410  lpath.next(beadIndex) = lpath.worm.tail;
2411  lpath.prev(lpath.worm.tail) = beadIndex;
2412 
2413  for (int p = 0; p < numReps; p++) {
2414 
2415  /* Now we loop through all possible separations, evaluating the potential
2416  * action */
2417  for (int n = 0; n < NOBDMSEP; n++) {
2418 
2419  newAction = 0.0;
2420  ++numAttempted;
2421 
2422  /* Assign the new displaced tail position */
2423  newTailPos = oldTailPos + getRandomVector(n*dR);
2424  lpath.boxPtr->putInside(newTailPos);
2425  lpath.updateBead(lpath.worm.tail,newTailPos);
2426 
2427  /* Compute the free particle density matrix */
2428  rho0Norm = actionPtr->rho0(lpath.worm.head,lpath.worm.tail,lpath.worm.gap);
2429 
2430  /* action shift coming from a finite chemical potential */
2431  double muShift = lpath.worm.gap*constants()->mu()*constants()->tau();
2432 
2433  /* Starting from the head, we generate new positions for the beads via
2434  * staging, and accumulate the potential action */
2435  beadIndex = lpath.worm.head;
2436  int k = 0;
2437  do {
2438  if (!all(beadIndex==lpath.worm.head) && !all(beadIndex==lpath.worm.tail)) {
2439  lpath.updateBead(beadIndex,
2440  newStagingPosition(path.prev(beadIndex),lpath.worm.tail,lpath.worm.gap,k));
2441  ++k;
2442  }
2443 
2444  newAction += actionPtr->potentialAction(beadIndex);
2445 
2446  beadIndex = lpath.next(beadIndex);
2447  } while (!all(beadIndex==lpath.next(lpath.worm.tail)));
2448 
2449  double expAction = exp(-newAction + oldAction + muShift);
2450 
2451  estimator(n) += rho0Norm*expAction;
2452 
2453  /* Record the probability of accepting the move */
2454  if (random.randExc() < rho0Norm*expAction)
2455  ++numAccepted;
2456 
2457  } // end for n
2458 
2459  } // end for k
2460 
2461  /* Now we must undo any damge we have caused by reverting the tail to its previous position,
2462  * and turning off all intermediate beads */
2463  lpath.updateBead(lpath.worm.tail,oldTailPos);
2464 
2465  /* Delete all the beads that were added. */
2466  beadIndex = lpath.next(lpath.worm.head);
2467  while (!all(beadIndex==lpath.worm.tail)) {
2468  beadIndex = lpath.delBeadGetNext(beadIndex);
2469  }
2470  lpath.next(lpath.worm.head) = XXX;
2471  lpath.prev(lpath.worm.tail) = XXX;
2472 }
2473 
2474 /*************************************************************************/
2479 
2480  (*outFilePtr) << format("# accepted: %16.8E attempted: %16.8E ratio: %16.4E\n")
2481  % (1.0*numAccepted) % (1.0*numAttempted) % (1.0*numAccepted/(1.0*numAttempted));
2482 }
2483 
2484 // ---------------------------------------------------------------------------
2485 // ---------------------------------------------------------------------------
2486 // PAIR CORRELATION ESTIMATOR CLASS ------------------------------------------
2487 // ---------------------------------------------------------------------------
2488 // ---------------------------------------------------------------------------
2489 
2490 /*************************************************************************/
2498  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2499  int _frequency, string _label) :
2500  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
2501 {
2502  /* The spatial discretization */
2503  dR = 0.5*sqrt(sum(path.boxPtr->periodic))*path.boxPtr->side[NDIM-1] / (1.0*NPCFSEP);
2504 
2505  /* This is a diagonal estimator that gets its own file */
2507 
2508  /* The header is the first line which contains the spatial separations */
2509  header = str(format("#%15.3E") % 0.0);
2510  for (int n = 1; n < NPCFSEP; n++)
2511  header.append(str(format("%16.3E") % ((n)*dR)));
2512 
2513  /* The normalization factor for the pair correlation function depends
2514  * on the dimensionality */
2515 // TinyVector<double,3> gNorm;
2516 // gNorm[0] = 0.5;
2517 // gNorm[1] = 1.0/(4.0*M_PI);
2518 // gNorm[2] = 1.0/(8.0*M_PI);
2519 // norm(0) = 1.0;
2520 // for (int n = 1; n < NPCFSEP; n++)
2521 // norm(n) = (gNorm[NDIM-1]*path.boxPtr->volume) / (dR*pow(n*dR,NDIM-1));
2522 
2523  /* The normalization factor for the pair correlation function depends
2524  * on the dimensionality, and container type */
2525  if (path.boxPtr->name == "Cylinder") {
2526  for (int n = 0; n < NPCFSEP; n++)
2527  norm(n) = 0.5*path.boxPtr->side[NDIM-1] / dR;
2528  }
2529  else {
2530  TinyVector<double,3> gNorm;
2531  gNorm[0] = 1.0;
2532  gNorm[1] = 1.0/(M_PI);
2533  gNorm[2] = 3.0/(2.0*M_PI);
2534  double dV;
2535  for (int n = 0; n < NPCFSEP; n++) {
2536  dV = pow((n+1)*dR,NDIM)-pow(n*dR,NDIM);
2537  norm(n) = 0.5*(gNorm[NDIM-1]*path.boxPtr->volume) / dV;
2538  }
2539  }
2540 }
2541 
2542 /*************************************************************************/
2546 }
2547 
2548 /*************************************************************************/
2554 void PairCorrelationEstimator::accumulate() {
2555  int numParticles = path.getTrueNumParticles();
2556  double lnorm = 1.0*(numParticles-1)/(1.0*numParticles);
2557  if (numParticles > 1) {
2558  estimator += lnorm*(1.0*actionPtr->sepHist /
2559  (1.0*sum(actionPtr->sepHist)));
2560  }
2561  else
2562  estimator += 0.0;
2563 }
2564 
2565 // ---------------------------------------------------------------------------
2566 // ---------------------------------------------------------------------------
2567 // STATIC STRUCTURE FACTOR ESTIMATOR CLASS -----------------------------------
2568 // ---------------------------------------------------------------------------
2569 // ---------------------------------------------------------------------------
2570 
2571 /*************************************************************************/
2578  const Path &_path, ActionBase *_actionPtr, const MTRand &_random,
2579  double _maxR, int _frequency, string _label) :
2580  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
2581 {
2582 
2583  numq = 10;
2584  q.resize(numq);
2585  for (int n = 0; n < numq; n++)
2586  q(n) = (2.0*M_PI/path.boxPtr->side[0])*n;
2587 
2588  /* Initialize the accumulator intermediate scattering function*/
2589  sf.resize(numq);
2590  sf = 0.0;
2591 
2592  /* This is a diagonal estimator that gets its own file */
2593  initialize(numq);
2594 
2595  /* The magnitude of q */
2596  header = str(format("#%15.6E") % 0.0);
2597  for (int n = 1; n < numq; n++)
2598  header.append(str(format("%16.6E") % q(n)));
2599 
2600  /* Utilize imaginary time translational symmetry */
2601  norm = 1.0/constants()->numTimeSlices();
2602 }
2603 
2604 /*************************************************************************/
2608 }
2609 
2610 /*************************************************************************/
2616 void StaticStructureFactorEstimator::accumulate() {
2617 
2618  int numParticles = path.getTrueNumParticles();
2619  int numTimeSlices = constants()->numTimeSlices();
2620 
2621  beadLocator bead1,bead2; // The bead locator
2622  sf = 0.0; // initialize
2623 
2624  dVec pos1,pos2; // The two bead positions
2625  dVec lq; // The value of the wave-vector
2626  lq = 0.0;
2627 
2628  for (int nq = 0; nq < numq; nq++) {
2629  lq[0] = q(nq);
2630 
2631  /* Average over all initial time slices */
2632  for (int slice = 0; slice < numTimeSlices; slice++) {
2633 
2634  bead1[0] = bead2[0] = slice;
2635 
2636  for (bead1[1] = 0; bead1[1] < path.numBeadsAtSlice(slice); bead1[1]++) {
2637 
2638  pos1 = path(bead1);
2639  double lq1 = dot(lq,pos1);
2640 
2641  for (bead2[1] = 0; bead2[1] < path.numBeadsAtSlice(slice); bead2[1]++) {
2642 
2643  pos2 = path(bead2);
2644  double lq2 = dot(lq,pos2);
2645 
2646  sf(nq) += cos(lq1)*cos(lq2) + sin(lq1)*sin(lq2);
2647 
2648  } // bead2[1]
2649  } // bead1[1]
2650  } //slice
2651  } // nq
2652 
2653  estimator += sf/numParticles;
2654 }
2655 
2656 // ---------------------------------------------------------------------------
2657 // ---------------------------------------------------------------------------
2658 // INTERMEDIATE SCATTERING FUNCTION ESTIMATOR CLASS --------------------------
2659 // ---------------------------------------------------------------------------
2660 // ---------------------------------------------------------------------------
2661 
2662 /*************************************************************************/
2669  const Path &_path, ActionBase *_actionPtr, const MTRand &_random,
2670  double _maxR, int _frequency, string _label) :
2671  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
2672 {
2673 
2674  int numTimeSlices = constants()->numTimeSlices();
2675 
2676  /* these are the hard-coded q-vectors for now */
2677  numq = 3;
2678  Array <double, 1> qMag(numq); // the q-vector magnitudes
2679  /* qMag.resize(numq); */
2680  qMag = 0.761,1.75,1.81;
2681 
2682  /* initialize the number of vectors with each magnitude */
2683  numqVecs.resize(numq);
2684  numqVecs = 0;
2685 
2686  /* The allowable error in the q-vector magnitude */
2687  double eps = 2.0*M_PI/min(path.boxPtr->side)/sqrt(NDIM);
2688  eps *= eps;
2689 
2690  /* Determine the set of q-vectors that have these magintudes */
2691  for (int nq = 0; nq < numq; nq++)
2692  {
2693  double cq = qMag(nq);
2694  vector <dVec> qvecs;
2695 
2696  int maxComp = ceil(cq*blitz::min(path.boxPtr->side)/(2.0*M_PI))+1;
2697  int maxNumQ = ipow(2*maxComp + 1,NDIM);
2698 
2699  iVec qi;
2700  for (int n = 0; n < maxNumQ; n++) {
2701  for (int i = 0; i < NDIM; i++) {
2702  int scale = 1;
2703  for (int j = i+1; j < NDIM; j++)
2704  scale *= (2*maxComp + 1);
2705  qi[i] = (n/scale) % (2*maxComp + 1);
2706 
2707  /* Wrap into the appropriate winding sector */
2708  qi[i] -= (qi[i] > maxComp)*(2*maxComp + 1);
2709  }
2710  dVec qd = 2.0*M_PI*qi/path.boxPtr->side;
2711 
2712  /* Store the winding number */
2713  if (abs(dot(qd,qd)-cq*cq) < eps) {
2714  qvecs.push_back(qd);
2715  numqVecs(nq)++;
2716  }
2717  }
2718 
2719  /* Make sure we have some q-vectors */
2720  if (qvecs.size() < 1) {
2721  cerr << "\nERROR: Intermediate Scattering function: "
2722  << "No valid q-vectors were added to the list for measurment."
2723  << endl << "Action: modify q-magintudes." << endl;
2724  exit(0);
2725  }
2726 
2727  q.push_back(qvecs);
2728  }
2729 
2730  /* get more accurate q-magnitudes */
2731  for (int nq = 0; nq < numq; nq++)
2732  qMag(nq) = sqrt(dot(q[nq][0],q[nq][0]));
2733 
2734  /* Initialize the accumulator for the intermediate scattering function*/
2735  /* N.B. for now we hard-code three wave-vectors */
2736  isf.resize(numq*numTimeSlices);
2737  isf = 0.0;
2738 
2739  /* This is a diagonal estimator that gets its own file */
2740  initialize(numq*numTimeSlices);
2741 
2742  /* the q-values */
2743  header = str(format("#%15.6E") % qMag(0));
2744  for (int n = 1; n < numq; n++)
2745  header.append(str(format("%16.6E") % qMag(n)));
2746  header.append("\n");
2747 
2748  /* The imaginary time values */
2749  header.append(str(format("#%15.6E") % 0.0));
2750  for (int n = 1; n < numTimeSlices; n++)
2751  header.append(str(format("%16.6E") % (constants()->tau()*n)));
2752 
2753  for (int nq = 1; nq < numq; nq++) {
2754  for (int n = 0; n < numTimeSlices; n++)
2755  header.append(str(format("%16.6E") % (constants()->tau()*n)));
2756  }
2757 
2758  /* utilize imaginary time translational symmetry */
2759  norm = 1.0/numTimeSlices;
2760 }
2761 
2762 /*************************************************************************/
2766 }
2767 
2768 /*************************************************************************/
2774 void IntermediateScatteringFunctionEstimator::accumulate() {
2775 
2776  int numParticles = path.getTrueNumParticles();
2777  int numTimeSlices = constants()->numTimeSlices();
2778 
2779  beadLocator bead1,bead2; // The bead locator
2780  isf = 0.0; // initialize
2781  dVec pos1,pos2; // The two bead positions
2782 
2783  /* q-magnitudes */
2784  for (int nq = 0; nq < numq; nq++) {
2785 
2786  /* q-vectors */
2787  for (const auto &cqvec : q[nq]) {
2788 
2789  /* Average over all initial time slices */
2790  for (bead1[0] = 0; bead1[0] < numTimeSlices; bead1[0]++) {
2791 
2792  /* compute for each tau separation */
2793  for (int tausep = 0; tausep < numTimeSlices; tausep++){
2794 
2795  bead2[0] = (bead1[0] + tausep) % numTimeSlices;
2796 
2797  for (bead1[1] = 0; bead1[1] < path.numBeadsAtSlice(bead1[0]); bead1[1]++) {
2798 
2799  pos1 = path(bead1);
2800  double lq1 = dot(cqvec,pos1);
2801 
2802  for (bead2[1] = 0; bead2[1] < path.numBeadsAtSlice(bead2[0]); bead2[1]++) {
2803 
2804  pos2 = path(bead2);
2805  double lq2 = dot(cqvec,pos2);
2806 
2807  isf(nq*numTimeSlices + tausep) += (cos(lq1)*cos(lq2) + sin(lq1)*sin(lq2))/numqVecs(nq);
2808  } // bead2[1]
2809  } // bead1[1]
2810  } //tausep
2811  } //bead1[0]
2812  } //q-vectors
2813  } //q-magnitudes
2814 
2815  estimator += isf/numParticles;
2816 }
2817 
2818 // ---------------------------------------------------------------------------
2819 // ---------------------------------------------------------------------------
2820 // RADIAL DENSITY ESTIMATOR CLASS --------------------------------------------
2821 // ---------------------------------------------------------------------------
2822 // ---------------------------------------------------------------------------
2823 
2824 /*************************************************************************/
2830  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2831  int _frequency, string _label) :
2832  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
2833 {
2834  /* The spatial discretization */
2835  dR = 0.5*path.boxPtr->side[0] / (1.0*NRADSEP);
2836 
2837  /* This is a diagonal estimator that gets its own file */
2839 
2840  /* The header is the first line which contains the spatial separations */
2841  header = str(format("#%15.3E") % 0.0);
2842  for (int n = 1; n < NRADSEP; n++)
2843  header.append(str(format("%16.3E") % ((n)*dR)));
2844 
2845  norm = 1.0 / (path.boxPtr->side[NDIM-1]*path.numTimeSlices);
2846  for (int n = 0; n < NRADSEP; n++)
2847  norm(n) /= (M_PI*(2*n+1)*dR*dR);
2848 }
2849 
2850 /*************************************************************************/
2854 }
2855 
2856 /*************************************************************************/
2859 void RadialDensityEstimator::accumulate() {
2860 
2861  dVec pos;
2862  double rsq;
2863  beadLocator beadIndex;
2864  for (int slice = 0; slice < path.numTimeSlices; slice++) {
2865  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
2866  beadIndex = slice,ptcl;
2867  pos = path(beadIndex);
2868  rsq = 0.0;
2869  for (int i = 0; i < NDIM-1; i++)
2870  rsq += pos[i]*pos[i];
2871  int k = int(sqrt(rsq)/dR);
2872  if (k < NRADSEP)
2873  estimator(k) += 1.0;
2874  }
2875  }
2876 }
2877 
2880 // CYLINDER ESTIMATORS ///////////////////////////////////////////////////
2883 
2884 /*************************************************************************/
2887 inline bool include(const dVec &r, double maxR) {
2888  return (r[0]*r[0] + r[1]*r[1] < maxR*maxR);
2889 }
2890 
2891 /*************************************************************************/
2896 int num1DParticles(const Path &path, double maxR) {
2897  int tot = 0;
2898  dVec r;
2899  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(0); ptcl++) {
2900  r = path(0,ptcl);
2901  if (include(path(0,ptcl),maxR))
2902  tot++;
2903  }
2904  return tot;
2905 }
2906 
2907 // ---------------------------------------------------------------------------
2908 // ---------------------------------------------------------------------------
2909 // CYLINDER ENERGY ESTIMATOR CLASS -------------------------------------------
2910 // ---------------------------------------------------------------------------
2911 // ---------------------------------------------------------------------------
2912 
2913 /*************************************************************************/
2920  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
2921  int _frequency, string _label) :
2922  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
2923 {
2924 
2925  /* We compute three diagonal estimators, kinetic, potential and total energy
2926  * per particle */
2927  initialize(7);
2928  endLine = false;
2929 
2930  /* Set estimator header, we will always report the energy
2931  * first, hence the comment symbol*/
2932  header = str(format("#%15s%16s%16s%16s%16s%16s%16s")
2933  % "K" % "V" % "E" % "E_mu" % "K/N" % "V/N" % "E/N");
2934 }
2935 
2936 /*************************************************************************/
2940 }
2941 
2942 /*************************************************************************/
2949 void CylinderEnergyEstimator::accumulate() {
2950 
2951  double totK = 0.0;
2952  double totV = 0.0;
2953 
2954  int numParticles = num1DParticles(path,maxR);
2955  int numTimeSlices = path.numTimeSlices;
2956 
2957  /* The kinetic normalization factor */
2958  double kinNorm = constants()->fourLambdaTauInv() / (constants()->tau() * numTimeSlices);
2959 
2960  /* The classical contribution to the kinetic energy per particle
2961  * including the chemical potential */
2962  double classicalKinetic = (0.5 * NDIM / constants()->tau()) * numParticles;
2963 
2964  /* We first calculate the kinetic energy. Even though there
2965  * may be multiple mixing and swaps, it doesn't matter as we always
2966  * just advance one time step at a time, as taken care of through the
2967  * linking arrays. This has been checked! */
2968  beadLocator beadIndex;
2969  dVec vel;
2970  for (int slice = 0; slice < numTimeSlices; slice++) {
2971  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
2972  beadIndex = slice,ptcl;
2973  if (include(path(beadIndex),maxR)) {
2974  vel = path.getVelocity(beadIndex);
2975  totK -= dot(vel,vel);
2976  }
2977  }
2978  }
2979 
2980  /* Normalize the accumulated link-action part */
2981  totK *= kinNorm;
2982 
2983  /* Now we compute the potential and kinetic energy. We use an operator estimater
2984  * for V and the thermodynamic estimator for K */
2985  int eo;
2986  double t1 = 0.0;
2987  double t2 = 0.0;
2988  for (int slice = 0; slice < numTimeSlices; slice++) {
2989  eo = (slice % 2);
2990  t1 += actionPtr->derivPotentialActionLambda(slice,maxR);
2991  t2 += actionPtr->derivPotentialActionTau(slice,maxR);
2992  if (eo==0)
2993  totV += actionPtr->potential(slice,maxR);
2994  }
2995 
2996  /* Normalize the action correction and the total potential*/
2997  t1 *= constants()->lambda()/(constants()->tau()*numTimeSlices);
2998  t2 /= 1.0*numTimeSlices;
2999  totV /= (0.5 * numTimeSlices);
3000 
3001  /* Perform all the normalizations and compute the individual energy terms */
3002  totK += (classicalKinetic + t1);
3003 
3004  /* Now we accumulate the average total, kinetic and potential energy,
3005  * as well as their values per particles, provided we have at least one
3006  * particle in the central region. */
3007  if (numParticles > 0) {
3008  estimator(0) += totK;
3009  estimator(1) += totV;
3010  estimator(2) += totK + totV;
3011 
3012  estimator(3) += totK + totV - constants()->mu()*numParticles;
3013 
3014  estimator(4) += totK/(1.0*numParticles);
3015  estimator(5) += totV/(1.0*numParticles);
3016  estimator(6) += (totK + totV)/(1.0*numParticles);
3017  }
3018 }
3019 
3020 // ---------------------------------------------------------------------------
3021 // ---------------------------------------------------------------------------
3022 // CYLINDER NUM PARTICLES ESTIMATOR CLASS ------------------------------------
3023 // ---------------------------------------------------------------------------
3024 // ---------------------------------------------------------------------------
3025 
3026 /*************************************************************************/
3033  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3034  int _frequency, string _label) :
3035  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3036 {
3037  /* We compute three diagonal estimators, the total number of particles,
3038  * total number of particles squared and density. */
3039  initialize(3);
3040 
3041  /* Set estimator header */
3042  header = str(format("%16s%16s%16s") % "N" % "N^2" % "density");
3043 }
3044 
3045 /*************************************************************************/
3049 }
3050 
3051 /*************************************************************************/
3054 void CylinderNumberParticlesEstimator::accumulate() {
3055  int numParticles = num1DParticles(path,maxR);
3056  estimator(0) += 1.0*numParticles;
3057  estimator(1) += 1.0*numParticles*numParticles;
3058  estimator(2) += 1.0*numParticles/(M_PI*maxR*maxR*path.boxPtr->side[NDIM-1]);
3059 }
3060 
3061 // ---------------------------------------------------------------------------
3062 // ---------------------------------------------------------------------------
3063 // CYLINDER NUMBER DISTRIBUTION ESTIMATOR CLASS ------------------------------
3064 // ---------------------------------------------------------------------------
3065 // ---------------------------------------------------------------------------
3066 
3067 /*************************************************************************/
3075  (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3076  int _frequency, string _label) :
3077  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3078 {
3079 
3080  /* For now, we assume a maximum of 200 total particles. */
3081  maxNumParticles = 200;
3082  initialize(maxNumParticles);
3083 
3084  /* Set estimator header */
3085  header = str(format("#%15d") % 0);
3086  for (int n = 1; n < maxNumParticles; n++)
3087  header.append(str(format("%16d") % n));
3088 }
3089 
3090 /*************************************************************************/
3094 }
3095 
3096 /*************************************************************************/
3099 void CylinderNumberDistributionEstimator::accumulate() {
3100 
3101  /* Get the correct particle Number index, and increment the corresponding bin */
3102  int index = num1DParticles(path,maxR);
3103  if (index >= 0 && index < maxNumParticles)
3104  estimator(index) += 1.0;
3105 }
3106 
3107 // ---------------------------------------------------------------------------
3108 // ---------------------------------------------------------------------------
3109 // CYLINDER LINEAR DENSITY ESTIMATOR CLASS -----------------------------------
3110 // ---------------------------------------------------------------------------
3111 // ---------------------------------------------------------------------------
3112 
3113 /*************************************************************************/
3120  (const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3121  int _frequency, string _label) :
3122  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3123 {
3124  /* The length of the cylinder */
3125  Lz = path.boxPtr->side[NDIM-1];
3126 
3127  /* The spatial discretization */
3128  dz = Lz / (1.0*NRADSEP);
3129 
3130  /* This is a diagonal estimator that gets its own file */
3132 
3133  /* The header is the first line which contains the spatial positions */
3134  header = str(format("#%15.3E") % 0.0);
3135  for (int n = 1; n < NRADSEP; n++)
3136  header.append(str(format("%16.3E") % (n*dz)));
3137 
3138  /* The normalization factor for the linear density*/
3139  norm = 1.0/(dz * constants()->numTimeSlices());
3140 }
3141 
3142 /*************************************************************************/
3146 }
3147 
3148 /*************************************************************************/
3151 void CylinderLinearDensityEstimator::accumulate() {
3152 
3153  dVec pos;
3154  beadLocator beadIndex;
3155  /* visit each bead */
3156  for (int slice = 0; slice < path.numTimeSlices; slice++) {
3157  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
3158  beadIndex = slice,ptcl;
3159  pos = path(beadIndex);
3160 
3161  /* If we are inside the cutoff cylinder, accumulate the density
3162  * histogram */
3163  if (include(pos,maxR)) {
3164  int k = int((0.5*Lz + pos[NDIM-1])/dz);
3165  if (k < NRADSEP)
3166  estimator(k) += 1.0;
3167  }
3168  }
3169  }
3170 }
3171 
3172 // ---------------------------------------------------------------------------
3173 // ---------------------------------------------------------------------------
3174 // CYLINDER SUPERFLUID FRACTION ESTIMATOR CLASS ------------------------------
3175 // ---------------------------------------------------------------------------
3176 // ---------------------------------------------------------------------------
3177 
3178 /*************************************************************************/
3187  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3188  int _frequency, string _label) :
3189  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3190 {
3191 
3192  windMax = 10;
3193  /* We compute a bunch of estimators here, the superfluid fraction, the winding
3194  * number in all possible dimensions, and the winding number histograms up to
3195  * windMax windings. These are all diagonal estimators and we have our own
3196  * output file.*/
3197  initialize(4+2*windMax+1);
3198 
3199  /* Set estimator header */
3200  header = str(format("#%15s%16s%16s%16s") % "rho_s/rho" % "W^2(x)" % "W^2(y)" % "W^2(z)");
3201  for (int w = -windMax; w <= windMax; w++)
3202  header += str(format("%11sP(%+1d)") % " " % w);
3203 
3204  /* The pre-factor for the superfluid density is always the same */
3205  norm(0) = constants()->T() / (2.0 * sum(path.boxPtr->periodic) * constants()->lambda());
3206 }
3207 
3208 /*************************************************************************/
3212 }
3213 
3214 /*************************************************************************/
3221 void CylinderSuperfluidFractionEstimator::accumulate() {
3222 
3223  double locW2oN = 0.0;
3224 
3225  /* Sum up the winding number over all particles */
3226  dVec W,locW,vel;
3227  W = 0.0;
3228  locW = 0.0;
3229 
3230  /* The start bead for each world line, and the moving index */
3231  beadLocator startBead;
3232  beadLocator beadIndex;
3233 
3234  int numWorldlines = path.numBeadsAtSlice(0);
3235 
3236  /* We create a local vector, which determines whether or not we have
3237  * already included a bead at slice 0*/
3238  doBead.resize(numWorldlines);
3239  doBead = true;
3240 
3241  /* Needed to ensure an included world line */
3242  bool includeWorldline = true;
3243 
3244  /* We go through each particle/worldline */
3245  for (int n = 0; n < numWorldlines; n++) {
3246 
3247  /* The initial bead to be moved */
3248  startBead = 0,n;
3249 
3250  /* We make sure we don't try to touch the same worldline twice */
3251  if (doBead(n)) {
3252 
3253  /* Mark the beads as touched and increment the number of worldlines */
3254  beadIndex = startBead;
3255 
3256  /* Go through all worldlines, summing up the winding number */
3257  locW = 0.0;
3258  includeWorldline = true;
3259  do {
3260 
3261  /* We turn off any zero-slice beads we have touched */
3262  if (beadIndex[0]==0)
3263  doBead(beadIndex[1]) = false;
3264 
3265  /* If the bead is inside our cutoff radius, include its winding */
3266  if (include(path(beadIndex),maxR)) {
3267  vel = path.getVelocity(beadIndex);
3268  locW += vel;
3269  }
3270  else
3271  includeWorldline = false;
3272 
3273  beadIndex = path.next(beadIndex);
3274  } while (!all(beadIndex==startBead));
3275 
3276  if (includeWorldline)
3277  W += locW;
3278 
3279  } // doBead
3280  } // worldLine
3281 
3282  /* Scale by the periodicity of the boundary conditions */
3283  W *= path.boxPtr->periodic;
3284 
3285  /* Compute the locally scaled W^2/N */
3286  int numParticles = num1DParticles(path,maxR);
3287  if (numParticles > 0)
3288  locW2oN = dot(W,W)/(1.0*numParticles);
3289  else
3290  locW2oN = 0.0;
3291 
3292  /* The average winding number squared */
3293  estimator(0) += locW2oN;
3294 
3295  /* Scale by the length of the system in each dimension*/
3296  W *= path.boxPtr->sideInv;
3297 
3298  /* The individual winding numbers, we always store 3 values regardless
3299  * of the dimensionality to ensure output file consistency */
3300  int i;
3301  for (i = 0; i < NDIM; i++)
3302  estimator(1+i) += W[i]*W[i];
3303  for (int j = i; j < 3; j++)
3304  estimator(1+j) += 0.0;
3305 
3306  /* Calcluate the winding number probablity in the NDIM^th dimension */
3307  int n = 0;
3308  for (int p = -windMax; p <= windMax; p++) {
3309  if (abs(W[NDIM-1]-1.0*p) < 0.2)
3310  estimator(4+n) += 1.0;
3311  ++n;
3312  }
3313 }
3314 
3315 
3316 // ---------------------------------------------------------------------------
3317 // ---------------------------------------------------------------------------
3318 // CYLINDER ONE BODY DENSITY MATRIX ESTIMATOR CLASS --------------------------
3319 // ---------------------------------------------------------------------------
3320 // ---------------------------------------------------------------------------
3321 
3322 /*************************************************************************/
3330  (Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3331  int _frequency, string _label) :
3332  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label),
3333  lpath(_path)
3334 {
3335  sqrt2LambdaTau = sqrt(2.0 * constants()->lambda() * constants()->tau());
3336 
3337  /* We chooose the maximum separation to be sqrt(NDIM)*L/2 */
3338  dR = 0.5*sqrt(sum(path.boxPtr->periodic))*path.boxPtr->side[NDIM-1] / (1.0*NOBDMSEP);
3339 
3340  /* This is an off-diagonal estimator that gets its own file */
3342  diagonal = false;
3343 
3344  /* The header is the first line which contains the spatial separations */
3345  header = str(format("#%15.3E") % 0.0);
3346  for (int n = 1; n < NOBDMSEP; n++)
3347  header.append(str(format("%16.3E") % (n*dR)));
3348 
3349  numReps = 10;
3350  norm = 1.0 / (1.0*numReps);
3351 }
3352 
3353 /*************************************************************************/
3357 }
3358 
3359 /*************************************************************************/
3367  numSampled++;
3368  if ( frequency &&
3369  ((numSampled % frequency) == 0) &&
3371  (path.worm.gap > 0) && (path.worm.gap <= constants()->Mbar()) &&
3372  ( (lpath.worm.tail[0] % 2) == 0) ) {
3373 
3374  /* We only attempt the partial-close if both the head and tail
3375  * are within the include region. */
3376  if ( include(path(path.worm.head),maxR) && include(path(path.worm.tail),maxR) ) {
3378  numAccumulated++;
3379  accumulate();
3380  }
3381  }
3382 }
3383 
3384 /*************************************************************************/
3391 inline dVec CylinderOneBodyDensityMatrixEstimator::getRandomVector(const double r) {
3392  dVec rVec;
3393  rVec = 0.0;
3394  if (random.rand() < 0.5)
3395  rVec[NDIM-1] = r;
3396  else
3397  rVec[NDIM-1] = -r;
3398 
3399  return rVec;
3400 }
3401 
3402 /*************************************************************************/
3412 dVec CylinderOneBodyDensityMatrixEstimator::newStagingPosition(const beadLocator &neighborIndex,
3413  const beadLocator &endIndex, const int stageLength, const int k) {
3414 
3415  /* The rescaled value of lambda used for staging */
3416  double f1 = 1.0 * (stageLength - k - 1);
3417  double f2 = 1.0 / (1.0*(stageLength - k));
3418  double sqrtLambdaKTau = sqrt2LambdaTau * sqrt(f1 * f2);
3419 
3420  /* We find the new 'midpoint' position which exactly samples the kinetic
3421  * density matrix */
3422  neighborPos = lpath(neighborIndex);
3423  newRanPos = lpath(endIndex) - neighborPos;
3424  lpath.boxPtr->putInBC(newRanPos);
3425  newRanPos *= f2;
3426  newRanPos += neighborPos;
3427 
3428  /* This is the random kick around that midpoint */
3429  for (int i = 0; i < NDIM; i++)
3430  newRanPos[i] = random.randNorm(newRanPos[i],sqrtLambdaKTau);
3431 
3432  lpath.boxPtr->putInside(newRanPos);
3433 
3434  return newRanPos;
3435 }
3436 
3437 /*************************************************************************/
3445 void CylinderOneBodyDensityMatrixEstimator::accumulate() {
3446 
3447  oldTailPos = lpath(lpath.worm.tail);
3448  oldAction = actionPtr->potentialAction(lpath.worm.tail);
3449 
3450  /* We make a list of all the beads involved in the move, adding them
3451  * as we go. */
3452  beadLocator beadIndex;
3453  beadIndex = lpath.worm.head;
3454  dVec pos;
3455  pos = 0.0;
3456  for (int k = 0; k < (lpath.worm.gap-1); k++)
3457  beadIndex = lpath.addNextBead(beadIndex,pos);
3458 
3459  /* Perform the final connection to the tail*/
3460  lpath.next(beadIndex) = lpath.worm.tail;
3461  lpath.prev(lpath.worm.tail) = beadIndex;
3462 
3463  for (int p = 0; p < numReps; p++) {
3464 
3465  /* Now we loop through all possible separations, evaluating the potential
3466  * action */
3467  for (int n = 0; n < NOBDMSEP; n++) {
3468 
3469  newAction = 0.0;
3470  ++numAttempted;
3471 
3472  /* Assign the new displaced tail position */
3473  newTailPos = oldTailPos + getRandomVector(n*dR);
3474  lpath.boxPtr->putInside(newTailPos);
3475  lpath.updateBead(lpath.worm.tail,newTailPos);
3476 
3477  /* Compute the free particle density matrix */
3478  rho0Norm = actionPtr->rho0(lpath.worm.head,lpath.worm.tail,lpath.worm.gap);
3479 
3480  /* action shift coming from a finite chemical potential */
3481  double muShift = lpath.worm.gap*constants()->mu()*constants()->tau();
3482 
3483  /* Starting from the head, we generate new positions for the beads via
3484  * staging, and accumulate the potential action */
3485  beadIndex = lpath.worm.head;
3486  int k = 0;
3487  do {
3488  if (!all(beadIndex==lpath.worm.head) && !all(beadIndex==lpath.worm.tail)) {
3489  lpath.updateBead(beadIndex,
3490  newStagingPosition(path.prev(beadIndex),lpath.worm.tail,lpath.worm.gap,k));
3491  ++k;
3492  }
3493 
3494  newAction += actionPtr->potentialAction(beadIndex);
3495 
3496  beadIndex = lpath.next(beadIndex);
3497  } while (!all(beadIndex==lpath.next(lpath.worm.tail)));
3498 
3499  double expAction = exp(-newAction + oldAction + muShift);
3500  estimator(n) += rho0Norm*expAction;
3501 
3502  /* Record the probability of accepting the move */
3503  if (random.randExc() < expAction)
3504  ++numAccepted;
3505 
3506  } // end for n
3507 
3508  } // end for k
3509 
3510  /* Now we must undo any damge we have caused by reverting the tail to its previous position,
3511  * and turning off all intermediate beads */
3512  lpath.updateBead(lpath.worm.tail,oldTailPos);
3513 
3514  /* Delete all the beads that were added. */
3515  beadIndex = lpath.next(lpath.worm.head);
3516  while (!all(beadIndex==lpath.worm.tail)) {
3517  beadIndex = lpath.delBeadGetNext(beadIndex);
3518  }
3519  lpath.next(lpath.worm.head) = XXX;
3520  lpath.prev(lpath.worm.tail) = XXX;
3521 }
3522 
3523 // ---------------------------------------------------------------------------
3524 // ---------------------------------------------------------------------------
3525 // CYLINDER PAIR CORRELATION ESTIMATOR CLASS ---------------------------------
3526 // ---------------------------------------------------------------------------
3527 // ---------------------------------------------------------------------------
3528 
3529 /*************************************************************************/
3537  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3538  int _frequency, string _label) :
3539  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3540 {
3541  /* The spatial discretization */
3542  dR = 0.5*sqrt(sum(path.boxPtr->periodic))*path.boxPtr->side[NDIM-1] / (1.0*NPCFSEP);
3543 
3544  /* This is a diagonal estimator that gets its own file */
3546 
3547  /* The header is the first line which contains the spatial separations */
3548  header = str(format("#%15.3E") % 0.0);
3549  for (int n = 1; n < NPCFSEP; n++)
3550  header.append(str(format("%16.3E") % ((n)*dR)));
3551 
3552  /* The normalization factor for the pair correlation function */
3553  norm = 0.5*path.boxPtr->side[NDIM-1] / dR;
3554 }
3555 
3556 /*************************************************************************/
3560 }
3561 
3562 /*************************************************************************/
3568 void CylinderPairCorrelationEstimator::accumulate() {
3569  int N1D = num1DParticles(path,maxR);
3570  if (N1D > 1) {
3571  double lnorm = 1.0*sum(actionPtr->cylSepHist);
3572  lnorm /= 1.0*(N1D-1)/(1.0*N1D);
3573  estimator += 1.0*actionPtr->cylSepHist / (1.0*lnorm);
3574  }
3575 }
3576 
3577 /**************************************************************************/
3584  numSampled++;
3585 
3586  if (baseSample() && (sum(actionPtr->cylSepHist) > 0)) {
3588  numAccumulated++;
3589  accumulate();
3590  }
3591 }
3592 
3593 // ---------------------------------------------------------------------------
3594 // ---------------------------------------------------------------------------
3595 // CYLINDER LINEAR POTENTIAL ESTIMATOR CLASS ---------------------------------
3596 // ---------------------------------------------------------------------------
3597 // ---------------------------------------------------------------------------
3598 
3599 /*************************************************************************/
3606  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3607  int _frequency, string _label) :
3608  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3609 {
3610  /* The length of the cylinder */
3611  Lz = path.boxPtr->side[NDIM-1];
3612 
3613  /* The spatial discretization */
3614  dz = Lz / (1.0*NRADSEP);
3615 
3616  /* This is a diagonal estimator that gets its own file */
3618 
3619  /* The header is the first line which contains the spatial separations */
3620  header = str(format("#%15.3E") % 0.0);
3621  for (int n = 1; n < NRADSEP; n++)
3622  header.append(str(format("%16.3E") % ((n)*dz)));
3623 }
3624 
3625 /*************************************************************************/
3629 }
3630 
3631 /*************************************************************************/
3634 void CylinderLinearPotentialEstimator::accumulate() {
3635 
3636  double totV = 0.0;
3637  dVec r1,r2; // The two bead positions
3638  r1 = 0.0;
3639 
3640  dVec sep; // The bead separation
3641  beadLocator bead2; // The bead locator
3642 
3643  /* sample all positions along the pore */
3644  for (int n = 0; n < NRADSEP; n++) {
3645 
3646  r1[NDIM-1] = -0.5*Lz + n*dz;
3647 
3648  /* Get the external potential */
3649  totV = 0.0;
3650 
3651  /* We sum up the interaction energy over all slices*/
3652  int numBeads = 0;
3653  for (int slice = 0; slice < path.numTimeSlices; slice++) {
3654  bead2[0] = slice;
3655 
3656  /* Sum over particles */
3657  for (bead2[1] = 0; bead2[1] < path.numBeadsAtSlice(slice); bead2[1]++) {
3658 
3659  r2 = path(bead2);
3660  if (!include(r2,maxR)) {
3661  sep = r2 - r1;
3662  path.boxPtr->putInBC(sep);
3663  totV += actionPtr->interactionPtr->V(sep);
3664  numBeads++;
3665 
3666  } // bead2 is outside maxR
3667  } // bead2
3668  } // slice
3669 
3670  totV /= 1.0*numBeads;
3671 
3672  /* Add the constant piece from the external potential */
3673  totV += actionPtr->externalPtr->V(r1);
3674 
3675  estimator(n) += totV;
3676  } // n
3677 }
3678 
3679 
3680 // ---------------------------------------------------------------------------
3681 // ---------------------------------------------------------------------------
3682 // CYLINDER RADIAL POTENTIAL ESTIMATOR CLASS ---------------------------------
3683 // ---------------------------------------------------------------------------
3684 // ---------------------------------------------------------------------------
3685 
3686 /*************************************************************************/
3693  ActionBase *_actionPtr, const MTRand &_random, double _maxR, int _frequency, string _label) :
3694  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3695 {
3696  /* The spatial discretization */
3697  dR = 0.5*path.boxPtr->side[0] / (1.0*NRADSEP);
3698 
3699  /* This is a diagonal estimator that gets its own file */
3701  radPot.resize(NRADSEP);
3702 
3703  /* The header is the first line which contains the spatial separations */
3704  header = str(format("#%15.3E") % 0.0);
3705  for (int n = 1; n < NRADSEP; n++)
3706  header.append(str(format("%16.3E") % ((n)*dR)));
3707 }
3708 
3709 /*************************************************************************/
3713 }
3714 
3715 /*************************************************************************/
3719 void CylinderRadialPotentialEstimator::accumulate() {
3720 
3721  double totV = 0.0;
3722  dVec r1,r2; // The two bead positions
3723  dVec sep; // The bead separation
3724 
3725  beadLocator bead2; // The bead locator
3726 
3727  /* Choose a random position */
3728  for (int n = 0; n < NRADSEP; n++) {
3729 
3730  totV = 0.0;
3731 
3732  double theta = 2.0*M_PI*random.rand();
3733  r1[0] = n*dR*cos(theta);
3734  r1[1] = n*dR*sin(theta);
3735  r1[2] = path.boxPtr->side[2]*(-0.5 + random.randExc());
3736 
3737  /* We sum up the external and interaction energy over all slices*/
3738  for (int slice = 0; slice < path.numTimeSlices; slice++) {
3739  bead2[0] = slice;
3740 
3741  int numParticles = path.numBeadsAtSlice(slice);
3742 
3743  /* Sum over particles */
3744  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
3745 
3746  r2 = path(bead2);
3747  if (!include(r2,maxR)) {
3748  sep = r2 - r1;
3749  path.boxPtr->putInBC(sep);
3750  totV += actionPtr->interactionPtr->V(sep);
3751  } // bead2 is outside maxR
3752  } // bead2
3753  } // slice
3754 
3755  totV /= 1.0*path.numTimeSlices;
3756  totV += actionPtr->externalPtr->V(r1);
3757 
3758  estimator(n) += totV;
3759  } // n
3760 }
3761 
3762 /*************************************************************************/
3768 void CylinderRadialPotentialEstimator::accumulate1() {
3769 
3770  double totV = 0.0;
3771  dVec r1,r2; // The two bead positions
3772  dVec sep; // The bead separation
3773  double rad1,rad2; // The two bead radii
3774  int nR; // The bin number
3775 
3776  beadLocator bead1,bead2; // The bead locators
3777  bool found1,found2; // Are the beads in the central chain
3778  found1 = found2 = false;
3779  radPot = 0.0;
3780  int numFound1 = 0;
3781 
3782  /* We sum up the external and interaction energy over all slices*/
3783  for (int slice = 0; slice < path.numTimeSlices; slice++) {
3784  bead1[0] = bead2[0] = slice;
3785 
3786  int numParticles = path.numBeadsAtSlice(slice);
3787 
3788  /* Sum over particles */
3789  for (bead1[1] = 0; bead1[1] < numParticles; bead1[1]++) {
3790 
3791  r1 = path(bead1);
3792  rad1 = r1[0]*r1[0] + r1[1]*r1[1];
3793  found1 = (rad1 < maxR*maxR);
3794 
3795  /* If the first particle is in the central chain, looks for its
3796  * interacting partners */
3797  if (found1) {
3798  totV = actionPtr->externalPtr->V(r1);
3799  numFound1 ++;
3800 
3801  /* We don't have to worry about double counting here, as
3802  * we never allow two particles in the central chain to
3803  * interact */
3804  for (bead2[1] = 0; bead2[1] < numParticles; bead2[1]++) {
3805 
3806  r2 = path(bead2);
3807  rad2 = r2[0]*r2[0] + r2[1]*r2[1];
3808  found2 = (rad2 < maxR*maxR);
3809 
3810  /* Only accumulate the energy if bead1 is in the central
3811  * chain while bead2 is not */
3812  if (!found2) {
3813  sep = path.getSeparation(bead2,bead1);
3814  totV += actionPtr->interactionPtr->V(sep);
3815  } // !found2
3816  } // bead2
3817 
3818  nR = int(sqrt(rad1)/dR);
3819  if (nR < NRADSEP)
3820  radPot(nR) += totV;
3821  } // found1
3822  } // bead1
3823  } // slice
3824 
3825  radPot /= (1.0*numFound1);
3826  estimator += radPot;
3827 }
3828 
3829 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
3830 // BEGIN PIGS ESTIMATORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
3831 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
3832 
3833 // ---------------------------------------------------------------------------
3834 // ---------------------------------------------------------------------------
3835 // POTENTIAL ENERGY ESTIMATOR CLASS ------------------------------------------
3836 // ---------------------------------------------------------------------------
3837 // ---------------------------------------------------------------------------
3838 
3839 /*************************************************************************/
3845  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3846  int _frequency, string _label) :
3847  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3848 {
3849  /* We measure on every other time slice */
3850  initialize( (constants()->numTimeSlices()-1)/2 +1);
3851 
3852  /* Set estimator header */
3853  header = str(format("#%15f") % 0.0 );
3854  for (int n = 2; n < constants()->numTimeSlices(); n+=2)
3855  header.append(str(format("%16f") % (n*constants()->tau()) ));
3856 }
3857 
3858 /*************************************************************************/
3862  // empty destructor
3863 }
3864 
3865 /*************************************************************************/
3868 void PotentialEnergyEstimator::accumulate() {
3869 
3870  /* The total tail correction */
3871  double tailV = (1.0*path.getTrueNumParticles()*path.getTrueNumParticles()
3873 
3874  /* We use a simple operator estimator for V. */
3875  for (int slice = 0; slice <= path.numTimeSlices; slice+=2)
3876  estimator(slice/2) += sum(actionPtr->potential(slice)) + tailV;
3877 }
3878 
3879 // ---------------------------------------------------------------------------
3880 // ---------------------------------------------------------------------------
3881 // KINETIC ENERGY ESTIMATOR CLASS ----------------------------------------------
3882 // ---------------------------------------------------------------------------
3883 // ---------------------------------------------------------------------------
3884 
3885 /*************************************************************************/
3891  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3892  int _frequency, string _label) :
3893  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3894 {
3895 
3896  /* We measure on every other time slice */
3897  initialize( (constants()->numTimeSlices()-1)/2 );
3898 
3899  /* Set estimator header */
3900  header = str(format("#%15f") % constants()->tau());
3901  for (int n = 2; n < (constants()->numTimeSlices()-1); n+=2)
3902  header.append(str(format("%16f") % ((n+1)*constants()->tau()) ));
3903 }
3904 
3905 /*************************************************************************/
3909  // empty destructor
3910 }
3911 
3912 /*************************************************************************/
3915 void KineticEnergyEstimator::accumulate() {
3916 
3917  int numTimeSlices = constants()->numTimeSlices();
3918  int numParticles = path.getTrueNumParticles();
3919 
3920  /* The kinetic normalization factor */
3921  double kinNorm = constants()->fourLambdaTauInv() / (constants()->tau()*2.0);
3922 
3923  /* The classical contribution to the kinetic energy per particle
3924  * including the chemical potential */
3925  double classicalKinetic = (0.5 * NDIM / constants()->tau()) * numParticles;
3926 
3927  beadLocator beadIndex;
3928  dVec vel,pos;
3929  for (int slice = 0; slice < (numTimeSlices-1); slice+=2) {
3930  double K = 0.0;
3931  for (int eo = 0; eo < 2; eo++){
3932  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice+eo); ptcl++) {
3933  beadIndex = slice+eo,ptcl;
3934  vel = path.getVelocity(beadIndex);
3935  K -= dot(vel,vel);
3936  }
3937  }
3938  /* Normalize the accumulated link-action part */
3939  K *= kinNorm;
3940 
3941  /* Copmute the correction to the accumulated link-action part */
3942  double t1 = 0.0;
3943  for (int eo = 0; eo < 2; eo++){
3944  t1 += actionPtr->derivPotentialActionLambda(slice+eo);
3945  }
3946 
3947  t1 *= constants()->lambda()/(2.0*constants()->tau());
3948 
3949  /* Perform all the normalizations and compute the individual energy terms */
3950  K += (classicalKinetic + t1);
3951 
3952  estimator(slice/2) += K;
3953  }
3954 }
3955 
3956 // ---------------------------------------------------------------------------
3957 // ---------------------------------------------------------------------------
3958 // TOTAL ENERGY ESTIMATOR CLASS ----------------------------------------------
3959 // ---------------------------------------------------------------------------
3960 // ---------------------------------------------------------------------------
3961 
3962 /*************************************************************************/
3968  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
3969  int _frequency, string _label) :
3970  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
3971 {
3972 
3973  /* We measure on every other time slice */
3974  initialize( (constants()->numTimeSlices()-1) );
3975 
3976  /* Set estimator header */
3977  header = str(format("#%15f") % constants()->tau());
3978  for (int n = 1; n < (constants()->numTimeSlices()-1); n++)
3979  header.append(str(format("%16f") % (n*constants()->tau()) ));
3980 }
3981 
3982 /*************************************************************************/
3986  // empty destructor
3987 }
3988 
3989 
3990 /*************************************************************************/
3993 void TotalEnergyEstimator::accumulate() {
3994 
3995  int numTimeSlices = constants()->numTimeSlices();
3996  int numParticles = path.getTrueNumParticles();
3997 
3998  /* The kinetic normalization factor */
3999  double kinNorm = constants()->fourLambdaTauInv() / (constants()->tau());
4000 
4001  /* The classical contribution to the kinetic energy per particle
4002  * including the chemical potential */
4003  double classicalKinetic = (0.5 * NDIM / constants()->tau()) * numParticles;
4004 
4005  beadLocator beadIndex;
4006  dVec vel,pos;
4007  for (int slice = 0; slice < (numTimeSlices-1); slice++) {
4008  double K = 0.0;
4009  for (int ptcl = 0; ptcl < path.numBeadsAtSlice(slice); ptcl++) {
4010  beadIndex = slice,ptcl;
4011  vel = path.getVelocity(beadIndex);
4012  K -= dot(vel,vel);
4013  }
4014  /* Normalize the accumulated link-action part */
4015  K *= kinNorm;
4016 
4017  /* Perform all the normalizations and compute the individual energy terms */
4018  K += (classicalKinetic);
4019 
4020  double dUdtau = actionPtr->derivPotentialActionTau(slice);
4021  estimator(slice) += K+dUdtau;
4022  }
4023 }
4024 
4025 
4026 // ---------------------------------------------------------------------------
4027 // ---------------------------------------------------------------------------
4028 // THERMODYNAMIC POTENTIAL ENERGY ESTIMATOR CLASS ----------------------------------------------
4029 // ---------------------------------------------------------------------------
4030 // ---------------------------------------------------------------------------
4031 
4032 /*************************************************************************/
4038  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4039  int _frequency, string _label):
4040  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4041 {
4042 
4043  /* We measure on every other time slice */
4044  initialize( (constants()->numTimeSlices()-1) );
4045 
4046  /* Set estimator header */
4047  header = str(format("#%15f") % constants()->tau());
4048  for (int n = 1; n < (constants()->numTimeSlices()-1); n++)
4049  header.append(str(format("%16f") % (n*constants()->tau()) ));
4050 }
4051 
4052 /*************************************************************************/
4056  // empty destructor
4057 }
4058 
4059 /*************************************************************************/
4062 void ThermoPotentialEnergyEstimator::accumulate() {
4063 
4064  int numTimeSlices = constants()->numTimeSlices();
4065 
4066  for (int slice = 0; slice < (numTimeSlices-1); slice++) {
4067  double dUdtau = actionPtr->derivPotentialActionTau(slice);
4068  double dUdlam = actionPtr->derivPotentialActionLambda(slice);
4069  estimator(slice) += dUdtau - (constants()->lambda()/constants()->tau())*dUdlam;
4070  }
4071 }
4072 
4073 // ---------------------------------------------------------------------------
4074 // ---------------------------------------------------------------------------
4075 // POSITION ESTIMATOR CLASS --------------------------------------------------
4076 // ---------------------------------------------------------------------------
4077 // ---------------------------------------------------------------------------
4078 
4079 /*************************************************************************/
4085  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4086  int _frequency, string _label) :
4087  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4088 {
4089 
4090  /* We measure on each time slice */
4091  initialize(constants()->numTimeSlices());
4092 
4093  /* Set estimator header */
4094  header = str(format("#%15d") % 0);
4095  for (int n = 1; n < constants()->numTimeSlices(); n++)
4096  header.append(str(format("%16d") % n));
4097 }
4098 
4099 /*************************************************************************/
4103  // empty destructor
4104 }
4105 
4106 /*************************************************************************/
4109 void PositionEstimator::accumulate() {
4110 
4111  /* We use a simple operator estimator for V. */
4112  beadLocator beadIndex;
4113  double x;
4114  for (beadIndex[0] = 0; beadIndex[0] < path.numTimeSlices; ++beadIndex[0]) {
4115  x = 0.0;
4116  for (beadIndex[1] = 0; beadIndex[1] <
4117  path.numBeadsAtSlice(beadIndex[0]); ++beadIndex[1])
4118  x += path(beadIndex)[0];
4119  estimator(beadIndex[0]) += x;
4120  }
4121 }
4122 
4123 // ---------------------------------------------------------------------------
4124 // ---------------------------------------------------------------------------
4125 // PARTICLE RESOLVED POSITION ESTIMATOR CLASS --------------------------------------------------
4126 // ---------------------------------------------------------------------------
4127 // ---------------------------------------------------------------------------
4128 
4129 /*************************************************************************/
4135  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4136  int _frequency, string _label) :
4137  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4138 {
4139 
4140  /* We measure on each time slice */
4141  initialize(constants()->initialNumParticles()*2);
4142 
4143  /* Set estimator header */
4144  header = str(format("#%15d") % 0);
4145  header.append(str(format("%16d") % 0));
4146  for (int n = 1; n < constants()->initialNumParticles(); n++){
4147  header.append(str(format("%16d") % n));
4148  header.append(str(format("%16d") % n));
4149  }
4150 }
4151 
4152 /*************************************************************************/
4156  // empty destructor
4157 }
4158 
4159 /*************************************************************************/
4162 void ParticleResolvedPositionEstimator::accumulate() {
4163 
4164  /* We use a simple operator estimator for V. */
4165  beadLocator beadIndex;
4166  double x;
4167 
4168  beadIndex[0] = (path.numTimeSlices-1)/2;
4169  for (beadIndex[1] = 0; beadIndex[1] <path.numBeadsAtSlice(beadIndex[0]);
4170  ++beadIndex[1]){
4171  x = path(beadIndex)[0];
4172  if ( beadIndex[1] < constants()->initialNumParticles()){
4173  estimator(beadIndex[1]*2) += x;
4174  estimator(beadIndex[1]*2+1) += x*x;
4175  }
4176  }
4177 }
4178 
4179 
4180 // ---------------------------------------------------------------------------
4181 // ---------------------------------------------------------------------------
4182 // PARTICLE CORRELATION ESTIMATOR CLASS --------------------------------------------------
4183 // ---------------------------------------------------------------------------
4184 // ---------------------------------------------------------------------------
4185 
4186 /*************************************************************************/
4192  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4193  int _frequency, string _label) :
4194  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4195 {
4196 
4197  /* We measure on each time slice */
4198  initialize(constants()->initialNumParticles()-1);
4199 
4200  /* Set estimator header */
4201  header = str(format("#%15d") % 1);
4202  for (int n = 2; n < constants()->initialNumParticles(); n++)
4203  header.append(str(format("%16d") % n));
4204 }
4205 
4206 /*************************************************************************/
4210  // empty destructor
4211 }
4212 
4213 /*************************************************************************/
4216 void ParticleCorrelationEstimator::accumulate() {
4217 
4218  /* We use a simple operator estimator for V. */
4219  beadLocator beadIndex0,beadIndex;
4220 
4221  beadIndex0[0] = (path.numTimeSlices-1)/2;
4222  beadIndex[0] = beadIndex0[0];
4223  dVec r;
4224  r = 0.0;
4225 
4226  beadIndex0[1]=0;
4227  for (beadIndex[1] = 1; beadIndex[1] <path.numBeadsAtSlice(beadIndex[0]);
4228  ++beadIndex[1]){
4229  if ( beadIndex[1] < constants()->initialNumParticles()) {
4230  r = path.getSeparation(beadIndex0,beadIndex);
4231  estimator(beadIndex[1]-1) += dot(r,r);
4232  }
4233  }
4234 }
4235 
4236 
4237 
4238 // ---------------------------------------------------------------------------
4239 // ---------------------------------------------------------------------------
4240 // Velocity ESTIMATOR CLASS --------------------------------------------------
4241 // ---------------------------------------------------------------------------
4242 // ---------------------------------------------------------------------------
4243 
4244 /*************************************************************************/
4250  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4251  int _frequency, string _label) :
4252  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4253 {
4254 
4255  /* We measure on each time slice */
4256  initialize(constants()->numTimeSlices()-1);
4257 
4258  /* Set estimator header */
4259  header = str(format("#%15d") % 0);
4260  for (int n = 1; n < constants()->numTimeSlices()-1; n++)
4261  header.append(str(format("%16d") % n));
4262 }
4263 
4264 /*************************************************************************/
4268  // empty destructor
4269 }
4270 
4271 /*************************************************************************/
4274 void VelocityEstimator::accumulate() {
4275 
4276  beadLocator beadIndex;
4277  dVec vel;
4278 
4279  beadIndex[1] = 0;
4280  for (beadIndex[0] = 0; beadIndex[0] < (path.numTimeSlices-1); ++beadIndex[0]) {
4281  if ( (path.breakSlice > 0) && (beadIndex[0] == path.breakSlice)
4282  &&( all(path.next(beadIndex)==XXX) ) ){
4283  beadLocator nextBead = beadIndex;
4284  nextBead[0]++;
4285  vel = path.getSeparation(beadIndex,nextBead);
4286  }else
4287  vel = path.getVelocity(beadIndex);
4288  estimator(beadIndex[0]) += sqrt(dot(vel,vel));
4289  }
4290 }
4291 
4292 
4293 // ---------------------------------------------------------------------------
4294 // ---------------------------------------------------------------------------
4295 // SubregionOccupation ESTIMATOR CLASS ---------------------------------------
4296 // ---------------------------------------------------------------------------
4297 // ---------------------------------------------------------------------------
4298 
4299 /*************************************************************************/
4305  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4306  int _frequency, string _label) :
4307  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label)
4308 {
4309 
4310  /* We measure on each time slice */
4311  initialize(3);
4312 
4313  /* Set estimator header */
4314  header = str(format("#%15s") % "Z");
4315  header.append(str(format("%16s") % "pA"));
4316  header.append(str(format("%16s") % "pB"));
4317 }
4318 
4319 /*************************************************************************/
4323  // empty destructor
4324 }
4325 
4326 /*************************************************************************/
4329 void SubregionOccupationEstimator::accumulate() {
4330 
4331  beadLocator midLIndex, midRIndex;
4332  double rho0Mid,Z,pA,pB;
4333 
4334  midLIndex[0] = path.breakSlice;
4335  midRIndex[0] = path.breakSlice+1;
4336  midLIndex[1] = 0;
4337  midRIndex[1] = 0;
4338 
4339  Z = 0.0;
4340  if( path.inSubregionA(midRIndex) ){
4341  rho0Mid = actionPtr->rho0(midLIndex,midRIndex,1);
4342  Z = rho0Mid;
4343  pA = rho0Mid;
4344  pB = 0.0;
4345  }else if( path.inSubregionB(midRIndex) ){
4346  Z = 1.0;
4347  pA = 0.0;
4348  pB = 1.0;
4349  }else{
4350  Z = 0.0;
4351  pA = 0.0;
4352  pB = 0.0;
4353  cout << "Error!! Invalid configuration for SubregionOccupatoin!!" << endl;
4354  }
4355 
4356  estimator(0) += Z;
4357  estimator(1) += pA;
4358  estimator(2) += pB;
4359 }
4360 
4361 
4362 
4363 // ---------------------------------------------------------------------------
4364 // ---------------------------------------------------------------------------
4365 // ONE BODY DENSITY MATRIX ESTIMATOR CLASS -----------------------------------
4366 // ---------------------------------------------------------------------------
4367 // ---------------------------------------------------------------------------
4368 
4369 /*************************************************************************/
4377  ActionBase *_actionPtr, const MTRand &_random, double _maxR,
4378  int _frequency, string _label) :
4379  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label),
4380  lpath(_path)
4381 {
4382 
4383  sqrt2LambdaTau = sqrt(2.0 * constants()->lambda() * constants()->tau());
4384 
4385  /* We chooose the maximum separation to be sqrt(NDIM)*min(L)/2 */
4386  dR = 0.5*sqrt(sum(path.boxPtr->periodic))*(blitz::min(path.boxPtr->side)) / (1.0*NOBDMSEP);
4387 
4388  /* This is an off-diagonal estimator*/
4390  diagonal = false;
4391 
4392  /* The header is the first line which contains the spatial separations */
4393  header = str(format("#%15.3E") % 0.0);
4394  for (int n = 1; n < NOBDMSEP; n++)
4395  header.append(str(format("%16.3E") % (n*dR)));
4396 
4397  numReps = 5;
4398  norm = 1.0 / (1.0*numReps);
4399 }
4400 
4401 /*************************************************************************/
4405 }
4406 
4407 /*************************************************************************/
4415  numSampled++;
4416  if ( frequency &&
4417  ((numSampled % frequency) == 0)
4418  // && (path.worm.isConfigDiagonal == diagonal) &&
4419  //(path.worm.gap > 0) && (path.worm.gap <= constants()->Mbar()) &&
4420  //(actionPtr->eFactor[(lpath.worm.tail[0] % 2)] < EPS)
4421  ){
4422 
4423  /* If we are canonical, we want the closed configuration to be close
4424  * to our ideal one */
4425  if ( (!canonical) ||
4426  (abs(path.worm.getNumBeadsOn()+path.worm.gap-numBeads0) <= 2) ) {
4428  numAccumulated++;
4429  accumulate();
4430  }
4431  }
4432 }
4433 
4434 /*************************************************************************/
4443 inline dVec PIGSOneBodyDensityMatrixEstimator::getRandomVector(const double r) {
4444  dVec rVec;
4445  rVec = 0.0;
4446 #if NDIM==1
4447  if (random.rand() < 0.5)
4448  rVec = r;
4449  else
4450  rVec = -r;
4451 #elif NDIM==2
4452  double theta = 2.0*M_PI*random.rand();
4453  rVec[0] = r*cos(theta);
4454  rVec[1] = r*sin(theta);
4455 #elif NDIM==3
4456  if (lpath.boxPtr->name == "Prism") {
4457  double theta = 2.0*M_PI*random.rand();
4458  double phi = acos(2*random.rand() - 1.0);
4459  rVec[0] = r*sin(theta)*cos(phi);
4460  rVec[1] = r*sin(theta)*sin(phi);
4461  rVec[2] = r*cos(phi);
4462  }
4463  else {
4464  if (random.rand() < 0.5)
4465  rVec[NDIM-1] = r;
4466  else
4467  rVec[NDIM-1] = -r;
4468  }
4469 #endif
4470  return rVec;
4471 }
4472 
4473 /*************************************************************************/
4481 void PIGSOneBodyDensityMatrixEstimator::accumulate() {
4482 
4483  beadLocator beadIndexL,beadIndexR;
4484  beadIndexL[0] = lpath.breakSlice;
4485  beadIndexL[1] = path.brokenWorldlinesL.front();
4486  beadIndexR[0] = lpath.breakSlice+1;
4487  beadIndexR[1] = path.brokenWorldlinesR.front();
4488 
4489  oldTailPos = lpath(beadIndexR);
4490  //oldAction = actionPtr->potentialAction(beadIndexR);
4491 
4492  dVec pos;
4493  pos = 0.0;
4494 
4495  /* Connection the broken beads*/
4496  //lpath.next(beadIndexL) = beadIndexR;
4497  //lpath.prev(beadIndexR) = beadIndexL;
4498 
4499  //for (int p = 0; p < numReps; p++) {
4500 
4501  /* Now we loop through all possible separations, evaluating the potential
4502  * action */
4503  for (int n = 0; n < NOBDMSEP; n++) {
4504 
4505  newAction = 0.0;
4506  ++numAttempted;
4507 
4508  /* Assign the new displaced tail position */
4509  newTailPos = oldTailPos + getRandomVector(n*dR);
4510  lpath.boxPtr->putInside(newTailPos);
4511  lpath.updateBead(beadIndexR,newTailPos);
4512 
4513  /* Compute the free particle density matrix */
4514 
4515  /* CMH: Need to sample winding sector for general dimension here */
4516  //double rho0 = actionPtr->rho01D(beadIndexL,beadIndexR,1);
4517 
4518  double rho0 = 1.0;
4519 
4520  /* action shift coming from a finite chemical potential */
4521  //double muShift = lpath.worm.gap*constants()->mu()*constants()->tau();
4522 
4523  /* Copmute the potential the potential action */
4524  newAction += actionPtr->potentialAction(beadIndexR);
4525 
4526  //double expAction = exp(-newAction + oldAction + muShift);
4527  double expAction = exp(-0.5*newAction + 0.5*oldAction);
4528  //double expAction = exp(-newAction);
4529 
4530  estimator(n) += rho0*expAction;
4531 
4532  /* Record the probability of accepting the move */
4533  if (random.randExc() < rho0*expAction)
4534  ++numAccepted;
4535 
4536  } // end for n
4537 
4538  //} // end for k
4539 
4540  /* Now we must undo any damge we have caused by reverting the tail to its previous position*/
4541  lpath.updateBead(beadIndexR,oldTailPos);
4542  //lpath.next(beadIndexL) = XXX;
4543  //lpath.prev(beadIndexR) = XXX;
4544 }
4545 
4546 /*************************************************************************/
4551 
4552  (*outFilePtr) << format("# accepted: %16.8E attempted: %16.8E ratio: %16.4E\n")
4553  % (1.0*numAccepted) % (1.0*numAttempted) % (1.0*numAccepted/(1.0*numAttempted));
4554 }
4555 
4556 
4557 // ---------------------------------------------------------------------------
4558 // ---------------------------------------------------------------------------
4559 // DOUBLED ESTIMATOR BASE CLASS ----------------------------------------------------
4560 // ---------------------------------------------------------------------------
4561 // ---------------------------------------------------------------------------
4562 
4563 /*************************************************************************/
4566 DoubledEstimator::DoubledEstimator (const Path &_path, const Path &_path2,
4567  ActionBase *_actionPtr, ActionBase* _actionPtr2, const MTRand &_random, double _maxR,
4568  int _frequency, string _label) :
4569  EstimatorBase(_path,_actionPtr,_random,_maxR,_frequency,_label), path2(_path2)
4570 {
4571 }
4572 
4573 /*************************************************************************/
4577 }
4578 
4579 
4580 // ---------------------------------------------------------------------------
4581 // ---------------------------------------------------------------------------
4582 // Swap Estimator Class ----------------------------------------------------
4583 // ---------------------------------------------------------------------------
4584 // ---------------------------------------------------------------------------
4585 
4586 /*************************************************************************/
4589 SwapEstimator::SwapEstimator (Path &_path, Path &_path2, ActionBase *_actionPtr,
4590  ActionBase *_actionPtr2, const MTRand &_random, double _maxR,
4591  int _frequency, string _label) :
4592 DoubledEstimator(_path,_path2,_actionPtr,_actionPtr2,_random,_maxR,_frequency,_label),
4593  lpath(_path),lpath2(_path2),
4594  actionPtr(_actionPtr),
4595  actionPtr2(_actionPtr2)
4596 {
4597 
4598  /* Set estimator header */
4599  header = str(format("#%15s%16s%16s") % "Z" % "S" % "ZS");
4600  initialize(3);
4601 }
4602 
4603 /*************************************************************************/
4607 }
4608 
4609 /*************************************************************************/
4612 void SwapEstimator::accumulate() {
4613  if (lpath.breakSlice > 0)
4614  accumulateOpen();
4615  else
4616  accumulateClosed();
4617 }
4618 
4619 /*************************************************************************/
4622 void SwapEstimator::accumulateOpen() {
4623 
4624  double S,Z; // Swap and normalization
4625 
4626  beadLocator beadIndexL,beadIndexR,beadIndexL2,beadIndexR2;
4627  beadIndexL[0] = lpath.breakSlice;
4628  beadIndexR[0] = lpath.breakSlice+1;
4629  beadIndexL2[0] = lpath2.breakSlice;
4630  beadIndexR2[0] = lpath2.breakSlice+1;
4631 
4632  /* Old tail positions & potential actions */
4633  vector<dVec> oldTailPos(lpath.brokenWorldlinesR.size());
4634  vector<dVec> oldTailPos2(lpath2.brokenWorldlinesR.size());
4635 
4636  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
4637  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4638  oldTailPos[i] = lpath(beadIndexR);
4639  }
4640  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
4641  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4642  oldTailPos2[i] = lpath2(beadIndexR2);
4643  }
4644 
4645  /* Compute direct propagator for Z */
4646  double oldPotAction,oldPotAction2;
4647  double rho0Dir, rho0Dir2;
4648 
4649  /* Compute direct potential actions for both paths */
4650  /* loop over broken beads */
4651  oldPotAction = 0.0;
4652  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
4653  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4654  oldPotAction += actionPtr->potentialAction(beadIndexR);
4655  }
4656  oldPotAction2 = 0.0;
4657  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
4658  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4659  oldPotAction2 += actionPtr2->potentialAction(beadIndexR2);
4660  }
4661 
4662 
4663  /* Initialize permuation vector */
4664  vector<int> permutation(lpath.brokenWorldlinesR.size());
4665  int Nperm = 0;
4666  double rho0perm;
4667  for( uint32 i=0; i<permutation.size(); i++)
4668  permutation[i] = i;
4669 
4670  /* Compute direct free particle density matricies for both paths */
4671  if ( lpath.brokenWorldlinesL.size() == 0){
4672  rho0Dir = 1.0;
4673  }else{
4674  rho0Dir = 0.0;
4675  /* sum over permutations */
4676  do {
4677  /* sum over broken worldlines */
4678  rho0perm = 1.0;
4679  for( uint32 i=0; i<permutation.size(); i++){
4680  beadIndexL[1] = lpath.brokenWorldlinesL[i];
4681  beadIndexR[1] = lpath.brokenWorldlinesR[permutation[i]];
4682  rho0perm *= actionPtr->rho0(beadIndexL,beadIndexR,1);
4683  }
4684  rho0Dir += rho0perm;
4685  Nperm++;
4686  } while (next_permutation(permutation.begin(),permutation.end()));
4687  rho0Dir *= 1.0/((double)Nperm);
4688  }
4689 
4690  /* Re-initialize permuation vector */
4691  permutation.resize(lpath2.brokenWorldlinesR.size());
4692  for( uint32 i=0; i<permutation.size(); i++)
4693  permutation[i] = i;
4694  Nperm = 0;
4695  if ( lpath2.brokenWorldlinesL.size() == 0){
4696  rho0Dir2 = 1.0;
4697  }else{
4698  rho0Dir2 = 0.0;
4699  /* sum over permutations */
4700  do {
4701  /* sum over broken worldlines */
4702  rho0perm = 1.0;
4703  for( uint32 i=0; i<permutation.size(); i++){
4704  beadIndexL2[1] = lpath2.brokenWorldlinesL[i];
4705  beadIndexR2[1] = lpath2.brokenWorldlinesR[permutation[i]];
4706  rho0perm *= actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
4707  }
4708  rho0Dir2 += rho0perm;
4709  Nperm++;
4710  } while (next_permutation(permutation.begin(),permutation.end()));
4711  rho0Dir2 *= 1.0/((double)Nperm);
4712  }
4713 
4714  /* Compute the swapped propagator for S */
4715 
4716  if( (lpath.brokenWorldlinesR.size() == lpath2.brokenWorldlinesR.size()) ){
4717 
4718  if ( lpath.brokenWorldlinesR.size() == 0){
4719  S = 1.0;
4720  Z = 1.0;
4721  }else{
4722  /* Swap the tail positions */
4723  for( uint32 i=0; i<oldTailPos2.size(); i++){
4724  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4725  lpath.updateBead(beadIndexR,oldTailPos2[i]);
4726  }
4727  for( uint32 i=0; i<oldTailPos.size(); i++){
4728  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4729  lpath2.updateBead(beadIndexR2,oldTailPos[i]);
4730  }
4731 
4732  /* Compute the swapped free particle density matrix */
4733  /* Re-initialize permuation vector */
4734  for( uint32 i=0; i<permutation.size(); i++)
4735  permutation[i] = i;
4736  Nperm = 0;
4737  double rho0Swap = 0.0;
4738  /* sum over permutations */
4739  do {
4740  /* sum over broken worldlines */
4741  rho0perm = 1.0;
4742  for( uint32 i=0; i<permutation.size(); i++){
4743  beadIndexL[1] = lpath.brokenWorldlinesL[i];
4744  beadIndexR[1] = lpath.brokenWorldlinesR[permutation[i]];
4745  rho0perm *= actionPtr->rho0(beadIndexL,beadIndexR,1);
4746  }
4747  rho0Swap += rho0perm;
4748  Nperm++;
4749  } while (next_permutation(permutation.begin(),permutation.end()));
4750  rho0Swap*= 1.0/((double)Nperm);
4751 
4752  /* Re-initialize permuation vector */
4753  for( uint32 i=0; i<permutation.size(); i++)
4754  permutation[i] = i;
4755  Nperm = 0;
4756  double rho0Swap2 = 0.0;
4757  /* sum over permutations */
4758  do {
4759  /* sum over broken worldlines */
4760  rho0perm = 1.0;
4761  for( uint32 i=0; i<permutation.size(); i++){
4762  beadIndexL2[1] = lpath2.brokenWorldlinesL[i];
4763  beadIndexR2[1] = lpath2.brokenWorldlinesR[permutation[i]];
4764  rho0perm *= actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
4765  }
4766  rho0Swap2 += rho0perm;
4767  Nperm++;
4768  } while (next_permutation(permutation.begin(),permutation.end()));
4769  rho0Swap2*= 1.0/((double)Nperm);
4770 
4771  /* Compute the potential the potential action */
4772  /* Compute direct potential actions for both paths */
4773  /* loop over broken beads */
4774  double newPotAction = 0.0;
4775  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
4776  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4777  newPotAction += actionPtr->potentialAction(beadIndexR);
4778  }
4779  double newPotAction2 = 0.0;
4780  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
4781  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4782  newPotAction2 += actionPtr2->potentialAction(beadIndexR2);
4783  }
4784 
4785  /* Now we must undo any damge we have caused by reverting the tail to its previous position*/
4786  for( uint32 i=0; i<oldTailPos.size(); i++){
4787  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4788  lpath.updateBead(beadIndexR,oldTailPos[i]);
4789  }
4790  for( uint32 i=0; i<oldTailPos2.size(); i++){
4791  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4792  lpath2.updateBead(beadIndexR2,oldTailPos2[i]);
4793  }
4794  S = rho0Swap*rho0Swap2*exp(-(0.5)*(newPotAction+newPotAction2)+(0.5)*(oldPotAction+oldPotAction2));
4795  Z = rho0Dir*rho0Dir2;
4796  }
4797  }else{
4798  S = 0.0;
4799  Z = rho0Dir*rho0Dir2;
4800  }
4801 
4802  /* In the normalization factor we must account for the factor of 1/2 in the
4803  open path weight */
4804  //Z = rho0Dir*rho0Dir2*exp(-(oldPotAction+oldPotAction2));
4805  //S = rho0Swap*rho0Swap2*exp(-(newPotAction+newPotAction2));
4806 
4807  estimator(0) += Z;
4808  estimator(1) += S;
4809  estimator(2) += S*Z;
4810 }
4811 
4812 /*************************************************************************/
4815 void SwapEstimator::accumulateClosed() {
4816 
4817  double S,Z; // Swap and normalization
4818 
4819  /* We assume the broken bead is bead 0 */
4820  int swapSlice = (lpath.numTimeSlices-1)/2-1;
4821 
4822  beadLocator beadIndexL,beadIndexR,beadIndexL2,beadIndexR2;
4823  beadIndexL[0] = swapSlice;
4824  beadIndexR[0] = swapSlice+1;
4825  beadIndexL2[0] = swapSlice;
4826  beadIndexR2[0] = swapSlice+1;
4827 
4828  S = 0.0;
4829  Z = 1.0;
4830  for (int brokenBeadIndex1=0; brokenBeadIndex1<lpath.getNumParticles(); brokenBeadIndex1++){
4831 
4832  beadIndexL[1] = brokenBeadIndex1;
4833  beadIndexR[1] = brokenBeadIndex1;
4834 
4835  /* Old tail positions & potential actions */
4836  dVec oldTailPos = lpath(beadIndexR);
4837  double oldPotAction = actionPtr->potentialAction(beadIndexR);
4838 
4839  /* Compute direct free particle density matricies */
4840  double rho0Dir = actionPtr->rho0(beadIndexL,beadIndexR,1);
4841 
4842  for (int brokenBeadIndex2=0; brokenBeadIndex2<lpath2.getNumParticles(); brokenBeadIndex2++){
4843 
4844  beadIndexL2[1] = brokenBeadIndex2;
4845  beadIndexR2[1] = brokenBeadIndex2;
4846 
4847  /* Old tail positions & potential actions */
4848  dVec oldTailPos2 = lpath2(beadIndexR2);
4849  double oldPotAction2 = actionPtr2->potentialAction(beadIndexR2);
4850 
4851  /* Compute direct free particle density matricies */
4852  double rho0Dir2 = actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
4853 
4854  /* Swap the tail positions */
4855  lpath.updateBead(beadIndexR,oldTailPos2);
4856  lpath2.updateBead(beadIndexR2,oldTailPos);
4857 
4858  /* Compute the swapped free particle density matrix */
4859  double rho0Swap = actionPtr->rho0(beadIndexL,beadIndexR,1);
4860  double rho0Swap2 = actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
4861 
4862  /* Copmute the potential the potential action */
4863  double newPotAction = actionPtr->potentialAction(beadIndexR);
4864  double newPotAction2 = actionPtr2->potentialAction(beadIndexR2);
4865 
4866  /* Now we must undo any damge we have caused by reverting the tail to its previous position*/
4867  lpath.updateBead(beadIndexR,oldTailPos);
4868  lpath2.updateBead(beadIndexR2,oldTailPos2);
4869 
4870  S += (rho0Swap*rho0Swap2/(rho0Dir*rho0Dir2))*exp(-(0.5)*(newPotAction+newPotAction2)+(0.5)*(oldPotAction+oldPotAction2));
4871  }
4872  }
4873 
4874  S /= lpath.getNumParticles()*lpath2.getNumParticles();
4875 
4876  estimator(0) += Z;
4877  estimator(1) += S;
4878 }
4879 
4880 // ---------------------------------------------------------------------------
4881 // ---------------------------------------------------------------------------
4882 // ----------- Entanglement of Particles Estimator Class ---------------------
4883 // ---------------------------------------------------------------------------
4884 // ---------------------------------------------------------------------------
4885 
4886 /*************************************************************************/
4890  ActionBase *_actionPtr,ActionBase *_actionPtr2,
4891  const MTRand &_random, double _maxR,
4892  int _frequency, string _label) :
4893 DoubledEstimator(_path,_path2,_actionPtr, _actionPtr2,_random,_maxR,_frequency,_label),
4894  lpath(_path),lpath2(_path2),
4895  actionPtr(_actionPtr),
4896  actionPtr2(_actionPtr2)
4897 {
4898  stringstream headerSS;
4899 
4900  /* Set estimator name and header */
4901  header = str(format("#%15s") % "Z" );
4902  for (int n = 1; n < constants()->initialNumParticles(); n++){
4903  headerSS.str("");
4904  headerSS << 'Z' << n;
4905  header.append(str(format("%16s") % headerSS.str().c_str()));
4906  headerSS.str("");
4907  headerSS << 'S' << n;
4908  header.append(str(format("%16s") % headerSS.str().c_str()));
4909  }
4910  initialize(1+2*(constants()->initialNumParticles()-1));
4911 }
4912 
4913 /*************************************************************************/
4917 }
4918 
4919 /*************************************************************************/
4922 void EntPartEstimator::accumulate() {
4923  double S,Z; // Swap and normalization
4924 
4925  bool nMatch = false; //True if both paths have the same number of broken paths>0
4926  int nBin; // number of broken paths if nMatch=True;
4927 
4928  beadLocator beadIndexL,beadIndexR,beadIndexL2,beadIndexR2;
4929  beadIndexL[0] = lpath.breakSlice;
4930  beadIndexR[0] = lpath.breakSlice+1;
4931  beadIndexL2[0] = lpath2.breakSlice;
4932  beadIndexR2[0] = lpath2.breakSlice+1;
4933 
4934  /* Old tail positions & potential actions */
4935  vector<dVec> oldTailPos(lpath.brokenWorldlinesR.size());
4936  vector<dVec> oldTailPos2(lpath2.brokenWorldlinesR.size());
4937 
4938  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
4939  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4940  oldTailPos[i] = lpath(beadIndexR);
4941  }
4942  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
4943  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4944  oldTailPos2[i] = lpath2(beadIndexR2);
4945  }
4946 
4947  /* Compute direct propagator for Z */
4948  double oldPotAction,oldPotAction2;
4949  double rho0Dir, rho0Dir2;
4950 
4951  /* Compute direct potential actions for both paths */
4952  /* loop over broken beads */
4953  oldPotAction = 0.0;
4954  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
4955  beadIndexR[1] = lpath.brokenWorldlinesR[i];
4956  oldPotAction += actionPtr->potentialAction(beadIndexR);
4957  }
4958  oldPotAction2 = 0.0;
4959  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
4960  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
4961  oldPotAction2 += actionPtr2->potentialAction(beadIndexR2);
4962  }
4963 
4964 
4965  /* Initialize permuation vector */
4966  vector<int> permutation(lpath.brokenWorldlinesR.size());
4967  int Nperm = 0;
4968  double rho0perm;
4969  for( uint32 i=0; i<permutation.size(); i++)
4970  permutation[i] = i;
4971 
4972  /* Compute direct free particle density matricies for both paths */
4973  if ( lpath.brokenWorldlinesL.size() == 0){
4974  rho0Dir = 1.0;
4975  }else{
4976  rho0Dir = 0.0;
4977  /* sum over permutations */
4978  do {
4979  /* sum over broken worldlines */
4980  rho0perm = 1.0;
4981  for( uint32 i=0; i<permutation.size(); i++){
4982  beadIndexL[1] = lpath.brokenWorldlinesL[i];
4983  beadIndexR[1] = lpath.brokenWorldlinesR[permutation[i]];
4984  rho0perm *= actionPtr->rho0(beadIndexL,beadIndexR,1);
4985  }
4986  rho0Dir += rho0perm;
4987  Nperm++;
4988  } while (next_permutation(permutation.begin(),permutation.end()));
4989  rho0Dir *= 1.0/((double)Nperm);
4990  }
4991 
4992  /* Re-initialize permuation vector */
4993  permutation.resize(lpath2.brokenWorldlinesR.size());
4994  for( uint32 i=0; i<permutation.size(); i++)
4995  permutation[i] = i;
4996  Nperm = 0;
4997  if ( lpath2.brokenWorldlinesL.size() == 0){
4998  rho0Dir2 = 1.0;
4999  }else{
5000  rho0Dir2 = 0.0;
5001  /* sum over permutations */
5002  do {
5003  /* sum over broken worldlines */
5004  rho0perm = 1.0;
5005  for( uint32 i=0; i<permutation.size(); i++){
5006  beadIndexL2[1] = lpath2.brokenWorldlinesL[i];
5007  beadIndexR2[1] = lpath2.brokenWorldlinesR[permutation[i]];
5008  //cout << beadIndexL2[1] << '\t' << beadIndexR2[1] << '\t' << permutation[i] << endl;
5009  rho0perm *= actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
5010  }
5011  rho0Dir2 += rho0perm;
5012  Nperm++;
5013  } while (next_permutation(permutation.begin(),permutation.end()));
5014  rho0Dir2 *= 1.0/((double)Nperm);
5015  }
5016 
5017  /* Compute the swapped propagator for S */
5018 
5019  if( (lpath.brokenWorldlinesR.size() == lpath2.brokenWorldlinesR.size()) ){
5020 
5021  if ( lpath.brokenWorldlinesR.size() == 0){
5022  S = 1.0;
5023  Z = 1.0;
5024  }else{
5025  /* Swap the tail positions */
5026  for( uint32 i=0; i<oldTailPos2.size(); i++){
5027  beadIndexR[1] = lpath.brokenWorldlinesR[i];
5028  lpath.updateBead(beadIndexR,oldTailPos2[i]);
5029  }
5030  for( uint32 i=0; i<oldTailPos.size(); i++){
5031  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
5032  lpath2.updateBead(beadIndexR2,oldTailPos[i]);
5033  }
5034 
5035  /* Compute the swapped free particle density matrix */
5036  /* Re-initialize permuation vector */
5037  for( uint32 i=0; i<permutation.size(); i++)
5038  permutation[i] = i;
5039  Nperm = 0;
5040  double rho0Swap = 0.0;
5041  /* sum over permutations */
5042  do {
5043  /* sum over broken worldlines */
5044  rho0perm = 1.0;
5045  for( uint32 i=0; i<permutation.size(); i++){
5046  beadIndexL[1] = lpath.brokenWorldlinesL[i];
5047  beadIndexR[1] = lpath.brokenWorldlinesR[permutation[i]];
5048  rho0perm *= actionPtr->rho0(beadIndexL,beadIndexR,1);
5049  }
5050  rho0Swap += rho0perm;
5051  Nperm++;
5052  } while (next_permutation(permutation.begin(),permutation.end()));
5053  rho0Swap*= 1.0/((double)Nperm);
5054 
5055  /* Re-initialize permuation vector */
5056  for( uint32 i=0; i<permutation.size(); i++)
5057  permutation[i] = i;
5058  Nperm = 0;
5059  double rho0Swap2 = 0.0;
5060  /* sum over permutations */
5061  do {
5062  /* sum over broken worldlines */
5063  rho0perm = 1.0;
5064  for( uint32 i=0; i<permutation.size(); i++){
5065  beadIndexL2[1] = lpath2.brokenWorldlinesL[i];
5066  beadIndexR2[1] = lpath2.brokenWorldlinesR[permutation[i]];
5067  rho0perm *= actionPtr2->rho0(beadIndexL2,beadIndexR2,1);
5068  }
5069  rho0Swap2 += rho0perm;
5070  Nperm++;
5071  } while (next_permutation(permutation.begin(),permutation.end()));
5072  rho0Swap2*= 1.0/((double)Nperm);
5073 
5074  /* Compute the potential the potential action */
5075  /* Compute direct potential actions for both paths */
5076  /* loop over broken beads */
5077  double newPotAction = 0.0;
5078  for( uint32 i=0; i<lpath.brokenWorldlinesR.size();i++){
5079  beadIndexR[1] = lpath.brokenWorldlinesR[i];
5080  newPotAction += actionPtr->potentialAction(beadIndexR);
5081  }
5082  double newPotAction2 = 0.0;
5083  for( uint32 i=0; i<lpath2.brokenWorldlinesR.size();i++){
5084  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
5085  newPotAction2 += actionPtr2->potentialAction(beadIndexR2);
5086  }
5087 
5088  /* Now we must undo any damge we have caused by reverting the tail to its previous position*/
5089  for( uint32 i=0; i<oldTailPos.size(); i++){
5090  beadIndexR[1] = lpath.brokenWorldlinesR[i];
5091  lpath.updateBead(beadIndexR,oldTailPos[i]);
5092  }
5093  for( uint32 i=0; i<oldTailPos2.size(); i++){
5094  beadIndexR2[1] = lpath2.brokenWorldlinesR[i];
5095  lpath2.updateBead(beadIndexR2,oldTailPos2[i]);
5096  }
5097  S = rho0Swap*rho0Swap2*exp(-(0.5)*(newPotAction+newPotAction2)+(0.5)*(oldPotAction+oldPotAction2));
5098  Z = rho0Dir*rho0Dir2;
5099 
5100  nBin = lpath.brokenWorldlinesR.size();
5101  if( nBin < constants()->initialNumParticles() )
5102  nMatch = true;
5103  }
5104  }else{
5105  S = 0.0;
5106  Z = rho0Dir*rho0Dir2;
5107  }
5108 
5109  /* In the normalization factor we must account for the factor of 1/2 in the
5110  open path weight */
5111  //Z = rho0Dir*rho0Dir2*exp(-(oldPotAction+oldPotAction2));
5112  //S = rho0Swap*rho0Swap2*exp(-(newPotAction+newPotAction2));
5113 
5114  //cout << rho0Dir << '\t' << rho0Dir2 << '\t' << Z << '\t' << S << endl;
5115 
5116  estimator(0) += Z;
5117  if( nMatch ){
5118  estimator(nBin*2-1) += Z;
5119  estimator(nBin*2) += S;
5120  }
5121 }
5122 
5123 
5124 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
5125 // END PIGS ESTIMATORS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
5126 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
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
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
Array< int, 1 > sepHist
A histogram of separations.
Definition: action.h:111
PotentialBase * interactionPtr
The interaction potential.
Definition: action.h:109
PotentialBase * externalPtr
The external potential.
Definition: action.h:108
double rho0(const dVec &, const dVec &, int)
The free-particle density matrix.
Definition: action.cpp:83
Compute density inside film and in bulk separately for Excluded volume potentials.
Definition: estimator.h:265
~BipartitionDensityEstimator()
Destructor.
Definition: estimator.cpp:894
BipartitionDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="bipart_dens")
Constructor.
Definition: estimator.cpp:878
File * file(string type)
Get method returning file object.
Definition: communicator.h:85
int numTimeSlices()
Get number of time slices.
Definition: constants.h:99
double T() const
Get temperature.
Definition: constants.h:41
double mu() const
Get chemical potential.
Definition: constants.h:43
double lambda() const
Get lambda = hbar^2/(2mk_B)
Definition: constants.h:46
double V() const
Get cell volume.
Definition: constants.h:51
int virialWindow() const
Get centroid virial window size.
Definition: constants.h:55
double tau() const
Get imaginary time step.
Definition: constants.h:44
double fourLambdaTauInv() const
Get (4lambda/tau)^{-1}.
Definition: constants.h:62
bool canonical() const
Get ensemble.
Definition: constants.h:89
int initialNumParticles()
Get initial number of particles.
Definition: constants.h:100
bool restart() const
Get restart state.
Definition: constants.h:86
dVec gridSize
The grid size in each dimension.
Definition: container.h:44
double volume
The volume of the container in A^3.
Definition: container.h:35
int numGrid
The number of grid boxes for the position grid.
Definition: container.h:41
dVec sideInv
The inverse box dimensions.
Definition: container.h:32
TinyVector< unsigned int, NDIM > periodic
Determines which dimensions have periodic bc.
Definition: container.h:29
virtual double gridBoxVolume(const int) const =0
The physical size of a NDIM-dimensional grid box.
string name
The name of the container.
Definition: container.h:39
void putInBC(dVec &r) const
Place a vector in boundary conditions.
Definition: container.h:50
virtual int gridIndex(const dVec &) const =0
Map a position into a grid index.
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
Computes the total energy via the thermodynamic estimator.
Definition: estimator.h:813
CylinderEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_estimator")
Constructor.
Definition: estimator.cpp:2919
~CylinderEnergyEstimator()
Destructor.
Definition: estimator.cpp:2939
Computes the density as a function of distance along the cylinder axis.
Definition: estimator.h:877
CylinderLinearDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_linedensity")
Constructor.
Definition: estimator.cpp:3120
~CylinderLinearDensityEstimator()
Destructor.
Definition: estimator.cpp:3145
Compute the effective linear potential along the axis of the cylinder.
Definition: estimator.h:998
~CylinderLinearPotentialEstimator()
Destructor.
Definition: estimator.cpp:3628
CylinderLinearPotentialEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_linepotential")
Constructor.
Definition: estimator.cpp:3605
Computes the probability distribution function for the number of particles.
Definition: estimator.h:855
~CylinderNumberDistributionEstimator()
Destructor.
Definition: estimator.cpp:3093
CylinderNumberDistributionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_number")
Constructor.
Definition: estimator.cpp:3075
Computes the average number of particles, as well as density.
Definition: estimator.h:835
~CylinderNumberParticlesEstimator()
Destructor.
Definition: estimator.cpp:3048
CylinderNumberParticlesEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_estimator")
Constructor.
Definition: estimator.cpp:3032
Compute the one body density matrix n(r) which can be used to find the momentum distribution function...
Definition: estimator.h:930
CylinderOneBodyDensityMatrixEstimator(Path &, ActionBase *, const MTRand &, double, int _frequency=20, string _label="cyl_obdm")
Constructor.
Definition: estimator.cpp:3330
Compute the two-body pair-correlation function, g(r) ~ <rho(r)rho(0)>.
Definition: estimator.h:975
~CylinderPairCorrelationEstimator()
Destructor.
Definition: estimator.cpp:3559
void sample()
Sample the estimator.
Definition: estimator.cpp:3583
CylinderPairCorrelationEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_pair")
Constructor.
Definition: estimator.cpp:3536
Compute the effective radial potential in a cylinder.
Definition: estimator.h:1022
CylinderRadialPotentialEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_potential")
Constructor.
Definition: estimator.cpp:3692
~CylinderRadialPotentialEstimator()
Destructor.
Definition: estimator.cpp:3712
Compute the superfluid fraction, as well as the winding number probability distribution.
Definition: estimator.h:901
~CylinderSuperfluidFractionEstimator()
Destructor.
Definition: estimator.cpp:3211
CylinderSuperfluidFractionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="cyl_super")
Constructor.
Definition: estimator.cpp:3186
Compute the fraction of time we spend in the diagonal ensemble.
Definition: estimator.h:568
void sample()
Overload sampling to make sure it is always done, regardless of ensemble.
Definition: estimator.cpp:1944
~DiagonalFractionEstimator()
Destructor.
Definition: estimator.cpp:1929
DiagonalFractionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="estimator")
Constructor.
Definition: estimator.cpp:1915
Base class for estimators that use two paths.
Definition: estimator.h:1295
~DoubledEstimator()
Destructor.
Definition: estimator.cpp:4576
DoubledEstimator(const Path &, const Path &, ActionBase *, ActionBase *, const MTRand &, double, int _frequency=1, string _label="")
Constructor.
Definition: estimator.cpp:4566
Computes the total energy via the thermodynamic estimator.
Definition: estimator.h:162
EnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="estimator")
Constructor.
Definition: estimator.cpp:409
~EnergyEstimator()
Destructor.
Definition: estimator.cpp:420
Computes the Swap Estimator between two paths.
Definition: estimator.h:1347
EntPartEstimator(Path &, Path &, ActionBase *, ActionBase *, const MTRand &, double, int _frequency=1, string _label="entpart")
Constructor.
Definition: estimator.cpp:4889
~EntPartEstimator()
Destructor.
Definition: estimator.cpp:4916
The base class that all estimator classes will be derived from.
Definition: estimator.h:28
virtual void outputFlat()
Output a flat estimator value to disk.
Definition: estimator.cpp:305
int endSlice
Where imaginary time averages end.
Definition: estimator.h:96
bool diagonal
Is this a diagonal estimator?
Definition: estimator.h:106
void reset()
Reset numAccumulated and the estimator to 0.
Definition: estimator.cpp:261
Array< double, 1 > estimator
The estimator array.
Definition: estimator.h:90
ActionBase * actionPtr
A pointer to the action.
Definition: estimator.h:82
virtual ~EstimatorBase()
Destructor.
Definition: estimator.cpp:146
Array< double, 1 > norm
The normalization factor for each estimator.
Definition: estimator.h:91
bool canonical
Are we in the canonical ensemble?
Definition: estimator.h:108
int endDiagSlice
Where imaginary time averages end for diagonal estimiators.
Definition: estimator.h:97
virtual void output()
Output the estimator value to disk.
Definition: estimator.cpp:283
vector< double > sliceFactor
Used to properly incorporate end affects.
Definition: estimator.h:98
void restart(const uint32, const uint32)
Restart the measurment process from a previous state.
Definition: estimator.cpp:269
void prepare()
Prepare the estimator for i/o.
Definition: estimator.cpp:240
string header
The data file header.
Definition: estimator.h:110
bool endLine
Should we output a carriage return?
Definition: estimator.h:107
int numEst
The number of individual quantities measured.
Definition: estimator.h:93
int startSlice
Where imaginary time averages begin.
Definition: estimator.h:95
int frequency
The frequency at which we accumulate.
Definition: estimator.h:94
void appendLabel(string append)
Append to default label.
Definition: estimator.cpp:325
map< string, int > estIndex
Map estimator labels to indices.
Definition: estimator.h:88
uint32 totNumAccumulated
The total number of accumulated values.
Definition: estimator.h:103
virtual void sample()
Sample the estimator.
Definition: estimator.cpp:187
EstimatorBase(const Path &_path, ActionBase *_actionPtr, const MTRand &_random, double _maxR, int _frequency=1, string _label="")
Constructor.
Definition: estimator.cpp:103
uint32 numSampled
The number of times we have sampled.
Definition: estimator.h:101
virtual void accumulate()
Accumulate the estimator.
Definition: estimator.h:113
uint32 numAccumulated
The number of accumulated values.
Definition: estimator.h:102
bool baseSample()
Determine the basic sampling condition.
Definition: estimator.cpp:161
const Path & path
A constant reference to the paths.
Definition: estimator.h:78
int numBeads0
The target number of beads for the canonical ensemble.
Definition: estimator.h:104
fstream * outFilePtr
The output fie.
Definition: estimator.h:86
void initialize(int)
Initialize estimator.
Definition: estimator.cpp:201
string label
The label used for the output file.
Definition: estimator.h:99
void reset()
Reset a file.
void rename()
Rename a file.
bool exists()
did the file exist before opening?
Definition: communicator.h:48
Compute the intermediate scattering function F(q,\tau)
Definition: estimator.h:734
IntermediateScatteringFunctionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="isf")
Constructor.
Definition: estimator.cpp:2668
Computes the total energy using a mixed estimator.
Definition: estimator.h:1073
KineticEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="kinetic")
Constructor.
Definition: estimator.cpp:3890
~KineticEnergyEstimator()
Destructor.
Definition: estimator.cpp:3908
Create a 1d histogram of particle positions in the z-direction.
Definition: estimator.h:286
~LinearParticlePositionEstimator()
Destructor.
Definition: estimator.cpp:986
LinearParticlePositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="lineardensity")
Constructor.
Definition: estimator.cpp:955
Particle permutation number density histogram.
Definition: estimator.h:613
LocalPermutationEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="locperm")
Constructor.
Definition: estimator.cpp:2117
~LocalPermutationEstimator()
Destructor.
Definition: estimator.cpp:2140
Compute the local superfluid density.
Definition: estimator.h:439
LocalSuperfluidDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="locsuper")
Constructor.
Definition: estimator.cpp:1769
~LocalSuperfluidDensityEstimator()
Destructor.
Definition: estimator.cpp:1808
void output()
overload the output
Definition: estimator.cpp:1818
Computes the probability distribution function for the number of particles.
Definition: estimator.h:390
~NumberDistributionEstimator()
Destructor.
Definition: estimator.cpp:788
NumberDistributionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="number")
Constructor.
Definition: estimator.cpp:759
Computes the average number of particles, as well as density.
Definition: estimator.h:220
NumberParticlesEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="estimator")
Constructor.
Definition: estimator.cpp:719
~NumberParticlesEstimator()
Destructor.
Definition: estimator.cpp:733
Compute the one body density matrix n(r) which can be used to find the momentum distribution function...
Definition: estimator.h:644
void outputFooter()
For the one body density matrix estimator, we would like to output the acceptance information for the...
Definition: estimator.cpp:2478
OneBodyDensityMatrixEstimator(Path &, ActionBase *, const MTRand &, double, int _frequency=20, string _label="obdm")
Constructor.
Definition: estimator.cpp:2256
~OneBodyDensityMatrixEstimator()
Destructor.
Definition: estimator.cpp:2284
void sample()
Sample the OBDM.
Definition: estimator.cpp:2296
Compute the one body density matrix n(r) which can be used to find the momentum distribution function...
Definition: estimator.h:1253
void outputFooter()
For the one body density matrix estimator, we would like to output the acceptance information for the...
Definition: estimator.cpp:4550
~PIGSOneBodyDensityMatrixEstimator()
Destructor.
Definition: estimator.cpp:4404
PIGSOneBodyDensityMatrixEstimator(Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="obdm")
Constructor.
Definition: estimator.cpp:4376
void sample()
Sample the OBDM.
Definition: estimator.cpp:4414
Compute the two-body pair-correlation function, g(r) ~ <rho(r)rho(0)>.
Definition: estimator.h:690
PairCorrelationEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="pair")
Constructor.
Definition: estimator.cpp:2497
~PairCorrelationEstimator()
Destructor.
Definition: estimator.cpp:2545
Computes the average position of each particle in 1D at the center time slice.
Definition: estimator.h:1182
~ParticleCorrelationEstimator()
Destructor.
Definition: estimator.cpp:4209
ParticleCorrelationEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="prcorrelation")
Constructor.
Definition: estimator.cpp:4191
Create histogram of particle positions.
Definition: estimator.h:241
ParticlePositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="position")
Constructor.
Definition: estimator.cpp:816
~ParticlePositionEstimator()
Destructor.
Definition: estimator.cpp:843
Computes the average position of each particle in 1D at the center time slice.
Definition: estimator.h:1159
ParticleResolvedPositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="prposition")
Constructor.
Definition: estimator.cpp:4134
~ParticleResolvedPositionEstimator()
Destructor.
Definition: estimator.cpp:4155
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
int getNumParticles() const
Get the size of the worldline array.
Definition: path.h:51
beadLocator delBeadGetNext(const beadLocator &)
Delete a bead and move forwards.
Definition: path.cpp:326
dVec getVelocity(const beadLocator &) const
Return the velocity between two time slices of a given particle as a ndim-vector.
Definition: path.h:183
vector< int > brokenWorldlinesR
A list of particles with broken worldlines on right of break.
Definition: path.h:40
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
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
int breakSlice
The location of the break in the path (0=>no break)
Definition: path.h:38
bool inSubregionB(const beadLocator &) const
Check if bead is in subregion B.
Definition: path.cpp:533
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
int getTrueNumParticles() const
The number of active particles.
Definition: path.h:54
Computes the particle permutation cycle probability distribution.
Definition: estimator.h:590
~PermutationCycleEstimator()
Destructor.
Definition: estimator.cpp:2037
PermutationCycleEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="pcycle")
Constructor.
Definition: estimator.cpp:2015
Compute the radially averaged local superfluid density.
Definition: estimator.h:494
~PlaneAreaSuperfluidDensityEstimator()
Destructor.
Definition: estimator.cpp:1530
PlaneAreaSuperfluidDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="planearea")
Constructor.
Definition: estimator.cpp:1500
Create a 2d histogram of particle positions but only store the average.
Definition: estimator.h:362
PlaneAverageExternalPotentialEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="planeaveVext")
Constructor.
Definition: estimator.cpp:1191
void output()
Output a flat estimator value to disk.
Definition: estimator.cpp:1261
Create a 2d histogram of particle positions but only store the average.
Definition: estimator.h:335
PlaneParticleAveragePositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="planeavedensity")
Constructor.
Definition: estimator.cpp:1112
Create a 2d histogram of particle positions.
Definition: estimator.h:310
PlaneParticlePositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="planedensity")
Constructor.
Definition: estimator.cpp:1029
~PlaneParticlePositionEstimator()
Destructor.
Definition: estimator.cpp:1066
Compute the radially averaged local superfluid density.
Definition: estimator.h:468
PlaneWindingSuperfluidDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="planewind")
Constructor.
Definition: estimator.cpp:1411
Computes the average value of the position in 1D.
Definition: estimator.h:1137
~PositionEstimator()
Destructor.
Definition: estimator.cpp:4102
PositionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="position")
Constructor.
Definition: estimator.cpp:4084
double tailV
Tail correction factor.
Definition: potential.h:61
virtual Array< double, 1 > getExcLen()
Array to hold data elements.
Definition: potential.cpp:135
virtual double V(const dVec &)
The potential.
Definition: potential.h:39
Computes the potential energy along the worldline.
Definition: estimator.h:1052
PotentialEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="potential")
Constructor.
Definition: estimator.cpp:3844
~PotentialEnergyEstimator()
Destructor.
Definition: estimator.cpp:3861
Compute the radially averaged local superfluid density.
Definition: estimator.h:544
RadialAreaSuperfluidDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="radarea")
Constructor.
Definition: estimator.cpp:1681
~RadialAreaSuperfluidDensityEstimator()
Destructor.
Definition: estimator.cpp:1710
Compute the density as a function of position in the radial direction.
Definition: estimator.h:759
~RadialDensityEstimator()
Destructor.
Definition: estimator.cpp:2853
RadialDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="radial")
Constructor.
Definition: estimator.cpp:2829
Compute the radially averaged local superfluid density.
Definition: estimator.h:520
RadialWindingSuperfluidDensityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="radwind")
Constructor.
Definition: estimator.cpp:1595
Compute the static structure factor S(q)
Definition: estimator.h:711
StaticStructureFactorEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="ssf")
Constructor.
Definition: estimator.cpp:2577
~StaticStructureFactorEstimator()
Destructor.
Definition: estimator.cpp:2607
Computes the imaginary time resolved "velocity" for the first particle .
Definition: estimator.h:1228
~SubregionOccupationEstimator()
Destructor.
Definition: estimator.cpp:4322
SubregionOccupationEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="subregionocc")
Constructor.
Definition: estimator.cpp:4304
Compute the superfluid fraction, as well as the winding number probability distribution.
Definition: estimator.h:416
SuperfluidFractionEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="super")
Constructor.
Definition: estimator.cpp:1297
~SuperfluidFractionEstimator()
Destructor.
Definition: estimator.cpp:1324
Computes the Swap Estimator between two paths.
Definition: estimator.h:1319
SwapEstimator(Path &, Path &, ActionBase *, ActionBase *, const MTRand &, double, int _frequency=1, string _label="swap")
Constructor.
Definition: estimator.cpp:4589
~SwapEstimator()
Destructor.
Definition: estimator.cpp:4606
Computes the total energy using a mixed estimator.
Definition: estimator.h:1115
~ThermoPotentialEnergyEstimator()
Destructor.
Definition: estimator.cpp:4055
ThermoPotentialEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="thpotential")
Constructor.
Definition: estimator.cpp:4037
An estimator which tracks the ammount of time between bins, summing them into a total at the end.
Definition: estimator.h:128
void sample()
Overload sampling to make sure it is always done, regardless of ensemble.
Definition: estimator.cpp:354
TimeEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="estimator")
Constructor.
Definition: estimator.cpp:340
void output()
Grab the final time and write to disk.
Definition: estimator.cpp:376
Computes the total energy using a mixed estimator.
Definition: estimator.h:1094
~TotalEnergyEstimator()
Destructor.
Definition: estimator.cpp:3985
TotalEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="energy")
Constructor.
Definition: estimator.cpp:3967
Computes the imaginary time resolved "velocity" for the first particle .
Definition: estimator.h:1206
~VelocityEstimator()
Destructor.
Definition: estimator.cpp:4267
VelocityEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="velocity")
Constructor.
Definition: estimator.cpp:4249
Computes the total energy via the thermodynamic estimator.
Definition: estimator.h:199
VirialEnergyEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="virial")
Constructor.
Definition: estimator.cpp:523
~VirialEnergyEstimator()
Destructor.
Definition: estimator.cpp:539
Compute various properties related to the worm in the simulation.
Definition: estimator.h:780
WormPropertiesEstimator(const Path &, ActionBase *, const MTRand &, double, int _frequency=1, string _label="worm")
Constructor.
Definition: estimator.cpp:1968
~WormPropertiesEstimator()
Destructor.
Definition: estimator.cpp:1985
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
dVec sep
The spatial separation between head and tail.
Definition: worm.h:36
beadLocator head
The coordinates of the worm head.
Definition: worm.h:31
int getNumBeadsOn() const
Return the number of active beads.
Definition: worm.h:88
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 NOBDMSEP
Spatial separations to be used in the one body density matrix.
Definition: common.h:91
#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
#define NRADSEP
Spatial separations to be used in the radial density.
Definition: common.h:92
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
#define NGRIDSEP
Spatial separations to be used in each dimension of the particle position grid.
Definition: common.h:93
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
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
REGISTER_ESTIMATOR("energy", EnergyEstimator)
Estimator naming conventions:
EstimatorFactory estimatorFactory
Setup the estimator factory.
Definition: estimator.cpp:19
int num1DParticles(const Path &path, double maxR)
Count the number of particles inside a given radius.
Definition: estimator.cpp:2896
bool include(const dVec &r, double maxR)
Determine if a position is inside the cutoff radius.
Definition: estimator.cpp:2887
MultiEstimatorFactory multiEstimatorFactory
Setup the estimator factory for multi path estimators.
Definition: estimator.cpp:81
Estimator class definitions.
Factory class definitions.
Path class definition.
All possible potential classes.