QMCPACK
NonLocalECPotential.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) 2022 QMCPACK developers.
6 //
7 // File developed by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
10 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
11 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
12 // Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Laboratory
13 //
14 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
15 //////////////////////////////////////////////////////////////////////////////////////
16 
17 
18 #include "NonLocalECPotential.h"
19 
20 #include <optional>
21 
22 #include <DistanceTable.h>
23 #include <IteratorUtility.h>
24 #include <ResourceCollection.h>
25 #include "NonLocalECPComponent.h"
26 #include "NLPPJob.h"
27 
28 namespace qmcplusplus
29 {
30 
32 {
33  NonLocalECPotentialMultiWalkerResource() : Resource("NonLocalECPotential") {}
34 
35  std::unique_ptr<Resource> makeClone() const override
36  {
37  return std::make_unique<NonLocalECPotentialMultiWalkerResource>(*this);
38  }
39 
40 
41  ResourceCollection collection{"NLPPcollection"};
42  /// a crowds worth of per particle nonlocal ecp potential values
45 };
46 
48 
49 /** constructor
50  *\param ions the positions of the ions
51  *\param els the positions of the electrons
52  *\param psi trial wavefunction
53  */
55  ParticleSet& els,
56  TrialWaveFunction& psi,
57  bool computeForces,
58  bool enable_DLA)
59  : ForceBase(ions, els),
60  myRNG(nullptr),
61  IonConfig(ions),
62  Psi(psi),
63  ComputeForces(computeForces),
64  use_DLA(enable_DLA),
65  Peln(els),
66  ElecNeighborIons(els),
67  IonNeighborElecs(ions),
68  UseTMove(TMOVE_OFF)
69 {
71  twoBodyQuantumDomain(ions, els);
72  myTableIndex = els.addTable(ions);
73  NumIons = ions.getTotalNum();
74  //els.resizeSphere(NumIons);
75  PP.resize(NumIons, nullptr);
76  prefix_ = "FNL";
79  update_mode_.set(NONLOCAL, 1);
80  nlpp_jobs.resize(els.groups());
81  for (size_t ig = 0; ig < els.groups(); ig++)
82  {
83  // this should be enough in most calculations assuming that every electron cannot be in more than two pseudo regions.
84  nlpp_jobs[ig].reserve(2 * els.groupsize(ig));
85  }
86 }
87 
89 
90 #if !defined(REMOVE_TRACEMANAGER)
92 
94 {
97  {
100  }
101 }
102 
104 {
106  {
107  delete Ve_sample;
108  delete Vi_sample;
109  }
110 }
111 #endif
112 
114 {
115  evaluateImpl(P, false);
116  return value_;
117 }
118 
120 {
121  evaluateImpl(P, false, true);
122  return value_;
123 }
124 
127  const RefVectorWithLeader<ParticleSet>& p_list) const
128 {
129  mw_evaluateImpl(o_list, wf_list, p_list, false, std::nullopt);
130 }
131 
133 {
134  if (UseTMove == TMOVE_V0 || UseTMove == TMOVE_V3)
135  evaluateImpl(P, true);
136  else
137  evaluateImpl(P, false);
138  return value_;
139 }
140 
143  const RefVectorWithLeader<ParticleSet>& p_list) const
144 {
145  if (UseTMove == TMOVE_V0 || UseTMove == TMOVE_V3)
146  mw_evaluateImpl(o_list, wf_list, p_list, true, std::nullopt);
147  else
148  mw_evaluateImpl(o_list, wf_list, p_list, false, std::nullopt);
149 }
150 
153  const RefVectorWithLeader<ParticleSet>& p_list,
154  const std::vector<ListenerVector<Real>>& listeners,
155  const std::vector<ListenerVector<Real>>& listeners_ions) const
156 {
157  std::optional<ListenerOption<Real>> l_opt(std::in_place, listeners, listeners_ions);
158  mw_evaluateImpl(o_list, wf_list, p_list, false, l_opt);
159 }
160 
162  const RefVectorWithLeader<OperatorBase>& o_list,
164  const RefVectorWithLeader<ParticleSet>& p_list,
165  const std::vector<ListenerVector<Real>>& listeners,
166  const std::vector<ListenerVector<Real>>& listeners_ions) const
167 {
168  std::optional<ListenerOption<Real>> l_opt(std::in_place, listeners, listeners_ions);
169  if (UseTMove == TMOVE_V0 || UseTMove == TMOVE_V3)
170  mw_evaluateImpl(o_list, wf_list, p_list, true, l_opt);
171  else
172  mw_evaluateImpl(o_list, wf_list, p_list, false, l_opt);
173 }
174 
175 void NonLocalECPotential::evaluateImpl(ParticleSet& P, bool Tmove, bool keep_grid)
176 {
177  if (Tmove)
178  tmove_xy_.clear();
179 
180  value_ = 0.0;
181 #if !defined(REMOVE_TRACEMANAGER)
182  auto& Ve_samp = *Ve_sample;
183  auto& Vi_samp = *Vi_sample;
185  {
186  Ve_samp = 0.0;
187  Vi_samp = 0.0;
188  }
189 #endif
190  for (int ipp = 0; ipp < PPset.size(); ipp++)
191  if (PPset[ipp])
192  if (!keep_grid)
193  PPset[ipp]->rotateQuadratureGrid(generateRandomRotationMatrix(*myRNG));
194 
195  //loop over all the ions
196  const auto& myTable = P.getDistTableAB(myTableIndex);
197  // clear all the electron and ion neighbor lists
198  for (int iat = 0; iat < NumIons; iat++)
199  IonNeighborElecs.getNeighborList(iat).clear();
200  for (int jel = 0; jel < P.getTotalNum(); jel++)
201  ElecNeighborIons.getNeighborList(jel).clear();
202 
203  if (ComputeForces)
204  {
205  forces_ = 0;
206  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
207  {
208  Psi.prepareGroup(P, ig);
209  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
210  {
211  const auto& dist = myTable.getDistRow(jel);
212  const auto& displ = myTable.getDisplRow(jel);
213  std::vector<int>& NeighborIons = ElecNeighborIons.getNeighborList(jel);
214  for (int iat = 0; iat < NumIons; iat++)
215  if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
216  {
217  Real pairpot = PP[iat]->evaluateOneWithForces(P, iat, Psi, jel, dist[iat], -displ[iat], forces_[iat]);
218  if (Tmove)
219  PP[iat]->contributeTxy(jel, tmove_xy_);
220  value_ += pairpot;
221  NeighborIons.push_back(iat);
222  IonNeighborElecs.getNeighborList(iat).push_back(jel);
223  }
224  }
225  }
226  }
227  else
228  {
229  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
230  {
231  Psi.prepareGroup(P, ig);
232  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
233  {
234  const auto& dist = myTable.getDistRow(jel);
235  const auto& displ = myTable.getDisplRow(jel);
236  std::vector<int>& NeighborIons = ElecNeighborIons.getNeighborList(jel);
237  for (int iat = 0; iat < NumIons; iat++)
238  if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
239  {
240  Real pairpot = PP[iat]->evaluateOne(P, iat, Psi, jel, dist[iat], -displ[iat], use_DLA);
241  if (Tmove)
242  PP[iat]->contributeTxy(jel, tmove_xy_);
243 
244  value_ += pairpot;
245  NeighborIons.push_back(iat);
246  IonNeighborElecs.getNeighborList(iat).push_back(jel);
247 
249  {
250  Ve_samp(jel) += 0.5 * pairpot;
251  Vi_samp(iat) += 0.5 * pairpot;
252  }
253  }
254  }
255  }
256  }
257 
258 #if !defined(TRACE_CHECK)
260  {
261  Return_t Vnow = value_;
262  Real Visum = Vi_sample->sum();
263  Real Vesum = Ve_sample->sum();
264  Real Vsum = Vesum + Visum;
265  if (std::abs(Vsum - Vnow) > TraceManager::trace_tol)
266  {
267  app_log() << "accumtest: NonLocalECPotential::evaluate()" << std::endl;
268  app_log() << "accumtest: tot:" << Vnow << std::endl;
269  app_log() << "accumtest: sum:" << Vsum << std::endl;
270  APP_ABORT("Trace check failed");
271  }
272  if (std::abs(Vesum - Visum) > TraceManager::trace_tol)
273  {
274  app_log() << "sharetest: NonLocalECPotential::evaluate()" << std::endl;
275  app_log() << "sharetest: e share:" << Vesum << std::endl;
276  app_log() << "sharetest: i share:" << Visum << std::endl;
277  APP_ABORT("Trace check failed");
278  }
279  }
280 #endif
281 }
282 
285  const RefVectorWithLeader<ParticleSet>& p_list,
286  bool Tmove,
287  const std::optional<ListenerOption<Real>> listeners,
288  bool keep_grid)
289 {
290  auto& O_leader = o_list.getCastedLeader<NonLocalECPotential>();
291  ParticleSet& pset_leader = p_list.getLeader();
292  const size_t nw = o_list.size();
293 
294  if (O_leader.ComputeForces)
295  APP_ABORT("NonLocalECPotential::mw_evaluateImpl(): Forces not imlpemented\n");
296 
297  for (size_t iw = 0; iw < nw; iw++)
298  {
299  auto& O = o_list.getCastedElement<NonLocalECPotential>(iw);
300  const ParticleSet& P(p_list[iw]);
301 
302  if (Tmove)
303  O.tmove_xy_.clear();
304 
305  if (!keep_grid)
306  for (int ipp = 0; ipp < O.PPset.size(); ipp++)
307  if (O.PPset[ipp])
308  O.PPset[ipp]->rotateQuadratureGrid(generateRandomRotationMatrix(*O.myRNG));
309 
310  //loop over all the ions
311  const auto& myTable = P.getDistTableAB(O.myTableIndex);
312  // clear all the electron and ion neighbor lists
313  for (int iat = 0; iat < O.NumIons; iat++)
314  O.IonNeighborElecs.getNeighborList(iat).clear();
315  for (int jel = 0; jel < P.getTotalNum(); jel++)
316  O.ElecNeighborIons.getNeighborList(jel).clear();
317 
318  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
319  {
320  auto& joblist = O.nlpp_jobs[ig];
321  joblist.clear();
322 
323  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
324  {
325  const auto& dist = myTable.getDistRow(jel);
326  const auto& displ = myTable.getDisplRow(jel);
327  std::vector<int>& NeighborIons = O.ElecNeighborIons.getNeighborList(jel);
328  for (int iat = 0; iat < O.NumIons; iat++)
329  if (O.PP[iat] != nullptr && dist[iat] < O.PP[iat]->getRmax())
330  {
331  NeighborIons.push_back(iat);
332  O.IonNeighborElecs.getNeighborList(iat).push_back(jel);
333  joblist.emplace_back(iat, jel, dist[iat], -displ[iat]);
334  }
335  }
336  }
337 
338  O.value_ = 0.0;
339  }
340 
341  if (listeners)
342  {
343  auto& ve_samples = O_leader.mw_res_handle_.getResource().ve_samples;
344  auto& vi_samples = O_leader.mw_res_handle_.getResource().vi_samples;
345  ve_samples.resize(nw, pset_leader.getTotalNum());
346  vi_samples.resize(nw, O_leader.IonConfig.getTotalNum());
347  }
348 
349  // the VP of the first NonLocalECPComponent is responsible for holding the shared resource.
350  auto pp_component = std::find_if(O_leader.PPset.begin(), O_leader.PPset.end(), [](auto& ptr) { return bool(ptr); });
351  assert(pp_component != std::end(O_leader.PPset));
352 
353  RefVector<NonLocalECPotential> ecp_potential_list;
354  RefVectorWithLeader<NonLocalECPComponent> ecp_component_list(**pp_component);
355  RefVectorWithLeader<ParticleSet> pset_list(pset_leader);
356  RefVectorWithLeader<TrialWaveFunction> psi_list(O_leader.Psi);
357  // we are moving away from internally stored Psi, double check before Psi gets finally removed.
358  assert(&O_leader.Psi == &wf_list.getLeader());
359  for (size_t iw = 0; iw < nw; iw++)
360  assert(&o_list.getCastedElement<NonLocalECPotential>(iw).Psi == &wf_list[iw]);
361 
362  RefVector<const NLPPJob<Real>> batch_list;
363  std::vector<Real> pairpots(nw);
364 
365  ecp_potential_list.reserve(nw);
366  ecp_component_list.reserve(nw);
367  pset_list.reserve(nw);
368  psi_list.reserve(nw);
369  batch_list.reserve(nw);
370 
371  for (int ig = 0; ig < pset_leader.groups(); ++ig) //loop over species
372  {
373  TrialWaveFunction::mw_prepareGroup(wf_list, p_list, ig);
374 
375  // find the max number of jobs of all the walkers
376  size_t max_num_jobs = 0;
377  for (size_t iw = 0; iw < nw; iw++)
378  {
379  const auto& O = o_list.getCastedElement<NonLocalECPotential>(iw);
380  max_num_jobs = std::max(max_num_jobs, O.nlpp_jobs[ig].size());
381  }
382 
383  for (size_t jobid = 0; jobid < max_num_jobs; jobid++)
384  {
385  ecp_potential_list.clear();
386  ecp_component_list.clear();
387  pset_list.clear();
388  psi_list.clear();
389  batch_list.clear();
390  for (size_t iw = 0; iw < nw; iw++)
391  {
392  auto& O = o_list.getCastedElement<NonLocalECPotential>(iw);
393  if (jobid < O.nlpp_jobs[ig].size())
394  {
395  const auto& job = O.nlpp_jobs[ig][jobid];
396  ecp_potential_list.push_back(O);
397  ecp_component_list.push_back(*O.PP[job.ion_id]);
398  pset_list.push_back(p_list[iw]);
399  psi_list.push_back(wf_list[iw]);
400  batch_list.push_back(job);
401  }
402  }
403 
404  NonLocalECPComponent::mw_evaluateOne(ecp_component_list, pset_list, psi_list, batch_list, pairpots,
405  O_leader.mw_res_handle_.getResource().collection, O_leader.use_DLA);
406 
407  // Right now this is just over walker but could and probably should be over a set
408  // larger than the walker count. The easiest way to not complicate the per particle
409  // reporting code would be to add the crowd walker index to the nlpp job meta data.
410  for (size_t j = 0; j < ecp_potential_list.size(); j++)
411  {
412  ecp_potential_list[j].get().value_ += pairpots[j];
413  if (Tmove)
414  ecp_component_list[j].contributeTxy(batch_list[j].get().electron_id, ecp_potential_list[j].get().tmove_xy_);
415 
416  if (listeners)
417  {
418  auto& ve_samples = O_leader.mw_res_handle_.getResource().ve_samples;
419  auto& vi_samples = O_leader.mw_res_handle_.getResource().vi_samples;
420  // CAUTION! This may not be so simple in the future
421  int iw = j;
422  ve_samples(iw, batch_list[j].get().electron_id) += pairpots[j];
423  vi_samples(iw, batch_list[j].get().ion_id) += pairpots[j];
424  }
425 
426 #ifdef DEBUG_NLPP_BATCHED
427  Real check_value =
428  ecp_component_list[j].evaluateOne(pset_list[j], batch_list[j].get().ion_id, psi_list[j],
429  batch_list[j].get().electron_id, batch_list[j].get().ion_elec_dist,
430  batch_list[j].get().ion_elec_displ, O_leader.use_DLA);
431  if (std::abs(check_value - pairpots[j]) > 1e-5)
432  std::cout << "check " << check_value << " wrong " << pairpots[j] << " diff "
433  << std::abs(check_value - pairpots[j]) << std::endl;
434 #endif
435  }
436  }
437  }
438 
439  if (listeners)
440  {
441  // Motivation for this repeated definition is to make factoring this listener code out easy
442  // and making it ignorable when reading this function.
443  auto& ve_samples = O_leader.mw_res_handle_.getResource().ve_samples;
444  auto& vi_samples = O_leader.mw_res_handle_.getResource().vi_samples;
445  int num_electrons = pset_leader.getTotalNum();
446  for (int iw = 0; iw < nw; ++iw)
447  {
448  Vector<Real> ve_sample(ve_samples.begin(iw), num_electrons);
449  Vector<Real> vi_sample(vi_samples.begin(iw), O_leader.NumIons);
450  for (const ListenerVector<Real>& listener : listeners->electron_values)
451  listener.report(iw, O_leader.getName(), ve_sample);
452  for (const ListenerVector<Real>& listener : listeners->ion_values)
453  listener.report(iw, O_leader.getName(), vi_sample);
454  }
455  ve_samples = 0.0;
456  vi_samples = 0.0;
457  }
458 }
459 
460 
462  ParticleSet& ions,
463  TrialWaveFunction& psi,
464  ParticleSet::ParticlePos& hf_terms,
465  ParticleSet::ParticlePos& pulay_terms,
466  bool keepGrid)
467 {
468  //We're going to ignore psi and use the internal Psi.
469  //
470  //Dummy vector for now. Tmoves not implemented
471  bool Tmove = false;
472 
473  forces_ = 0;
474  PulayTerm = 0;
475 
476  value_ = 0.0;
477  if (!keepGrid)
478  {
479  for (int ipp = 0; ipp < PPset.size(); ipp++)
480  if (PPset[ipp])
481  PPset[ipp]->rotateQuadratureGrid(generateRandomRotationMatrix(*myRNG));
482  }
483  //loop over all the ions
484  const auto& myTable = P.getDistTableAB(myTableIndex);
485  // clear all the electron and ion neighbor lists
486  for (int iat = 0; iat < NumIons; iat++)
487  IonNeighborElecs.getNeighborList(iat).clear();
488  for (int jel = 0; jel < P.getTotalNum(); jel++)
489  ElecNeighborIons.getNeighborList(jel).clear();
490 
491  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
492  {
493  Psi.prepareGroup(P, ig);
494  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
495  {
496  const auto& dist = myTable.getDistRow(jel);
497  const auto& displ = myTable.getDisplRow(jel);
498  std::vector<int>& NeighborIons = ElecNeighborIons.getNeighborList(jel);
499  for (int iat = 0; iat < NumIons; iat++)
500  if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
501  {
502  value_ +=
503  PP[iat]->evaluateOneWithForces(P, ions, iat, Psi, jel, dist[iat], -displ[iat], forces_[iat], PulayTerm);
504  if (Tmove)
505  PP[iat]->contributeTxy(jel, tmove_xy_);
506  NeighborIons.push_back(iat);
507  IonNeighborElecs.getNeighborList(iat).push_back(jel);
508  }
509  }
510  }
511 
512  hf_terms -= forces_;
513  pulay_terms -= PulayTerm;
514 }
515 
517  ParticleSet& ions,
518  TrialWaveFunction& psi,
519  ParticleSet::ParticlePos& hf_terms,
520  ParticleSet::ParticlePos& pulay_terms)
521 {
522  evalIonDerivsImpl(P, ions, psi, hf_terms, pulay_terms);
523  return value_;
524 }
525 
527  ParticleSet& P,
528  ParticleSet& ions,
529  TrialWaveFunction& psi,
530  ParticleSet::ParticlePos& hf_terms,
531  ParticleSet::ParticlePos& pulay_terms)
532 {
533  evalIonDerivsImpl(P, ions, psi, hf_terms, pulay_terms, true);
534  return value_;
535 }
536 
538 {
539  tmove_xy_.clear();
540  const auto& myTable = P.getDistTableAB(myTableIndex);
541  const std::vector<int>& NeighborIons = ElecNeighborIons.getNeighborList(ref_elec);
542 
543  const auto& dist = myTable.getDistRow(ref_elec);
544  const auto& displ = myTable.getDisplRow(ref_elec);
545  for (int atom_index = 0; atom_index < NeighborIons.size(); atom_index++)
546  {
547  const int iat = NeighborIons[atom_index];
548  PP[iat]->evaluateOne(P, iat, Psi, ref_elec, dist[iat], -displ[iat], use_DLA);
549  PP[iat]->contributeTxy(ref_elec, tmove_xy_);
550  }
551 }
552 
554  const TWFFastDerivWrapper& psi,
555  std::vector<ValueMatrix>& B)
556 {
557  bool keepGrid = true;
558  for (int ipp = 0; ipp < PPset.size(); ipp++)
559  if (PPset[ipp])
560  if (!keepGrid)
561  PPset[ipp]->rotateQuadratureGrid(generateRandomRotationMatrix(*myRNG));
562 
563  //loop over all the ions
564  const auto& myTable = P.getDistTableAB(myTableIndex);
565  // clear all the electron and ion neighbor lists
566  for (int iat = 0; iat < NumIons; iat++)
567  IonNeighborElecs.getNeighborList(iat).clear();
568  for (int jel = 0; jel < P.getTotalNum(); jel++)
569  ElecNeighborIons.getNeighborList(jel).clear();
570 
571  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
572  {
573  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
574  {
575  const auto& dist = myTable.getDistRow(jel);
576  const auto& displ = myTable.getDisplRow(jel);
577  auto& NeighborIons = ElecNeighborIons.getNeighborList(jel);
578  for (int iat = 0; iat < NumIons; iat++)
579  if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
580  {
581  PP[iat]->evaluateOneBodyOpMatrixContribution(P, iat, psi, jel, dist[iat], -displ[iat], B);
582  NeighborIons.push_back(iat);
583  IonNeighborElecs.getNeighborList(iat).push_back(jel);
584  }
585  }
586  }
587 }
588 
590  ParticleSet& source,
591  const TWFFastDerivWrapper& psi,
592  const int iat_source,
593  std::vector<std::vector<ValueMatrix>>& Bforce)
594 {
595  bool keepGrid = true;
596  for (int ipp = 0; ipp < PPset.size(); ipp++)
597  if (PPset[ipp])
598  if (!keepGrid)
599  PPset[ipp]->rotateQuadratureGrid(generateRandomRotationMatrix(*myRNG));
600 
601  //loop over all the ions
602  const auto& myTable = P.getDistTableAB(myTableIndex);
603  // clear all the electron and ion neighbor lists
604  for (int iat = 0; iat < NumIons; iat++)
605  IonNeighborElecs.getNeighborList(iat).clear();
606  for (int jel = 0; jel < P.getTotalNum(); jel++)
607  ElecNeighborIons.getNeighborList(jel).clear();
608 
609  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
610  {
611  for (int jel = P.first(ig); jel < P.last(ig); ++jel)
612  {
613  const auto& dist = myTable.getDistRow(jel);
614  const auto& displ = myTable.getDisplRow(jel);
615  auto& NeighborIons = ElecNeighborIons.getNeighborList(jel);
616  for (int iat = 0; iat < NumIons; iat++)
617  if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
618  {
619  PP[iat]->evaluateOneBodyOpMatrixdRContribution(P, source, iat, iat_source, psi, jel, dist[iat], -displ[iat],
620  Bforce);
621  NeighborIons.push_back(iat);
622  IonNeighborElecs.getNeighborList(iat).push_back(jel);
623  }
624  }
625  }
626 }
628 {
629  int NonLocalMoveAccepted = 0;
630  auto& RandomGen(*myRNG);
631  if (UseTMove == TMOVE_V0)
632  {
633  const NonLocalData* oneTMove = nonLocalOps.selectMove(RandomGen(), tmove_xy_);
634  //make a non-local move
635  if (oneTMove)
636  {
637  const int iat = oneTMove->PID;
638  Psi.prepareGroup(P, P.getGroupID(iat));
639  GradType grad_iat;
640  if (P.makeMoveAndCheck(iat, oneTMove->Delta) && Psi.calcRatioGrad(P, iat, grad_iat) != ValueType(0))
641  {
642  Psi.acceptMove(P, iat, true);
643  P.acceptMove(iat);
644  NonLocalMoveAccepted++;
645  }
646  }
647  }
648  else if (UseTMove == TMOVE_V1)
649  {
650  GradType grad_iat;
651  //make a non-local move per particle
652  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
653  {
654  Psi.prepareGroup(P, ig);
655  for (int iat = P.first(ig); iat < P.last(ig); ++iat)
656  {
657  computeOneElectronTxy(P, iat);
658  const NonLocalData* oneTMove = nonLocalOps.selectMove(RandomGen(), tmove_xy_);
659  if (oneTMove)
660  {
661  if (P.makeMoveAndCheck(iat, oneTMove->Delta) && Psi.calcRatioGrad(P, iat, grad_iat) != ValueType(0))
662  {
663  Psi.acceptMove(P, iat, true);
664  P.acceptMove(iat);
665  NonLocalMoveAccepted++;
666  }
667  }
668  }
669  }
670  }
671  else if (UseTMove == TMOVE_V3)
672  {
673  elecTMAffected.assign(P.getTotalNum(), false);
675  GradType grad_iat;
676  //make a non-local move per particle
677  for (int ig = 0; ig < P.groups(); ++ig) //loop over species
678  {
679  Psi.prepareGroup(P, ig);
680  for (int iat = P.first(ig); iat < P.last(ig); ++iat)
681  {
682  const NonLocalData* oneTMove;
683  if (elecTMAffected[iat])
684  {
685  // recompute Txy for the given electron effected by Tmoves
686  computeOneElectronTxy(P, iat);
687  oneTMove = nonLocalOps.selectMove(RandomGen(), tmove_xy_);
688  }
689  else
690  oneTMove = nonLocalOps.selectMove(RandomGen(), iat);
691  if (oneTMove)
692  {
693  if (P.makeMoveAndCheck(iat, oneTMove->Delta) && Psi.calcRatioGrad(P, iat, grad_iat) != ValueType(0))
694  {
695  Psi.acceptMove(P, iat, true);
696  // mark all affected electrons
698  P.acceptMove(iat);
699  NonLocalMoveAccepted++;
700  }
701  }
702  }
703  }
704  }
705 
706  if (NonLocalMoveAccepted > 0)
707  {
709  // this step also updates electron positions on the device.
710  P.donePbyP(true);
711  }
712 
713  return NonLocalMoveAccepted;
714 }
715 
717 {
718  std::vector<int>& NeighborIons = ElecNeighborIons.getNeighborList(iel);
719  for (int iat = 0; iat < NumIons; iat++)
720  {
721  if (PP[iat] == nullptr)
722  continue;
723  Real old_distance = 0.0;
724  Real new_distance = 0.0;
725  old_distance = myTable.getDistRow(iel)[iat];
726  new_distance = myTable.getTempDists()[iat];
727  bool moved = false;
728  // move out
729  if (old_distance < PP[iat]->getRmax() && new_distance >= PP[iat]->getRmax())
730  {
731  moved = true;
732  std::vector<int>& NeighborElecs = IonNeighborElecs.getNeighborList(iat);
733  auto iter_at = std::find(NeighborIons.begin(), NeighborIons.end(), iat);
734  auto iter_el = std::find(NeighborElecs.begin(), NeighborElecs.end(), iel);
735  *iter_at = NeighborIons.back();
736  *iter_el = NeighborElecs.back();
737  NeighborIons.pop_back();
738  NeighborElecs.pop_back();
739  elecTMAffected[iel] = true;
740  }
741  // move in
742  if (old_distance >= PP[iat]->getRmax() && new_distance < PP[iat]->getRmax())
743  {
744  moved = true;
745  std::vector<int>& NeighborElecs = IonNeighborElecs.getNeighborList(iat);
746  NeighborElecs.push_back(iel);
747  NeighborIons.push_back(iat);
748  }
749  // move around
750  if (moved || (old_distance < PP[iat]->getRmax() && new_distance < PP[iat]->getRmax()))
751  {
752  std::vector<int>& NeighborElecs = IonNeighborElecs.getNeighborList(iat);
753  for (int jel = 0; jel < NeighborElecs.size(); ++jel)
754  elecTMAffected[NeighborElecs[jel]] = true;
755  }
756  }
757 }
758 
759 void NonLocalECPotential::addComponent(int groupID, std::unique_ptr<NonLocalECPComponent>&& ppot)
760 {
761  for (int iat = 0; iat < PP.size(); iat++)
762  if (IonConfig.GroupID[iat] == groupID)
763  PP[iat] = ppot.get();
764  PPset[groupID] = std::move(ppot);
765 }
766 
768 {
769  auto new_res = std::make_unique<NonLocalECPotentialMultiWalkerResource>();
770  for (int ig = 0; ig < PPset.size(); ++ig)
771  if (PPset[ig] && PPset[ig]->getVP()) // H pp doesn't contain non-local channels and PPset[ig] can be nullptr
772  {
773  PPset[ig]->getVP()->createResource(new_res->collection);
774  // the VP of the first NonLocalECPComponent is responsible for creating the shared resource.
775  break;
776  }
777  auto resource_index = collection.addResource(std::move(new_res));
778 }
779 
781  const RefVectorWithLeader<OperatorBase>& o_list) const
782 {
783  auto& O_leader = o_list.getCastedLeader<NonLocalECPotential>();
785 }
786 
788  const RefVectorWithLeader<OperatorBase>& o_list) const
789 {
790  auto& O_leader = o_list.getCastedLeader<NonLocalECPotential>();
791  collection.takebackResource(O_leader.mw_res_handle_);
792 }
793 
794 std::unique_ptr<OperatorBase> NonLocalECPotential::makeClone(ParticleSet& qp, TrialWaveFunction& psi)
795 {
796  std::unique_ptr<NonLocalECPotential> myclone =
797  std::make_unique<NonLocalECPotential>(IonConfig, qp, psi, ComputeForces, use_DLA);
798  for (int ig = 0; ig < PPset.size(); ++ig)
799  if (PPset[ig])
800  myclone->addComponent(ig, std::make_unique<NonLocalECPComponent>(*PPset[ig], qp));
801  return myclone;
802 }
803 
804 
806 {
807  OperatorBase::addValue(plist);
808  if (ComputeForces)
809  {
810  if (first_force_index_ < 0)
811  first_force_index_ = plist.size();
812  for (int iat = 0; iat < n_nuc_; iat++)
813  {
814  for (int x = 0; x < OHMMS_DIM; x++)
815  {
816  std::ostringstream obsName1, obsName2;
817  obsName1 << "FNL"
818  << "_" << iat << "_" << x;
819  plist.add(obsName1.str());
820  // obsName2 << "FNL_Pulay" << "_" << iat << "_" << x;
821  // plist.add(obsName2.str());
822  }
823  }
824  }
825 }
826 
827 void NonLocalECPotential::registerObservables(std::vector<ObservableHelper>& h5list, hdf_archive& file) const
828 {
829  using namespace std::string_literals;
830 
831  OperatorBase::registerObservables(h5list, file);
832  if (ComputeForces)
833  {
834  std::vector<int> ndim(2);
835  ndim[0] = n_nuc_;
836  ndim[1] = OHMMS_DIM;
837  h5list.push_back({{"FNL"s}});
838  auto& h5o1 = h5list.back();
839  h5o1.set_dimensions(ndim, first_force_index_);
840  }
841 }
842 
844 {
846  if (ComputeForces)
847  {
848  int index = first_force_index_;
849  for (int iat = 0; iat < n_nuc_; iat++)
850  {
851  for (int x = 0; x < OHMMS_DIM; x++)
852  {
853  plist[index++] = forces_[iat][x];
854  // plist[index++] = PulayTerm[iat][x];
855  }
856  }
857  }
858 }
859 
860 
862 {
864  if (ComputeForces)
865  {
866  int index = first_force_index_ + offset;
867  for (int iat = 0; iat < n_nuc_; iat++)
868  {
869  for (int x = 0; x < OHMMS_DIM; x++)
870  {
871  plist[index++] = forces_[iat][x];
872  // plist[index++] = PulayTerm[iat][x];
873  }
874  }
875  }
876 }
877 
878 } // namespace qmcplusplus
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
void twoBodyQuantumDomain(const ParticleSet &P)
set quantum domain for two-body operator
void groupByElectron(size_t num_elec, const std::vector< NonLocalData > &txy)
sort all the Txy elements by electron
void resetTargetParticleSet(ParticleSet &P) override
Reset the data with the target ParticleSet.
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
size_t addResource(std::unique_ptr< Resource > &&res, bool noprint=false)
virtual void registerObservables(std::vector< ObservableHelper > &h5desc, hdf_archive &file) const
add to observable descriptor for hdf5 The default implementation is to register a scalar for this->va...
void takebackResource(ResourceHandle< RS > &res_handle)
Return_t evaluateWithToperator(ParticleSet &P) override
Evaluate the local energy contribution of this component with Toperators updated if requested...
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
bool streaming_array(const std::string &name)
Definition: TraceManager.h:249
const DistRow & getDistRow(int iel) const
return a row of distances for a given target particle
ParticleSet::ParticlePos forces_
Definition: ForceBase.h:87
std::vector< NonLocalData > tmove_xy_
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
void setObservables(PropertySetType &plist) override
Set the values evaluated by this object to plist Default implementation is to assign Value which is u...
size_t getTotalNum() const
Definition: ParticleSet.h:493
void acceptMove(ParticleSet &P, int iat, bool safe_to_delay=false)
update the state with the new data
static void mw_prepareGroup(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, int ig)
batched version of prepareGroup
std::ostream & app_log()
Definition: OutputManager.h:65
void acquireResource(ResourceCollection &collection, const RefVectorWithLeader< OperatorBase > &o_list) const override
acquire a shared resource from a collection
void releaseResource(ResourceCollection &collection, const RefVectorWithLeader< OperatorBase > &o_list) const override
return a shared resource to a collection
An object of this type is a listener expecting a callback to the report function with a vector of val...
Definition: Listener.hpp:38
void evaluateOneBodyOpMatrixForceDeriv(ParticleSet &P, ParticleSet &source, const TWFFastDerivWrapper &psi, const int iat, std::vector< std::vector< ValueMatrix >> &Bforce) override
Evaluate "dB/dR" matrices for observable.
ParticleSet & IonConfig
reference to the center ion
class to handle hdf file
Definition: hdf_archive.h:51
int first(int igroup) const
return the first index of a group i
Definition: ParticleSet.h:514
Vectorized record engine for scalar properties.
std::vector< NonLocalECPComponent * > PP
the set of local-potentials (one for each ion)
int myTableIndex
index of distance table for the ion-el pair
NonLocalTOperator nonLocalOps
non local operator
bool ComputeForces
true if we should compute forces
Attaches a unit to a Vector for IO.
TWFFastDerivWrapper is a wrapper class for TrialWavefunction that provides separate and low level acc...
std::string prefix_
Definition: ForceBase.h:96
void registerObservables(std::vector< ObservableHelper > &h5list, hdf_archive &file) const override
add to observable descriptor for hdf5 The default implementation is to register a scalar for this->va...
#define OHMMS_DIM
Definition: config.h:64
TraceRequest request_
whether traces are being collected
Definition: OperatorBase.h:531
ParticleIndex GroupID
Species ID.
Definition: ParticleSet.h:77
ResourceHandle< NonLocalECPotentialMultiWalkerResource > mw_res_handle_
mult walker shared resource
int getTotalNum() const
return the number of species
Definition: SpeciesSet.h:55
const DistanceTableAB & getDistTableAB(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAB
int groups() const
return the number of groups
Definition: ParticleSet.h:511
int addTable(const ParticleSet &psrc, DTModes modes=DTModes::ALL_OFF)
add a distance table
Array< TraceReal, 1 > * Ve_sample
single particle trace samples
std::string name_
name of this object
Definition: OperatorBase.h:527
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
void evaluateOneBodyOpMatrix(ParticleSet &P, const TWFFastDerivWrapper &psi, std::vector< ValueMatrix > &B) override
Evaluate "B" matrix for observable.
int makeNonLocalMovesPbyP(ParticleSet &P)
make non local moves with particle-by-particle moves
void createResource(ResourceCollection &collection) const override
initialize a shared resource and hand it to a collection
Matrix< Real > ve_samples
a crowds worth of per particle nonlocal ecp potential values
static void mw_evaluateImpl(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, bool Tmove, std::optional< ListenerOption< Real >> listeners, bool keepGrid=false)
the actual implementation for batched walkers, used by mw_evaluate, mw_evaluateWithToperator mw_evalu...
QTBase::ValueType ValueType
Definition: Configuration.h:60
ParticleSet & Peln
reference to the electrons
const DistRow & getTempDists() const
return the temporary distances when a move is proposed
void computeOneElectronTxy(ParticleSet &P, const int ref_elec)
compute the T move transition probability for a given electron member variable nonLocalOps.Txy is updated
int add(const std::string &aname)
AB type of DistanceTable containing storage.
void mw_evaluate(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list) const override
Evaluate the contribution of this component of multiple walkers.
static void mw_evaluateOne(const RefVectorWithLeader< NonLocalECPComponent > &ecp_component_list, const RefVectorWithLeader< ParticleSet > &p_list, const RefVectorWithLeader< TrialWaveFunction > &psi_list, const RefVector< const NLPPJob< RealType >> &joblist, std::vector< RealType > &pairpots, ResourceCollection &collection, bool use_DLA)
Evaluate the nonlocal pp contribution via randomized quadrature grid to total energy from ion "iat" a...
ReportingFunction report
Definition: Listener.hpp:55
CASTTYPE & getCastedElement(size_t i) const
int groupsize(int igroup) const
return the size of a group
Definition: ParticleSet.h:527
void addComponent(int groupID, std::unique_ptr< NonLocalECPComponent > &&pp)
RandomBase< FullPrecRealType > * myRNG
random number generator
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
void checkoutParticleQuantities(TraceManager &tm) override
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
void setEnergyDomain(EnergyDomains edomain)
Set the Energy Domain.
void evaluateImpl(ParticleSet &P, bool Tmove, bool keepGrid=false)
the actual implementation, used by evaluate and evaluateWithToperator
NeighborLists IonNeighborElecs
neighborlist of ions
void addValue(PropertySetType &plist)
named values to the property list
QMCTraits::TensorType generateRandomRotationMatrix(RandomBase< QMCTraits::FullPrecRealType > &rng)
Create a random 3D rotation matrix using a random generator.
SpeciesSet & getSpeciesSet()
retrun the SpeciesSet of this particle set
Definition: ParticleSet.h:231
Array< TraceReal, D > * checkout_real(const std::string &name, int n1=1, int n2=0, int n3=0, int n4=0)
NonLocalECPotential(ParticleSet &ions, ParticleSet &els, TrialWaveFunction &psi, bool computeForces, bool enable_DLA)
constructor
FullPrecRealType Return_t
type of return value of evaluate
Definition: OperatorBase.h:64
Type_t sum() const
Definition: OhmmsArray.h:214
std::vector< std::reference_wrapper< T > > RefVector
bool use_DLA
true, determinant localization approximation(DLA) is enabled
Return_t evaluateWithIonDerivs(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi, ParticleSet::ParticlePos &hf_terms, ParticleSet::ParticlePos &pulay_terms) override
Evaluate contribution to local energy and derivatives w.r.t ionic coordinates from OperatorBase...
virtual void setParticlePropertyList(PropertySetType &plist, int offset)
Evaluate the semi local potentials.
NeighborLists ElecNeighborIons
neighborlist of electrons
Class to represent a many-body trial wave function.
void addObservables(PropertySetType &plist, BufferType &collectables) override
named values to the property list Default implementaton uses addValue(plist_)
Return_t value_
current value
Definition: OperatorBase.h:524
Return_t evaluate(ParticleSet &P) override
Evaluate the local energy contribution of this component.
void markAffectedElecs(const DistanceTableAB &myTable, int iel)
mark all the electrons affected by Tmoves and update ElecNeighborIons and IonNeighborElecs ...
std::vector< std::vector< NLPPJob< Real > > > nlpp_jobs
NLPP job list of ion-electron pairs by spin group.
void mw_evaluateWithToperator(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list) const override
Evaluate the contribution of this component of multiple walkers.
std::vector< bool > elecTMAffected
ture if an electron is affected by other electrons moved by T-moves
void contribute_array(const std::string &name, bool default_quantity=false)
Definition: TraceManager.h:198
const NonLocalData * selectMove(RealType prob, const std::vector< NonLocalData > &txy)
select the move for a given probability
Return_t evaluateWithIonDerivsDeterministic(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi, ParticleSet::ParticlePos &hf_terms, ParticleSet::ParticlePos &pulay_terms) override
Evaluate contribution to local energy and derivatives w.r.t ionic coordinates from OperatorBase...
bool makeMoveAndCheck(Index_t iat, const SingleParticlePos &displ)
move the iat-th particle to active_pos_
std::vector< int > & getNeighborList(int source)
get the neighbor list of the source particle
Definition: NeighborLists.h:32
virtual void setObservables(PropertySetType &plist)
Set the values evaluated by this object to plist Default implementation is to assign Value which is u...
Return_t evaluateDeterministic(ParticleSet &P) override
Evaluate the local energy contribution of this component, deterministically based on current state...
ResourceHandle< RS > lendResource()
std::unique_ptr< OperatorBase > makeClone(ParticleSet &qp, TrialWaveFunction &psi) override
double B(double x, int k, int i, const std::vector< double > &t)
std::vector< std::unique_ptr< NonLocalECPComponent > > PPset
unique NonLocalECPComponent to remove
ParticleSet::ParticlePos PulayTerm
Pulay force vector.
void prepareGroup(ParticleSet &P, int ig)
Prepare internal data for updating WFC correspond to a particle group Particle groups usually corresp...
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
void evalIonDerivsImpl(ParticleSet &P, ParticleSet &ions, TrialWaveFunction &psi, ParticleSet::ParticlePos &hf_terms, ParticleSet::ParticlePos &pulay_terms, bool keepGrid=false)
void mw_evaluatePerParticleWithToperator(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const std::vector< ListenerVector< Real >> &listeners, const std::vector< ListenerVector< Real >> &listeners_ions) const override
void setParticlePropertyList(PropertySetType &plist, int offset) override
ValueType calcRatioGrad(ParticleSet &P, int iat, GradType &grad_iat)
compute psi(R_new) / psi(R_current) ratio and ln(psi(R_new)) gradients It returns a complex value if...
void donePbyP(bool skipSK=false)
update structure factor and unmark active_ptcl_
Convenience container for common optional element to mw_eval.._impl.
Definition: Listener.hpp:76
TrialWaveFunction & Psi
target TrialWaveFunction
std::bitset< 8 > update_mode_
set the current update mode
Definition: OperatorBase.h:521
void completeUpdates()
complete all the delayed or asynchronous operations before leaving the p-by-p move region...
int getGroupID(int iat) const
return the group id of a given particle in the particle set.
Definition: ParticleSet.h:520
void mw_evaluatePerParticle(const RefVectorWithLeader< OperatorBase > &o_list, const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< ParticleSet > &p_list, const std::vector< ListenerVector< Real >> &listeners, const std::vector< ListenerVector< Real >> &listeners_ions) const override