QMCPACK
SplineR2R.cpp
Go to the documentation of this file.
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) 2019 QMCPACK developers.
6 //
7 // File developed by: Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
8 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
9 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
10 // Ye Luo, yeluo@anl.gov, Argonne National Laboratory
11 //
12 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 //////////////////////////////////////////////////////////////////////////////////////
14 
15 
16 #include "Concurrency/OpenMP.h"
17 #include "SplineR2R.h"
18 #include "spline2/MultiBsplineEval.hpp"
20 #include "Platforms/CPU/BLAS.hpp"
22 
23 namespace qmcplusplus
24 {
25 template<typename ST>
26 SplineR2R<ST>::SplineR2R(const SplineR2R& in) = default;
27 
28 template<typename ST>
30  SingleSplineType* spline_i,
31  int twist,
32  int ispline,
33  int level)
34 {
35  SplineInst->copy_spline(spline_r, ispline);
36 }
37 
38 template<typename ST>
40 {
41  std::ostringstream o;
42  o << "spline_" << MyIndex;
43  einspline_engine<SplineType> bigtable(SplineInst->getSplinePtr());
44  return h5f.readEntry(bigtable, o.str().c_str()); //"spline_0");
45 }
46 
47 template<typename ST>
49 {
50  std::ostringstream o;
51  o << "spline_" << MyIndex;
52  einspline_engine<SplineType> bigtable(SplineInst->getSplinePtr());
53  return h5f.writeEntry(bigtable, o.str().c_str()); //"spline_0");
54 }
55 
56 template<typename ST>
58 {
59  const auto spline_ptr = SplineInst->getSplinePtr();
60  const auto coefs_tot_size = spline_ptr->coefs_size;
61  coef_copy_ = std::make_shared<std::vector<ST>>(coefs_tot_size);
62 
63  std::copy_n(spline_ptr->coefs, coefs_tot_size, coef_copy_->begin());
64 }
65 
66 /*
67  ~~ Notes for rotation ~~
68  spl_coefs = Raw pointer to spline coefficients
69  basis_set_size = Number of spline coefs per orbital
70  OrbitalSetSize = Number of orbitals (excluding padding)
71 
72  spl_coefs has a complicated layout depending on dimensionality of splines.
73  Luckily, for our purposes, we can think of spl_coefs as pointing to a
74  matrix of size BasisSetSize x (OrbitalSetSize + padding), with the spline
75  index adjacent in memory. The orbital index is SIMD aligned and therefore
76  may include padding.
77 
78  As a result, due to SIMD alignment, Nsplines may be larger than the
79  actual number of splined orbitals. This means that in practice rot_mat
80  may be smaller than the number of 'columns' in the coefs array!
81 
82  SplineR2R spl_coef layout:
83  ^ | sp1 | ... | spN | pad |
84  | |=====|=====|=====|=====|
85  | | c11 | ... | c1N | 0 |
86  basis_set_size | c21 | ... | c2N | 0 |
87  | | ... | ... | ... | 0 |
88  | | cM1 | ... | cMN | 0 |
89  v |=====|=====|=====|=====|
90  <------ Nsplines ------>
91 
92  SplineC2C spl_coef layout:
93  ^ | sp1_r | sp1_i | ... | spN_r | spN_i | pad |
94  | |=======|=======|=======|=======|=======|=======|
95  | | c11_r | c11_i | ... | c1N_r | c1N_i | 0 |
96  basis_set_size | c21_r | c21_i | ... | c2N_r | c2N_i | 0 |
97  | | ... | ... | ... | ... | ... | ... |
98  | | cM1_r | cM1_i | ... | cMN_r | cMN_i | 0 |
99  v |=======|=======|=======|=======|=======|=======|
100  <------------------ Nsplines ------------------>
101 
102  NB: For splines (typically) BasisSetSize >> OrbitalSetSize, so the spl_coefs
103  "matrix" is very tall and skinny.
104 */
105 template<typename ST>
106 void SplineR2R<ST>::applyRotation(const ValueMatrix& rot_mat, bool use_stored_copy)
107 {
108  // SplineInst is a MultiBspline. See src/spline2/MultiBspline.hpp
109  const auto spline_ptr = SplineInst->getSplinePtr();
110  assert(spline_ptr != nullptr);
111  const auto spl_coefs = spline_ptr->coefs;
112  const auto Nsplines = spline_ptr->num_splines; // May include padding
113  const auto coefs_tot_size = spline_ptr->coefs_size;
114  const auto BasisSetSize = coefs_tot_size / Nsplines;
115  const auto TrueNOrbs = rot_mat.size1(); // == Nsplines - padding
116  assert(OrbitalSetSize == rot_mat.rows());
117  assert(OrbitalSetSize == rot_mat.cols());
118 
119  if (!use_stored_copy)
120  {
121  assert(coef_copy_ != nullptr);
122  std::copy_n(spl_coefs, coefs_tot_size, coef_copy_->begin());
123  }
124 
125 
126  if constexpr (std::is_same_v<ST, RealType>)
127  {
128  //Here, ST should be equal to ValueType, which will be double for R2R. Using BLAS to make things faster
129  BLAS::gemm('N', 'N', OrbitalSetSize, BasisSetSize, OrbitalSetSize, ST(1.0), rot_mat.data(), OrbitalSetSize,
130  coef_copy_->data(), Nsplines, ST(0.0), spl_coefs, Nsplines);
131  }
132  else
133  {
134  //Here, ST is float but ValueType is double for R2R. Due to issues with type conversions, just doing naive matrix multiplication in this case to not lose precision on rot_mat
135  for (IndexType i = 0; i < BasisSetSize; i++)
136  for (IndexType j = 0; j < OrbitalSetSize; j++)
137  {
138  const auto cur_elem = Nsplines * i + j;
139  FullPrecValueType newval{0.};
140  for (IndexType k = 0; k < OrbitalSetSize; k++)
141  {
142  const auto index = i * Nsplines + k;
143  newval += (*coef_copy_)[index] * rot_mat[k][j];
144  }
145  spl_coefs[cur_elem] = newval;
146  }
147  }
148 }
149 
150 
151 template<typename ST>
152 inline void SplineR2R<ST>::assign_v(int bc_sign, const vContainer_type& myV, ValueVector& psi, int first, int last)
153  const
154 {
155  // protect last against kPoints.size() and psi.size()
156  size_t last_real = std::min(kPoints.size(), psi.size());
157  last = last > last_real ? last_real : last;
158 
159  const ST signed_one = (bc_sign & 1) ? -1 : 1;
160 #pragma omp simd
161  for (size_t j = first; j < last; ++j)
162  psi[first_spo + j] = signed_one * myV[j];
163 }
164 
165 template<typename ST>
166 void SplineR2R<ST>::evaluateValue(const ParticleSet& P, const int iat, ValueVector& psi)
167 {
168  const PointType& r = P.activeR(iat);
169  PointType ru;
170  int bc_sign = convertPos(r, ru);
171 
172 #pragma omp parallel
173  {
174  int first, last;
175  FairDivideAligned(psi.size(), getAlignment<ST>(), omp_get_num_threads(), omp_get_thread_num(), first, last);
176 
177  spline2::evaluate3d(SplineInst->getSplinePtr(), ru, myV, first, last);
178  assign_v(bc_sign, myV, psi, first, last);
179  }
180 }
181 
182 template<typename ST>
184  ValueVector& psi,
185  const ValueVector& psiinv,
186  std::vector<TT>& ratios)
187 {
188  const bool need_resize = ratios_private.rows() < VP.getTotalNum();
189 
190 #pragma omp parallel
191  {
192  int tid = omp_get_thread_num();
193  // initialize thread private ratios
194  if (need_resize)
195  {
196  if (tid == 0) // just like #pragma omp master, but one fewer call to the runtime
197  ratios_private.resize(VP.getTotalNum(), omp_get_num_threads());
198 #pragma omp barrier
199  }
200  int first, last;
201  FairDivideAligned(psi.size(), getAlignment<ST>(), omp_get_num_threads(), tid, first, last);
202  const int last_real = kPoints.size() < last ? kPoints.size() : last;
203 
204  for (int iat = 0; iat < VP.getTotalNum(); ++iat)
205  {
206  const PointType& r = VP.activeR(iat);
207  PointType ru;
208  int bc_sign = convertPos(r, ru);
209 
210  spline2::evaluate3d(SplineInst->getSplinePtr(), ru, myV, first, last);
211  assign_v(bc_sign, myV, psi, first, last_real);
212  ratios_private[iat][tid] = simd::dot(psi.data() + first, psiinv.data() + first, last_real - first);
213  }
214  }
215 
216  // do the reduction manually
217  for (int iat = 0; iat < VP.getTotalNum(); ++iat)
218  {
219  ratios[iat] = TT(0);
220  for (int tid = 0; tid < ratios_private.cols(); tid++)
221  ratios[iat] += ratios_private[iat][tid];
222  }
223 }
224 
225 template<typename ST>
226 inline void SplineR2R<ST>::assign_vgl(int bc_sign,
227  ValueVector& psi,
228  GradVector& dpsi,
229  ValueVector& d2psi,
230  int first,
231  int last) const
232 {
233  // protect last against kPoints.size() and psi.size()
234  size_t last_real = std::min(kPoints.size(), psi.size());
235  last = last > last_real ? last_real : last;
236 
237  const ST signed_one = (bc_sign & 1) ? -1 : 1;
238  const ST g00 = PrimLattice.G(0), g01 = PrimLattice.G(1), g02 = PrimLattice.G(2), g10 = PrimLattice.G(3),
239  g11 = PrimLattice.G(4), g12 = PrimLattice.G(5), g20 = PrimLattice.G(6), g21 = PrimLattice.G(7),
240  g22 = PrimLattice.G(8);
241  const ST symGG[6] = {GGt[0], GGt[1] + GGt[3], GGt[2] + GGt[6], GGt[4], GGt[5] + GGt[7], GGt[8]};
242 
243  const ST* restrict g0 = myG.data(0);
244  const ST* restrict g1 = myG.data(1);
245  const ST* restrict g2 = myG.data(2);
246  const ST* restrict h00 = myH.data(0);
247  const ST* restrict h01 = myH.data(1);
248  const ST* restrict h02 = myH.data(2);
249  const ST* restrict h11 = myH.data(3);
250  const ST* restrict h12 = myH.data(4);
251  const ST* restrict h22 = myH.data(5);
252 
253 #pragma omp simd
254  for (size_t j = first; j < last; ++j)
255  {
256  const size_t psiIndex = first_spo + j;
257  psi[psiIndex] = signed_one * myV[j];
258  dpsi[psiIndex][0] = signed_one * (g00 * g0[j] + g01 * g1[j] + g02 * g2[j]);
259  dpsi[psiIndex][1] = signed_one * (g10 * g0[j] + g11 * g1[j] + g12 * g2[j]);
260  dpsi[psiIndex][2] = signed_one * (g20 * g0[j] + g21 * g1[j] + g22 * g2[j]);
261  d2psi[psiIndex] = signed_one * SymTrace(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], symGG);
262  }
263 }
264 
265 /** assign_vgl_from_l can be used when myL is precomputed and myV,myG,myL in cartesian
266  */
267 template<typename ST>
268 inline void SplineR2R<ST>::assign_vgl_from_l(int bc_sign, ValueVector& psi, GradVector& dpsi, ValueVector& d2psi)
269 {
270  const ST signed_one = (bc_sign & 1) ? -1 : 1;
271  const ST* restrict g0 = myG.data(0);
272  const ST* restrict g1 = myG.data(1);
273  const ST* restrict g2 = myG.data(2);
274 
275  const size_t last_real = last_spo > psi.size() ? psi.size() : last_spo;
276 #pragma omp simd
277  for (int psiIndex = first_spo; psiIndex < last_real; ++psiIndex)
278  {
279  const size_t j = psiIndex - first_spo;
280  psi[psiIndex] = signed_one * myV[j];
281  dpsi[psiIndex][0] = signed_one * g0[j];
282  dpsi[psiIndex][1] = signed_one * g1[j];
283  dpsi[psiIndex][2] = signed_one * g2[j];
284  d2psi[psiIndex] = signed_one * myL[j];
285  }
286 }
287 
288 template<typename ST>
290  const int iat,
291  ValueVector& psi,
292  GradVector& dpsi,
293  ValueVector& d2psi)
294 {
295  const PointType& r = P.activeR(iat);
296  PointType ru;
297  int bc_sign = convertPos(r, ru);
298 
299 #pragma omp parallel
300  {
301  int first, last;
302  FairDivideAligned(psi.size(), getAlignment<ST>(), omp_get_num_threads(), omp_get_thread_num(), first, last);
303 
304  spline2::evaluate3d_vgh(SplineInst->getSplinePtr(), ru, myV, myG, myH, first, last);
305  assign_vgl(bc_sign, psi, dpsi, d2psi, first, last);
306  }
307 }
308 
309 template<typename ST>
310 void SplineR2R<ST>::assign_vgh(int bc_sign,
311  ValueVector& psi,
312  GradVector& dpsi,
313  HessVector& grad_grad_psi,
314  int first,
315  int last) const
316 {
317  // protect last against kPoints.size() and psi.size()
318  const size_t last_real = std::min(kPoints.size(), psi.size());
319  last = last > last_real ? last_real : last;
320 
321  const ST signed_one = (bc_sign & 1) ? -1 : 1;
322  const ST g00 = PrimLattice.G(0), g01 = PrimLattice.G(1), g02 = PrimLattice.G(2), g10 = PrimLattice.G(3),
323  g11 = PrimLattice.G(4), g12 = PrimLattice.G(5), g20 = PrimLattice.G(6), g21 = PrimLattice.G(7),
324  g22 = PrimLattice.G(8);
325 
326  const ST* restrict g0 = myG.data(0);
327  const ST* restrict g1 = myG.data(1);
328  const ST* restrict g2 = myG.data(2);
329  const ST* restrict h00 = myH.data(0);
330  const ST* restrict h01 = myH.data(1);
331  const ST* restrict h02 = myH.data(2);
332  const ST* restrict h11 = myH.data(3);
333  const ST* restrict h12 = myH.data(4);
334  const ST* restrict h22 = myH.data(5);
335 
336 #pragma omp simd
337  for (size_t j = first; j < last; ++j)
338  {
339  //dot(PrimLattice.G,myG[j])
340  const ST dX_r = g00 * g0[j] + g01 * g1[j] + g02 * g2[j];
341  const ST dY_r = g10 * g0[j] + g11 * g1[j] + g12 * g2[j];
342  const ST dZ_r = g20 * g0[j] + g21 * g1[j] + g22 * g2[j];
343 
344  const size_t psiIndex = j + first_spo;
345  psi[psiIndex] = signed_one * myV[j];
346  dpsi[psiIndex][0] = signed_one * dX_r;
347  dpsi[psiIndex][1] = signed_one * dY_r;
348  dpsi[psiIndex][2] = signed_one * dZ_r;
349 
350  const ST h_xx_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g00, g01, g02);
351  const ST h_xy_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g10, g11, g12);
352  const ST h_xz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g20, g21, g22);
353  const ST h_yx_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g10, g11, g12, g00, g01, g02);
354  const ST h_yy_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g10, g11, g12, g10, g11, g12);
355  const ST h_yz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g10, g11, g12, g20, g21, g22);
356  const ST h_zx_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g20, g21, g22, g00, g01, g02);
357  const ST h_zy_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g20, g21, g22, g10, g11, g12);
358  const ST h_zz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g20, g21, g22, g20, g21, g22);
359 
360  grad_grad_psi[psiIndex][0] = signed_one * h_xx_r;
361  grad_grad_psi[psiIndex][1] = signed_one * h_xy_r;
362  grad_grad_psi[psiIndex][2] = signed_one * h_xz_r;
363  grad_grad_psi[psiIndex][3] = signed_one * h_yx_r;
364  grad_grad_psi[psiIndex][4] = signed_one * h_yy_r;
365  grad_grad_psi[psiIndex][5] = signed_one * h_yz_r;
366  grad_grad_psi[psiIndex][6] = signed_one * h_zx_r;
367  grad_grad_psi[psiIndex][7] = signed_one * h_zy_r;
368  grad_grad_psi[psiIndex][8] = signed_one * h_zz_r;
369  }
370 }
371 
372 template<typename ST>
374  const int iat,
375  ValueVector& psi,
376  GradVector& dpsi,
377  HessVector& grad_grad_psi)
378 {
379  const PointType& r = P.activeR(iat);
380  PointType ru;
381  int bc_sign = convertPos(r, ru);
382 
383 #pragma omp parallel
384  {
385  int first, last;
386  FairDivideAligned(psi.size(), getAlignment<ST>(), omp_get_num_threads(), omp_get_thread_num(), first, last);
387 
388  spline2::evaluate3d_vgh(SplineInst->getSplinePtr(), ru, myV, myG, myH, first, last);
389  assign_vgh(bc_sign, psi, dpsi, grad_grad_psi, first, last);
390  }
391 }
392 
393 template<typename ST>
395  ValueVector& psi,
396  GradVector& dpsi,
397  HessVector& grad_grad_psi,
398  GGGVector& grad_grad_grad_psi,
399  int first,
400  int last) const
401 {
402  // protect last against kPoints.size() and psi.size()
403  const size_t last_real = std::min(kPoints.size(), psi.size());
404  last = last < 0 ? last_real : (last > last_real ? last_real : last);
405 
406  const ST signed_one = (bc_sign & 1) ? -1 : 1;
407  const ST g00 = PrimLattice.G(0), g01 = PrimLattice.G(1), g02 = PrimLattice.G(2), g10 = PrimLattice.G(3),
408  g11 = PrimLattice.G(4), g12 = PrimLattice.G(5), g20 = PrimLattice.G(6), g21 = PrimLattice.G(7),
409  g22 = PrimLattice.G(8);
410 
411  const ST* restrict g0 = myG.data(0);
412  const ST* restrict g1 = myG.data(1);
413  const ST* restrict g2 = myG.data(2);
414  const ST* restrict h00 = myH.data(0);
415  const ST* restrict h01 = myH.data(1);
416  const ST* restrict h02 = myH.data(2);
417  const ST* restrict h11 = myH.data(3);
418  const ST* restrict h12 = myH.data(4);
419  const ST* restrict h22 = myH.data(5);
420 
421  const ST* restrict gh000 = mygH.data(0);
422  const ST* restrict gh001 = mygH.data(1);
423  const ST* restrict gh002 = mygH.data(2);
424  const ST* restrict gh011 = mygH.data(3);
425  const ST* restrict gh012 = mygH.data(4);
426  const ST* restrict gh022 = mygH.data(5);
427  const ST* restrict gh111 = mygH.data(6);
428  const ST* restrict gh112 = mygH.data(7);
429  const ST* restrict gh122 = mygH.data(8);
430  const ST* restrict gh222 = mygH.data(9);
431 
432  //SIMD doesn't work quite right yet. Comment out until further debugging.
433  //#pragma omp simd
434  for (size_t j = first; j < last; ++j)
435  {
436  const ST val_r = myV[j];
437 
438 
439  //dot(PrimLattice.G,myG[j])
440  const ST dX_r = g00 * g0[j] + g01 * g1[j] + g02 * g2[j];
441  const ST dY_r = g10 * g0[j] + g11 * g1[j] + g12 * g2[j];
442  const ST dZ_r = g20 * g0[j] + g21 * g1[j] + g22 * g2[j];
443 
444  const size_t psiIndex = j + first_spo;
445  psi[psiIndex] = signed_one * val_r;
446  dpsi[psiIndex][0] = signed_one * dX_r;
447  dpsi[psiIndex][1] = signed_one * dY_r;
448  dpsi[psiIndex][2] = signed_one * dZ_r;
449 
450  //intermediates for computation of hessian. \partial_i \partial_j phi in cartesian coordinates.
451  const ST f_xx_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g00, g01, g02);
452  const ST f_xy_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g10, g11, g12);
453  const ST f_xz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g00, g01, g02, g20, g21, g22);
454  const ST f_yy_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g10, g11, g12, g10, g11, g12);
455  const ST f_yz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g10, g11, g12, g20, g21, g22);
456  const ST f_zz_r = v_m_v(h00[j], h01[j], h02[j], h11[j], h12[j], h22[j], g20, g21, g22, g20, g21, g22);
457 
458  /* const ST h_xx_r=f_xx_r;
459  const ST h_xy_r=f_xy_r+(kX*dY_i+kY*dX_i)-kX*kY*val_r;
460  const ST h_xz_r=f_xz_r+(kX*dZ_i+kZ*dX_i)-kX*kZ*val_r;
461  const ST h_yy_r=f_yy_r+2*kY*dY_i-kY*kY*val_r;
462  const ST h_yz_r=f_yz_r+(kY*dZ_i+kZ*dY_i)-kY*kZ*val_r;
463  const ST h_zz_r=f_zz_r+2*kZ*dZ_i-kZ*kZ*val_r; */
464 
465  grad_grad_psi[psiIndex][0] = f_xx_r * signed_one;
466  grad_grad_psi[psiIndex][1] = f_xy_r * signed_one;
467  grad_grad_psi[psiIndex][2] = f_xz_r * signed_one;
468  grad_grad_psi[psiIndex][4] = f_yy_r * signed_one;
469  grad_grad_psi[psiIndex][5] = f_yz_r * signed_one;
470  grad_grad_psi[psiIndex][8] = f_zz_r * signed_one;
471 
472  //symmetry:
473  grad_grad_psi[psiIndex][3] = grad_grad_psi[psiIndex][1];
474  grad_grad_psi[psiIndex][6] = grad_grad_psi[psiIndex][2];
475  grad_grad_psi[psiIndex][7] = grad_grad_psi[psiIndex][5];
476  //These are the real and imaginary components of the third SPO derivative. _xxx denotes
477  // third derivative w.r.t. x, _xyz, a derivative with resepect to x,y, and z, and so on.
478 
479  const ST f3_xxx_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
480  gh122[j], gh222[j], g00, g01, g02, g00, g01, g02, g00, g01, g02);
481  const ST f3_xxy_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
482  gh122[j], gh222[j], g00, g01, g02, g00, g01, g02, g10, g11, g12);
483  const ST f3_xxz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
484  gh122[j], gh222[j], g00, g01, g02, g00, g01, g02, g20, g21, g22);
485  const ST f3_xyy_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
486  gh122[j], gh222[j], g00, g01, g02, g10, g11, g12, g10, g11, g12);
487  const ST f3_xyz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
488  gh122[j], gh222[j], g00, g01, g02, g10, g11, g12, g20, g21, g22);
489  const ST f3_xzz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
490  gh122[j], gh222[j], g00, g01, g02, g20, g21, g22, g20, g21, g22);
491  const ST f3_yyy_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
492  gh122[j], gh222[j], g10, g11, g12, g10, g11, g12, g10, g11, g12);
493  const ST f3_yyz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
494  gh122[j], gh222[j], g10, g11, g12, g10, g11, g12, g20, g21, g22);
495  const ST f3_yzz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
496  gh122[j], gh222[j], g10, g11, g12, g20, g21, g22, g20, g21, g22);
497  const ST f3_zzz_r = t3_contract(gh000[j], gh001[j], gh002[j], gh011[j], gh012[j], gh022[j], gh111[j], gh112[j],
498  gh122[j], gh222[j], g20, g21, g22, g20, g21, g22, g20, g21, g22);
499 
500  //Here is where we build up the components of the physical hessian gradient, namely, d^3/dx^3(e^{-ik*r}\phi(r)
501  /* const ST gh_xxx_r= f3_xxx_r + 3*kX*f_xx_i - 3*kX*kX*dX_r - kX*kX*kX*val_i;
502  const ST gh_xxy_r= f3_xxy_r +(kY*f_xx_i+2*kX*f_xy_i) - (kX*kX*dY_r+2*kX*kY*dX_r)-kX*kX*kY*val_i;
503  const ST gh_xxz_r= f3_xxz_r +(kZ*f_xx_i+2*kX*f_xz_i) - (kX*kX*dZ_r+2*kX*kZ*dX_r)-kX*kX*kZ*val_i;
504  const ST gh_xyy_r= f3_xyy_r +(2*kY*f_xy_i+kX*f_yy_i) - (2*kX*kY*dY_r+kY*kY*dX_r)-kX*kY*kY*val_i;
505  const ST gh_xyz_r= f3_xyz_r +(kX*f_yz_i+kY*f_xz_i+kZ*f_xy_i)-(kX*kY*dZ_r+kY*kZ*dX_r+kZ*kX*dY_r) - kX*kY*kZ*val_i;
506  const ST gh_xzz_r= f3_xzz_r +(2*kZ*f_xz_i+kX*f_zz_i) - (2*kX*kZ*dZ_r+kZ*kZ*dX_r)-kX*kZ*kZ*val_i;
507  const ST gh_yyy_r= f3_yyy_r + 3*kY*f_yy_i - 3*kY*kY*dY_r - kY*kY*kY*val_i;
508  const ST gh_yyz_r= f3_yyz_r +(kZ*f_yy_i+2*kY*f_yz_i) - (kY*kY*dZ_r+2*kY*kZ*dY_r)-kY*kY*kZ*val_i;
509  const ST gh_yzz_r= f3_yzz_r +(2*kZ*f_yz_i+kY*f_zz_i) - (2*kY*kZ*dZ_r+kZ*kZ*dY_r)-kY*kZ*kZ*val_i;
510  const ST gh_zzz_r= f3_zzz_r + 3*kZ*f_zz_i - 3*kZ*kZ*dZ_r - kZ*kZ*kZ*val_i;*/
511  //[x][xx] //These are the unique entries
512  grad_grad_grad_psi[psiIndex][0][0] = signed_one * f3_xxx_r;
513  grad_grad_grad_psi[psiIndex][0][1] = signed_one * f3_xxy_r;
514  grad_grad_grad_psi[psiIndex][0][2] = signed_one * f3_xxz_r;
515  grad_grad_grad_psi[psiIndex][0][4] = signed_one * f3_xyy_r;
516  grad_grad_grad_psi[psiIndex][0][5] = signed_one * f3_xyz_r;
517  grad_grad_grad_psi[psiIndex][0][8] = signed_one * f3_xzz_r;
518 
519  //filling in the symmetric terms. Filling out the xij terms
520  grad_grad_grad_psi[psiIndex][0][3] = grad_grad_grad_psi[psiIndex][0][1];
521  grad_grad_grad_psi[psiIndex][0][6] = grad_grad_grad_psi[psiIndex][0][2];
522  grad_grad_grad_psi[psiIndex][0][7] = grad_grad_grad_psi[psiIndex][0][5];
523 
524  //Now for everything that's a permutation of the above:
525  grad_grad_grad_psi[psiIndex][1][0] = grad_grad_grad_psi[psiIndex][0][1];
526  grad_grad_grad_psi[psiIndex][1][1] = grad_grad_grad_psi[psiIndex][0][4];
527  grad_grad_grad_psi[psiIndex][1][2] = grad_grad_grad_psi[psiIndex][0][5];
528  grad_grad_grad_psi[psiIndex][1][3] = grad_grad_grad_psi[psiIndex][0][4];
529  grad_grad_grad_psi[psiIndex][1][6] = grad_grad_grad_psi[psiIndex][0][5];
530 
531  grad_grad_grad_psi[psiIndex][2][0] = grad_grad_grad_psi[psiIndex][0][2];
532  grad_grad_grad_psi[psiIndex][2][1] = grad_grad_grad_psi[psiIndex][0][5];
533  grad_grad_grad_psi[psiIndex][2][2] = grad_grad_grad_psi[psiIndex][0][8];
534  grad_grad_grad_psi[psiIndex][2][3] = grad_grad_grad_psi[psiIndex][0][5];
535  grad_grad_grad_psi[psiIndex][2][6] = grad_grad_grad_psi[psiIndex][0][8];
536 
537  grad_grad_grad_psi[psiIndex][1][4] = signed_one * f3_yyy_r;
538  grad_grad_grad_psi[psiIndex][1][5] = signed_one * f3_yyz_r;
539  grad_grad_grad_psi[psiIndex][1][8] = signed_one * f3_yzz_r;
540 
541  grad_grad_grad_psi[psiIndex][1][7] = grad_grad_grad_psi[psiIndex][1][5];
542  grad_grad_grad_psi[psiIndex][2][4] = grad_grad_grad_psi[psiIndex][1][5];
543  grad_grad_grad_psi[psiIndex][2][5] = grad_grad_grad_psi[psiIndex][1][8];
544  grad_grad_grad_psi[psiIndex][2][7] = grad_grad_grad_psi[psiIndex][1][8];
545 
546  grad_grad_grad_psi[psiIndex][2][8] = signed_one * f3_zzz_r;
547  }
548 }
549 
550 template<typename ST>
552  const int iat,
553  ValueVector& psi,
554  GradVector& dpsi,
555  HessVector& grad_grad_psi,
556  GGGVector& grad_grad_grad_psi)
557 {
558  const PointType& r = P.activeR(iat);
559  PointType ru;
560  int bc_sign = convertPos(r, ru);
561 
562 #pragma omp parallel
563  {
564  int first, last;
565  FairDivideAligned(psi.size(), getAlignment<ST>(), omp_get_num_threads(), omp_get_thread_num(), first, last);
566 
567  spline2::evaluate3d_vghgh(SplineInst->getSplinePtr(), ru, myV, myG, myH, mygH, first, last);
568  assign_vghgh(bc_sign, psi, dpsi, grad_grad_psi, grad_grad_grad_psi, first, last);
569  }
570 }
571 
572 template class SplineR2R<float>;
573 template class SplineR2R<double>;
574 
575 } // namespace qmcplusplus
OrbitalSetTraits< ValueType >::HessVector HessVector
Definition: SPOSet.h:53
T SymTrace(T h00, T h01, T h02, T h11, T h12, T h22, const T gg[6])
compute Trace(H*G)
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
void assign_vgl(int bc_sign, ValueVector &psi, GradVector &dpsi, ValueVector &d2psi, int first, int last) const
Definition: SplineR2R.cpp:226
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
T dot(const T *restrict a, const T *restrict b, int n, TRES res=TRES())
dot product
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
SplineR2R(const std::string &my_name)
Definition: SplineR2R.h:79
OrbitalSetTraits< ValueType >::ValueMatrix ValueMatrix
Definition: SPOSet.h:50
void evaluateDetRatios(const VirtualParticleSet &VP, ValueVector &psi, const ValueVector &psiinv, std::vector< TT > &ratios) override
Definition: SplineR2R.cpp:183
T v_m_v(T h00, T h01, T h02, T h11, T h12, T h22, T g1x, T g1y, T g1z, T g2x, T g2y, T g2z)
compute vector[3]^T x matrix[3][3] x vector[3]
T t3_contract(T h000, T h001, T h002, T h011, T h012, T h022, T h111, T h112, T h122, T h222, T g1x, T g1y, T g1z, T g2x, T g2y, T g2z, T g3x, T g3y, T g3z)
Coordinate transform for a 3rd rank symmetric tensor representing coordinate derivatives (hence t3_co...
class to handle hdf file
Definition: hdf_archive.h:51
void assign_v(ST x, ST y, ST z, TT *restrict results_scratch_ptr, const ST *restrict offload_scratch_ptr, const ST *restrict myKcart_ptr, size_t myKcart_padded_size, size_t first_spo, int index)
T min(T a, T b)
void evaluateVGH(const ParticleSet &P, const int iat, ValueVector &psi, GradVector &dpsi, HessVector &grad_grad_psi) override
evaluate the values, gradients and hessians of this single-particle orbital set
Definition: SplineR2R.cpp:373
void assign_vgh(int bc_sign, ValueVector &psi, GradVector &dpsi, HessVector &grad_grad_psi, int first, int last) const
Definition: SplineR2R.cpp:310
void evaluateVGHGH(const ParticleSet &P, const int iat, ValueVector &psi, GradVector &dpsi, HessVector &grad_grad_psi, GGGVector &grad_grad_grad_psi) override
evaluate the values, gradients, hessians, and grad hessians of this single-particle orbital set ...
Definition: SplineR2R.cpp:551
omp_int_t omp_get_thread_num()
Definition: OpenMP.h:25
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
QTFull::ValueType FullPrecValueType
Definition: Configuration.h:67
void applyRotation(const ValueMatrix &rot_mat, bool use_stored_copy) override
apply rotation to all the orbitals
Definition: SplineR2R.cpp:106
bool read_splines(hdf_archive &h5f)
Definition: SplineR2R.cpp:39
void FairDivideAligned(const int ntot, const int base, const int npart, const int me, int &first, int &last)
Partition ntot over npart and the size of each partition is a multiple of base size.
Definition: FairDivide.h:96
void set_spline(SingleSplineType *spline_r, SingleSplineType *spline_i, int twist, int ispline, int level)
Definition: SplineR2R.cpp:29
void assign_vghgh(int bc_sign, ValueVector &psi, GradVector &dpsi, HessVector &grad_grad_psi, GGGVector &grad_grad_grad_psi, int first=0, int last=-1) const
Definition: SplineR2R.cpp:394
OrbitalSetTraits< ValueType >::ValueVector ValueVector
Definition: SPOSet.h:49
typename BsplineSet::ValueType TT
Definition: SplineR2R.h:43
const PosType & activeR(int iat) const
return the active position if the particle is active or the return current position if not ...
Definition: ParticleSet.h:265
void storeParamsBeforeRotation() override
Store an original copy of the spline coefficients for orbital rotation.
Definition: SplineR2R.cpp:57
omp_int_t omp_get_num_threads()
Definition: OpenMP.h:27
OHMMS_INDEXTYPE IndexType
define other types
Definition: Configuration.h:65
bool write_splines(hdf_archive &h5f)
Definition: SplineR2R.cpp:48
void evaluateVGL(const ParticleSet &P, const int iat, ValueVector &psi, GradVector &dpsi, ValueVector &d2psi) override
evaluate the values, gradients and laplacians of this single-particle orbital set ...
Definition: SplineR2R.cpp:289
OrbitalSetTraits< ValueType >::GradHessVector GGGVector
Definition: SPOSet.h:55
sycl::event copy_n(sycl::queue &aq, const T1 *restrict VA, size_t array_size, T2 *restrict VC, const std::vector< sycl::event > &events)
Definition: syclBLAS.cpp:548
OrbitalSetTraits< ValueType >::GradVector GradVector
Definition: SPOSet.h:51
void evaluateValue(const ParticleSet &P, const int iat, ValueVector &psi) override
evaluate the values of this single-particle orbital set
Definition: SplineR2R.cpp:166
void assign_vgl(ST x, ST y, ST z, TT *restrict results_scratch_ptr, size_t orb_padded_size, const ST *mKK_ptr, const ST *restrict offload_scratch_ptr, size_t spline_padded_size, const ST G[9], const ST *myKcart_ptr, size_t myKcart_padded_size, size_t first_spo, int index)
assign_vgl
UBspline_3d_d SingleSplineType
Definition: SplineR2R.h:41
static void gemm(char Atrans, char Btrans, int M, int N, int K, double alpha, const double *A, int lda, const double *restrict B, int ldb, double beta, double *restrict C, int ldc)
Definition: BLAS.hpp:235
bool readEntry(T &data, const std::string &aname)
read the data from the group aname and return status use read() for inbuilt error checking ...
Definition: hdf_archive.h:293
void assign_vgl_from_l(int bc_sign, ValueVector &psi, GradVector &dpsi, ValueVector &d2psi)
assign_vgl_from_l can be used when myL is precomputed and myV,myG,myL in cartesian ...
Definition: SplineR2R.cpp:268
void assign_v(int bc_sign, const vContainer_type &myV, ValueVector &psi, int first, int last) const
Definition: SplineR2R.cpp:152
bool writeEntry(T &data, const std::string &aname)
write the data to the group aname and return status use write() for inbuilt error checking ...
Definition: hdf_archive.h:244
class to match ST real spline with BsplineSet::ValueType (real) SPOs
Definition: SplineR2R.h:34