QMCPACK
ParticleSet.cpp
Go to the documentation of this file.
1 //////////////////////////////////////////////////////////////////////////////////////
2 // This file is distributed under the University of Illinois/NCSA Open Source License.
3 // See LICENSE file in top directory for details.
4 //
5 // Copyright (c) 2020 QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Luke Shulenburger, lshulen@sandia.gov, Sandia National Laboratories
9 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
10 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
12 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
13 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
14 // Mark Dewing, markdewing@gmail.com, University of Illinois at Urbana-Champaign
15 //
16 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
17 //////////////////////////////////////////////////////////////////////////////////////
18 
19 
20 #include <numeric>
21 #include <iomanip>
22 #include "ParticleSet.h"
24 #include "Particle/DistanceTable.h"
26 #include "LongRange/StructFact.h"
30 #include "ResourceCollection.h"
31 
32 namespace qmcplusplus
33 {
35 
37 {
45 };
46 
47 static const TimerNameList_t<PSetTimers> generatePSetTimerNames(std::string& obj_name)
48 {
49  return {{PS_newpos, "ParticleSet:" + obj_name + "::computeNewPosDT"},
50  {PS_donePbyP, "ParticleSet:" + obj_name + "::donePbyP"},
51  {PS_accept, "ParticleSet:" + obj_name + "::acceptMove"},
52  {PS_loadWalker, "ParticleSet:" + obj_name + "::loadWalker"},
53  {PS_update, "ParticleSet:" + obj_name + "::update"},
54  {PS_dt_move, "ParticleSet:" + obj_name + "::dt_move"},
55  {PS_mw_copy, "ParticleSet:" + obj_name + "::mw_copy"}};
56 }
57 
59  : quantum_domain(classical),
60  Properties(0, 0, 1, WP::MAXPROPERTIES),
61  simulation_cell_(simulation_cell),
62  same_mass_(true),
63  is_spinor_(false),
64  active_ptcl_(-1),
65  active_spin_val_(0.0),
67  myTwist(0.0),
68  ParentName("0"),
69  TotalNum(0),
70  group_offsets_(std::make_shared<Vector<int, OMPallocator<int>>>()),
71  coordinates_(createDynamicCoordinates(kind))
72 {
74 }
75 
77  : Properties(p.Properties),
78  simulation_cell_(p.simulation_cell_),
79  same_mass_(true),
80  is_spinor_(false),
81  active_ptcl_(-1),
82  active_spin_val_(0.0),
83  my_species_(p.getSpeciesSet()),
85  myTwist(0.0),
86  ParentName(p.parentName()),
87  group_offsets_(p.group_offsets_),
88  coordinates_(p.coordinates_->makeClone())
89 {
91 
92  resize(p.getTotalNum());
93  R.InUnit = p.R.InUnit;
94  R = p.R;
95  spins = p.spins;
96  GroupID = p.GroupID;
98 
99  //need explicit copy:
100  Mass = p.Mass;
101  Z = p.Z;
102  //std::ostringstream o;
103  //o<<p.getName()<<ObjectTag;
104  //this->setName(o.str());
105  //app_log() << " Copying a particle set " << p.getName() << " to " << this->getName() << " groups=" << groups() << std::endl;
106  myName = p.getName();
111  //construct the distance tables with the same order
112  for (int i = 0; i < p.DistTables.size(); ++i)
113  addTable(p.DistTables[i]->get_origin(), p.DistTables[i]->getModes());
114 
115  if (p.structure_factor_)
116  structure_factor_ = std::make_unique<StructFact>(*p.structure_factor_);
117  myTwist = p.myTwist;
118 
119  G = p.G;
120  L = p.L;
121 }
122 
123 ParticleSet::~ParticleSet() = default;
124 
125 void ParticleSet::create(const std::vector<int>& agroup)
126 {
127  auto& group_offsets(*group_offsets_);
128  group_offsets.resize(agroup.size() + 1);
129  group_offsets[0] = 0;
130  for (int is = 0; is < agroup.size(); is++)
131  group_offsets[is + 1] = group_offsets[is] + agroup[is];
132  group_offsets.updateTo();
133  const size_t nsum = group_offsets[agroup.size()];
134  resize(nsum);
135  TotalNum = nsum;
136  int loc = 0;
137  for (int i = 0; i < agroup.size(); i++)
138  for (int j = 0; j < agroup[i]; j++, loc++)
139  GroupID[loc] = i;
140 }
141 
143 {
144  if (quantumDomainValid(qdomain))
145  quantum_domain = qdomain;
146  else
147  throw std::runtime_error("ParticleSet::setQuantumDomain\n input quantum domain is not valid for particles");
148 }
149 
151 {
152  const int nspecies = my_species_.getTotalNum();
153  // Usually an empty ParticleSet indicates an error in the input file,
154  // but in some cases it is useful. Allow an empty ParticleSet if it
155  // has the special name "empty".
156  if (nspecies == 0 && getName() != "empty")
157  {
158  throw std::runtime_error("ParticleSet::resetGroups() Failed. No species exisits");
159  }
160  int natt = my_species_.numAttributes();
161  int qind = my_species_.addAttribute("charge");
162  if (natt == qind)
163  {
164  app_log() << " Missing charge attribute of the SpeciesSet " << myName << " particleset" << std::endl;
165  app_log() << " Assume neutral particles Z=0.0 " << std::endl;
166  for (int ig = 0; ig < nspecies; ig++)
167  my_species_(qind, ig) = 0.0;
168  }
169  for (int iat = 0; iat < Z.size(); iat++)
170  Z[iat] = my_species_(qind, GroupID[iat]);
171  natt = my_species_.numAttributes();
172  int massind = my_species_.addAttribute("mass");
173  if (massind == natt)
174  {
175  for (int ig = 0; ig < nspecies; ig++)
176  my_species_(massind, ig) = 1.0;
177  }
178  same_mass_ = true;
179  double m0 = my_species_(massind, 0);
180  for (int ig = 1; ig < nspecies; ig++)
181  same_mass_ &= (my_species_(massind, ig) == m0);
182  if (same_mass_)
183  app_log() << " All the species have the same mass " << m0 << std::endl;
184  else
185  app_log() << " Distinctive masses for each species " << std::endl;
186  for (int iat = 0; iat < Mass.size(); iat++)
187  Mass[iat] = my_species_(massind, GroupID[iat]);
188 
189  int membersize = my_species_.addAttribute("membersize");
190  for (int ig = 0; ig < nspecies; ++ig)
191  my_species_(membersize, ig) = groupsize(ig);
192 
193  for (int iat = 0; iat < GroupID.size(); iat++)
194  assert(GroupID[iat] < nspecies);
195 }
196 
198 {
199  SpeciesSet& srcSpSet(src.getSpeciesSet());
200  SpeciesSet& spSet(getSpeciesSet());
201  int srcChargeIndx = srcSpSet.addAttribute("charge");
202  int srcMemberIndx = srcSpSet.addAttribute("membersize");
203  int ChargeIndex = spSet.addAttribute("charge");
204  int MemberIndx = spSet.addAttribute("membersize");
205  int Nsrc = src.getTotalNum();
206  int Nptcl = getTotalNum();
207  int NumSpecies = spSet.TotalNum;
208  int NumSrcSpecies = srcSpSet.TotalNum;
209  //Store information about charges and number of each species
210  std::vector<int> Zat, Zspec, NofSpecies, NofSrcSpecies, CurElec;
211  Zat.resize(Nsrc);
212  Zspec.resize(NumSrcSpecies);
213  NofSpecies.resize(NumSpecies);
214  CurElec.resize(NumSpecies);
215  NofSrcSpecies.resize(NumSrcSpecies);
216  for (int spec = 0; spec < NumSrcSpecies; spec++)
217  {
218  Zspec[spec] = (int)round(srcSpSet(srcChargeIndx, spec));
219  NofSrcSpecies[spec] = (int)round(srcSpSet(srcMemberIndx, spec));
220  }
221  for (int spec = 0; spec < NumSpecies; spec++)
222  {
223  NofSpecies[spec] = (int)round(spSet(MemberIndx, spec));
224  CurElec[spec] = first(spec);
225  }
226  int totQ = 0;
227  for (int iat = 0; iat < Nsrc; iat++)
228  totQ += Zat[iat] = Zspec[src.GroupID[iat]];
229  app_log() << " Total ion charge = " << totQ << std::endl;
230  totQ -= Nptcl;
231  app_log() << " Total system charge = " << totQ << std::endl;
232  // Now, loop over ions, attaching electrons to them to neutralize
233  // charge
234  int spToken = 0;
235  // This is decremented when we run out of electrons in each species
236  int spLeft = NumSpecies;
237  std::vector<PosType> gaussRand(Nptcl);
238  makeGaussRandom(gaussRand);
239  for (int iat = 0; iat < Nsrc; iat++)
240  {
241  // Loop over electrons to add, selecting round-robin from the
242  // electron species
243  int z = Zat[iat];
244  while (z > 0 && spLeft)
245  {
246  int sp = spToken++ % NumSpecies;
247  if (NofSpecies[sp])
248  {
249  NofSpecies[sp]--;
250  z--;
251  int elec = CurElec[sp]++;
252  app_log() << " Assigning " << (sp ? "down" : "up ") << " electron " << elec << " to ion " << iat
253  << " with charge " << z << std::endl;
254  double radius = 0.5 * std::sqrt((double)Zat[iat]);
255  R[elec] = src.R[iat] + radius * gaussRand[elec];
256  }
257  else
258  spLeft--;
259  }
260  }
261  // Assign remaining electrons
262  int ion = 0;
263  for (int sp = 0; sp < NumSpecies; sp++)
264  {
265  for (int ie = 0; ie < NofSpecies[sp]; ie++)
266  {
267  int iat = ion++ % Nsrc;
268  double radius = std::sqrt((double)Zat[iat]);
269  int elec = CurElec[sp]++;
270  R[elec] = src.R[iat] + radius * gaussRand[elec];
271  }
272  }
273 }
274 
275 void ParticleSet::print(std::ostream& os, const size_t maxParticlesToPrint) const
276 {
277  os << " ParticleSet '" << getName() << "' contains " << TotalNum << " particles : ";
278  if (auto& group_offsets(*group_offsets_); group_offsets.size() > 0)
279  for (int i = 0; i < group_offsets.size() - 1; i++)
280  os << " " << my_species_.speciesName[i] << "(" << group_offsets[i + 1] - group_offsets[i] << ")";
281  os << std::endl << std::endl;
282 
283  const size_t numToPrint = maxParticlesToPrint == 0 ? TotalNum : std::min(TotalNum, maxParticlesToPrint);
284 
285  for (int i = 0; i < numToPrint; i++)
286  {
287  os << " " << my_species_.speciesName[GroupID[i]] << R[i] << std::endl;
288  }
289  if (numToPrint < TotalNum)
290  {
291  os << " (... and " << (TotalNum - numToPrint) << " more particle positions ...)" << std::endl;
292  }
293  os << std::endl;
294 
295  for (const std::string& description : distTableDescriptions)
296  os << description;
297  os << std::endl;
298 }
299 
300 bool ParticleSet::get(std::ostream& is) const { return true; }
301 bool ParticleSet::put(std::istream& is) { return true; }
302 void ParticleSet::reset() { app_log() << "<<<< going to set properties >>>> " << std::endl; }
303 
304 ///read the particleset
305 bool ParticleSet::put(xmlNodePtr cur) { return true; }
306 
308 {
309  if (myName == "none" || psrc.getName() == "none")
310  throw std::runtime_error("ParticleSet::addTable needs proper names for both source and target particle sets.");
311 
312  int tid;
313  std::map<std::string, int>::iterator tit(myDistTableMap.find(psrc.getName()));
314  if (tit == myDistTableMap.end())
315  {
316  std::ostringstream description;
317  tid = DistTables.size();
318  if (myName == psrc.getName())
319  DistTables.push_back(createDistanceTable(*this, description));
320  else
321  DistTables.push_back(createDistanceTable(psrc, *this, description));
322  distTableDescriptions.push_back(description.str());
323  myDistTableMap[psrc.getName()] = tid;
324  app_debug() << " ... ParticleSet::addTable Create Table #" << tid << " " << DistTables[tid]->getName()
325  << std::endl;
326  }
327  else
328  {
329  tid = (*tit).second;
330  app_debug() << " ... ParticleSet::addTable Reuse Table #" << tid << " " << DistTables[tid]->getName() << std::endl;
331  }
332 
333  DistTables[tid]->setModes(DistTables[tid]->getModes() | modes);
334 
335  app_log().flush();
336  return tid;
337 }
338 
340 {
341  return dynamic_cast<DistanceTableAA&>(*DistTables[table_ID]);
342 }
343 
345 {
346  return dynamic_cast<DistanceTableAB&>(*DistTables[table_ID]);
347 }
348 
349 void ParticleSet::update(bool skipSK)
350 {
351  ScopedTimer update_scope(myTimers[PS_update]);
352 
353  coordinates_->setAllParticlePos(R);
354  for (int i = 0; i < DistTables.size(); i++)
355  DistTables[i]->evaluate(*this);
356  if (!skipSK && structure_factor_)
357  structure_factor_->updateAllPart(*this);
358 
359  active_ptcl_ = -1;
360 }
361 
363 {
364  auto& p_leader = p_list.getLeader();
365  ScopedTimer update_scope(p_leader.myTimers[PS_update]);
366 
367  for (ParticleSet& pset : p_list)
368  pset.coordinates_->setAllParticlePos(pset.R);
369 
370  auto& dts = p_leader.DistTables;
371  for (int i = 0; i < dts.size(); ++i)
372  {
373  const auto dt_list(extractDTRefList(p_list, i));
374  dts[i]->mw_evaluate(dt_list, p_list);
375  }
376 
377  if (!skipSK && p_leader.structure_factor_)
378  for (int iw = 0; iw < p_list.size(); iw++)
379  p_list[iw].structure_factor_->updateAllPart(p_list[iw]);
380 }
381 
382 void ParticleSet::makeMove(Index_t iat, const SingleParticlePos& displ, bool maybe_accept)
383 {
384  active_ptcl_ = iat;
385  active_pos_ = R[iat] + displ;
386  active_spin_val_ = spins[iat];
387  computeNewPosDistTables(iat, active_pos_, maybe_accept);
388 }
389 
390 void ParticleSet::makeMoveWithSpin(Index_t iat, const SingleParticlePos& displ, const Scalar_t& sdispl)
391 {
392  makeMove(iat, displ);
393  active_spin_val_ += sdispl;
394 }
395 
396 template<CoordsType CT>
397 void ParticleSet::mw_makeMove(const RefVectorWithLeader<ParticleSet>& p_list, Index_t iat, const MCCoords<CT>& displs)
398 {
399  mw_makeMove(p_list, iat, displs.positions);
400  if constexpr (CT == CoordsType::POS_SPIN)
401  mw_makeSpinMove(p_list, iat, displs.spins);
402 }
403 
405  Index_t iat,
406  const std::vector<SingleParticlePos>& displs)
407 {
408  std::vector<SingleParticlePos> new_positions;
409  new_positions.reserve(displs.size());
410 
411  for (int iw = 0; iw < p_list.size(); iw++)
412  {
413  p_list[iw].active_ptcl_ = iat;
414  p_list[iw].active_pos_ = p_list[iw].R[iat] + displs[iw];
415  new_positions.push_back(p_list[iw].active_pos_);
416  }
417 
418  mw_computeNewPosDistTables(p_list, iat, new_positions);
419 }
420 
422  Index_t iat,
423  const std::vector<Scalar_t>& sdispls)
424 {
425  for (int iw = 0; iw < p_list.size(); iw++)
426  p_list[iw].active_spin_val_ = p_list[iw].spins[iat] + sdispls[iw];
427 }
428 
429 bool ParticleSet::makeMoveAndCheck(Index_t iat, const SingleParticlePos& displ)
430 {
431  active_ptcl_ = iat;
432  active_pos_ = R[iat] + displ;
433  active_spin_val_ = spins[iat];
434  bool is_valid = true;
437  {
438  if (Lattice.outOfBound(Lattice.toUnit(displ)))
439  is_valid = false;
440  else
441  {
443  if (!Lattice.isValid(newRedPos))
444  is_valid = false;
445  }
446  }
448  return is_valid;
449 }
450 
451 bool ParticleSet::makeMoveAndCheckWithSpin(Index_t iat, const SingleParticlePos& displ, const Scalar_t& sdispl)
452 {
453  bool is_valid = makeMoveAndCheck(iat, displ);
454  active_spin_val_ += sdispl;
455  return is_valid;
456 }
457 
458 void ParticleSet::computeNewPosDistTables(Index_t iat, const SingleParticlePos& newpos, bool maybe_accept)
459 {
460  ScopedTimer compute_newpos_scope(myTimers[PS_newpos]);
461 
462  for (int i = 0; i < DistTables.size(); ++i)
463  DistTables[i]->move(*this, newpos, iat, maybe_accept);
464 }
465 
467  Index_t iat,
468  const std::vector<SingleParticlePos>& new_positions,
469  bool maybe_accept)
470 {
471  ParticleSet& p_leader = p_list.getLeader();
472  ScopedTimer compute_newpos_scope(p_leader.myTimers[PS_newpos]);
473 
474  {
475  ScopedTimer copy_scope(p_leader.myTimers[PS_mw_copy]);
476  const auto coords_list(extractCoordsRefList(p_list));
477  p_leader.coordinates_->mw_copyActivePos(coords_list, iat, new_positions);
478  }
479 
480  {
481  ScopedTimer dt_scope(p_leader.myTimers[PS_dt_move]);
482  const int dist_tables_size = p_leader.DistTables.size();
483  for (int i = 0; i < dist_tables_size; ++i)
484  {
485  const auto dt_list(extractDTRefList(p_list, i));
486  p_leader.DistTables[i]->mw_move(dt_list, p_list, new_positions, iat, maybe_accept);
487  }
488 
489  // DistTables mw_move calls are asynchronous. Wait for them before return.
490  PRAGMA_OFFLOAD("omp taskwait")
491  }
492 }
493 
494 
495 bool ParticleSet::makeMoveAllParticles(const Walker_t& awalker, const ParticlePos& deltaR, RealType dt)
496 {
497  active_ptcl_ = -1;
500  {
501  for (int iat = 0; iat < deltaR.size(); ++iat)
502  {
503  SingleParticlePos displ(dt * deltaR[iat]);
504  if (Lattice.outOfBound(Lattice.toUnit(displ)))
505  return false;
506  SingleParticlePos newpos(awalker.R[iat] + displ);
507  if (!Lattice.isValid(Lattice.toUnit(newpos)))
508  return false;
509  R[iat] = newpos;
510  }
511  }
512  else
513  {
514  for (int iat = 0; iat < deltaR.size(); ++iat)
515  R[iat] = awalker.R[iat] + dt * deltaR[iat];
516  }
517  coordinates_->setAllParticlePos(R);
518  for (int i = 0; i < DistTables.size(); i++)
519  DistTables[i]->evaluate(*this);
520  if (structure_factor_)
521  structure_factor_->updateAllPart(*this);
522  //every move is valid
523  return true;
524 }
525 
527  const ParticlePos& deltaR,
528  const std::vector<RealType>& dt)
529 {
530  active_ptcl_ = -1;
533  {
534  for (int iat = 0; iat < deltaR.size(); ++iat)
535  {
536  SingleParticlePos displ(dt[iat] * deltaR[iat]);
537  if (Lattice.outOfBound(Lattice.toUnit(displ)))
538  return false;
539  SingleParticlePos newpos(awalker.R[iat] + displ);
540  if (!Lattice.isValid(Lattice.toUnit(newpos)))
541  return false;
542  R[iat] = newpos;
543  }
544  }
545  else
546  {
547  for (int iat = 0; iat < deltaR.size(); ++iat)
548  R[iat] = awalker.R[iat] + dt[iat] * deltaR[iat];
549  }
550  coordinates_->setAllParticlePos(R);
551  for (int i = 0; i < DistTables.size(); i++)
552  DistTables[i]->evaluate(*this);
553  if (structure_factor_)
554  structure_factor_->updateAllPart(*this);
555  //every move is valid
556  return true;
557 }
558 
559 /** move a walker by dt*deltaR + drift
560  * @param awalker initial walker configuration
561  * @param drift drift vector
562  * @param deltaR random displacement
563  * @param dt timestep
564  * @return true, if all the particle moves are legal under the boundary conditions
565  */
567  const ParticlePos& drift,
568  const ParticlePos& deltaR,
569  RealType dt)
570 {
571  active_ptcl_ = -1;
574  {
575  for (int iat = 0; iat < deltaR.size(); ++iat)
576  {
577  SingleParticlePos displ(dt * deltaR[iat] + drift[iat]);
578  if (Lattice.outOfBound(Lattice.toUnit(displ)))
579  return false;
580  SingleParticlePos newpos(awalker.R[iat] + displ);
581  if (!Lattice.isValid(Lattice.toUnit(newpos)))
582  return false;
583  R[iat] = newpos;
584  }
585  }
586  else
587  {
588  for (int iat = 0; iat < deltaR.size(); ++iat)
589  R[iat] = awalker.R[iat] + dt * deltaR[iat] + drift[iat];
590  }
591  coordinates_->setAllParticlePos(R);
592  for (int i = 0; i < DistTables.size(); i++)
593  DistTables[i]->evaluate(*this);
594  if (structure_factor_)
595  structure_factor_->updateAllPart(*this);
596  //every move is valid
597  return true;
598 }
599 
601  const ParticlePos& drift,
602  const ParticlePos& deltaR,
603  const std::vector<RealType>& dt)
604 {
605  active_ptcl_ = -1;
608  {
609  for (int iat = 0; iat < deltaR.size(); ++iat)
610  {
611  SingleParticlePos displ(dt[iat] * deltaR[iat] + drift[iat]);
612  if (Lattice.outOfBound(Lattice.toUnit(displ)))
613  return false;
614  SingleParticlePos newpos(awalker.R[iat] + displ);
615  if (!Lattice.isValid(Lattice.toUnit(newpos)))
616  return false;
617  R[iat] = newpos;
618  }
619  }
620  else
621  {
622  for (int iat = 0; iat < deltaR.size(); ++iat)
623  R[iat] = awalker.R[iat] + dt[iat] * deltaR[iat] + drift[iat];
624  }
625  coordinates_->setAllParticlePos(R);
626 
627  for (int i = 0; i < DistTables.size(); i++)
628  DistTables[i]->evaluate(*this);
629  if (structure_factor_)
630  structure_factor_->updateAllPart(*this);
631  //every move is valid
632  return true;
633 }
634 
635 /** update the particle attribute by the proposed move
636  *
637  * When the active_ptcl_ is equal to iat, overwrite the position and update the
638  * content of the distance tables.
639  */
640 void ParticleSet::acceptMove(Index_t iat)
641 {
642 #ifndef NDEBUG
643  if (iat != active_ptcl_)
644  throw std::runtime_error("Bug detected by acceptMove! Request electron is not active!");
645 #endif
646  ScopedTimer update_scope(myTimers[PS_accept]);
647  //Update position + distance-table
648  coordinates_->setOneParticlePos(active_pos_, iat);
649  for (int i = 0; i < DistTables.size(); i++)
650  DistTables[i]->update(iat);
651 
652  R[iat] = active_pos_;
653  spins[iat] = active_spin_val_;
654  active_ptcl_ = -1;
655 }
656 
658 {
659  assert(iat == active_ptcl_);
660  ScopedTimer update_scope(myTimers[PS_accept]);
661  //Update position + distance-table
662  coordinates_->setOneParticlePos(active_pos_, iat);
663  for (int i = 0; i < DistTables.size(); i++)
664  DistTables[i]->updatePartial(iat, true);
665 
666  R[iat] = active_pos_;
667  spins[iat] = active_spin_val_;
668  active_ptcl_ = -1;
669 }
670 
671 void ParticleSet::accept_rejectMove(Index_t iat, bool accepted, bool forward_mode)
672 {
673  if (forward_mode)
674  if (accepted)
676  else
678  else if (accepted)
679  acceptMove(iat);
680  else
681  rejectMove(iat);
682 }
683 
684 void ParticleSet::rejectMove(Index_t iat)
685 {
686 #ifndef NDEBUG
687  if (iat != active_ptcl_)
688  throw std::runtime_error("Bug detected by rejectMove! Request electron is not active!");
689 #endif
690  active_ptcl_ = -1;
691 }
692 
694 {
695  assert(iat == active_ptcl_);
696  //Update distance-table
697  for (int i = 0; i < DistTables.size(); i++)
698  DistTables[i]->updatePartial(iat, false);
699  active_ptcl_ = -1;
700 }
701 
702 template<CoordsType CT>
704  Index_t iat,
705  const std::vector<bool>& isAccepted,
706  bool forward_mode)
707 {
708  if constexpr (CT == CoordsType::POS_SPIN)
709  mw_accept_rejectSpinMove(p_list, iat, isAccepted);
710  mw_accept_rejectMove(p_list, iat, isAccepted, forward_mode);
711 }
712 
713 
715  Index_t iat,
716  const std::vector<bool>& isAccepted,
717  bool forward_mode)
718 {
719  if (forward_mode)
720  {
721  ParticleSet& p_leader = p_list.getLeader();
722  ScopedTimer update_scope(p_leader.myTimers[PS_accept]);
723 
724  const auto coords_list(extractCoordsRefList(p_list));
725  std::vector<SingleParticlePos> new_positions;
726  new_positions.reserve(p_list.size());
727  for (const ParticleSet& pset : p_list)
728  new_positions.push_back(pset.active_pos_);
729  p_leader.coordinates_->mw_acceptParticlePos(coords_list, iat, new_positions, isAccepted);
730 
731  auto& dts = p_leader.DistTables;
732  for (int i = 0; i < dts.size(); ++i)
733  {
734  const auto dt_list(extractDTRefList(p_list, i));
735  dts[i]->mw_updatePartial(dt_list, iat, isAccepted);
736  }
737 
738  for (int iw = 0; iw < p_list.size(); iw++)
739  {
740  assert(iat == p_list[iw].active_ptcl_);
741  if (isAccepted[iw])
742  p_list[iw].R[iat] = p_list[iw].active_pos_;
743  p_list[iw].active_ptcl_ = -1;
744  assert(p_list[iw].R[iat] == p_list[iw].coordinates_->getAllParticlePos()[iat]);
745  }
746  }
747  else
748  {
749  // loop over single walker acceptMove/rejectMove doesn't work safely.
750  // need to code carefully for both coordinate and distance table updates
751  // disable non-forward mode cases
752  if (!forward_mode)
753  throw std::runtime_error("BUG calling mw_accept_rejectMove in non-forward mode");
754  }
755 }
756 
758  Index_t iat,
759  const std::vector<bool>& isAccepted)
760 {
761  for (int iw = 0; iw < p_list.size(); iw++)
762  {
763  assert(iat == p_list[iw].active_ptcl_);
764  if (isAccepted[iw])
765  p_list[iw].spins[iat] = p_list[iw].active_spin_val_;
766  }
767 }
768 
769 void ParticleSet::donePbyP(bool skipSK)
770 {
771  ScopedTimer donePbyP_scope(myTimers[PS_donePbyP]);
772  coordinates_->donePbyP();
773  if (!skipSK && structure_factor_)
774  structure_factor_->updateAllPart(*this);
775  for (size_t i = 0; i < DistTables.size(); ++i)
776  DistTables[i]->finalizePbyP(*this);
777  active_ptcl_ = -1;
778 }
779 
781 {
782  ParticleSet& p_leader = p_list.getLeader();
783  ScopedTimer donePbyP_scope(p_leader.myTimers[PS_donePbyP]);
784 
785  for (ParticleSet& pset : p_list)
786  {
787  pset.coordinates_->donePbyP();
788  pset.active_ptcl_ = -1;
789  }
790 
791  if (!skipSK && p_leader.structure_factor_)
792  {
793  auto sk_list = extractSKRefList(p_list);
795  }
796 
797  auto& dts = p_leader.DistTables;
798  for (int i = 0; i < dts.size(); ++i)
799  {
800  const auto dt_list(extractDTRefList(p_list, i));
801  dts[i]->mw_finalizePbyP(dt_list, p_list);
802  }
803 }
804 
806 {
807  active_ptcl_ = -1;
808  active_pos_ = newpos;
809  for (size_t i = 0; i < DistTables.size(); ++i)
810  DistTables[i]->move(*this, newpos, active_ptcl_, false);
811 }
812 
813 void ParticleSet::loadWalker(Walker_t& awalker, bool pbyp)
814 {
815  ScopedTimer update_scope(myTimers[PS_loadWalker]);
816  R = awalker.R;
817  spins = awalker.spins;
818  coordinates_->setAllParticlePos(R);
819 #if !defined(SOA_MEMORY_OPTIMIZED)
820  G = awalker.G;
821  L = awalker.L;
822 #endif
823  if (pbyp)
824  {
825  // in certain cases, full tables must be ready
826  for (int i = 0; i < DistTables.size(); i++)
827  if (DistTables[i]->getModes() & DTModes::NEED_FULL_TABLE_ANYTIME)
828  DistTables[i]->evaluate(*this);
829  }
830 
831  active_ptcl_ = -1;
832 }
833 
836  const std::vector<bool>& recompute,
837  bool pbyp)
838 {
839  auto& p_leader = p_list.getLeader();
840  ScopedTimer load_scope(p_leader.myTimers[PS_loadWalker]);
841 
842  auto loadWalkerConfig = [](ParticleSet& pset, Walker_t& awalker) {
843  pset.R = awalker.R;
844  pset.spins = awalker.spins;
845  pset.coordinates_->setAllParticlePos(pset.R);
846  };
847  for (int iw = 0; iw < p_list.size(); ++iw)
848  if (recompute[iw])
849  loadWalkerConfig(p_list[iw], walkers[iw]);
850 
851  if (pbyp)
852  {
853  auto& dts = p_leader.DistTables;
854  for (int i = 0; i < dts.size(); ++i)
855  {
856  const auto dt_list(extractDTRefList(p_list, i));
857  dts[i]->mw_recompute(dt_list, p_list, recompute);
858  }
859  }
860 }
861 
863 {
864  awalker.R = R;
865  awalker.spins = spins;
866 #if !defined(SOA_MEMORY_OPTIMIZED)
867  awalker.G = G;
868  awalker.L = L;
869 #endif
870 }
871 
873 {
874  for (int iw = 0; iw < psets.size(); ++iw)
875  psets[iw].saveWalker(walkers[iw]);
876 }
877 
878 
880 {
882  //Need to add the default Properties according to the enumeration
883  PropertyList.add("LogPsi");
884  PropertyList.add("SignPsi");
885  PropertyList.add("UmbrellaWeight");
886  PropertyList.add("R2Accepted");
887  PropertyList.add("R2Proposed");
888  PropertyList.add("DriftScale");
889  PropertyList.add("AltEnergy");
890  PropertyList.add("LocalEnergy");
891  PropertyList.add("LocalPotential");
892 
893  // There is no point in checking this, its quickly not consistent as other objects update property list.
894  // if (PropertyList.size() != WP::NUMPROPERTIES)
895  // {
896  // app_error() << "The number of default properties for walkers is not consistent." << std::endl;
897  // app_error() << "NUMPROPERTIES " << WP::NUMPROPERTIES << " size of PropertyList " << PropertyList.size() << std::endl;
898  // throw std::runtime_error("ParticleSet::initPropertyList");
899  // }
900 }
901 
903 {
904  int newL = PropertyHistory.size();
905  PropertyHistory.push_back(std::vector<FullPrecRealType>(leng, 0.0));
906  PHindex.push_back(0);
907  return newL;
908 }
909 
910 // void ParticleSet::resetPropertyHistory( )
911 // {
912 // for(int i=0;i<PropertyHistory.size();i++)
913 // {
914 // PHindex[i]=0;
915 // for(int k=0;k<PropertyHistory[i].size();k++)
916 // {
917 // PropertyHistory[i][k]=0.0;
918 // }
919 // }
920 // }
921 
922 // void ParticleSet::addPropertyHistoryPoint(int index, RealType data)
923 // {
924 // PropertyHistory[index][PHindex[index]]=(data);
925 // PHindex[index]++;
926 // if (PHindex[index]==PropertyHistory[index].size()) PHindex[index]=0;
927 // // PropertyHistory[index].pop_back();
928 // }
929 
930 // void ParticleSet::rejectedMove()
931 // {
932 // for(int dindex=0;dindex<PropertyHistory.size();dindex++){
933 // int lastIndex=PHindex[dindex]-1;
934 // if (lastIndex<0) lastIndex+=PropertyHistory[dindex].size();
935 // PropertyHistory[dindex][PHindex[dindex]]=PropertyHistory[dindex][lastIndex];
936 // PHindex[dindex]++;
937 // if (PHindex[dindex]==PropertyHistory[dindex].size()) PHindex[dindex]=0;
938 // // PropertyHistory[dindex].push_front(PropertyHistory[dindex].front());
939 // // PropertyHistory[dindex].pop_back();
940 // }
941 // }
942 
943 
945 {
946  coordinates_->createResource(collection);
947  for (int i = 0; i < DistTables.size(); i++)
948  DistTables[i]->createResource(collection);
949  if (structure_factor_)
950  collection.addResource(std::make_unique<SKMultiWalkerMem>());
951 }
952 
954 {
955  auto& ps_leader = p_list.getLeader();
956  ps_leader.coordinates_->acquireResource(collection, extractCoordsRefList(p_list));
957  for (int i = 0; i < ps_leader.DistTables.size(); i++)
958  ps_leader.DistTables[i]->acquireResource(collection, extractDTRefList(p_list, i));
959 
960  if (ps_leader.structure_factor_)
961  p_list.getLeader().mw_structure_factor_data_handle_ = collection.lendResource<SKMultiWalkerMem>();
962 }
963 
965 {
966  auto& ps_leader = p_list.getLeader();
967  ps_leader.coordinates_->releaseResource(collection, extractCoordsRefList(p_list));
968  for (int i = 0; i < ps_leader.DistTables.size(); i++)
969  ps_leader.DistTables[i]->releaseResource(collection, extractDTRefList(p_list, i));
970 
971  if (ps_leader.structure_factor_)
972  collection.takebackResource(p_list.getLeader().mw_structure_factor_data_handle_);
973 }
974 
976 {
977  RefVectorWithLeader<DistanceTable> dt_list(*p_list.getLeader().DistTables[id]);
978  dt_list.reserve(p_list.size());
979  for (ParticleSet& p : p_list)
980  dt_list.push_back(*p.DistTables[id]);
981  return dt_list;
982 }
983 
985  const RefVectorWithLeader<ParticleSet>& p_list)
986 {
987  RefVectorWithLeader<DynamicCoordinates> coords_list(*p_list.getLeader().coordinates_);
988  coords_list.reserve(p_list.size());
989  for (ParticleSet& p : p_list)
990  coords_list.push_back(*p.coordinates_);
991  return coords_list;
992 }
993 
995 {
996  RefVectorWithLeader<StructFact> sk_list(*p_list.getLeader().structure_factor_);
997  sk_list.reserve(p_list.size());
998  for (ParticleSet& p : p_list)
999  sk_list.push_back(*p.structure_factor_);
1000  return sk_list;
1001 }
1002 
1003 //explicit instantiations
1004 template void ParticleSet::mw_makeMove<CoordsType::POS>(const RefVectorWithLeader<ParticleSet>& p_list,
1005  Index_t iat,
1006  const MCCoords<CoordsType::POS>& displs);
1007 template void ParticleSet::mw_makeMove<CoordsType::POS_SPIN>(const RefVectorWithLeader<ParticleSet>& p_list,
1008  Index_t iat,
1009  const MCCoords<CoordsType::POS_SPIN>& displs);
1010 template void ParticleSet::mw_accept_rejectMove<CoordsType::POS>(const RefVectorWithLeader<ParticleSet>& p_list,
1011  Index_t iat,
1012  const std::vector<bool>& isAccepted,
1013  bool forward_mode);
1014 template void ParticleSet::mw_accept_rejectMove<CoordsType::POS_SPIN>(const RefVectorWithLeader<ParticleSet>& p_list,
1015  Index_t iat,
1016  const std::vector<bool>& isAccepted,
1017  bool forward_mode);
1018 } // namespace qmcplusplus
multi walker shared memory buffer
Definition: StructFact.h:111
a class that defines a supercell in D-dimensional Euclean space.
int numAttributes() const
return the number of attributes in our list
Definition: SpeciesSet.h:59
DynamicCoordinateKind
enumerator for DynamicCoordinates kinds
bool isValid(const TinyVector< T, D > &u) const
return true if all the open direction of reduced coordinates u are in the range [0,1)
ResourceHandle< SKMultiWalkerMem > mw_structure_factor_data_handle_
multi walker structure factor data
Definition: ParticleSet.h:620
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
void acceptMoveForwardMode(Index_t iat)
actual implemenation for accepting a proposed move in forward mode
quantum_domains quantum_domain
quantum_domain of the particles, default = classical
Definition: ParticleSet.h:73
const std::string & getName() const
return the name
static void mw_makeMove(const RefVectorWithLeader< ParticleSet > &p_list, int iat, const MCCoords< CT > &displs)
batched version of makeMove
size_t addResource(std::unique_ptr< Resource > &&res, bool noprint=false)
void takebackResource(ResourceHandle< RS > &res_handle)
Index_t active_ptcl_
the index of the active particle during particle-by-particle moves
Definition: ParticleSet.h:599
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
const DistanceTableAA & getDistTableAA(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAA
static void mw_accept_rejectSpinMove(const RefVectorWithLeader< ParticleSet > &p_list, Index_t iat, const std::vector< bool > &isAccepted)
batched version of acceptMove and reject Move fused, but only for spins
ParticleScalar spins
internal spin variables for dynamical spin calculations
Definition: ParticleSet.h:81
std::string myName
the name of the node, corresponds to the xml tag
std::vector< TimerIDName_t< T > > TimerNameList_t
Definition: TimerManager.h:156
std::unique_ptr< DynamicCoordinates > createDynamicCoordinates(const DynamicCoordinateKind kind)
create DynamicCoordinates based on kind
PosUnit InUnit
The unit type.
#define app_debug
Definition: OutputManager.h:75
size_t getTotalNum() const
Definition: ParticleSet.h:493
std::ostream & app_log()
Definition: OutputManager.h:65
size_t TotalNum
total number of particles
Definition: ParticleSet.h:642
static void mw_makeSpinMove(const RefVectorWithLeader< ParticleSet > &p_list, int iat, const std::vector< Scalar_t > &sdispls)
batched version makeMove for spin variable only
static void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< ParticleSet > &p_list)
release external resource Note: use RAII ResourceCollectionTeamLock whenever possible ...
static RefVectorWithLeader< StructFact > extractSKRefList(const RefVectorWithLeader< ParticleSet > &p_list)
bool same_mass_
true if the particles have the same mass
Definition: ParticleSet.h:590
std::vector< std::vector< FullPrecRealType > > PropertyHistory
Property history vector.
Definition: ParticleSet.h:129
void createResource(ResourceCollection &collection) const
initialize a shared resource and hand it to a collection
int first(int igroup) const
return the first index of a group i
Definition: ParticleSet.h:514
const char walkers[]
Definition: HDFVersion.h:36
void update(bool skipSK=false)
update the internal data
ParticleLaplacian L
laplacians of the particles
Definition: ParticleSet.h:85
static RefVectorWithLeader< DistanceTable > extractDTRefList(const RefVectorWithLeader< ParticleSet > &p_list, int id)
static void mw_saveWalker(const RefVectorWithLeader< ParticleSet > &psets, const RefVector< Walker_t > &walkers)
batched version of saveWalker
static void mw_accept_rejectMove(const RefVectorWithLeader< ParticleSet > &p_list, Index_t iat, const std::vector< bool > &isAccepted, bool forward_mode=true)
batched version of acceptMove and rejectMove fused, templated on CoordsType
int addAttribute(const std::string &aname)
for a new attribute, allocate the data, !More often used to get the index of a species ...
Definition: SpeciesSet.cpp:45
SingleParticlePos myTwist
Definition: ParticleSet.h:637
Scalar_t active_spin_val_
the proposed spin of active_ptcl_ during particle-by-particle moves
Definition: ParticleSet.h:603
std::map< std::string, int > myDistTableMap
map to handle distance tables
Definition: ParticleSet.h:627
T min(T a, T b)
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
void rejectMoveForwardMode(Index_t iat)
reject a proposed move in forward mode
PropertySetType PropertyList
name-value map of Walker Properties
Definition: ParticleSet.h:112
int getTotalNum() const
return the number of species
Definition: SpeciesSet.h:55
static const TimerNameList_t< PSetTimers > generatePSetTimerNames(std::string &obj_name)
Definition: ParticleSet.cpp:47
static void mw_updateAllPart(const RefVectorWithLeader< StructFact > &sk_list, const RefVectorWithLeader< ParticleSet > &p_list, SKMultiWalkerMem &mw_mem)
Update RhoK for all particles for multiple walkers particles.
Definition: StructFact.cpp:63
const DistanceTableAB & getDistTableAB(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAB
std::unique_ptr< StructFact > structure_factor_
Structure factor.
Definition: ParticleSet.h:617
std::vector< std::string > Names
ParticleScalar spins
Definition: Walker.h:117
ParticleSet(const SimulationCell &simulation_cell, const DynamicCoordinateKind kind=DynamicCoordinateKind::DC_POS)
default constructor
Definition: ParticleSet.cpp:58
int addTable(const ParticleSet &psrc, DTModes modes=DTModes::ALL_OFF)
add a distance table
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
size_type size() const
return the current size
Definition: OhmmsVector.h:162
const Lattice & getLattice() const
int add(const std::string &aname)
void makeGaussRandom(std::vector< TinyVector< T, D >> &a)
AB type of DistanceTable containing storage.
void rejectMove(Index_t iat)
reject a proposed move in regular mode
void resize(size_t numPtcl)
resize internal storage
Definition: ParticleSet.h:683
ParticleGradient G
gradients of the particles
Definition: ParticleSet.h:83
bool makeMoveAndCheckWithSpin(Index_t iat, const SingleParticlePos &displ, const Scalar_t &sdispl)
makeMoveAndCheck, but now includes an update to the spin variable
static void mw_computeNewPosDistTables(const RefVectorWithLeader< ParticleSet > &p_list, Index_t iat, const std::vector< SingleParticlePos > &new_positions, bool maybe_accept=true)
compute temporal DistTables and SK for a new particle position for each walker in a batch ...
void saveWalker(Walker_t &awalker)
save this to awalker
std::vector< int > PHindex
Definition: ParticleSet.h:130
int groupsize(int igroup) const
return the size of a group
Definition: ParticleSet.h:527
void accept_rejectMove(Index_t iat, bool accepted, bool forward_mode=true)
accept or reject a proposed move Two operation modes: The using and updating distance tables via Part...
void reset() override
dummy. For satisfying OhmmsElementBase.
int addPropertyHistory(int leng)
void makeMoveWithSpin(Index_t iat, const SingleParticlePos &displ, const Scalar_t &sdispl)
makeMove, but now includes an update to the spin variable
ParticlePos R
Position.
Definition: ParticleSet.h:79
SingleParticlePos toUnit(const TinyVector< T1, D > &r) const
Convert a cartesian vector to a unit vector.
std::vector< std::string > distTableDescriptions
Descriptions from distance table creation. Same order as DistTables.
Definition: ParticleSet.h:633
OMPallocator is an allocator with fused device and dualspace allocator functionality.
bool is_spinor_
true is a dynamic spin calculation
Definition: ParticleSet.h:592
ParticleScalar Z
charge of each particle
Definition: ParticleSet.h:89
AA type of DistanceTable containing storage.
void loadWalker(Walker_t &awalker, bool pbyp)
load a Walker_t to the current ParticleSet
void computeNewPosDistTables(Index_t iat, const SingleParticlePos &newpos, bool maybe_accept=true)
compute temporal DistTables and SK for a new particle position
Buffer_t Collectables
observables in addition to those registered in Properties/PropertyList
Definition: ParticleSet.h:126
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
void create(const std::vector< int > &agroup)
create grouped particles
static void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< ParticleSet > &p_list)
acquire external resource and assocaite it with the list of ParticleSet Note: use RAII ResourceCollec...
std::vector< std::string > speciesName
Species name list.
Definition: SpeciesSet.h:44
std::unique_ptr< DynamicCoordinates > coordinates_
internal representation of R. It can be an SoA copy of R
Definition: ParticleSet.h:648
std::vector< std::reference_wrapper< T > > RefVector
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
std::shared_ptr< Vector< int, OMPallocator< int > > > group_offsets_
array to handle a group of distinct particles per species
Definition: ParticleSet.h:645
std::unique_ptr< DistanceTable > createDistanceTable(ParticleSet &s, std::ostream &description)
whether full table needs to be ready at anytime or not during PbyP Optimization can be implemented du...
SpeciesSet my_species_
SpeciesSet of particles.
Definition: ParticleSet.h:614
void print(std::ostream &os, const size_t maxParticlesToPrint=0) const
print particle coordinates to a std::ostream
~ParticleSet() override
default destructor
bool quantumDomainValid() const
check whether quantum domain is valid for particles
Definition: ParticleSet.h:179
void makeMove(Index_t iat, const SingleParticlePos &displ, bool maybe_accept=true)
move the iat-th particle to active_pos_
ParticleScalar Mass
mass of each particle
Definition: ParticleSet.h:87
static RefVectorWithLeader< DynamicCoordinates > extractCoordsRefList(const RefVectorWithLeader< ParticleSet > &p_list)
SingleParticlePos active_pos_
the proposed position of active_ptcl_ during particle-by-particle moves
Definition: ParticleSet.h:601
Indexes
an enum denoting index of physical properties
static void mw_update(const RefVectorWithLeader< ParticleSet > &p_list, bool skipSK=false)
batched version of update
static void mw_donePbyP(const RefVectorWithLeader< ParticleSet > &p_list, bool skipSK=false)
batched version of donePbyP
bool put(std::istream &) override
dummy. For satisfying OhmmsElementBase.
bool makeMoveAllParticlesWithDrift(const Walker_t &awalker, const ParticlePos &drift, const ParticlePos &deltaR, RealType dt)
move all the particles including the drift
bool makeMoveAndCheck(Index_t iat, const SingleParticlePos &displ)
move the iat-th particle to active_pos_
bool outOfBound(const TinyVector< T, D > &u) const
return true if any direction of reduced coordinates u goes larger than 0.5
void setQuantumDomain(quantum_domains qdomain)
specify quantum_domain of particles
TimerManager< NewTimer > & getGlobalTimerManager()
ResourceHandle< RS > lendResource()
void randomizeFromSource(ParticleSet &src)
Initialize particles around another ParticleSet Used to initialize an electron ParticleSet by an ion ...
bool explicitly_defined
true, the lattice is defined by the input instead of an artificial default
Custom container for set of attributes for a set of species.
Definition: SpeciesSet.h:33
void evaluate(Matrix< T, Alloc > &lhs, const Op &op, const Expression< RHS > &rhs)
Definition: OhmmsMatrix.h:514
static void mw_loadWalker(const RefVectorWithLeader< ParticleSet > &p_list, const RefVector< Walker_t > &walkers, const std::vector< bool > &recompute, bool pbyp)
batched version of loadWalker
std::vector< std::unique_ptr< DistanceTable > > DistTables
distance tables that need to be updated by moving this ParticleSet
Definition: ParticleSet.h:630
bool get(std::ostream &os) const override
dummy. For satisfying OhmmsElementBase.
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
Declare a global Random Number Generator.
bool makeMoveAllParticles(const Walker_t &awalker, const ParticlePos &deltaR, RealType dt)
move all the particles of a walker
A container class to represent a walker.
Definition: Walker.h:49
const SimulationCell & simulation_cell_
reference to global simulation cell
Definition: ParticleSet.h:587
void donePbyP(bool skipSK=false)
update structure factor and unmark active_ptcl_
void makeVirtualMoves(const SingleParticlePos &newpos)
Handles virtual moves for all the particles to a single newpos.
ParticleLaplacian L
^2_i d for the i-th particle
Definition: Walker.h:122
ParticlePos R
The configuration vector (3N-dimensional vector to store the positions of all the particles for a sin...
Definition: Walker.h:114
std::vector< T > Values