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