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: D. Das, University of Illinois at Urbana-Champaign 8 // Bryan Clark, bclark@Princeton.edu, Princeton University 9 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign 10 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign 11 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign 12 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory 13 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory 14 // 15 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign 16 ////////////////////////////////////////////////////////////////////////////////////// 17 18 19 #ifndef QMCPLUSPLUS_PARTICLESET_H 20 #define QMCPLUSPLUS_PARTICLESET_H 21 22 #include <Configuration.h> 23 #include "ParticleTags.h" 24 #include "DynamicCoordinates.h" 25 #include "Walker.h" 26 #include "Utilities/SpeciesSet.h" 27 #include "Utilities/PooledData.h" 28 #include "OhmmsPETE/OhmmsArray.h" 29 #include "Utilities/TimerManager.h" 30 #include "OhmmsSoA/VectorSoaContainer.h" 31 #include "type_traits/template_types.hpp" 32 33 namespace qmcplusplus 34 { 35 ///forward declaration of DistanceTableData 36 class DistanceTableData; 37 class ResourceCollection; 38 class StructFact; 39 40 /** Specialized paritlce class for atomistic simulations 41 * 42 * Derived from QMCTraits, ParticleBase<PtclOnLatticeTraits> and OhmmsElementBase. 43 * The ParticleLayout class represents a supercell with/without periodic boundary 44 * conditions. The ParticleLayout class also takes care of spatial decompositions 45 * for efficient evaluations for the interactions with a finite cutoff. 46 */ 47 class ParticleSet : public QMCTraits, public OhmmsElementBase, public PtclOnLatticeTraits 48 { 49 public: 50 /// walker type 51 typedef Walker<QMCTraits, PtclOnLatticeTraits> Walker_t; 52 /// container type to store the property 53 typedef Walker_t::PropertyContainer_t PropertyContainer_t; 54 /// buffer type for a serialized buffer 55 typedef PooledData<RealType> Buffer_t; 56 57 enum quantum_domains 58 { 59 no_quantum_domain = 0, 60 classical, 61 quantum 62 }; 63 64 ///quantum_domain of the particles, default = classical 65 quantum_domains quantum_domain; 66 67 //@{ public data members 68 ///ParticleLayout 69 ParticleLayout_t Lattice, PrimitiveLattice; 70 ///Long-range box 71 ParticleLayout_t LRBox; 72 73 ///unique, persistent ID for each particle 74 ParticleIndex_t ID; 75 ///index to the primitice cell with tiling 76 ParticleIndex_t PCID; 77 /** ID map that reflects species group 78 * 79 * IsGrouped=true, if ID==IndirectID 80 */ 81 ParticleIndex_t IndirectID; 82 ///Species ID 83 ParticleIndex_t GroupID; 84 ///Position 85 ParticlePos_t R; 86 ///internal spin variables for dynamical spin calculations 87 ParticleScalar_t spins; 88 ///gradients of the particles 89 ParticleGradient_t G; 90 ///laplacians of the particles 91 ParticleLaplacian_t L; 92 ///differential gradients of the particles 93 ParticleGradient_t dG; 94 ///differential laplacians of the particles 95 ParticleLaplacian_t dL; 96 ///mass of each particle 97 ParticleScalar_t Mass; 98 ///charge of each particle 99 ParticleScalar_t Z; 100 101 ///true if the particles are grouped 102 bool IsGrouped; 103 ///true if the particles have the same mass 104 bool SameMass; 105 ///threa id 106 Index_t ThreadID; 107 /** the index of the active particle during particle-by-particle moves 108 * 109 * when a single particle move is proposed, the particle id is assigned to activePtcl 110 * No matter the move is accepted or rejected, activePtcl is marked back to -1. 111 * This state flag is used for picking coordinates and distances for SPO evaluation. 112 */ 113 Index_t activePtcl; 114 ///the group of the active particle during particle-by-particle moves 115 Index_t activeGroup; 116 ///the index of the active bead for particle-by-particle moves 117 Index_t activeBead; 118 ///the direction reptile traveling 119 Index_t direction; 120 121 ///the proposed position of activePtcl during particle-by-particle moves 122 SingleParticlePos_t activePos; 123 124 ///the proposed spin of activePtcl during particle-by-particle moves 125 Scalar_t activeSpinVal; 126 127 ///the proposed position in the Lattice unit 128 SingleParticlePos_t newRedPos; 129 130 ///SpeciesSet of particles 131 SpeciesSet mySpecies; 132 133 ///Structure factor 134 std::unique_ptr<StructFact> SK; 135 136 ///Particle density in G-space for MPC interaction 137 std::vector<TinyVector<int, OHMMS_DIM>> DensityReducedGvecs; 138 std::vector<ComplexType> Density_G; 139 Array<RealType, OHMMS_DIM> Density_r; 140 141 /// DFT potential 142 std::vector<TinyVector<int, OHMMS_DIM>> VHXCReducedGvecs; 143 std::vector<ComplexType> VHXC_G[2]; 144 Array<RealType, OHMMS_DIM> VHXC_r[2]; 145 146 /** name-value map of Walker Properties 147 * 148 * PropertyMap is used to keep the name-value mapping of 149 * Walker_t::Properties. PropertyList::Values are not 150 * necessarily updated during the simulations. 151 */ 152 PropertySetType PropertyList; 153 154 /** properties of the current walker 155 * 156 * The internal order is identical to PropertyList, which holds 157 * the matching names. 158 */ 159 PropertyContainer_t Properties; 160 161 /** observables in addition to those registered in Properties/PropertyList 162 * 163 * Such observables as density, gofr, sk are not stored per walker but 164 * collected during QMC iterations. 165 */ 166 Buffer_t Collectables; 167 168 ///clones of this object: used by the thread pool 169 std::vector<ParticleSet*> myClones; 170 171 ///Property history vector 172 std::vector<std::vector<FullPrecRealType>> PropertyHistory; 173 std::vector<int> PHindex; 174 ///@} 175 176 ///current MC step 177 int current_step; 178 179 ///default constructor 180 ParticleSet(const DynamicCoordinateKind kind = DynamicCoordinateKind::DC_POS); 181 182 ///copy constructor 183 ParticleSet(const ParticleSet& p); 184 185 ///default destructor 186 virtual ~ParticleSet(); 187 188 /** create particles 189 * @param n number of particles 190 */ 191 void create(int n); 192 /** create grouped particles 193 * @param agroup number of particles per group 194 */ 195 void create(const std::vector<int>& agroup); 196 197 ///write to a std::ostream 198 bool get(std::ostream&) const; 199 200 ///read from std::istream 201 bool put(std::istream&); 202 203 ///reset member data 204 void reset(); 205 206 ///initialize ParticleSet from xmlNode 207 bool put(xmlNodePtr cur); 208 209 ///specify quantum_domain of particles 210 void set_quantum_domain(quantum_domains qdomain); 211 set_quantum()212 void set_quantum() { quantum_domain = quantum; } 213 is_classical()214 inline bool is_classical() const { return quantum_domain == classical; } 215 is_quantum()216 inline bool is_quantum() const { return quantum_domain == quantum; } 217 218 ///check whether quantum domain is valid for particles quantum_domain_valid(quantum_domains qdomain)219 inline bool quantum_domain_valid(quantum_domains qdomain) const { return qdomain != no_quantum_domain; } 220 221 ///check whether quantum domain is valid for particles quantum_domain_valid()222 inline bool quantum_domain_valid() const { return quantum_domain_valid(quantum_domain); } 223 224 /** add a distance table 225 * @param psrc source particle set 226 * @param need_full_table if true, DT is fully computed in loadWalker() and maintained up-to-date during p-by-p moving 227 * 228 * if this->myName == psrc.getName(), AA type. Otherwise, AB type. 229 */ 230 int addTable(const ParticleSet& psrc, bool need_full_table = false); 231 232 /** get a distance table by table_ID 233 */ getDistTable(int table_ID)234 inline const DistanceTableData& getDistTable(int table_ID) const { return *DistTables[table_ID]; } 235 236 /** reset all the collectable quantities during a MC iteration 237 */ resetCollectables()238 inline void resetCollectables() { std::fill(Collectables.begin(), Collectables.end(), 0.0); } 239 240 /** update the internal data 241 *@param skip SK update if skipSK is true 242 */ 243 void update(bool skipSK = false); 244 245 /// batched version of update 246 static void mw_update(const RefVectorWithLeader<ParticleSet>& p_list, bool skipSK = false); 247 248 /** create Structure Factor with PBCs 249 */ 250 void createSK(); 251 252 /** Turn on per particle storage in Structure Factor 253 */ 254 void turnOnPerParticleSK(); 255 256 ///retrun the SpeciesSet of this particle set getSpeciesSet()257 inline SpeciesSet& getSpeciesSet() { return mySpecies; } 258 ///retrun the const SpeciesSet of this particle set getSpeciesSet()259 inline const SpeciesSet& getSpeciesSet() const { return mySpecies; } 260 261 ///return parent's name parentName()262 inline const std::string& parentName() const { return ParentName; } setName(const std::string & aname)263 inline void setName(const std::string& aname) 264 { 265 myName = aname; 266 if (ParentName == "0") 267 { 268 ParentName = aname; 269 } 270 } 271 getCoordinates()272 inline const DynamicCoordinates& getCoordinates() const { return *coordinates_; } setCoordinates(const ParticlePos_t & R)273 inline void setCoordinates(const ParticlePos_t& R) { return coordinates_->setAllParticlePos(R); } 274 275 //inline RealType getTotalWeight() const { return EnsembleProperty.Weight; } 276 277 void resetGroups(); 278 279 /** return the position of the active particle 280 * 281 * activePtcl=-1 is used to flag non-physical moves 282 */ activeR(int iat)283 inline const PosType& activeR(int iat) const { return (activePtcl == iat) ? activePos : R[iat]; } activeSpin(int iat)284 inline const Scalar_t& activeSpin(int iat) const { return (activePtcl == iat) ? activeSpinVal : spins[iat]; } 285 /** move the iat-th particle to activePos 286 * @param iat the index of the particle to be moved 287 * @param displ the displacement of the iat-th particle position 288 * @param maybe_accept if false, the caller guarantees that the proposed move will not be accepted. 289 * 290 * Update activePtcl index and activePos position (R[iat]+displ) for a proposed move. 291 * Evaluate the related distance table data DistanceTableData::Temp. 292 * If maybe_accept = false, certain operations for accepting moves will be skipped for optimal performance. 293 */ 294 void makeMove(Index_t iat, const SingleParticlePos_t& displ, bool maybe_accept = true); 295 /// makeMove, but now includes an update to the spin variable 296 void makeMoveWithSpin(Index_t iat, const SingleParticlePos_t& displ, const Scalar_t& sdispl); 297 298 /// batched version of makeMove 299 static void mw_makeMove(const RefVectorWithLeader<ParticleSet>& p_list, 300 int iat, 301 const std::vector<SingleParticlePos_t>& displs); 302 303 /** move the iat-th particle to activePos 304 * @param iat the index of the particle to be moved 305 * @param displ random displacement of the iat-th particle 306 * @return true, if the move is valid 307 * 308 * Update activePtcl index and activePos position (R[iat]+displ) for a proposed move. 309 * Evaluate the related distance table data DistanceTableData::Temp. 310 * 311 * When a Lattice is defined, passing two checks makes a move valid. 312 * outOfBound(displ): invalid move, if displ is larger than half, currently, of the box in any direction 313 * isValid(Lattice.toUnit(activePos)): invalid move, if activePos goes out of the Lattice in any direction marked with open BC. 314 * Note: activePos and distances tables are always evaluated no matter the move is valid or not. 315 */ 316 bool makeMoveAndCheck(Index_t iat, const SingleParticlePos_t& displ); 317 /// makeMoveAndCheck, but now includes an update to the spin variable 318 bool makeMoveAndCheckWithSpin(Index_t iat, const SingleParticlePos_t& displ, const Scalar_t& sdispl); 319 320 /** Handles virtual moves for all the particles to a single newpos. 321 * 322 * The state activePtcl remains -1 and rejectMove is not needed. 323 * acceptMove can not be used. 324 * See QMCHamiltonians::MomentumEstimator as an example 325 */ 326 void makeVirtualMoves(const SingleParticlePos_t& newpos); 327 328 /** move all the particles of a walker 329 * @param awalker the walker to operate 330 * @param deltaR proposed displacement 331 * @param dt factor of deltaR 332 * @return true if all the moves are legal. 333 * 334 * If big displacements or illegal positions are detected, return false. 335 * If all good, R = awalker.R + dt* deltaR 336 */ 337 bool makeMoveAllParticles(const Walker_t& awalker, const ParticlePos_t& deltaR, RealType dt); 338 339 bool makeMoveAllParticles(const Walker_t& awalker, const ParticlePos_t& deltaR, const std::vector<RealType>& dt); 340 /** move all the particles including the drift 341 * 342 * Otherwise, everything is the same as makeMove for a walker 343 */ 344 bool makeMoveAllParticlesWithDrift(const Walker_t& awalker, 345 const ParticlePos_t& drift, 346 const ParticlePos_t& deltaR, 347 RealType dt); 348 349 bool makeMoveAllParticlesWithDrift(const Walker_t& awalker, 350 const ParticlePos_t& drift, 351 const ParticlePos_t& deltaR, 352 const std::vector<RealType>& dt); 353 354 /** accept or reject a proposed move 355 * Two operation modes: 356 * The using and updating distance tables via `ParticleSet` operate in two modes, regular and forward modes. 357 * 358 * Regular mode 359 * The regular mode can only be used when the distance tables for particle pairs are fully up-to-date. 360 * This is the case after calling `ParticleSet::update()` in a unit test or after p-by-p moves in a QMC driver. 361 * In this mode, the distance tables remain up-to-date after calling `ParticleSet::acceptMove` 362 * and calling `ParticleSet::rejectMove` is not mandatory. 363 * 364 * Forward mode 365 * The forward mode assumes that distance table is not fully up-to-date until every particle is accepted 366 * or rejected to move once in order. This is the mode used in the p-by-p part of drivers. 367 * In this mode, calling `ParticleSet::accept_rejectMove` is required to handle accept/reject rather than 368 * calling individual `ParticleSet::acceptMove` and `ParticleSet::reject`. 369 * `ParticleSet::accept_rejectMove(iel)` ensures the distance tables (jel < iel) part is fully up-to-date 370 * regardless a move is accepted or rejected. For this reason, the rejecting operation inside 371 * `ParticleSet::accept_rejectMove` involves writing the distances with respect to the old particle position. 372 */ 373 void accept_rejectMove(Index_t iat, bool accepted, bool forward_mode = true); 374 375 /** accept the move and update the particle attribute by the proposed move in regular mode 376 *@param iat the index of the particle whose position and other attributes to be updated 377 */ 378 void acceptMove(Index_t iat); 379 380 /** reject a proposed move in regular mode 381 * @param iat the electron whose proposed move gets rejected. 382 */ 383 void rejectMove(Index_t iat); 384 /// batched version of acceptMove and rejectMove fused 385 static void mw_accept_rejectMove(const RefVectorWithLeader<ParticleSet>& p_list, 386 Index_t iat, 387 const std::vector<bool>& isAccepted, 388 bool forward_mode = true); 389 390 void initPropertyList(); addProperty(const std::string & pname)391 inline int addProperty(const std::string& pname) { return PropertyList.add(pname.c_str()); } 392 393 int addPropertyHistory(int leng); 394 // void rejectedMove(); 395 // void resetPropertyHistory( ); 396 // void addPropertyHistoryPoint(int index, RealType data); 397 398 void clearDistanceTables(); 399 400 void convert(const ParticlePos_t& pin, ParticlePos_t& pout); 401 void convert2Unit(const ParticlePos_t& pin, ParticlePos_t& pout); 402 void convert2Cart(const ParticlePos_t& pin, ParticlePos_t& pout); 403 void convert2Unit(ParticlePos_t& pout); 404 void convert2Cart(ParticlePos_t& pout); 405 void convert2UnitInBox(const ParticlePos_t& pint, ParticlePos_t& pout); 406 void convert2CartInBox(const ParticlePos_t& pint, ParticlePos_t& pout); 407 408 void applyBC(const ParticlePos_t& pin, ParticlePos_t& pout); 409 void applyBC(ParticlePos_t& pos); 410 void applyBC(const ParticlePos_t& pin, ParticlePos_t& pout, int first, int last); 411 void applyMinimumImage(ParticlePos_t& pinout); 412 413 /** load a Walker_t to the current ParticleSet 414 * @param awalker the reference to the walker to be loaded 415 * @param pbyp true if it is used by PbyP update 416 * 417 * PbyP requires the distance tables and Sk with awalker.R 418 */ 419 void loadWalker(Walker_t& awalker, bool pbyp); 420 /** batched version of loadWalker */ 421 static void mw_loadWalker(const RefVectorWithLeader<ParticleSet>& p_list, 422 const RefVector<Walker_t>& walkers, 423 const std::vector<bool>& recompute, 424 bool pbyp); 425 426 /** save this to awalker 427 * 428 * just the R, G, and L 429 * More duplicate data that makes code difficult to reason about should be removed. 430 */ 431 void saveWalker(Walker_t& awalker); 432 433 /** batched version of saveWalker 434 * 435 * just the R, G, and L 436 */ 437 static void mw_saveWalker(const RefVectorWithLeader<ParticleSet>& psets, const RefVector<Walker_t>& walkers); 438 439 /** update structure factor and unmark activePtcl 440 * 441 * The Coulomb interaction evaluation needs the structure factor. 442 * For these reason, call donePbyP after the loop of single 443 * electron moves before evaluating the Hamiltonian. Unmark 444 * activePtcl is more of a safety measure probably not needed. 445 */ 446 void donePbyP(); 447 /// batched version of donePbyP 448 static void mw_donePbyP(const RefVectorWithLeader<ParticleSet>& p_list); 449 450 ///return the address of the values of Hamiltonian terms getPropertyBase()451 inline FullPrecRealType* restrict getPropertyBase() { return Properties.data(); } 452 453 ///return the address of the values of Hamiltonian terms getPropertyBase()454 inline const FullPrecRealType* restrict getPropertyBase() const { return Properties.data(); } 455 456 ///return the address of the i-th properties getPropertyBase(int i)457 inline FullPrecRealType* restrict getPropertyBase(int i) { return Properties[i]; } 458 459 ///return the address of the i-th properties getPropertyBase(int i)460 inline const FullPrecRealType* restrict getPropertyBase(int i) const { return Properties[i]; } 461 setTwist(SingleParticlePos_t & t)462 inline void setTwist(SingleParticlePos_t& t) { myTwist = t; } getTwist()463 inline SingleParticlePos_t getTwist() const { return myTwist; } 464 465 /** Initialize particles around another ParticleSet 466 * Used to initialize an electron ParticleSet by an ion ParticleSet 467 */ 468 void randomizeFromSource(ParticleSet& src); 469 470 /** return the ip-th clone 471 * @param ip thread number 472 * 473 * Return itself if ip==0 474 */ get_clone(int ip)475 inline ParticleSet* get_clone(int ip) 476 { 477 if (ip >= myClones.size()) 478 return 0; 479 return (ip) ? myClones[ip] : this; 480 } 481 get_clone(int ip)482 inline const ParticleSet* get_clone(int ip) const 483 { 484 if (ip >= myClones.size()) 485 return 0; 486 return (ip) ? myClones[ip] : this; 487 } 488 clones_size()489 inline int clones_size() const { return myClones.size(); } 490 491 /** update R of its own and its clones 492 * @param rnew new position array of N 493 */ 494 template<typename PAT> update_clones(const PAT & rnew)495 inline void update_clones(const PAT& rnew) 496 { 497 if (R.size() != rnew.size()) 498 APP_ABORT("ParticleSet::updateR failed due to different sizes"); 499 R = rnew; 500 for (int ip = 1; ip < myClones.size(); ++ip) 501 myClones[ip]->R = rnew; 502 } 503 504 /** reset internal data of clones including itself 505 */ 506 void reset_clones(); 507 508 /** get species name of particle i 509 */ species_from_index(int i)510 inline const std::string& species_from_index(int i) { return mySpecies.speciesName[GroupID[i]]; } 511 getTotalNum()512 inline size_t getTotalNum() const { return TotalNum; } 513 resize(size_t numPtcl)514 inline void resize(size_t numPtcl) 515 { 516 TotalNum = numPtcl; 517 518 R.resize(numPtcl); 519 spins.resize(numPtcl); 520 ID.resize(numPtcl); 521 PCID.resize(numPtcl); 522 GroupID.resize(numPtcl); 523 G.resize(numPtcl); 524 dG.resize(numPtcl); 525 L.resize(numPtcl); 526 dL.resize(numPtcl); 527 Mass.resize(numPtcl); 528 Z.resize(numPtcl); 529 IndirectID.resize(numPtcl); 530 531 coordinates_->resize(numPtcl); 532 } 533 clear()534 inline void clear() 535 { 536 TotalNum = 0; 537 538 R.clear(); 539 spins.clear(); 540 ID.clear(); 541 PCID.clear(); 542 GroupID.clear(); 543 G.clear(); 544 dG.clear(); 545 L.clear(); 546 dL.clear(); 547 Mass.clear(); 548 Z.clear(); 549 IndirectID.clear(); 550 551 coordinates_->resize(0); 552 } 553 assign(const ParticleSet & ptclin)554 inline void assign(const ParticleSet& ptclin) 555 { 556 resize(ptclin.getTotalNum()); 557 Lattice = ptclin.Lattice; 558 PrimitiveLattice = ptclin.PrimitiveLattice; 559 R.InUnit = ptclin.R.InUnit; 560 R = ptclin.R; 561 spins = ptclin.spins; 562 ID = ptclin.ID; 563 GroupID = ptclin.GroupID; 564 if (ptclin.SubPtcl.size()) 565 { 566 SubPtcl.resize(ptclin.SubPtcl.size()); 567 SubPtcl = ptclin.SubPtcl; 568 } 569 } 570 571 ///return the number of groups groups()572 inline int groups() const { return SubPtcl.size() - 1; } 573 574 ///return the first index of a group i first(int igroup)575 inline int first(int igroup) const { return SubPtcl[igroup]; } 576 577 ///return the last index of a group i last(int igroup)578 inline int last(int igroup) const { return SubPtcl[igroup + 1]; } 579 580 ///return the group id of a given particle in the particle set. getGroupID(int iat)581 inline int getGroupID(int iat) const 582 { 583 assert(iat >= 0 && iat < TotalNum); 584 return GroupID[iat]; 585 } 586 587 ///return the size of a group groupsize(int igroup)588 inline int groupsize(int igroup) const { return SubPtcl[igroup + 1] - SubPtcl[igroup]; } 589 590 ///add attributes to list for IO 591 template<typename ATList> createAttributeList(ATList & AttribList)592 inline void createAttributeList(ATList& AttribList) 593 { 594 R.setTypeName(ParticleTags::postype_tag); 595 R.setObjName(ParticleTags::position_tag); 596 spins.setTypeName(ParticleTags::scalartype_tag); 597 spins.setObjName(ParticleTags::spins_tag); 598 ID.setTypeName(ParticleTags::indextype_tag); 599 ID.setObjName(ParticleTags::id_tag); 600 GroupID.setTypeName(ParticleTags::indextype_tag); 601 GroupID.setObjName(ParticleTags::ionid_tag); 602 //add basic attributes 603 AttribList.add(R); 604 AttribList.add(spins); 605 AttribList.add(ID); 606 AttribList.add(GroupID); 607 608 G.setTypeName(ParticleTags::gradtype_tag); 609 L.setTypeName(ParticleTags::laptype_tag); 610 dG.setTypeName(ParticleTags::gradtype_tag); 611 dL.setTypeName(ParticleTags::laptype_tag); 612 613 G.setObjName("grad"); 614 L.setObjName("lap"); 615 dG.setObjName("dgrad"); 616 dL.setObjName("dlap"); 617 618 AttribList.add(G); 619 AttribList.add(L); 620 AttribList.add(dG); 621 AttribList.add(dL); 622 623 //more particle attributes 624 Mass.setTypeName(ParticleTags::scalartype_tag); 625 Mass.setObjName("mass"); 626 AttribList.add(Mass); 627 628 Z.setTypeName(ParticleTags::scalartype_tag); 629 Z.setObjName("charge"); 630 AttribList.add(Z); 631 632 PCID.setTypeName(ParticleTags::indextype_tag); //add PCID tags 633 PCID.setObjName("pcid"); 634 AttribList.add(PCID); 635 636 IndirectID.setTypeName(ParticleTags::indextype_tag); //add IndirectID tags 637 IndirectID.setObjName("id1"); 638 AttribList.add(IndirectID); 639 } 640 getNumDistTables()641 inline int getNumDistTables() const { return DistTables.size(); } 642 643 /// initialize a shared resource and hand it to a collection 644 void createResource(ResourceCollection& collection) const; 645 /** acquire external resource and assocaite it with the list of ParticleSet 646 * Note: use RAII ResourceCollectionTeamLock whenever possible 647 */ 648 static void acquireResource(ResourceCollection& collection, const RefVectorWithLeader<ParticleSet>& p_list); 649 /** release external resource 650 * Note: use RAII ResourceCollectionTeamLock whenever possible 651 */ 652 static void releaseResource(ResourceCollection& collection, const RefVectorWithLeader<ParticleSet>& p_list); 653 654 static RefVectorWithLeader<DistanceTableData> extractDTRefList(const RefVectorWithLeader<ParticleSet>& p_list, 655 int id); 656 static RefVectorWithLeader<DynamicCoordinates> extractCoordsRefList(const RefVectorWithLeader<ParticleSet>& p_list); 657 658 protected: 659 /** map to handle distance tables 660 * 661 * myDistTableMap[source-particle-tag]= locator in the distance table 662 * myDistTableMap[ObjectTag] === 0 663 */ 664 std::map<std::string, int> myDistTableMap; 665 666 /// distance tables that need to be updated by moving this ParticleSet 667 std::vector<DistanceTableData*> DistTables; 668 669 /// Descriptions from distance table creation. Same order as DistTables. 670 std::vector<std::string> distTableDescriptions; 671 672 TimerList_t myTimers; 673 674 SingleParticlePos_t myTwist; 675 676 std::string ParentName; 677 678 ///total number of particles 679 size_t TotalNum; 680 681 ///array to handle a group of distinct particles per species 682 ParticleIndex_t SubPtcl; 683 ///internal representation of R. It can be an SoA copy of R 684 std::unique_ptr<DynamicCoordinates> coordinates_; 685 686 /** compute temporal DistTables and SK for a new particle position 687 * 688 * @param iat the particle that is moved on a sphere 689 * @param newpos a new particle position 690 * @param maybe_accept if false, the caller guarantees that the proposed move will not be accepted. 691 */ 692 void computeNewPosDistTablesAndSK(Index_t iat, const SingleParticlePos_t& newpos, bool maybe_accept = true); 693 694 695 /** compute temporal DistTables and SK for a new particle position for each walker in a batch 696 * 697 * @param p_list the list of wrapped ParticleSet references in a walker batch 698 * @param iat the particle that is moved on a sphere 699 * @param new_positions new particle positions 700 * @param maybe_accept if false, the caller guarantees that the proposed move will not be accepted. 701 */ 702 static void mw_computeNewPosDistTablesAndSK(const RefVectorWithLeader<ParticleSet>& p_list, 703 Index_t iat, 704 const std::vector<SingleParticlePos_t>& new_positions, 705 bool maybe_accept = true); 706 707 /** actual implemenation for accepting a proposed move, support both regular and forward modes 708 * 709 * @param iat the index of the particle whose position and other attributes to be updated 710 * @param forward_mode if ture, in forward mode. 711 */ 712 void acceptMove_impl(Index_t iat, bool forward_mode); 713 714 /** reject a proposed move in forward mode 715 * @param iat the electron whose proposed move gets rejected. 716 */ 717 void rejectMoveForwardMode(Index_t iat); 718 }; 719 720 } // namespace qmcplusplus 721 #endif 722