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: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
8 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
9 //
10 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
11 //////////////////////////////////////////////////////////////////////////////////////
12
13
14 #include "QMCHamiltonians/NonLocalECPComponent.h"
15 #include "QMCHamiltonians/NonLocalECPotential.h"
16 #include "CPU/BLAS.hpp"
17 #include "Utilities/Timer.h"
18
19 namespace qmcplusplus
20 {
evaluateValueAndDerivatives(ParticleSet & P,const opt_variables_type & optvars,const std::vector<ValueType> & dlogpsi,std::vector<ValueType> & dhpsioverpsi)21 NonLocalECPotential::Return_t NonLocalECPotential::evaluateValueAndDerivatives(ParticleSet& P,
22 const opt_variables_type& optvars,
23 const std::vector<ValueType>& dlogpsi,
24 std::vector<ValueType>& dhpsioverpsi)
25 {
26 Value = 0.0;
27 for (int ipp = 0; ipp < PPset.size(); ipp++)
28 if (PPset[ipp])
29 PPset[ipp]->randomize_grid(*myRNG);
30 const auto& myTable = P.getDistTable(myTableIndex);
31 for (int jel = 0; jel < P.getTotalNum(); jel++)
32 {
33 const auto& dist = myTable.getDistRow(jel);
34 const auto& displ = myTable.getDisplRow(jel);
35 for (int iat = 0; iat < NumIons; iat++)
36 if (PP[iat] != nullptr && dist[iat] < PP[iat]->getRmax())
37 Value += PP[iat]->evaluateValueAndDerivatives(P, iat, Psi, jel, dist[iat], -displ[iat], optvars, dlogpsi,
38 dhpsioverpsi);
39 }
40 return Value;
41 }
42
43 /** evaluate the non-local potential of the iat-th ionic center
44 * @param W electron configuration
45 * @param iat ionic index
46 * @param psi trial wavefunction
47 * @param optvars optimizables
48 * @param dlogpsi derivatives of the wavefunction at W.R
49 * @param hdpsioverpsi derivatives of Vpp
50 * @param return the non-local component
51 *
52 * This is a temporary solution which uses TrialWaveFunction::evaluateDerivatives
53 * assuming that the distance tables are fully updated for each ratio computation.
54 */
evaluateValueAndDerivatives(ParticleSet & W,int iat,TrialWaveFunction & psi,int iel,RealType r,const PosType & dr,const opt_variables_type & optvars,const std::vector<ValueType> & dlogpsi,std::vector<ValueType> & dhpsioverpsi)55 NonLocalECPComponent::RealType NonLocalECPComponent::evaluateValueAndDerivatives(ParticleSet& W,
56 int iat,
57 TrialWaveFunction& psi,
58 int iel,
59 RealType r,
60 const PosType& dr,
61 const opt_variables_type& optvars,
62 const std::vector<ValueType>& dlogpsi,
63 std::vector<ValueType>& dhpsioverpsi)
64 {
65 dratio.resize(optvars.num_active_vars, nknot);
66 dlogpsi_vp.resize(dlogpsi.size());
67
68 ValueType pairpot;
69 ParticleSet::ParticlePos_t deltarV(nknot);
70
71 //displacements wrt W.R[iel]
72 for (int j = 0; j < nknot; j++)
73 deltarV[j] = r * rrotsgrid_m[j] - dr;
74
75 for (int j = 0; j < nknot; j++)
76 {
77 PosType pos_now = W.R[iel];
78 W.makeMove(iel, deltarV[j]);
79 psiratio[j] = psi.calcRatio(W, iel);
80 psi.acceptMove(W, iel);
81 W.acceptMove(iel);
82
83 //use existing methods
84 std::fill(dlogpsi_vp.begin(), dlogpsi_vp.end(), 0.0);
85 psi.evaluateDerivativesWF(W, optvars, dlogpsi_vp);
86 for (int v = 0; v < dlogpsi_vp.size(); ++v)
87 dratio(v, j) = dlogpsi_vp[v];
88
89 W.makeMove(iel, -deltarV[j]);
90 psi.calcRatio(W, iel);
91 psi.acceptMove(W, iel);
92 W.acceptMove(iel);
93 }
94
95 for (int j = 0; j < nknot; ++j)
96 psiratio[j] *= sgridweight_m[j];
97
98 for (int ip = 0; ip < nchannel; ip++)
99 vrad[ip] = nlpp_m[ip]->splint(r) * wgt_angpp_m[ip];
100
101 const RealType rinv = RealType(1) / r;
102 // Compute spherical harmonics on grid
103 for (int j = 0, jl = 0; j < nknot; j++)
104 {
105 RealType zz = dot(dr, rrotsgrid_m[j]) * rinv;
106 // Forming the Legendre polynomials
107 lpol[0] = 1.0;
108 RealType lpolprev = 0.0;
109 for (int l = 0; l < lmax; l++)
110 {
111 lpol[l + 1] = Lfactor1[l] * zz * lpol[l] - l * lpolprev;
112 lpol[l + 1] *= Lfactor2[l];
113 lpolprev = lpol[l];
114 }
115 for (int l = 0; l < nchannel; l++, jl++)
116 Amat[jl] = lpol[angpp_m[l]];
117 }
118 if (nchannel == 1)
119 {
120 pairpot = vrad[0] * BLAS::dot(nknot, &Amat[0], &psiratio[0]);
121 for (int v = 0; v < dhpsioverpsi.size(); ++v)
122 {
123 for (int j = 0; j < nknot; ++j)
124 dratio(v, j) = psiratio[j] * (dratio(v, j) - dlogpsi[v]);
125 dhpsioverpsi[v] += vrad[0] * BLAS::dot(nknot, &Amat[0], dratio[v]);
126 }
127 }
128 else
129 {
130 BLAS::gemv(nknot, nchannel, &Amat[0], &psiratio[0], &wvec[0]);
131 pairpot = BLAS::dot(nchannel, &vrad[0], &wvec[0]);
132 for (int v = 0; v < dhpsioverpsi.size(); ++v)
133 {
134 for (int j = 0; j < nknot; ++j)
135 dratio(v, j) = psiratio[j] * (dratio(v, j) - dlogpsi[v]);
136 BLAS::gemv(nknot, nchannel, &Amat[0], dratio[v], &wvec[0]);
137 dhpsioverpsi[v] += BLAS::dot(nchannel, &vrad[0], &wvec[0]);
138 }
139 }
140
141 return std::real(pairpot);
142 }
143
144 } // namespace qmcplusplus
145