QMCPACK
NonLocalECPComponent.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) 2016 Jeongnim Kim and 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 //
13 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
14 //////////////////////////////////////////////////////////////////////////////////////
15 
16 
17 #include "Particle/DistanceTable.h"
18 #include "NonLocalECPComponent.h"
19 #include "NLPPJob.h"
20 #include "NonLocalData.h"
22 
23 namespace qmcplusplus
24 {
25 NonLocalECPComponent::NonLocalECPComponent() : lmax(0), nchannel(0), nknot(0), Rmax(-1), VP(nullptr), do_randomize_grid_(true) {}
26 
27 // unfortunately we continue the sloppy use of the default copy constructor followed by reassigning pointers.
28 // This prevents use of smart pointers and concievably sets us up for trouble with double frees and the destructor.
30  : NonLocalECPComponent(nl_ecpc)
31 {
32  for (int i = 0; i < nl_ecpc.nlpp_m.size(); ++i)
33  nlpp_m[i] = nl_ecpc.nlpp_m[i]->makeClone();
34  if (nl_ecpc.VP)
35  VP = new VirtualParticleSet(pset, nknot, nl_ecpc.VP->getNumDistTables());
36 }
37 
39 {
40  for (int ip = 0; ip < nlpp_m.size(); ip++)
41  delete nlpp_m[ip];
42  if (VP)
43  delete VP;
44 }
45 
46 void NonLocalECPComponent::set_randomize_grid(bool do_randomize_grid)
47 {
48  do_randomize_grid_ = do_randomize_grid;
49 }
50 
52 {
53  assert(VP == 0);
55  VP = new VirtualParticleSet(qp, nknot);
57 }
58 
60 {
61  if (VP)
62  delete VP;
63  VP = nullptr;
64 }
65 
67 {
68  angpp_m.push_back(l);
69  wgt_angpp_m.push_back(static_cast<RealType>(2 * l + 1));
70  nlpp_m.push_back(pp);
71 }
72 
74 {
75  psiratio.resize(n);
76  gradpsiratio.resize(n);
77  deltaV.resize(n);
78  cosgrad.resize(n);
79  wfngrad.resize(n);
80  knot_pots.resize(n);
81  vrad.resize(m);
82  dvrad.resize(m);
83  vgrad.resize(m);
84  wvec.resize(n);
85  lpol.resize(l + 1, 1.0);
86  //dlpol needs two data points to do a recursive construction. Also is only nontrivial for l>1.
87  //This +2 guards against l=0 case.
88  dlpol.resize(l + 2, 0.0);
89  rrotsgrid_m.resize(n);
90  nchannel = nlpp_m.size();
91  nknot = sgridxyz_m.size();
92 
93  //Now we inititalize the quadrature grid rrotsgrid_m to the unrotated grid.
95 
96  //This is just to check
97  //for(int nl=1; nl<nlpp_m.size(); nl++) nlpp_m[nl]->setGridManager(false);
98  if (lmax)
99  {
100  if (lmax > 7)
101  {
102  APP_ABORT("Increase the maximum angular momentum implemented.");
103  }
104  //Lfactor1.resize(lmax);
105  //Lfactor2.resize(lmax);
106  for (int nl = 0; nl < lmax; nl++)
107  {
108  Lfactor1[nl] = static_cast<RealType>(2 * nl + 1);
109  Lfactor2[nl] = 1.0e0 / static_cast<RealType>(nl + 1);
110  }
111  }
112 }
113 
114 void NonLocalECPComponent::print(std::ostream& os)
115 {
116  os << " Maximum angular momentum = " << lmax << std::endl;
117  os << " Number of non-local channels = " << nchannel << std::endl;
118  for (int l = 0; l < nchannel; l++)
119  os << " l(" << l << ")=" << angpp_m[l] << std::endl;
120  os << " Cutoff radius = " << Rmax << std::endl;
121  os << " Number of spherical integration grid points = " << nknot << std::endl;
123  {
124  os << " Spherical grid and weights: " << std::endl;
125  for (int ik = 0; ik < nknot; ik++)
126  os << " " << sgridxyz_m[ik] << std::setw(20) << sgridweight_m[ik] << std::endl;
127  }
128 }
129 
131  int iat,
132  TrialWaveFunction& psi,
133  int iel,
134  RealType r,
135  const PosType& dr,
136  bool use_DLA)
137 {
139 
140  if (VP)
141  {
142  // Compute ratios with VP
143  VP->makeMoves(W, iel, deltaV, true, iat);
144  if (use_DLA)
146  else
147  psi.evaluateRatios(*VP, psiratio);
148  }
149  else
150  {
151  // Compute ratio of wave functions
152  for (int j = 0; j < nknot; j++)
153  {
154  W.makeMove(iel, deltaV[j], false);
155  if (use_DLA)
157  else
158  psiratio[j] = psi.calcRatio(W, iel);
159  W.rejectMove(iel);
160  psi.resetPhaseDiff();
161  }
162  }
163 
164  return calculateProjector(r, dr);
165 }
166 
168 {
169  for (int j = 0; j < nknot; j++)
170  psiratio[j] *= sgridweight_m[j];
171 
172  // Compute radial potential, multiplied by (2l+1) factor.
173  for (int ip = 0; ip < nchannel; ip++)
174  vrad[ip] = nlpp_m[ip]->splint(r) * wgt_angpp_m[ip];
175 
176  constexpr RealType czero(0);
177  constexpr RealType cone(1);
178 
179  const RealType rinv = cone / r;
180  RealType pairpot = czero;
181  // Compute spherical harmonics on grid
182  for (int j = 0; j < nknot; j++)
183  {
184  RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
185  // Forming the Legendre polynomials
186  lpol[0] = cone;
187  RealType lpolprev = czero;
188  for (int l = 0; l < lmax; l++)
189  {
190  lpol[l + 1] = (Lfactor1[l] * zz * lpol[l] - l * lpolprev) * Lfactor2[l];
191  lpolprev = lpol[l];
192  }
193 
194  RealType lsum = 0.0;
195  for (int l = 0; l < nchannel; l++)
196  lsum += vrad[l] * lpol[angpp_m[l]];
197  knot_pots[j] = lsum * std::real(psiratio[j]);
198  pairpot += knot_pots[j];
199  }
200 
201  return pairpot;
202 }
203 
205  const RefVectorWithLeader<ParticleSet>& p_list,
207  const RefVector<const NLPPJob<RealType>>& joblist,
208  std::vector<RealType>& pairpots,
209  ResourceCollection& collection,
210  bool use_DLA)
211 {
212  auto& ecp_component_leader = ecp_component_list.getLeader();
213  if (ecp_component_leader.VP)
214  {
215  // Compute ratios with VP
216  RefVectorWithLeader<VirtualParticleSet> vp_list(*ecp_component_leader.VP);
217  RefVectorWithLeader<const VirtualParticleSet> const_vp_list(*ecp_component_leader.VP);
219  RefVector<std::vector<ValueType>> psiratios_list;
220  vp_list.reserve(ecp_component_list.size());
221  const_vp_list.reserve(ecp_component_list.size());
222  deltaV_list.reserve(ecp_component_list.size());
223  psiratios_list.reserve(ecp_component_list.size());
224 
225  for (size_t i = 0; i < ecp_component_list.size(); i++)
226  {
227  NonLocalECPComponent& component(ecp_component_list[i]);
228  const NLPPJob<RealType>& job = joblist[i];
229 
231 
232  vp_list.push_back(*component.VP);
233  const_vp_list.push_back(*component.VP);
234  deltaV_list.push_back(component.deltaV);
235  psiratios_list.push_back(component.psiratio);
236  }
237 
238  ResourceCollectionTeamLock<VirtualParticleSet> vp_res_lock(collection, vp_list);
239 
240  VirtualParticleSet::mw_makeMoves(vp_list, p_list, deltaV_list, joblist, true);
241 
242  if (use_DLA)
243  TrialWaveFunction::mw_evaluateRatios(psi_list, const_vp_list, psiratios_list,
245  else
246  TrialWaveFunction::mw_evaluateRatios(psi_list, const_vp_list, psiratios_list);
247  }
248  else
249  {
250  // Compute ratios without VP. This is working but very slow code path.
251  for (size_t i = 0; i < p_list.size(); i++)
252  {
253  NonLocalECPComponent& component(ecp_component_list[i]);
254  ParticleSet& W(p_list[i]);
255  TrialWaveFunction& psi(psi_list[i]);
256  const NLPPJob<RealType>& job = joblist[i];
257 
259 
260  // Compute ratio of wave functions
261  for (int j = 0; j < component.getNknot(); j++)
262  {
263  W.makeMove(job.electron_id, component.deltaV[j], false);
264  if (use_DLA)
266  else
267  component.psiratio[j] = psi.calcRatio(W, job.electron_id);
268  W.rejectMove(job.electron_id);
269  psi.resetPhaseDiff();
270  }
271  }
272  }
273 
274  for (size_t i = 0; i < p_list.size(); i++)
275  {
276  NonLocalECPComponent& component(ecp_component_list[i]);
277  const NLPPJob<RealType>& job = joblist[i];
278  pairpots[i] = component.calculateProjector(job.ion_elec_dist, job.ion_elec_displ);
279  }
280 }
281 
283  int iat,
284  TrialWaveFunction& psi,
285  int iel,
286  RealType r,
287  const PosType& dr,
288  PosType& force_iat)
289 {
290  constexpr RealType czero(0);
291  constexpr RealType cone(1);
292 
293  //We check that our quadrature grid is valid. Namely, that all points lie on the unit sphere.
294  //We check this by seeing if |r|^2 = 1 to machine precision.
295  for (int j = 0; j < nknot; j++)
296  assert(std::abs(std::sqrt(dot(rrotsgrid_m[j], rrotsgrid_m[j])) - 1) <
297  100 * std::numeric_limits<RealType>::epsilon());
298 
299 
300  for (int j = 0; j < nknot; j++)
301  deltaV[j] = r * rrotsgrid_m[j] - dr;
302 
303  GradType gradtmp_(0);
304  PosType realgradtmp_(0);
305 
306  //Pseudopotential derivative w.r.t. ions can be split up into 3 contributions:
307  // term coming from the gradient of the radial potential
308  PosType gradpotterm_(0);
309  // term coming from gradient of legendre polynomial
310  PosType gradlpolyterm_(0);
311  // term coming from dependence of quadrature grid on ion position.
312  PosType gradwfnterm_(0);
313 
314  if (VP)
315  {
316  APP_ABORT("NonLocalECPComponent::evaluateOneWithForces(...): Forces not implemented with virtual particle moves\n");
317  // Compute ratios with VP
318  VP->makeMoves(W, iel, deltaV, true, iat);
319  psi.evaluateRatios(*VP, psiratio);
320  }
321  else
322  {
323  // Compute ratio of wave functions
324  for (int j = 0; j < nknot; j++)
325  {
326  W.makeMove(iel, deltaV[j], false);
327  psiratio[j] = psi.calcRatioGrad(W, iel, gradtmp_);
328  //QMCPACK spits out $\nabla\Psi(q)/\Psi(q)$.
329  //Multiply times $\Psi(q)/\Psi(r)$ to get
330  // $\nabla\Psi(q)/\Psi(r)
331  gradtmp_ *= psiratio[j];
332 #if defined(QMC_COMPLEX)
333  //And now we take the real part and save it.
334  convertToReal(gradtmp_, gradpsiratio[j]);
335 #else
336  //Real nonlocalpp forces seem to differ from those in the complex build. Since
337  //complex build has been validated against QE, that indicates there's a bug for the real build.
338  gradpsiratio[j] = gradtmp_;
339 #endif
340  W.rejectMove(iel);
341  psi.resetPhaseDiff();
342  //psi.rejectMove(iel);
343  }
344  }
345 
346  for (int j = 0; j < nknot; j++)
347  psiratio[j] *= sgridweight_m[j];
348 
349  // This is just a temporary variable to dump d2/dr2 into for spline evaluation.
350  RealType secondderiv(0);
351 
352  const RealType rinv = cone / r;
353 
354  // Compute radial potential and its derivative times (2l+1)
355  for (int ip = 0; ip < nchannel; ip++)
356  {
357  //fun fact. NLPComponent stores v(r) as v(r), and not as r*v(r) like in other places.
358  vrad[ip] = nlpp_m[ip]->splint(r, dvrad[ip], secondderiv) * wgt_angpp_m[ip];
359  vgrad[ip] = dvrad[ip] * dr * wgt_angpp_m[ip] * rinv;
360  }
361 
362  RealType pairpot = 0;
363  // Compute spherical harmonics on grid
364  for (int j = 0; j < nknot; j++)
365  {
366  RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
367  PosType uminusrvec = rrotsgrid_m[j] - zz * dr * rinv;
368 
369  cosgrad[j] = rinv * uminusrvec;
370 
371  RealType udotgradpsi = dot(gradpsiratio[j], rrotsgrid_m[j]);
372  wfngrad[j] = gradpsiratio[j] - dr * (udotgradpsi * rinv);
373  wfngrad[j] *= sgridweight_m[j];
374 
375  // Forming the Legendre polynomials
376  //P_0(x)=1; P'_0(x)=0.
377  lpol[0] = cone;
378  dlpol[0] = czero;
379 
380  RealType lpolprev = czero;
381  RealType dlpolprev = czero;
382 
383  for (int l = 0; l < lmax; l++)
384  {
385  //Legendre polynomial recursion formula.
386  lpol[l + 1] = (Lfactor1[l] * zz * lpol[l] - l * lpolprev) * Lfactor2[l];
387 
388  //and for the derivative...
389  dlpol[l + 1] = (Lfactor1[l] * (zz * dlpol[l] + lpol[l]) - l * dlpolprev) * Lfactor2[l];
390 
391  lpolprev = lpol[l];
392  dlpolprev = dlpol[l];
393  }
394 
395  RealType lsum = czero;
396  // Now to compute the forces:
397  gradpotterm_ = 0;
398  gradlpolyterm_ = 0;
399  gradwfnterm_ = 0;
400 
401  for (int l = 0; l < nchannel; l++)
402  {
403  lsum += vrad[l] * lpol[angpp_m[l]];
404  gradpotterm_ += vgrad[l] * lpol[angpp_m[l]] * std::real(psiratio[j]);
405  gradlpolyterm_ += vrad[l] * dlpol[angpp_m[l]] * cosgrad[j] * std::real(psiratio[j]);
406  gradwfnterm_ += vrad[l] * lpol[angpp_m[l]] * wfngrad[j];
407  }
408  knot_pots[j] = lsum * std::real(psiratio[j]);
409  pairpot += knot_pots[j];
410  force_iat += gradpotterm_ + gradlpolyterm_ - gradwfnterm_;
411  }
412 
413  return pairpot;
414 }
415 
417  ParticleSet& ions,
418  int iat,
419  TrialWaveFunction& psi,
420  int iel,
421  RealType r,
422  const PosType& dr,
423  PosType& force_iat,
424  ParticleSet::ParticlePos& pulay_terms)
425 {
426  constexpr RealType czero(0);
427  constexpr RealType cone(1);
428 
429  //We check that our quadrature grid is valid. Namely, that all points lie on the unit sphere.
430  //We check this by seeing if |r|^2 = 1 to machine precision.
431  for (int j = 0; j < nknot; j++)
432  assert(std::abs(std::sqrt(dot(rrotsgrid_m[j], rrotsgrid_m[j])) - 1) <
433  100 * std::numeric_limits<RealType>::epsilon());
434 
435  for (int j = 0; j < nknot; j++)
436  deltaV[j] = r * rrotsgrid_m[j] - dr;
437 
438  GradType gradtmp_(0);
439  PosType realgradtmp_(0);
440 
441  //Pseudopotential derivative w.r.t. ions can be split up into 3 contributions:
442  // term coming from the gradient of the radial potential
443  PosType gradpotterm_(0);
444  // term coming from gradient of legendre polynomial
445  PosType gradlpolyterm_(0);
446  // term coming from dependence of quadrature grid on ion position.
447  PosType gradwfnterm_(0);
448 
449  //Now for the Pulay specific stuff...
450  // $\nabla_I \Psi(...r...)/\Psi(...r...)$
451  ParticleSet::ParticlePos pulay_ref;
452  ParticleSet::ParticlePos pulaytmp_;
453  // $\nabla_I \Psi(...q...)/\Psi(...r...)$ for each quadrature point.
454  std::vector<ParticleSet::ParticlePos> pulay_quad(nknot);
455 
456  //A working array for pulay stuff.
457  GradType iongradtmp_(0);
458  //resize everything.
459  pulay_ref.resize(ions.getTotalNum());
460  pulaytmp_.resize(ions.getTotalNum());
461  for (size_t j = 0; j < nknot; j++)
462  pulay_quad[j].resize(ions.getTotalNum());
463 
464  if (VP)
465  {
466  APP_ABORT("NonLocalECPComponent::evaluateOneWithForces(...): Forces not implemented with virtual particle moves\n");
467  // Compute ratios with VP
468  VP->makeMoves(W, iel, deltaV, true, iat);
469  psi.evaluateRatios(*VP, psiratio);
470  }
471  else
472  {
473  // Compute ratio of wave functions
474  for (int j = 0; j < nknot; j++)
475  {
476  W.makeMove(iel, deltaV[j], false);
477  psiratio[j] = psi.calcRatioGrad(W, iel, gradtmp_);
478  //QMCPACK spits out $\nabla\Psi(q)/\Psi(q)$.
479  //Multiply times $\Psi(q)/\Psi(r)$ to get
480  // $\nabla\Psi(q)/\Psi(r)
481  gradtmp_ *= psiratio[j];
482 #if defined(QMC_COMPLEX)
483  //And now we take the real part and save it.
484  convertToReal(gradtmp_, gradpsiratio[j]);
485 #else
486  //Real nonlocalpp forces seem to differ from those in the complex build. Since
487  //complex build has been validated against QE, that indicates there's a bug for the real build.
488  gradpsiratio[j] = gradtmp_;
489 #endif
490  W.rejectMove(iel);
491  psi.resetPhaseDiff();
492  //psi.rejectMove(iel);
493  }
494  }
495 
496  for (int j = 0; j < nknot; j++)
497  psiratio[j] *= sgridweight_m[j];
498 
499  // This is just a temporary variable to dump d2/dr2 into for spline evaluation.
500  RealType secondderiv(0);
501 
502  const RealType rinv = cone / r;
503 
504  // Compute radial potential and its derivative times (2l+1)
505  for (int ip = 0; ip < nchannel; ip++)
506  {
507  //fun fact. NLPComponent stores v(r) as v(r), and not as r*v(r) like in other places.
508  vrad[ip] = nlpp_m[ip]->splint(r, dvrad[ip], secondderiv) * wgt_angpp_m[ip];
509  vgrad[ip] = dvrad[ip] * dr * wgt_angpp_m[ip] * rinv;
510  }
511 
512  //Now to construct the 3N dimensional ionic wfn derivatives for pulay terms.
513  //This is going to be slow an painful for now.
514  for (size_t jat = 0; jat < ions.getTotalNum(); jat++)
515  {
516  convertToReal(psi.evalGradSource(W, ions, jat), pulay_ref[jat]);
517  gradpotterm_ = 0;
518  for (size_t j = 0; j < nknot; j++)
519  {
520  deltaV[j] = r * rrotsgrid_m[j] - dr;
521  //This sequence is necessary to update the distance tables and make the
522  //inverse matrix available for force computation. Move the particle to
523  //quadrature point...
524  W.makeMove(iel, deltaV[j]);
525  psi.calcRatio(W, iel);
526  psi.acceptMove(W, iel);
527  W.acceptMove(iel); // it only updates the jel-th row of e-e table
528  //Done with the move. Ready for force computation.
529 
530  iongradtmp_ = psi.evalGradSource(W, ions, jat);
531  iongradtmp_ *= psiratio[j];
532  convertToReal(iongradtmp_, pulay_quad[j][jat]);
533  //And move the particle back.
534  deltaV[j] = dr - r * rrotsgrid_m[j];
535 
536  // mirror the above in reverse order
537  W.makeMove(iel, deltaV[j]);
538  psi.calcRatio(W, iel);
539  psi.acceptMove(W, iel);
540  W.acceptMove(iel);
541  }
542  }
543 
544  RealType pairpot = 0;
545  // Compute spherical harmonics on grid
546  for (int j = 0; j < nknot; j++)
547  {
548  RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
549  PosType uminusrvec = rrotsgrid_m[j] - zz * dr * rinv;
550 
551  cosgrad[j] = rinv * uminusrvec;
552 
553  RealType udotgradpsi = dot(gradpsiratio[j], rrotsgrid_m[j]);
554  wfngrad[j] = gradpsiratio[j] - dr * (udotgradpsi * rinv);
555  wfngrad[j] *= sgridweight_m[j];
556 
557  // Forming the Legendre polynomials
558  //P_0(x)=1; P'_0(x)=0.
559  lpol[0] = cone;
560  dlpol[0] = czero;
561 
562  RealType lpolprev = czero;
563  RealType dlpolprev = czero;
564 
565  for (int l = 0; l < lmax; l++)
566  {
567  //Legendre polynomial recursion formula.
568  lpol[l + 1] = (Lfactor1[l] * zz * lpol[l] - l * lpolprev) * Lfactor2[l];
569 
570  //and for the derivative...
571  dlpol[l + 1] = (Lfactor1[l] * (zz * dlpol[l] + lpol[l]) - l * dlpolprev) * Lfactor2[l];
572 
573  lpolprev = lpol[l];
574  dlpolprev = dlpol[l];
575  }
576 
577  RealType lsum = czero;
578  // Now to compute the forces:
579  gradpotterm_ = 0;
580  gradlpolyterm_ = 0;
581  gradwfnterm_ = 0;
582  pulaytmp_ = 0;
583 
584  for (int l = 0; l < nchannel; l++)
585  {
586  //Note. Because we are computing "forces", there's a -1 difference between this and
587  //direct finite difference calculations.
588  lsum += vrad[l] * lpol[angpp_m[l]];
589  gradpotterm_ += vgrad[l] * lpol[angpp_m[l]] * std::real(psiratio[j]);
590  gradlpolyterm_ += vrad[l] * dlpol[angpp_m[l]] * cosgrad[j] * std::real(psiratio[j]);
591  gradwfnterm_ += vrad[l] * lpol[angpp_m[l]] * wfngrad[j];
592  pulaytmp_ -= vrad[l] * lpol[angpp_m[l]] * pulay_quad[j];
593  }
594  knot_pots[j] = lsum * std::real(psiratio[j]);
595  pulaytmp_ += knot_pots[j] * pulay_ref;
596  pairpot += knot_pots[j];
597  force_iat += gradpotterm_ + gradlpolyterm_ - gradwfnterm_;
598  pulay_terms += pulaytmp_;
599  }
600 
601  return pairpot;
602 }
603 
605  const int iat,
606  const TWFFastDerivWrapper& psi,
607  const int iel,
608  const RealType r,
609  const PosType& dr,
610  std::vector<ValueMatrix>& B)
611 
612 {
614  //Some initial computation to find out the species and row number of electron.
615  const IndexType gid = W.getGroupID(iel);
616  const IndexType sid = psi.getTWFGroupIndex(gid);
617  const IndexType firstIndex = W.first(gid);
618  const IndexType thisIndex = iel - firstIndex;
619 
620  const IndexType numOrbs = psi.numOrbitals(sid);
621  ValueVector phi_row; //phi_0(r), phi_1(r), ...
622  ValueVector temp_row;
623 
624  phi_row.resize(numOrbs);
625  temp_row.resize(numOrbs);
626 
628 
629 
630  constexpr RealType czero(0);
631  constexpr RealType cone(1);
632 
633  const RealType rinv = cone / r;
634 
635  for (int ip = 0; ip < nchannel; ip++)
636  vrad[ip] = nlpp_m[ip]->splint(r) * wgt_angpp_m[ip];
637 
638  for (int j = 0; j < nknot; j++)
639  {
640  W.makeMove(iel, deltaV[j], false); //Update distance tables.
641  psi.getRowM(W, iel, phi_row);
642  RealType jratio = psi.evaluateJastrowRatio(W, iel);
643  W.rejectMove(iel);
644 
645  RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
646  // Forming the Legendre polynomials
647  lpol[0] = cone;
648  RealType lpolprev = czero;
649  for (int l = 0; l < lmax; l++)
650  {
651  lpol[l + 1] = Lfactor2[l] * (Lfactor1[l] * zz * lpol[l] - l * lpolprev);
652  lpolprev = lpol[l];
653  }
654 
655  ValueType lsum = 0.0;
656  for (int l = 0; l < nchannel; l++)
657  {
658  temp_row = (vrad[l] * lpol[angpp_m[l]] * sgridweight_m[j]) * jratio * phi_row;
659  for (int iorb = 0; iorb < numOrbs; iorb++)
660  B[sid][thisIndex][iorb] += temp_row[iorb];
661  }
662  }
663 }
664 
666  ParticleSet& ions,
667  const int iat,
668  const int iat_src,
669  const TWFFastDerivWrapper& psi,
670  const int iel,
671  const RealType r,
672  const PosType& dr,
673  std::vector<std::vector<ValueMatrix>>& dB)
674 {
676  using GradVector = SPOSet::GradVector;
677  constexpr RealType czero(0);
678  constexpr RealType cone(1);
679 
680  //We check that our quadrature grid is valid. Namely, that all points lie on the unit sphere.
681  //We check this by seeing if |r|^2 = 1 to machine precision.
682  for (int j = 0; j < nknot; j++)
683  assert(std::abs(std::sqrt(dot(rrotsgrid_m[j], rrotsgrid_m[j])) - 1) <
684  100 * std::numeric_limits<RealType>::epsilon());
685 
686  for (int j = 0; j < nknot; j++)
687  deltaV[j] = r * rrotsgrid_m[j] - dr;
688 
689  // This is just a temporary variable to dump d2/dr2 into for spline evaluation.
690  RealType secondderiv(0);
691 
692  const RealType rinv = cone / r;
693 
694  // Compute radial potential and its derivative times (2l+1)
695  for (int ip = 0; ip < nchannel; ip++)
696  {
697  //fun fact. NLPComponent stores v(r) as v(r), and not as r*v(r) like in other places.
698  vrad[ip] = nlpp_m[ip]->splint(r, dvrad[ip], secondderiv) * wgt_angpp_m[ip];
699  vgrad[ip] = dvrad[ip] * dr * wgt_angpp_m[ip] * rinv;
700  }
701 
702  const IndexType gid = W.getGroupID(iel);
703  const IndexType sid = psi.getTWFGroupIndex(gid);
704  const IndexType thisEIndex = iel - W.first(gid);
705  const IndexType numptcls = W.last(gid) - W.first(gid);
706  const IndexType norbs = psi.numOrbitals(sid);
707  SPOSet& spo(*psi.getSPOSet(sid));
708 
709  RealType pairpot = 0;
710  // Compute spherical harmonics on grid
711  GradMatrix iongrad_phimat;
712  GradVector iongrad_phi;
713  ValueVector phi, laplphi;
714  ValueMatrix phimat, laplphimat;
715  GradMatrix gradphimat;
716  GradVector gradphi;
717  GradMatrix wfgradmat;
718 
719  //This stores all ion gradients of the Jastrow, evaluated on all quadrature points.
720  //Has length nknot.
722  jgrad_quad.resize(nknot);
723 
724  wfgradmat.resize(nknot, norbs);
725 
726  iongrad_phimat.resize(nknot, norbs);
727  laplphimat.resize(nknot, norbs);
728 
729  phimat.resize(nknot, norbs);
730  gradphimat.resize(nknot, norbs);
731  iongrad_phi.resize(norbs);
732  phi.resize(norbs);
733  gradphi.resize(norbs);
734  laplphi.resize(norbs);
735 
736  GradVector udotgradpsi, wfgradrow;
737  GradMatrix udotgradpsimat;
738  GradVector gpot, glpoly, gwfn;
739  ValueVector nlpp_prefactor;
740  GradVector dlpoly_prefactor;
741  GradVector dvdr_prefactor;
742 
743  nlpp_prefactor.resize(nknot);
744  dlpoly_prefactor.resize(nknot);
745  dvdr_prefactor.resize(nknot);
746 
747  udotgradpsimat.resize(nknot, norbs);
748  wfgradrow.resize(norbs);
749  udotgradpsi.resize(norbs);
750  gpot.resize(norbs);
751  glpoly.resize(norbs);
752  gwfn.resize(norbs);
753 
755  //This is the ion gradient of J at the original (non quadrature) coordinate.
756  GradType jigradref(0.0);
757 
758  jigradref = psi.evaluateJastrowGradSource(W, ions, iat_src);
759 
760  //Until we have a more efficient routine, we move to a quadrature point,
761  //update distance tables, compute the ion gradient of J, then move the particle back.
762  //At cost of distance table updates. Not good, but works.
763  for (int j = 0; j < nknot; j++)
764  {
765  W.makeMove(iel, deltaV[j], false);
766  W.acceptMove(iel);
767  jgrad_quad[j] = psi.evaluateJastrowGradSource(W, ions, iat_src);
768  W.makeMove(iel, -deltaV[j], false);
769  W.acceptMove(iel);
770  }
771 
772  for (int j = 0; j < nknot; j++)
773  {
774  W.makeMove(iel, deltaV[j], false);
775  iongrad_phi = 0.0;
776  spo.evaluateGradSourceRow(W, iel, ions, iat_src, iongrad_phi);
777  GradType jegrad(0.0);
778  GradType jigrad(0.0);
779 
780  RealType jratio = psi.calcJastrowRatioGrad(W, iel, jegrad);
781  jigrad = psi.evaluateJastrowGradSource(W, ions, iat_src);
782 
783  spo.evaluateVGL(W, iel, phi, gradphi, laplphi);
784 
785  //Quick comment on the matrix elements being computed below.
786  //For the no jastrow implementation, phimat, gradphimat, iongrad_phimat were straightforward containers storing phi_j(r_i), grad(phi_j), etc.
787  //Generalizing to jastrows is straightforward if we replace phi_j(q) with exp(J(q))/exp(J(r))*phi(q). Storing these in the phimat, gradphimat, etc.
788  //data structures allows us to not modify the rather complicated expressions we have already derived.
789  if (iat == iat_src)
790  {
791  for (int iorb = 0; iorb < norbs; iorb++)
792  {
793  //Treating exp(J(q))/exp(J(r))phi_j(q) as the fundamental block.
794  phimat[j][iorb] = jratio * phi[iorb];
795  //This is the electron gradient of the above expression.
796  gradphimat[j][iorb] = jratio * (gradphi[iorb] + GradType(jegrad) * phi[iorb]);
797  laplphimat[j][iorb] = laplphi[iorb]; //this is not used, so not including jastrow contribution.
798  }
799  }
800  for (int iorb = 0; iorb < norbs; iorb++)
801  {
802  //This is the ion gradient of exp(J(q))/exp(J(r))phi_j(q).
803  iongrad_phimat[j][iorb] = jratio * (iongrad_phi[iorb] + phi[iorb] * (GradType(jgrad_quad[j]) - jigradref));
804  }
805  W.rejectMove(iel);
806  }
807 
808  for (int j = 0; j < nknot; j++)
809  {
810  RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
811  PosType uminusrvec = rrotsgrid_m[j] - zz * dr * rinv;
812 
813  cosgrad[j] = rinv * uminusrvec;
814 
815  // Forming the Legendre polynomials
816  //P_0(x)=1; P'_0(x)=0.
817  lpol[0] = cone;
818  dlpol[0] = czero;
819  dlpol[1] = cone;
820 
821  RealType lpolprev = czero;
822  RealType dlpolprev = czero;
823 
824  for (int l = 0; l < lmax; l++)
825  {
826  //Legendre polynomial recursion formula.
827  lpol[l + 1] = Lfactor1[l] * zz * lpol[l] - l * lpolprev;
828  lpol[l + 1] *= Lfactor2[l];
829 
830  //and for the derivative...
831  dlpol[l + 1] = Lfactor1[l] * (zz * dlpol[l] + lpol[l]) - l * dlpolprev;
832  dlpol[l + 1] *= Lfactor2[l];
833 
834  lpolprev = lpol[l];
835  dlpolprev = dlpol[l];
836  }
837 
838  for (int l = 0; l < nchannel; l++)
839  {
840  //Note. Because we are computing "forces", there's a -1 difference between this and
841  //direct finite difference calculations.
842 
843  nlpp_prefactor[j] += sgridweight_m[j] * vrad[l] * lpol[angpp_m[l]];
844  dvdr_prefactor[j] += sgridweight_m[j] * vgrad[l] * lpol[angpp_m[l]];
845  dlpoly_prefactor[j] += sgridweight_m[j] * vrad[l] * dlpol[angpp_m[l]] * cosgrad[j];
846  }
847  }
848 
849 
850  for (int j = 0; j < nknot; j++)
851  for (int iorb = 0; iorb < norbs; iorb++)
852  gwfn[iorb] += nlpp_prefactor[j] * (iongrad_phimat[j][iorb]);
853 
854  if (iat == iat_src)
855  {
856  for (int j = 0; j < nknot; j++)
857  for (int iorb = 0; iorb < norbs; iorb++)
858  {
859  //this is for diagonal case.
860  //The GradType is necessary here, since rrotsgrid_m is real. This dot() will only return the real part in this case.
861  //Does correct thing if both entries are complex.
862  udotgradpsimat[j][iorb] = dot(gradphimat[j][iorb], GradType(rrotsgrid_m[j]));
863  wfgradmat[j][iorb] = gradphimat[j][iorb] - dr * (udotgradpsimat[j][iorb] * rinv);
864  gpot[iorb] += dvdr_prefactor[j] * phimat[j][iorb];
865  glpoly[iorb] += dlpoly_prefactor[j] * phimat[j][iorb];
866  gwfn[iorb] += nlpp_prefactor[j] * (wfgradmat[j][iorb]);
867  }
868  }
869  for (int idim = 0; idim < OHMMS_DIM; idim++)
870  for (int iorb = 0; iorb < norbs; iorb++)
871  dB[idim][sid][thisEIndex][iorb] += RealType(-1.0) * gpot[iorb][idim] - glpoly[iorb][idim] + gwfn[iorb][idim];
872 }
873 
874 ///Randomly rotate sgrid_m
876 {
877  for (int i = 0; i < sgridxyz_m.size(); i++)
878  if (do_randomize_grid_)
879  rrotsgrid_m[i] = dot(rmat, sgridxyz_m[i]);
880  else
881  rrotsgrid_m[i] = sgridxyz_m[i];
882 }
883 
884 template<typename T>
885 void NonLocalECPComponent::rotateQuadratureGrid(std::vector<T>& sphere, const TensorType& rmat)
886 {
887  SpherGridType::iterator it(sgridxyz_m.begin());
888  SpherGridType::iterator it_end(sgridxyz_m.end());
889  SpherGridType::iterator jt(rrotsgrid_m.begin());
890  while (it != it_end)
891  {
892  if (do_randomize_grid_)
893  *jt = dot(rmat, *it);
894  else
895  *jt = *it;
896  ++it;
897  ++jt;
898  }
899  //copy the randomized grid to sphere
900  for (int i = 0; i < rrotsgrid_m.size(); i++)
901  for (int j = 0; j < OHMMS_DIM; j++)
902  sphere[OHMMS_DIM * i + j] = rrotsgrid_m[i][j];
903 }
904 
906  const PosType& dr,
907  std::vector<PosType>& deltaV) const
908 {
909  for (int j = 0; j < nknot; j++)
910  deltaV[j] = r * rrotsgrid_m[j] - dr;
911 }
912 
913 void NonLocalECPComponent::contributeTxy(int iel, std::vector<NonLocalData>& Txy) const
914 {
915  for (int j = 0; j < nknot; j++)
916  Txy.push_back(NonLocalData(iel, knot_pots[j], deltaV[j]));
917 }
918 
919 /// \relates NonLocalEcpComponent
920 template void NonLocalECPComponent::rotateQuadratureGrid(std::vector<float>& sphere, const TensorType& rmat);
921 template void NonLocalECPComponent::rotateQuadratureGrid(std::vector<double>& sphere, const TensorType& rmat);
922 
923 
924 } // namespace qmcplusplus
base class for Single-particle orbital sets
Definition: SPOSet.h:46
void resize(size_type n, Type_t val=Type_t())
Resize the container.
Definition: OhmmsVector.h:166
void contributeTxy(int iel, std::vector< NonLocalData > &Txy) const
contribute local non-local move data
Contains a set of radial grid potentials around a center.
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
aligned_vector< RealType > wgt_angpp_m
Weight of the angular momentum.
ValueType calcRatio(ParticleSet &P, int iat, ComputeType ct=ComputeType::ALL)
compute psi(R_new) / psi(R_current) ratio It returns a complex value if the wavefunction is complex...
void pause()
Pause the summary and log streams.
void add(int l, RadialPotentialType *pp)
add a new Non Local component
std::vector< RadialPotentialType * > nlpp_m
Non-Local part of the pseudo-potential.
QMCTraits::RealType real
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
QTBase::GradType GradType
Definition: Configuration.h:62
QTBase::RealType RealType
Definition: Configuration.h:58
MakeReturn< UnaryNode< FnFabs, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t abs(const Vector< T1, C1 > &l)
int nchannel
the number of non-local channels
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
constexpr std::complex< float > czero
Definition: BLAS.hpp:51
constexpr std::complex< float > cone
Definition: BLAS.hpp:50
void evaluateOneBodyOpMatrixdRContribution(ParticleSet &P, ParticleSet &source, const int iat, const int iat_src, const TWFFastDerivWrapper &psi, const int iel, const RealType r, const PosType &dr, std::vector< std::vector< ValueMatrix >> &dB)
Evaluate contribution to dB/dR of election iel and ion iat.
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
void makeMoves(const ParticleSet &refp, int jel, const std::vector< PosType > &deltaV, bool sphere=false, int iat=-1)
move virtual particles to new postions and update distance tables
RealType evaluateJastrowRatio(ParticleSet &P, const int iel) const
Given a proposed move of electron iel from r->r&#39;, computes exp(J&#39;)/exp(J)
void convertToReal(const T1 &in, T2 &out)
generic conversion from type T1 to type T2 using implicit conversion
Definition: ConvertToReal.h:32
GradType evaluateJastrowGradSource(ParticleSet &P, ParticleSet &source, const int iat) const
Return ionic gradient of J(r).
bool do_randomize_grid_
Can disable grid randomization for testing.
int getNumDistTables() const
Definition: ParticleSet.h:566
int first(int igroup) const
return the first index of a group i
Definition: ParticleSet.h:514
RealType Rmax
Maximum cutoff the non-local pseudopotential.
IndexType numOrbitals(const IndexType sid) const
Attaches a unit to a Vector for IO.
TWFFastDerivWrapper is a wrapper class for TrialWavefunction that provides separate and low level acc...
OrbitalSetTraits< ValueType >::ValueVector ValueVector
RealType Lfactor2[8]
Lfactor1[l]=(l)/(l+1)
#define OHMMS_DIM
Definition: config.h:64
OutputManagerClass outputManager(Verbosity::HIGH)
void evaluateOneBodyOpMatrixContribution(ParticleSet &P, const int iat, const TWFFastDerivWrapper &psi, const int iel, const RealType r, const PosType &dr, std::vector< ValueMatrix > &B)
Evaluate contribution to B of election iel and ion iat.
std::vector< ValueType > wvec
Working arrays.
SPOSet::ValueMatrix ValueMatrix
For fast derivative evaluation.
void resume()
Resume the summary and log streams.
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
SpherGridType rrotsgrid_m
randomized spherical grid
RealType calcJastrowRatioGrad(ParticleSet &P, const int iel, GradType &grad) const
Given a proposed move of electron iel from r->r&#39;, computes exp(J(r&#39;))/exp(J(r)) and grad_iel(J(r&#39;))...
void rejectMove(Index_t iat)
reject a proposed move in regular mode
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...
OrbitalSetTraits< ValueType >::ValueVector ValueVector
Definition: SPOSet.h:49
RealType Lfactor1[8]
Lfactor1[l]=(2*l+1)/(l+1)
GradType evalGradSource(ParticleSet &P, ParticleSet &source, int iat)
Returns the logarithmic gradient of the trial wave function with respect to the iat^th atom of the so...
VirtualParticleSet * VP
virtual particle set: delayed initialization
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
int last(int igroup) const
return the last index of a group i
Definition: ParticleSet.h:517
RealType evaluateOne(ParticleSet &W, int iat, TrialWaveFunction &Psi, int iel, RealType r, const PosType &dr, bool use_DLA)
Evaluate the nonlocal pp contribution via randomized quadrature grid to total energy from ion "iat" a...
static void mw_makeMoves(const RefVectorWithLeader< VirtualParticleSet > &vp_list, const RefVectorWithLeader< ParticleSet > &p_list, const RefVector< const std::vector< PosType >> &deltaV_list, const RefVector< const NLPPJob< RealType >> &joblist, bool sphere)
OHMMS_INDEXTYPE IndexType
define other types
Definition: Configuration.h:65
const RealType ion_elec_dist
Definition: NLPPJob.h:32
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)
OrbitalSetTraits< ValueType >::GradVector GradVector
Definition: SPOSet.h:51
int lmax
Non Local part: angular momentum, potential and grid.
Class to represent a many-body trial wave function.
const int electron_id
Definition: NLPPJob.h:31
void makeMove(Index_t iat, const SingleParticlePos &displ, bool maybe_accept=true)
move the iat-th particle to active_pos_
void set_randomize_grid(bool do_randomize_grid_)
IndexType getRowM(const ParticleSet &P, const IndexType iel, ValueVector &val) const
Returns value of all orbitals (relevant to given species/group) at a particular particle coordinate...
RealType evaluateOneWithForces(ParticleSet &W, int iat, TrialWaveFunction &Psi, int iel, RealType r, const PosType &dr, PosType &force_iat)
Evaluate the nonlocal pp contribution via randomized quadrature grid to total energy from ion "iat" a...
handles acquire/release resource by the consumer (RefVectorWithLeader type).
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
LatticeGaussianProduct::ValueType ValueType
ParticleAttrib< QTFull::GradType > ParticleGradient
Definition: Configuration.h:95
meta data for NLPP calculation of a pair of ion and electron This is not just meta data...
void initVirtualParticle(const ParticleSet &qp)
IndexType getTWFGroupIndex(const IndexType gid) const
Takes particle set groupID and returns the TWF internal index for it.
double B(double x, int k, int i, const std::vector< double > &t)
SPOSet * getSPOSet(const IndexType sid) const
void buildQuadraturePointDeltaPositions(RealType r, const PosType &dr, std::vector< PosType > &deltaV) const
build QP position deltas from the reference electron using internally stored random grid points ...
const PosType ion_elec_displ
Definition: NLPPJob.h:33
void acceptMove(Index_t iat)
accept the move and update the particle attribute by the proposed move in regular mode ...
bool isActive(Verbosity level) const
void resize_warrays(int n, int m, int l)
RealType calculateProjector(RealType r, const PosType &dr)
finalize the calculation of ${V}{}$
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...
static void mw_evaluateRatios(const RefVectorWithLeader< TrialWaveFunction > &wf_list, const RefVectorWithLeader< const VirtualParticleSet > &Vp_list, const RefVector< std::vector< ValueType >> &ratios_list, ComputeType ct=ComputeType::ALL)
batched version of evaluateRatios Note: unlike other mw_ static functions, *this is the batch leader ...
std::vector< RealType > sgridweight_m
weight of the spherical grid
aligned_vector< int > angpp_m
Angular momentum map.
void evaluateRatios(const VirtualParticleSet &VP, std::vector< ValueType > &ratios, ComputeType ct=ComputeType::ALL)
compulte multiple ratios to handle non-local moves and other virtual moves
SpherGridType sgridxyz_m
fixed Spherical Grid for species
int getGroupID(int iat) const
return the group id of a given particle in the particle set.
Definition: ParticleSet.h:520
void rotateQuadratureGrid(const TensorType &rmat)
Randomly rotate sgrid_m.