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/DistanceTableData.h"
18 #include "NonLocalECPComponent.h"
19 #include "QMCHamiltonians/NLPPJob.h"
20
21 namespace qmcplusplus
22 {
NonLocalECPComponent()23 NonLocalECPComponent::NonLocalECPComponent() : lmax(0), nchannel(0), nknot(0), Rmax(-1), VP(nullptr) {}
24
~NonLocalECPComponent()25 NonLocalECPComponent::~NonLocalECPComponent()
26 {
27 for (int ip = 0; ip < nlpp_m.size(); ip++)
28 delete nlpp_m[ip];
29 if (VP)
30 delete VP;
31 }
32
makeClone(const ParticleSet & qp)33 NonLocalECPComponent* NonLocalECPComponent::makeClone(const ParticleSet& qp)
34 {
35 NonLocalECPComponent* myclone = new NonLocalECPComponent(*this);
36 for (int i = 0; i < nlpp_m.size(); ++i)
37 myclone->nlpp_m[i] = nlpp_m[i]->makeClone();
38 if (VP)
39 myclone->VP = new VirtualParticleSet(qp, nknot);
40 return myclone;
41 }
42
initVirtualParticle(const ParticleSet & qp)43 void NonLocalECPComponent::initVirtualParticle(const ParticleSet& qp)
44 {
45 assert(VP == 0);
46 outputManager.pause();
47 VP = new VirtualParticleSet(qp, nknot);
48 outputManager.resume();
49 }
50
add(int l,RadialPotentialType * pp)51 void NonLocalECPComponent::add(int l, RadialPotentialType* pp)
52 {
53 angpp_m.push_back(l);
54 wgt_angpp_m.push_back(static_cast<RealType>(2 * l + 1));
55 nlpp_m.push_back(pp);
56 }
57
resize_warrays(int n,int m,int l)58 void NonLocalECPComponent::resize_warrays(int n, int m, int l)
59 {
60 psiratio.resize(n);
61 gradpsiratio.resize(n);
62 deltaV.resize(n);
63 cosgrad.resize(n);
64 wfngrad.resize(n);
65 knot_pots.resize(n);
66 vrad.resize(m);
67 dvrad.resize(m);
68 vgrad.resize(m);
69 wvec.resize(m);
70 Amat.resize(n * m);
71 dAmat.resize(n * m);
72 lpol.resize(l + 1, 1.0);
73 dlpol.resize(l + 1, 0.0);
74 rrotsgrid_m.resize(n);
75 nchannel = nlpp_m.size();
76 nknot = sgridxyz_m.size();
77 //This is just to check
78 //for(int nl=1; nl<nlpp_m.size(); nl++) nlpp_m[nl]->setGridManager(false);
79 if (lmax)
80 {
81 if (lmax > 7)
82 {
83 APP_ABORT("Increase the maximum angular momentum implemented.");
84 }
85 //Lfactor1.resize(lmax);
86 //Lfactor2.resize(lmax);
87 for (int nl = 0; nl < lmax; nl++)
88 {
89 Lfactor1[nl] = static_cast<RealType>(2 * nl + 1);
90 Lfactor2[nl] = 1.0e0 / static_cast<RealType>(nl + 1);
91 }
92 }
93 }
94
print(std::ostream & os)95 void NonLocalECPComponent::print(std::ostream& os)
96 {
97 os << " Maximum angular mementum = " << lmax << std::endl;
98 os << " Number of non-local channels = " << nchannel << std::endl;
99 for (int l = 0; l < nchannel; l++)
100 os << " l(" << l << ")=" << angpp_m[l] << std::endl;
101 os << " Cutoff radius = " << Rmax << std::endl;
102 os << " Spherical grids and weights: " << std::endl;
103 for (int ik = 0; ik < nknot; ik++)
104 os << " " << sgridxyz_m[ik] << std::setw(20) << sgridweight_m[ik] << std::endl;
105 }
106
evaluateOne(ParticleSet & W,int iat,TrialWaveFunction & psi,int iel,RealType r,const PosType & dr,bool use_DLA)107 NonLocalECPComponent::RealType NonLocalECPComponent::evaluateOne(ParticleSet& W,
108 int iat,
109 TrialWaveFunction& psi,
110 int iel,
111 RealType r,
112 const PosType& dr,
113 bool use_DLA)
114 {
115 buildQuadraturePointDeltaPositions(r, dr, deltaV);
116
117 if (VP)
118 {
119 // Compute ratios with VP
120 VP->makeMoves(iel, W.R[iel], deltaV, true, iat);
121 if (use_DLA)
122 psi.evaluateRatios(*VP, psiratio, TrialWaveFunction::ComputeType::FERMIONIC);
123 else
124 psi.evaluateRatios(*VP, psiratio);
125 }
126 else
127 {
128 // Compute ratio of wave functions
129 for (int j = 0; j < nknot; j++)
130 {
131 W.makeMove(iel, deltaV[j], false);
132 if (use_DLA)
133 psiratio[j] = psi.calcRatio(W, iel, TrialWaveFunction::ComputeType::FERMIONIC);
134 else
135 psiratio[j] = psi.calcRatio(W, iel);
136 W.rejectMove(iel);
137 psi.resetPhaseDiff();
138 }
139 }
140
141 return calculateProjector(r, dr);
142 }
143
calculateProjector(RealType r,const PosType & dr)144 NonLocalECPComponent::RealType NonLocalECPComponent::calculateProjector(RealType r, const PosType& dr)
145 {
146 for (int j = 0; j < nknot; j++)
147 psiratio[j] *= sgridweight_m[j];
148
149 // Compute radial potential, multiplied by (2l+1) factor.
150 for (int ip = 0; ip < nchannel; ip++)
151 vrad[ip] = nlpp_m[ip]->splint(r) * wgt_angpp_m[ip];
152
153 constexpr RealType czero(0);
154 constexpr RealType cone(1);
155
156 const RealType rinv = cone / r;
157 RealType pairpot = czero;
158 // Compute spherical harmonics on grid
159 for (int j = 0; j < nknot; j++)
160 {
161 RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
162 // Forming the Legendre polynomials
163 lpol[0] = cone;
164 RealType lpolprev = czero;
165 for (int l = 0; l < lmax; l++)
166 {
167 //Not a big difference
168 //lpol[l+1]=(2*l+1)*zz*lpol[l]-l*lpolprev;
169 //lpol[l+1]/=(l+1);
170 lpol[l + 1] = Lfactor1[l] * zz * lpol[l] - l * lpolprev;
171 lpol[l + 1] *= Lfactor2[l];
172 lpolprev = lpol[l];
173 }
174
175 ValueType lsum = 0.0;
176 for (int l = 0; l < nchannel; l++)
177 lsum += vrad[l] * lpol[angpp_m[l]];
178 knot_pots[j] = std::real(lsum * psiratio[j]);
179 pairpot += knot_pots[j];
180 }
181
182 return pairpot;
183 }
184
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)185 void NonLocalECPComponent::mw_evaluateOne(const RefVectorWithLeader<NonLocalECPComponent>& ecp_component_list,
186 const RefVectorWithLeader<ParticleSet>& p_list,
187 const RefVectorWithLeader<TrialWaveFunction>& psi_list,
188 const RefVector<const NLPPJob<RealType>>& joblist,
189 std::vector<RealType>& pairpots,
190 ResourceCollection& collection,
191 bool use_DLA)
192 {
193 auto& ecp_component_leader = ecp_component_list.getLeader();
194 if (ecp_component_leader.VP)
195 {
196 // Compute ratios with VP
197 RefVectorWithLeader<VirtualParticleSet> vp_list(*ecp_component_leader.VP);
198 RefVector<const VirtualParticleSet> const_vp_list;
199 RefVector<const std::vector<PosType>> deltaV_list;
200 RefVector<std::vector<ValueType>> psiratios_list;
201 vp_list.reserve(ecp_component_list.size());
202 const_vp_list.reserve(ecp_component_list.size());
203 deltaV_list.reserve(ecp_component_list.size());
204 psiratios_list.reserve(ecp_component_list.size());
205
206 for (size_t i = 0; i < ecp_component_list.size(); i++)
207 {
208 NonLocalECPComponent& component(ecp_component_list[i]);
209 const NLPPJob<RealType>& job = joblist[i];
210
211 component.buildQuadraturePointDeltaPositions(job.ion_elec_dist, job.ion_elec_displ, component.deltaV);
212
213 vp_list.push_back(*component.VP);
214 const_vp_list.push_back(*component.VP);
215 deltaV_list.push_back(component.deltaV);
216 psiratios_list.push_back(component.psiratio);
217 }
218
219 auto vp_to_p_list = VirtualParticleSet::RefVectorWithLeaderParticleSet(vp_list);
220 ResourceCollectionTeamLock<ParticleSet> vp_res_lock(collection, vp_to_p_list);
221
222 VirtualParticleSet::mw_makeMoves(vp_list, deltaV_list, joblist, true);
223
224 if (use_DLA)
225 TrialWaveFunction::mw_evaluateRatios(psi_list, const_vp_list, psiratios_list,
226 TrialWaveFunction::ComputeType::FERMIONIC);
227 else
228 TrialWaveFunction::mw_evaluateRatios(psi_list, const_vp_list, psiratios_list);
229 }
230 else
231 {
232 // Compute ratios without VP. This is working but very slow code path.
233 #pragma omp parallel for
234 for (size_t i = 0; i < p_list.size(); i++)
235 {
236 NonLocalECPComponent& component(ecp_component_list[i]);
237 auto* VP = component.VP;
238 ParticleSet& W(p_list[i]);
239 TrialWaveFunction& psi(psi_list[i]);
240 const NLPPJob<RealType>& job = joblist[i];
241
242 component.buildQuadraturePointDeltaPositions(job.ion_elec_dist, job.ion_elec_displ, component.deltaV);
243
244 // Compute ratio of wave functions
245 for (int j = 0; j < component.getNknot(); j++)
246 {
247 W.makeMove(job.electron_id, component.deltaV[j], false);
248 if (use_DLA)
249 component.psiratio[j] = psi.calcRatio(W, job.electron_id, TrialWaveFunction::ComputeType::FERMIONIC);
250 else
251 component.psiratio[j] = psi.calcRatio(W, job.electron_id);
252 W.rejectMove(job.electron_id);
253 psi.resetPhaseDiff();
254 }
255 }
256 }
257
258 for (size_t i = 0; i < p_list.size(); i++)
259 {
260 NonLocalECPComponent& component(ecp_component_list[i]);
261 const NLPPJob<RealType>& job = joblist[i];
262 pairpots[i] = component.calculateProjector(job.ion_elec_dist, job.ion_elec_displ);
263 }
264 }
265
evaluateOneWithForces(ParticleSet & W,int iat,TrialWaveFunction & psi,int iel,RealType r,const PosType & dr,PosType & force_iat)266 NonLocalECPComponent::RealType NonLocalECPComponent::evaluateOneWithForces(ParticleSet& W,
267 int iat,
268 TrialWaveFunction& psi,
269 int iel,
270 RealType r,
271 const PosType& dr,
272 PosType& force_iat)
273 {
274 constexpr RealType czero(0);
275 constexpr RealType cone(1);
276
277 for (int j = 0; j < nknot; j++)
278 deltaV[j] = r * rrotsgrid_m[j] - dr;
279
280 GradType gradtmp_(0);
281 PosType realgradtmp_(0);
282
283 //Pseudopotential derivative w.r.t. ions can be split up into 3 contributions:
284 // term coming from the gradient of the radial potential
285 PosType gradpotterm_(0);
286 // term coming from gradient of legendre polynomial
287 PosType gradlpolyterm_(0);
288 // term coming from dependence of quadrature grid on ion position.
289 PosType gradwfnterm_(0);
290
291 if (VP)
292 {
293 APP_ABORT("NonLocalECPComponent::evaluateOneWithForces(...): Forces not implemented with virtual particle moves\n");
294 // Compute ratios with VP
295 VP->makeMoves(iel, W.R[iel], deltaV, true, iat);
296 psi.evaluateRatios(*VP, psiratio);
297 }
298 else
299 {
300 // Compute ratio of wave functions
301 for (int j = 0; j < nknot; j++)
302 {
303 W.makeMove(iel, deltaV[j], false);
304 psiratio[j] = psi.calcRatioGrad(W, iel, gradtmp_);
305 //QMCPACK spits out $\nabla\Psi(q)/\Psi(q)$.
306 //Multiply times $\Psi(q)/\Psi(r)$ to get
307 // $\nabla\Psi(q)/\Psi(r)
308 gradtmp_ *= psiratio[j];
309 #if defined(QMC_COMPLEX)
310 //And now we take the real part and save it.
311 convert(gradtmp_, gradpsiratio[j]);
312 #else
313 //Real nonlocalpp forces seem to differ from those in the complex build. Since
314 //complex build has been validated against QE, that indicates there's a bug for the real build.
315 gradpsiratio[j] = gradtmp_;
316 #endif
317 W.rejectMove(iel);
318 psi.resetPhaseDiff();
319 //psi.rejectMove(iel);
320 }
321 }
322
323 for (int j = 0; j < nknot; j++)
324 psiratio[j] *= sgridweight_m[j];
325
326 // This is just a temporary variable to dump d2/dr2 into for spline evaluation.
327 RealType secondderiv(0);
328
329 const RealType rinv = cone / r;
330
331 // Compute radial potential and its derivative times (2l+1)
332 for (int ip = 0; ip < nchannel; ip++)
333 {
334 //fun fact. NLPComponent stores v(r) as v(r), and not as r*v(r) like in other places.
335 vrad[ip] = nlpp_m[ip]->splint(r, dvrad[ip], secondderiv) * wgt_angpp_m[ip];
336 vgrad[ip] = dvrad[ip] * dr * wgt_angpp_m[ip] * rinv;
337 }
338
339 RealType pairpot = 0;
340 // Compute spherical harmonics on grid
341 for (int j = 0; j < nknot; j++)
342 {
343 RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
344 PosType uminusrvec = rrotsgrid_m[j] - zz * dr * rinv;
345
346 cosgrad[j] = rinv * uminusrvec;
347
348 RealType udotgradpsi = dot(gradpsiratio[j], rrotsgrid_m[j]);
349 wfngrad[j] = gradpsiratio[j] - dr * (udotgradpsi * rinv);
350 wfngrad[j] *= sgridweight_m[j];
351
352 // Forming the Legendre polynomials
353 //P_0(x)=1; P'_0(x)=0.
354 lpol[0] = cone;
355 dlpol[0] = czero;
356
357 RealType lpolprev = czero;
358 RealType dlpolprev = czero;
359
360 for (int l = 0; l < lmax; l++)
361 {
362 //Legendre polynomial recursion formula.
363 lpol[l + 1] = Lfactor1[l] * zz * lpol[l] - l * lpolprev;
364 lpol[l + 1] *= Lfactor2[l];
365
366 //and for the derivative...
367 dlpol[l + 1] = Lfactor1[l] * (zz * dlpol[l] + lpol[l]) - l * dlpolprev;
368 dlpol[l + 1] *= Lfactor2[l];
369
370 lpolprev = lpol[l];
371 dlpolprev = dlpol[l];
372 }
373
374 RealType lsum = czero;
375 // Now to compute the forces:
376 gradpotterm_ = 0;
377 gradlpolyterm_ = 0;
378 gradwfnterm_ = 0;
379
380 for (int l = 0; l < nchannel; l++)
381 {
382 lsum += std::real(vrad[l]) * lpol[angpp_m[l]];
383 gradpotterm_ += vgrad[l] * lpol[angpp_m[l]] * std::real(psiratio[j]);
384 gradlpolyterm_ += std::real(vrad[l]) * dlpol[angpp_m[l]] * cosgrad[j] * std::real(psiratio[j]);
385 gradwfnterm_ += std::real(vrad[l]) * lpol[angpp_m[l]] * wfngrad[j];
386 }
387 knot_pots[j] = std::real(lsum * psiratio[j]);
388 pairpot += knot_pots[j];
389 force_iat += gradpotterm_ + gradlpolyterm_ - gradwfnterm_;
390 }
391
392 return pairpot;
393 }
394
evaluateOneWithForces(ParticleSet & W,ParticleSet & ions,int iat,TrialWaveFunction & psi,int iel,RealType r,const PosType & dr,PosType & force_iat,ParticleSet::ParticlePos_t & pulay_terms)395 NonLocalECPComponent::RealType NonLocalECPComponent::evaluateOneWithForces(ParticleSet& W,
396 ParticleSet& ions,
397 int iat,
398 TrialWaveFunction& psi,
399 int iel,
400 RealType r,
401 const PosType& dr,
402 PosType& force_iat,
403 ParticleSet::ParticlePos_t& pulay_terms)
404 {
405 constexpr RealType czero(0);
406 constexpr RealType cone(1);
407
408 for (int j = 0; j < nknot; j++)
409 deltaV[j] = r * rrotsgrid_m[j] - dr;
410
411 GradType gradtmp_(0);
412 PosType realgradtmp_(0);
413
414 //Pseudopotential derivative w.r.t. ions can be split up into 3 contributions:
415 // term coming from the gradient of the radial potential
416 PosType gradpotterm_(0);
417 // term coming from gradient of legendre polynomial
418 PosType gradlpolyterm_(0);
419 // term coming from dependence of quadrature grid on ion position.
420 PosType gradwfnterm_(0);
421
422 //Now for the Pulay specific stuff...
423 // $\nabla_I \Psi(...r...)/\Psi(...r...)$
424 ParticleSet::ParticlePos_t pulay_ref;
425 ParticleSet::ParticlePos_t pulaytmp_;
426 // $\nabla_I \Psi(...q...)/\Psi(...r...)$ for each quadrature point.
427 std::vector<ParticleSet::ParticlePos_t> pulay_quad(nknot);
428
429 //A working array for pulay stuff.
430 GradType iongradtmp_(0);
431 //resize everything.
432 pulay_ref.resize(ions.getTotalNum());
433 pulaytmp_.resize(ions.getTotalNum());
434 for (size_t j = 0; j < nknot; j++)
435 pulay_quad[j].resize(ions.getTotalNum());
436
437 if (VP)
438 {
439 APP_ABORT("NonLocalECPComponent::evaluateOneWithForces(...): Forces not implemented with virtual particle moves\n");
440 // Compute ratios with VP
441 VP->makeMoves(iel, W.R[iel], deltaV, true, iat);
442 psi.evaluateRatios(*VP, psiratio);
443 }
444 else
445 {
446 // Compute ratio of wave functions
447 for (int j = 0; j < nknot; j++)
448 {
449 W.makeMove(iel, deltaV[j], false);
450 psiratio[j] = psi.calcRatioGrad(W, iel, gradtmp_);
451 //QMCPACK spits out $\nabla\Psi(q)/\Psi(q)$.
452 //Multiply times $\Psi(q)/\Psi(r)$ to get
453 // $\nabla\Psi(q)/\Psi(r)
454 gradtmp_ *= psiratio[j];
455 #if defined(QMC_COMPLEX)
456 //And now we take the real part and save it.
457 convert(gradtmp_, gradpsiratio[j]);
458 #else
459 //Real nonlocalpp forces seem to differ from those in the complex build. Since
460 //complex build has been validated against QE, that indicates there's a bug for the real build.
461 gradpsiratio[j] = gradtmp_;
462 #endif
463 W.rejectMove(iel);
464 psi.resetPhaseDiff();
465 //psi.rejectMove(iel);
466 }
467 }
468
469 for (int j = 0; j < nknot; j++)
470 psiratio[j] *= sgridweight_m[j];
471
472 // This is just a temporary variable to dump d2/dr2 into for spline evaluation.
473 RealType secondderiv(0);
474
475 const RealType rinv = cone / r;
476
477 // Compute radial potential and its derivative times (2l+1)
478 for (int ip = 0; ip < nchannel; ip++)
479 {
480 //fun fact. NLPComponent stores v(r) as v(r), and not as r*v(r) like in other places.
481 vrad[ip] = nlpp_m[ip]->splint(r, dvrad[ip], secondderiv) * wgt_angpp_m[ip];
482 vgrad[ip] = dvrad[ip] * dr * wgt_angpp_m[ip] * rinv;
483 }
484
485 //Now to construct the 3N dimensional ionic wfn derivatives for pulay terms.
486 //This is going to be slow an painful for now.
487 for (size_t jat = 0; jat < ions.getTotalNum(); jat++)
488 {
489 pulay_ref[jat] = psi.evalGradSource(W, ions, jat);
490 gradpotterm_ = 0;
491 for (size_t j = 0; j < nknot; j++)
492 {
493 deltaV[j] = r * rrotsgrid_m[j] - dr;
494 //This sequence is necessary to update the distance tables and make the
495 //inverse matrix available for force computation. Move the particle to
496 //quadrature point...
497 W.makeMove(iel, deltaV[j]);
498 psi.calcRatio(W, iel);
499 psi.acceptMove(W, iel);
500 W.acceptMove(iel); // it only updates the jel-th row of e-e table
501 //Done with the move. Ready for force computation.
502
503 iongradtmp_ = psi.evalGradSource(W, ions, jat);
504 iongradtmp_ *= psiratio[j];
505 #ifdef QMC_COMPLEX
506 convert(iongradtmp_, pulay_quad[j][jat]);
507 #endif
508 pulay_quad[j][jat] = iongradtmp_;
509 //And move the particle back.
510 deltaV[j] = dr - r * rrotsgrid_m[j];
511
512 // mirror the above in reverse order
513 W.makeMove(iel, deltaV[j]);
514 psi.calcRatio(W, iel);
515 psi.acceptMove(W, iel);
516 W.acceptMove(iel);
517 }
518 }
519
520 RealType pairpot = 0;
521 // Compute spherical harmonics on grid
522 for (int j = 0; j < nknot; j++)
523 {
524 RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
525 PosType uminusrvec = rrotsgrid_m[j] - zz * dr * rinv;
526
527 cosgrad[j] = rinv * uminusrvec;
528
529 RealType udotgradpsi = dot(gradpsiratio[j], rrotsgrid_m[j]);
530 wfngrad[j] = gradpsiratio[j] - dr * (udotgradpsi * rinv);
531 wfngrad[j] *= sgridweight_m[j];
532
533 // Forming the Legendre polynomials
534 //P_0(x)=1; P'_0(x)=0.
535 lpol[0] = cone;
536 dlpol[0] = czero;
537
538 RealType lpolprev = czero;
539 RealType dlpolprev = czero;
540
541 for (int l = 0; l < lmax; l++)
542 {
543 //Legendre polynomial recursion formula.
544 lpol[l + 1] = Lfactor1[l] * zz * lpol[l] - l * lpolprev;
545 lpol[l + 1] *= Lfactor2[l];
546
547 //and for the derivative...
548 dlpol[l + 1] = Lfactor1[l] * (zz * dlpol[l] + lpol[l]) - l * dlpolprev;
549 dlpol[l + 1] *= Lfactor2[l];
550
551 lpolprev = lpol[l];
552 dlpolprev = dlpol[l];
553 }
554
555 RealType lsum = czero;
556 // Now to compute the forces:
557 gradpotterm_ = 0;
558 gradlpolyterm_ = 0;
559 gradwfnterm_ = 0;
560 pulaytmp_ = 0;
561
562 for (int l = 0; l < nchannel; l++)
563 {
564 //Note. Because we are computing "forces", there's a -1 difference between this and
565 //direct finite difference calculations.
566 lsum += std::real(vrad[l]) * lpol[angpp_m[l]];
567 gradpotterm_ += vgrad[l] * lpol[angpp_m[l]] * std::real(psiratio[j]);
568 gradlpolyterm_ += std::real(vrad[l]) * dlpol[angpp_m[l]] * cosgrad[j] * std::real(psiratio[j]);
569 gradwfnterm_ += std::real(vrad[l]) * lpol[angpp_m[l]] * wfngrad[j];
570 pulaytmp_ -= std::real(vrad[l]) * lpol[angpp_m[l]] * pulay_quad[j];
571 }
572 knot_pots[j] = std::real(lsum * psiratio[j]);
573 pulaytmp_ += knot_pots[j] * pulay_ref;
574 pairpot += knot_pots[j];
575 force_iat += gradpotterm_ + gradlpolyterm_ - gradwfnterm_;
576 pulay_terms += pulaytmp_;
577 }
578
579 return pairpot;
580 }
581
582 ///Randomly rotate sgrid_m
randomize_grid(RandomGenerator_t & myRNG)583 void NonLocalECPComponent::randomize_grid(RandomGenerator_t& myRNG)
584 {
585 RealType phi(TWOPI * myRNG()), psi(TWOPI * myRNG()), cth(myRNG() - 0.5);
586 RealType sph(std::sin(phi)), cph(std::cos(phi)), sth(std::sqrt(1.0 - cth * cth)), sps(std::sin(psi)),
587 cps(std::cos(psi));
588 TensorType rmat(cph * cth * cps - sph * sps, sph * cth * cps + cph * sps, -sth * cps, -cph * cth * sps - sph * cps,
589 -sph * cth * sps + cph * cps, sth * sps, cph * sth, sph * sth, cth);
590 for (int i = 0; i < sgridxyz_m.size(); i++)
591 rrotsgrid_m[i] = dot(rmat, sgridxyz_m[i]);
592 }
593
594 template<typename T>
randomize_grid(std::vector<T> & sphere,RandomGenerator_t & myRNG)595 void NonLocalECPComponent::randomize_grid(std::vector<T>& sphere, RandomGenerator_t& myRNG)
596 {
597 RealType phi(TWOPI * myRNG()), psi(TWOPI * myRNG()), cth(myRNG() - 0.5);
598 RealType sph(std::sin(phi)), cph(std::cos(phi)), sth(std::sqrt(1.0 - cth * cth)), sps(std::sin(psi)),
599 cps(std::cos(psi));
600 TensorType rmat(cph * cth * cps - sph * sps, sph * cth * cps + cph * sps, -sth * cps, -cph * cth * sps - sph * cps,
601 -sph * cth * sps + cph * cps, sth * sps, cph * sth, sph * sth, cth);
602 SpherGridType::iterator it(sgridxyz_m.begin());
603 SpherGridType::iterator it_end(sgridxyz_m.end());
604 SpherGridType::iterator jt(rrotsgrid_m.begin());
605 while (it != it_end)
606 {
607 *jt = dot(rmat, *it);
608 ++it;
609 ++jt;
610 }
611 //copy the randomized grid to sphere
612 for (int i = 0; i < rrotsgrid_m.size(); i++)
613 for (int j = 0; j < OHMMS_DIM; j++)
614 sphere[OHMMS_DIM * i + j] = rrotsgrid_m[i][j];
615 }
616
buildQuadraturePointDeltaPositions(RealType r,const PosType & dr,std::vector<PosType> & deltaV) const617 void NonLocalECPComponent::buildQuadraturePointDeltaPositions(RealType r,
618 const PosType& dr,
619 std::vector<PosType>& deltaV) const
620 {
621 for (int j = 0; j < nknot; j++)
622 deltaV[j] = r * rrotsgrid_m[j] - dr;
623 }
624
contributeTxy(int iel,std::vector<NonLocalData> & Txy) const625 void NonLocalECPComponent::contributeTxy(int iel, std::vector<NonLocalData>& Txy) const
626 {
627 for (int j = 0; j < nknot; j++)
628 Txy.push_back(NonLocalData(iel, knot_pots[j], deltaV[j]));
629 }
630
631 /// \relates NonLocalEcpComponent
632 template void NonLocalECPComponent::randomize_grid(std::vector<float>& sphere, RandomGenerator_t& myRNG);
633 template void NonLocalECPComponent::randomize_grid(std::vector<double>& sphere, RandomGenerator_t& myRNG);
634
635
636 } // namespace qmcplusplus
637