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