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: Mark Dewing, mdewing@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Jeongnim Kim, jeongnim.kim@intel.com, Intel Corp.
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #include "LCAOrbitalSet.h"
14 #include "Numerics/MatrixOperators.h"
15 #include "CPU/BLAS.hpp"
16 
17 namespace qmcplusplus
18 {
LCAOrbitalSet(std::unique_ptr<basis_type> && bs,bool optimize)19 LCAOrbitalSet::LCAOrbitalSet(std::unique_ptr<basis_type>&& bs, bool optimize)
20     : SPOSet(false, true, optimize), BasisSetSize(bs ? bs->getBasisSetSize() : 0), Identity(true)
21 {
22   if (!bs)
23     throw std::runtime_error("LCAOrbitalSet cannot take nullptr as its  basis set!");
24   myBasisSet = std::move(bs);
25   Temp.resize(BasisSetSize);
26   Temph.resize(BasisSetSize);
27   Tempgh.resize(BasisSetSize);
28   OrbitalSetSize = BasisSetSize;
29   LCAOrbitalSet::checkObject();
30 }
31 
LCAOrbitalSet(const LCAOrbitalSet & in)32 LCAOrbitalSet::LCAOrbitalSet(const LCAOrbitalSet& in)
33     : SPOSet(in), myBasisSet(in.myBasisSet->makeClone()), C(in.C), BasisSetSize(in.BasisSetSize), Identity(in.Identity)
34 {
35   Temp.resize(BasisSetSize);
36   Temph.resize(BasisSetSize);
37   Tempgh.resize(BasisSetSize);
38   if (!in.Identity)
39   {
40     Tempv.resize(OrbitalSetSize);
41     Temphv.resize(OrbitalSetSize);
42     Tempghv.resize(OrbitalSetSize);
43   }
44   LCAOrbitalSet::checkObject();
45 }
46 
setOrbitalSetSize(int norbs)47 void LCAOrbitalSet::setOrbitalSetSize(int norbs)
48 {
49   if(C)
50     throw std::runtime_error("LCAOrbitalSet::setOrbitalSetSize cannot reset existing MO coefficients");
51 
52   Identity = false;
53   OrbitalSetSize = norbs;
54   C = std::make_shared<ValueMatrix_t>(OrbitalSetSize, BasisSetSize);
55   Tempv.resize(OrbitalSetSize);
56   Temphv.resize(OrbitalSetSize);
57   Tempghv.resize(OrbitalSetSize);
58   LCAOrbitalSet::checkObject();
59 }
60 
checkObject() const61 void LCAOrbitalSet::checkObject() const
62 {
63   if (Identity)
64   {
65     if (OrbitalSetSize != BasisSetSize)
66       throw std::runtime_error(
67           "LCAOrbitalSet::checkObject OrbitalSetSize and BasisSetSize must be equal if Identity = true!");
68     if (C)
69       throw std::runtime_error("LCAOrbitalSet::checkObject C should be nullptr if Identity = true!");
70   }
71   else
72   {
73     if (!C)
74       throw std::runtime_error("LCAOrbitalSet::checkObject C should not be nullptr if Identity = false!");
75     if (OrbitalSetSize != C->rows())
76       throw std::runtime_error("LCAOrbitalSet::checkObject C rows doesn't match OrbitalSetSize.");
77     if (BasisSetSize != C->cols())
78       throw std::runtime_error("LCAOrbitalSet::checkObject C columns doesn't match BasisSetSize.");
79   }
80 }
81 
makeClone() const82 SPOSet* LCAOrbitalSet::makeClone() const { return new LCAOrbitalSet(*this); }
83 
evaluateValue(const ParticleSet & P,int iat,ValueVector_t & psi)84 void LCAOrbitalSet::evaluateValue(const ParticleSet& P, int iat, ValueVector_t& psi)
85 {
86   if (Identity)
87   { //PAY ATTENTION TO COMPLEX
88     myBasisSet->evaluateV(P, iat, psi.data());
89   }
90   else
91   {
92     Vector<ValueType> vTemp(Temp.data(0), BasisSetSize);
93     myBasisSet->evaluateV(P, iat, vTemp.data());
94     assert(psi.size() <= OrbitalSetSize);
95     ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize);
96     simd::gemv(C_partial_view, vTemp.data(), psi.data());
97   }
98 }
99 
100 /** Find a better place for other user classes, Matrix should be padded as well */
101 template<typename T, unsigned D>
Product_ABt(const VectorSoaContainer<T,D> & A,const Matrix<T> & B,VectorSoaContainer<T,D> & C)102 inline void Product_ABt(const VectorSoaContainer<T, D>& A, const Matrix<T>& B, VectorSoaContainer<T, D>& C)
103 {
104   constexpr char transa = 't';
105   constexpr char transb = 'n';
106   constexpr T zone(1);
107   constexpr T zero(0);
108   BLAS::gemm(transa, transb, B.rows(), D, B.cols(), zone, B.data(), B.cols(), A.data(), A.capacity(), zero, C.data(),
109              C.capacity());
110 }
111 
evaluate_vgl_impl(const vgl_type & temp,ValueVector_t & psi,GradVector_t & dpsi,ValueVector_t & d2psi) const112 inline void LCAOrbitalSet::evaluate_vgl_impl(const vgl_type& temp,
113                                              ValueVector_t& psi,
114                                              GradVector_t& dpsi,
115                                              ValueVector_t& d2psi) const
116 {
117   const size_t output_size = psi.size();
118   std::copy_n(temp.data(0), output_size, psi.data());
119   const ValueType* restrict gx = temp.data(1);
120   const ValueType* restrict gy = temp.data(2);
121   const ValueType* restrict gz = temp.data(3);
122   for (size_t j = 0; j < output_size; j++)
123   {
124     dpsi[j][0] = gx[j];
125     dpsi[j][1] = gy[j];
126     dpsi[j][2] = gz[j];
127   }
128   std::copy_n(temp.data(4), output_size, d2psi.data());
129 }
130 
evaluate_vgh_impl(const vgh_type & temp,ValueVector_t & psi,GradVector_t & dpsi,HessVector_t & d2psi) const131 inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp,
132                                              ValueVector_t& psi,
133                                              GradVector_t& dpsi,
134                                              HessVector_t& d2psi) const
135 {
136   const size_t output_size = psi.size();
137   std::copy_n(temp.data(0), output_size, psi.data());
138   const ValueType* restrict gx  = temp.data(1);
139   const ValueType* restrict gy  = temp.data(2);
140   const ValueType* restrict gz  = temp.data(3);
141   const ValueType* restrict hxx = temp.data(4);
142   const ValueType* restrict hxy = temp.data(5);
143   const ValueType* restrict hxz = temp.data(6);
144   const ValueType* restrict hyy = temp.data(7);
145   const ValueType* restrict hyz = temp.data(8);
146   const ValueType* restrict hzz = temp.data(9);
147 
148   for (size_t j = 0; j < output_size; j++)
149   {
150     dpsi[j][0] = gx[j];
151     dpsi[j][1] = gy[j];
152     dpsi[j][2] = gz[j];
153 
154     d2psi[j](0, 0) = hxx[j];
155     d2psi[j](0, 1) = d2psi[j](1, 0) = hxy[j];
156     d2psi[j](0, 2) = d2psi[j](2, 0) = hxz[j];
157     d2psi[j](1, 1)                  = hyy[j];
158     d2psi[j](2, 1) = d2psi[j](1, 2) = hyz[j];
159     d2psi[j](2, 2)                  = hzz[j];
160   }
161 }
162 
evaluate_vghgh_impl(const vghgh_type & temp,int i,ValueMatrix_t & psi,GradMatrix_t & dpsi,HessMatrix_t & d2psi,GGGMatrix_t & dghpsi) const163 inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp,
164                                                int i,
165                                                ValueMatrix_t& psi,
166                                                GradMatrix_t& dpsi,
167                                                HessMatrix_t& d2psi,
168                                                GGGMatrix_t& dghpsi) const
169 {
170   const size_t output_size = psi.cols();
171   std::copy_n(temp.data(0), output_size, psi[i]);
172   const ValueType* restrict gx     = temp.data(1);
173   const ValueType* restrict gy     = temp.data(2);
174   const ValueType* restrict gz     = temp.data(3);
175   const ValueType* restrict hxx    = temp.data(4);
176   const ValueType* restrict hxy    = temp.data(5);
177   const ValueType* restrict hxz    = temp.data(6);
178   const ValueType* restrict hyy    = temp.data(7);
179   const ValueType* restrict hyz    = temp.data(8);
180   const ValueType* restrict hzz    = temp.data(9);
181   const ValueType* restrict gh_xxx = temp.data(10);
182   const ValueType* restrict gh_xxy = temp.data(11);
183   const ValueType* restrict gh_xxz = temp.data(12);
184   const ValueType* restrict gh_xyy = temp.data(13);
185   const ValueType* restrict gh_xyz = temp.data(14);
186   const ValueType* restrict gh_xzz = temp.data(15);
187   const ValueType* restrict gh_yyy = temp.data(16);
188   const ValueType* restrict gh_yyz = temp.data(17);
189   const ValueType* restrict gh_yzz = temp.data(18);
190   const ValueType* restrict gh_zzz = temp.data(19);
191 
192   for (size_t j = 0; j < output_size; j++)
193   {
194     dpsi[i][j][0] = gx[j];
195     dpsi[i][j][1] = gy[j];
196     dpsi[i][j][2] = gz[j];
197 
198     d2psi[i][j](0, 0) = hxx[j];
199     d2psi[i][j](0, 1) = d2psi[i][j](1, 0) = hxy[j];
200     d2psi[i][j](0, 2) = d2psi[i][j](2, 0) = hxz[j];
201     d2psi[i][j](1, 1)                     = hyy[j];
202     d2psi[i][j](2, 1) = d2psi[i][j](1, 2) = hyz[j];
203     d2psi[i][j](2, 2)                     = hzz[j];
204 
205     dghpsi[i][j][0](0, 0) = gh_xxx[j]; //x|xx
206     dghpsi[i][j][0](0, 1) = gh_xxy[j]; //x|xy
207     dghpsi[i][j][0](0, 2) = gh_xxz[j]; //x|xz
208     dghpsi[i][j][0](1, 0) = gh_xxy[j]; //x|yx = xxy
209     dghpsi[i][j][0](1, 1) = gh_xyy[j]; //x|yy
210     dghpsi[i][j][0](1, 2) = gh_xyz[j]; //x|yz
211     dghpsi[i][j][0](2, 0) = gh_xxz[j]; //x|zx = xxz
212     dghpsi[i][j][0](2, 1) = gh_xyz[j]; //x|zy = xyz
213     dghpsi[i][j][0](2, 2) = gh_xzz[j]; //x|zz
214 
215     dghpsi[i][j][1](0, 0) = gh_xxy[j]; //y|xx = xxy
216     dghpsi[i][j][1](0, 1) = gh_xyy[j]; //y|xy = xyy
217     dghpsi[i][j][1](0, 2) = gh_xyz[j]; //y|xz = xyz
218     dghpsi[i][j][1](1, 0) = gh_xyy[j]; //y|yx = xyy
219     dghpsi[i][j][1](1, 1) = gh_yyy[j]; //y|yy
220     dghpsi[i][j][1](1, 2) = gh_yyz[j]; //y|yz
221     dghpsi[i][j][1](2, 0) = gh_xyz[j]; //y|zx = xyz
222     dghpsi[i][j][1](2, 1) = gh_yyz[j]; //y|zy = yyz
223     dghpsi[i][j][1](2, 2) = gh_yzz[j]; //y|zz
224 
225     dghpsi[i][j][2](0, 0) = gh_xxz[j]; //z|xx = xxz
226     dghpsi[i][j][2](0, 1) = gh_xyz[j]; //z|xy = xyz
227     dghpsi[i][j][2](0, 2) = gh_xzz[j]; //z|xz = xzz
228     dghpsi[i][j][2](1, 0) = gh_xyz[j]; //z|yx = xyz
229     dghpsi[i][j][2](1, 1) = gh_yyz[j]; //z|yy = yyz
230     dghpsi[i][j][2](1, 2) = gh_yzz[j]; //z|yz = yzz
231     dghpsi[i][j][2](2, 0) = gh_xzz[j]; //z|zx = xzz
232     dghpsi[i][j][2](2, 1) = gh_yzz[j]; //z|zy = yzz
233     dghpsi[i][j][2](2, 2) = gh_zzz[j]; //z|zz
234   }
235 }
236 
evaluate_vghgh_impl(const vghgh_type & temp,ValueVector_t & psi,GradVector_t & dpsi,HessVector_t & d2psi,GGGVector_t & dghpsi) const237 inline void LCAOrbitalSet::evaluate_vghgh_impl(const vghgh_type& temp,
238                                                ValueVector_t& psi,
239                                                GradVector_t& dpsi,
240                                                HessVector_t& d2psi,
241                                                GGGVector_t& dghpsi) const
242 {
243   const size_t output_size = psi.size();
244   std::copy_n(temp.data(0), output_size, psi.data());
245   const ValueType* restrict gx     = temp.data(1);
246   const ValueType* restrict gy     = temp.data(2);
247   const ValueType* restrict gz     = temp.data(3);
248   const ValueType* restrict hxx    = temp.data(4);
249   const ValueType* restrict hxy    = temp.data(5);
250   const ValueType* restrict hxz    = temp.data(6);
251   const ValueType* restrict hyy    = temp.data(7);
252   const ValueType* restrict hyz    = temp.data(8);
253   const ValueType* restrict hzz    = temp.data(9);
254   const ValueType* restrict gh_xxx = temp.data(10);
255   const ValueType* restrict gh_xxy = temp.data(11);
256   const ValueType* restrict gh_xxz = temp.data(12);
257   const ValueType* restrict gh_xyy = temp.data(13);
258   const ValueType* restrict gh_xyz = temp.data(14);
259   const ValueType* restrict gh_xzz = temp.data(15);
260   const ValueType* restrict gh_yyy = temp.data(16);
261   const ValueType* restrict gh_yyz = temp.data(17);
262   const ValueType* restrict gh_yzz = temp.data(18);
263   const ValueType* restrict gh_zzz = temp.data(19);
264 
265   for (size_t j = 0; j < output_size; j++)
266   {
267     dpsi[j][0] = gx[j];
268     dpsi[j][1] = gy[j];
269     dpsi[j][2] = gz[j];
270 
271     d2psi[j](0, 0) = hxx[j];
272     d2psi[j](0, 1) = d2psi[j](1, 0) = hxy[j];
273     d2psi[j](0, 2) = d2psi[j](2, 0) = hxz[j];
274     d2psi[j](1, 1)                  = hyy[j];
275     d2psi[j](2, 1) = d2psi[j](1, 2) = hyz[j];
276     d2psi[j](2, 2)                  = hzz[j];
277 
278     dghpsi[j][0](0, 0) = gh_xxx[j]; //x|xx
279     dghpsi[j][0](0, 1) = gh_xxy[j]; //x|xy
280     dghpsi[j][0](0, 2) = gh_xxz[j]; //x|xz
281     dghpsi[j][0](1, 0) = gh_xxy[j]; //x|yx = xxy
282     dghpsi[j][0](1, 1) = gh_xyy[j]; //x|yy
283     dghpsi[j][0](1, 2) = gh_xyz[j]; //x|yz
284     dghpsi[j][0](2, 0) = gh_xxz[j]; //x|zx = xxz
285     dghpsi[j][0](2, 1) = gh_xyz[j]; //x|zy = xyz
286     dghpsi[j][0](2, 2) = gh_xzz[j]; //x|zz
287 
288     dghpsi[j][1](0, 0) = gh_xxy[j]; //y|xx = xxy
289     dghpsi[j][1](0, 1) = gh_xyy[j]; //y|xy = xyy
290     dghpsi[j][1](0, 2) = gh_xyz[j]; //y|xz = xyz
291     dghpsi[j][1](1, 0) = gh_xyy[j]; //y|yx = xyy
292     dghpsi[j][1](1, 1) = gh_yyy[j]; //y|yy
293     dghpsi[j][1](1, 2) = gh_yyz[j]; //y|yz
294     dghpsi[j][1](2, 0) = gh_xyz[j]; //y|zx = xyz
295     dghpsi[j][1](2, 1) = gh_xyy[j]; //y|xy = xyy
296     dghpsi[j][1](2, 2) = gh_yzz[j]; //y|zz
297 
298     dghpsi[j][2](0, 0) = gh_xzz[j]; //z|xx = xzz
299     dghpsi[j][2](0, 1) = gh_xyz[j]; //z|xy = xyz
300     dghpsi[j][2](0, 2) = gh_xzz[j]; //z|xz = xzz
301     dghpsi[j][2](1, 0) = gh_xyz[j]; //z|yx = xyz
302     dghpsi[j][2](1, 1) = gh_yyz[j]; //z|yy = yyz
303     dghpsi[j][2](1, 2) = gh_yzz[j]; //z|yz = yzz
304     dghpsi[j][2](2, 0) = gh_xzz[j]; //z|zx = xzz
305     dghpsi[j][2](2, 1) = gh_yzz[j]; //z|zy = yzz
306     dghpsi[j][2](2, 2) = gh_zzz[j]; //z|zz
307   }
308 }
309 
310 
evaluateVGL(const ParticleSet & P,int iat,ValueVector_t & psi,GradVector_t & dpsi,ValueVector_t & d2psi)311 void LCAOrbitalSet::evaluateVGL(const ParticleSet& P,
312                                 int iat,
313                                 ValueVector_t& psi,
314                                 GradVector_t& dpsi,
315                                 ValueVector_t& d2psi)
316 {
317   //TAKE CARE OF IDENTITY
318   myBasisSet->evaluateVGL(P, iat, Temp);
319   if (Identity)
320     evaluate_vgl_impl(Temp, psi, dpsi, d2psi);
321   else
322   {
323     assert(psi.size() <= OrbitalSetSize);
324     ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize);
325     Product_ABt(Temp, C_partial_view, Tempv);
326     evaluate_vgl_impl(Tempv, psi, dpsi, d2psi);
327   }
328 }
329 
evaluateDetRatios(const VirtualParticleSet & VP,ValueVector_t & psi,const ValueVector_t & psiinv,std::vector<ValueType> & ratios)330 void LCAOrbitalSet::evaluateDetRatios(const VirtualParticleSet& VP,
331                                       ValueVector_t& psi,
332                                       const ValueVector_t& psiinv,
333                                       std::vector<ValueType>& ratios)
334 {
335   Vector<ValueType> vTemp(Temp.data(0), BasisSetSize);
336   Vector<ValueType> invTemp(Temp.data(1), BasisSetSize);
337 
338   MatrixOperators::product_Atx(*C, psiinv, invTemp.data());
339 
340   for (size_t j = 0; j < VP.getTotalNum(); j++)
341   {
342     myBasisSet->evaluateV(VP, j, vTemp.data());
343     ratios[j] = simd::dot(vTemp.data(), invTemp.data(), BasisSetSize);
344   }
345 }
346 
evaluateVGH(const ParticleSet & P,int iat,ValueVector_t & psi,GradVector_t & dpsi,HessVector_t & dhpsi)347 void LCAOrbitalSet::evaluateVGH(const ParticleSet& P,
348                                 int iat,
349                                 ValueVector_t& psi,
350                                 GradVector_t& dpsi,
351                                 HessVector_t& dhpsi)
352 {
353   //TAKE CARE OF IDENTITY
354   myBasisSet->evaluateVGH(P, iat, Temph);
355   if (Identity)
356     evaluate_vgh_impl(Temph, psi, dpsi, dhpsi);
357   else
358   {
359     assert(psi.size() <= OrbitalSetSize);
360     ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize);
361     Product_ABt(Temph, C_partial_view, Temphv);
362     evaluate_vgh_impl(Temphv, psi, dpsi, dhpsi);
363   }
364 }
365 
evaluateVGHGH(const ParticleSet & P,int iat,ValueVector_t & psi,GradVector_t & dpsi,HessVector_t & dhpsi,GGGVector_t & dghpsi)366 void LCAOrbitalSet::evaluateVGHGH(const ParticleSet& P,
367                                   int iat,
368                                   ValueVector_t& psi,
369                                   GradVector_t& dpsi,
370                                   HessVector_t& dhpsi,
371                                   GGGVector_t& dghpsi)
372 {
373   // APP_ABORT("LCAORbitalSet::evaluate(psi,gpsi,hpsi,ghpsi) not implemented\n");
374 
375   //TAKE CARE OF IDENTITY
376   myBasisSet->evaluateVGHGH(P, iat, Tempgh);
377   if (Identity)
378     evaluate_vghgh_impl(Tempgh, psi, dpsi, dhpsi, dghpsi);
379   else
380   {
381     assert(psi.size() <= OrbitalSetSize);
382     ValueMatrix_t C_partial_view(C->data(), psi.size(), BasisSetSize);
383     Product_ABt(Tempgh, C_partial_view, Tempghv);
384     evaluate_vghgh_impl(Tempghv, psi, dpsi, dhpsi, dghpsi);
385   }
386 }
387 
388 /* implement using gemm algorithm */
evaluate_vgl_impl(const vgl_type & temp,int i,ValueMatrix_t & logdet,GradMatrix_t & dlogdet,ValueMatrix_t & d2logdet) const389 inline void LCAOrbitalSet::evaluate_vgl_impl(const vgl_type& temp,
390                                              int i,
391                                              ValueMatrix_t& logdet,
392                                              GradMatrix_t& dlogdet,
393                                              ValueMatrix_t& d2logdet) const
394 {
395   const size_t output_size = logdet.cols();
396   std::copy_n(temp.data(0), output_size, logdet[i]);
397   const ValueType* restrict gx = temp.data(1);
398   const ValueType* restrict gy = temp.data(2);
399   const ValueType* restrict gz = temp.data(3);
400   for (size_t j = 0; j < output_size; j++)
401   {
402     dlogdet[i][j][0] = gx[j];
403     dlogdet[i][j][1] = gy[j];
404     dlogdet[i][j][2] = gz[j];
405   }
406   std::copy_n(temp.data(4), output_size, d2logdet[i]);
407 }
408 
evaluate_vgh_impl(const vgh_type & temp,int i,ValueMatrix_t & psi,GradMatrix_t & dpsi,HessMatrix_t & d2psi) const409 inline void LCAOrbitalSet::evaluate_vgh_impl(const vgh_type& temp,
410                                              int i,
411                                              ValueMatrix_t& psi,
412                                              GradMatrix_t& dpsi,
413                                              HessMatrix_t& d2psi) const
414 {
415   const size_t output_size = psi.cols();
416   std::copy_n(temp.data(0), output_size, psi[i]);
417   const ValueType* restrict gx  = temp.data(1);
418   const ValueType* restrict gy  = temp.data(2);
419   const ValueType* restrict gz  = temp.data(3);
420   const ValueType* restrict hxx = temp.data(4);
421   const ValueType* restrict hxy = temp.data(5);
422   const ValueType* restrict hxz = temp.data(6);
423   const ValueType* restrict hyy = temp.data(7);
424   const ValueType* restrict hyz = temp.data(8);
425   const ValueType* restrict hzz = temp.data(9);
426 
427   for (size_t j = 0; j < output_size; j++)
428   {
429     dpsi[i][j][0] = gx[j];
430     dpsi[i][j][1] = gy[j];
431     dpsi[i][j][2] = gz[j];
432 
433     d2psi[i][j](0, 0) = hxx[j];
434     d2psi[i][j](0, 1) = d2psi[i][j](1, 0) = hxy[j];
435     d2psi[i][j](0, 2) = d2psi[i][j](2, 0) = hxz[j];
436     d2psi[i][j](1, 1)                     = hyy[j];
437     d2psi[i][j](2, 1) = d2psi[i][j](1, 2) = hyz[j];
438     d2psi[i][j](2, 2)                     = hzz[j];
439   }
440 }
441 
evaluate_ionderiv_v_impl(const vgl_type & temp,int i,GradMatrix_t & dpsi) const442 inline void LCAOrbitalSet::evaluate_ionderiv_v_impl(const vgl_type& temp, int i, GradMatrix_t& dpsi) const
443 {
444   const size_t output_size     = dpsi.cols();
445   const ValueType* restrict gx = temp.data(1);
446   const ValueType* restrict gy = temp.data(2);
447   const ValueType* restrict gz = temp.data(3);
448 
449   for (size_t j = 0; j < output_size; j++)
450   {
451     //As mentioned in SoaLocalizedBasisSet, LCAO's have a nice property that
452     // for an atomic center, the ion gradient is the negative of the elecron gradient.
453     // Hence minus signs for each of these.
454     dpsi[i][j][0] = -gx[j];
455     dpsi[i][j][1] = -gy[j];
456     dpsi[i][j][2] = -gz[j];
457   }
458 }
459 
evaluate_ionderiv_vgl_impl(const vghgh_type & temp,int i,GradMatrix_t & dpsi,HessMatrix_t & dgpsi,GradMatrix_t & dlpsi) const460 inline void LCAOrbitalSet::evaluate_ionderiv_vgl_impl(const vghgh_type& temp,
461                                                       int i,
462                                                       GradMatrix_t& dpsi,
463                                                       HessMatrix_t& dgpsi,
464                                                       GradMatrix_t& dlpsi) const
465 {
466   const size_t output_size         = dpsi.cols();
467   const ValueType* restrict gx     = temp.data(1);
468   const ValueType* restrict gy     = temp.data(2);
469   const ValueType* restrict gz     = temp.data(3);
470   const ValueType* restrict hxx    = temp.data(4);
471   const ValueType* restrict hxy    = temp.data(5);
472   const ValueType* restrict hxz    = temp.data(6);
473   const ValueType* restrict hyy    = temp.data(7);
474   const ValueType* restrict hyz    = temp.data(8);
475   const ValueType* restrict hzz    = temp.data(9);
476   const ValueType* restrict gh_xxx = temp.data(10);
477   const ValueType* restrict gh_xxy = temp.data(11);
478   const ValueType* restrict gh_xxz = temp.data(12);
479   const ValueType* restrict gh_xyy = temp.data(13);
480   const ValueType* restrict gh_xzz = temp.data(15);
481   const ValueType* restrict gh_yyy = temp.data(16);
482   const ValueType* restrict gh_yyz = temp.data(17);
483   const ValueType* restrict gh_yzz = temp.data(18);
484   const ValueType* restrict gh_zzz = temp.data(19);
485 
486   for (size_t j = 0; j < output_size; j++)
487   {
488     //As mentioned in SoaLocalizedBasisSet, LCAO's have a nice property that
489     // for an atomic center, the ion gradient is the negative of the elecron gradient.
490     // Hence minus signs for each of these.
491     dpsi[i][j][0] = -gx[j];
492     dpsi[i][j][1] = -gy[j];
493     dpsi[i][j][2] = -gz[j];
494 
495     dgpsi[i][j](0, 0) = -hxx[j];
496     dgpsi[i][j](0, 1) = dgpsi[i][j](1, 0) = -hxy[j];
497     dgpsi[i][j](0, 2) = dgpsi[i][j](2, 0) = -hxz[j];
498     dgpsi[i][j](1, 1)                     = -hyy[j];
499     dgpsi[i][j](2, 1) = dgpsi[i][j](1, 2) = -hyz[j];
500     dgpsi[i][j](2, 2)                     = -hzz[j];
501 
502     //Since this returns the ion gradient of the laplacian, we have to trace the grad hessian vector.
503     dlpsi[i][j][0] = -(gh_xxx[j] + gh_xyy[j] + gh_xzz[j]);
504     dlpsi[i][j][1] = -(gh_xxy[j] + gh_yyy[j] + gh_yzz[j]);
505     dlpsi[i][j][2] = -(gh_xxz[j] + gh_yyz[j] + gh_zzz[j]);
506   }
507 }
508 
evaluate_notranspose(const ParticleSet & P,int first,int last,ValueMatrix_t & logdet,GradMatrix_t & dlogdet,ValueMatrix_t & d2logdet)509 void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
510                                          int first,
511                                          int last,
512                                          ValueMatrix_t& logdet,
513                                          GradMatrix_t& dlogdet,
514                                          ValueMatrix_t& d2logdet)
515 {
516   if (Identity)
517   {
518     for (size_t i = 0, iat = first; iat < last; i++, iat++)
519     {
520       myBasisSet->evaluateVGL(P, iat, Temp);
521       evaluate_vgl_impl(Temp, i, logdet, dlogdet, d2logdet);
522     }
523   }
524   else
525   {
526     assert(logdet.cols() <= OrbitalSetSize);
527     ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize);
528     for (size_t i = 0, iat = first; iat < last; i++, iat++)
529     {
530       myBasisSet->evaluateVGL(P, iat, Temp);
531       Product_ABt(Temp, C_partial_view, Tempv);
532       evaluate_vgl_impl(Tempv, i, logdet, dlogdet, d2logdet);
533     }
534   }
535 }
536 
evaluate_notranspose(const ParticleSet & P,int first,int last,ValueMatrix_t & logdet,GradMatrix_t & dlogdet,HessMatrix_t & grad_grad_logdet)537 void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
538                                          int first,
539                                          int last,
540                                          ValueMatrix_t& logdet,
541                                          GradMatrix_t& dlogdet,
542                                          HessMatrix_t& grad_grad_logdet)
543 {
544   if (Identity)
545   {
546     for (size_t i = 0, iat = first; iat < last; i++, iat++)
547     {
548       myBasisSet->evaluateVGH(P, iat, Temph);
549       evaluate_vgh_impl(Temph, i, logdet, dlogdet, grad_grad_logdet);
550     }
551   }
552   else
553   {
554     assert(logdet.cols() <= OrbitalSetSize);
555     ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize);
556     for (size_t i = 0, iat = first; iat < last; i++, iat++)
557     {
558       myBasisSet->evaluateVGH(P, iat, Temph);
559       Product_ABt(Temph, C_partial_view, Temphv);
560       evaluate_vgh_impl(Temphv, i, logdet, dlogdet, grad_grad_logdet);
561     }
562   }
563 }
564 
evaluate_notranspose(const ParticleSet & P,int first,int last,ValueMatrix_t & logdet,GradMatrix_t & dlogdet,HessMatrix_t & grad_grad_logdet,GGGMatrix_t & grad_grad_grad_logdet)565 void LCAOrbitalSet::evaluate_notranspose(const ParticleSet& P,
566                                          int first,
567                                          int last,
568                                          ValueMatrix_t& logdet,
569                                          GradMatrix_t& dlogdet,
570                                          HessMatrix_t& grad_grad_logdet,
571                                          GGGMatrix_t& grad_grad_grad_logdet)
572 {
573   if (Identity)
574   {
575     for (size_t i = 0, iat = first; iat < last; i++, iat++)
576     {
577       myBasisSet->evaluateVGHGH(P, iat, Tempgh);
578       evaluate_vghgh_impl(Tempgh, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet);
579     }
580   }
581   else
582   {
583     assert(logdet.cols() <= OrbitalSetSize);
584     ValueMatrix_t C_partial_view(C->data(), logdet.cols(), BasisSetSize);
585     for (size_t i = 0, iat = first; iat < last; i++, iat++)
586     {
587       myBasisSet->evaluateVGHGH(P, iat, Tempgh);
588       Product_ABt(Tempgh, C_partial_view, Tempghv);
589       evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet);
590     }
591   }
592 }
593 
evaluateGradSource(const ParticleSet & P,int first,int last,const ParticleSet & source,int iat_src,GradMatrix_t & gradphi)594 void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P,
595                                        int first,
596                                        int last,
597                                        const ParticleSet& source,
598                                        int iat_src,
599                                        GradMatrix_t& gradphi)
600 {
601   if (Identity)
602   {
603     for (size_t i = 0, iat = first; iat < last; i++, iat++)
604     {
605       myBasisSet->evaluateGradSourceV(P, iat, source, iat_src, Temp);
606       evaluate_ionderiv_v_impl(Temp, i, gradphi);
607     }
608   }
609   else
610   {
611     for (size_t i = 0, iat = first; iat < last; i++, iat++)
612     {
613       myBasisSet->evaluateGradSourceV(P, iat, source, iat_src, Temp);
614       Product_ABt(Temp, *C, Tempv);
615       evaluate_ionderiv_v_impl(Tempv, i, gradphi);
616     }
617   }
618 }
619 
evaluateGradSource(const ParticleSet & P,int first,int last,const ParticleSet & source,int iat_src,GradMatrix_t & grad_phi,HessMatrix_t & grad_grad_phi,GradMatrix_t & grad_lapl_phi)620 void LCAOrbitalSet::evaluateGradSource(const ParticleSet& P,
621                                        int first,
622                                        int last,
623                                        const ParticleSet& source,
624                                        int iat_src,
625                                        GradMatrix_t& grad_phi,
626                                        HessMatrix_t& grad_grad_phi,
627                                        GradMatrix_t& grad_lapl_phi)
628 {
629   if (Identity)
630   {
631     for (size_t i = 0, iat = first; iat < last; i++, iat++)
632     {
633       myBasisSet->evaluateGradSourceVGL(P, iat, source, iat_src, Tempgh);
634       evaluate_ionderiv_vgl_impl(Tempgh, i, grad_phi, grad_grad_phi, grad_lapl_phi);
635     }
636   }
637   else
638   {
639     for (size_t i = 0, iat = first; iat < last; i++, iat++)
640     {
641       myBasisSet->evaluateGradSourceVGL(P, iat, source, iat_src, Tempgh);
642       Product_ABt(Tempgh, *C, Tempghv);
643       evaluate_ionderiv_vgl_impl(Tempghv, i, grad_phi, grad_grad_phi, grad_lapl_phi);
644       //  evaluate_vghgh_impl(Tempghv, i, logdet, dlogdet, grad_grad_logdet, grad_grad_grad_logdet);
645     }
646   }
647 }
648 
evaluateThirdDeriv(const ParticleSet & P,int first,int last,GGGMatrix_t & grad_grad_grad_logdet)649 void LCAOrbitalSet::evaluateThirdDeriv(const ParticleSet& P, int first, int last, GGGMatrix_t& grad_grad_grad_logdet)
650 {
651   APP_ABORT("LCAOrbitalSet::evaluateThirdDeriv(P,istart,istop,ggg_logdet) not implemented\n");
652 }
653 
applyRotation(const ValueMatrix_t & rot_mat,bool use_stored_copy)654 void LCAOrbitalSet::applyRotation(const ValueMatrix_t& rot_mat, bool use_stored_copy)
655 {
656   if (!use_stored_copy)
657     C_copy = *C;
658   //gemm is out-of-place
659   BLAS::gemm('N', 'T', BasisSetSize, OrbitalSetSize, OrbitalSetSize, RealType(1.0), C_copy.data(), BasisSetSize,
660              rot_mat.data(), OrbitalSetSize, RealType(0.0), C->data(), BasisSetSize);
661 
662   /* debugging code
663   app_log() << "PRINTING MO COEFFICIENTS AFTER ROTATION " << objectName << std::endl;
664   for (int j = 0; j < OrbitalSetSize; j++)
665     for (int i = 0; i < BasisSetSize; i++)
666     {
667       app_log() << " " << std::right << std::fixed << std::setprecision(16) << std::setw(23) << std::scientific
668                 << *(C->data() + j * BasisSetSize + i);
669 
670       if ((j * BasisSetSize + i + 1) % 4 == 0)
671         app_log() << std::endl;
672     }
673   */
674 }
675 
676 } // namespace qmcplusplus
677