QMCPACK
BsplineFunctor.h
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) 2022 QMCPACK developers.
6 //
7 // File developed by: John R. Gergely, University of Illinois at Urbana-Champaign
8 // Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
9 // Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
10 // Raymond Clay III, j.k.rofling@gmail.com, Lawrence Livermore National Laboratory
11 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
12 // Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
13 // Jaron T. Krogel, krogeljt@ornl.gov, Oak Ridge National Laboratory
14 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
15 // Amrita Mathuriya, amrita.mathuriya@intel.com, Intel Corp.
16 // Peter W. Doak, doakpw@ornl.gov, Oak Ridge National Lab
17 //
18 // File created by: Ken Esler, kpesler@gmail.com, University of Illinois at Urbana-Champaign
19 //////////////////////////////////////////////////////////////////////////////////////
20 
21 
22 #ifndef QMCPLUSPLUS_BSPLINE_FUNCTOR_H
23 #define QMCPLUSPLUS_BSPLINE_FUNCTOR_H
24 
25 #include <cstdio>
26 #include <memory>
27 #include "OptimizableFunctorBase.h"
29 #include "OhmmsData/AttributeSet.h"
30 #include "OhmmsPETE/OhmmsVector.h"
31 #include "Numerics/LinearFit.h"
33 #include "Numerics/SplineBound.hpp"
34 
35 namespace qmcplusplus
36 {
37 
38 /**BsplineFunctor class for the Jastrows
39  * REAL is the real type used by offload target, it is the correct type for the mw data pointers
40  * and is also used to coerce/implicitly convert the Real type inherited OptimizableFunctorBase into that buffer
41  * if offload is off this happens too but is just an implementation quirk.
42  */
43 template<typename REAL>
44 struct BsplineFunctor : public OptimizableFunctorBase
45 {
47 
48  static constexpr Real A0 = -1.0 / 6.0, A1 = 3.0 / 6.0, A2 = -3.0 / 6.0, A3 = 1.0 / 6.0;
49  static constexpr Real A4 = 3.0 / 6.0, A5 = -6.0 / 6.0, A6 = 0.0 / 6.0, A7 = 4.0 / 6.0;
50  static constexpr Real A8 = -3.0 / 6.0, A9 = 3.0 / 6.0, A10 = 3.0 / 6.0, A11 = 1.0 / 6.0;
51  static constexpr Real A12 = 1.0 / 6.0, A13 = 0.0 / 6.0, A14 = 0.0 / 6.0, A15 = 0.0 / 6.0;
52 
53  static constexpr Real dA0 = 0.0, dA1 = -0.5, dA2 = 1.0, dA3 = -0.5;
54  static constexpr Real dA4 = 0.0, dA5 = 1.5, dA6 = -2.0, dA7 = 0.0;
55  static constexpr Real dA8 = 0.0, dA9 = -1.5, dA10 = 1.0, dA11 = 0.5;
56  static constexpr Real dA12 = 0.0, dA13 = 0.5, dA14 = 0.0, dA15 = 0.0;
57 
58  static constexpr Real d2A0 = 0.0, d2A1 = 0.0, d2A2 = -1.0, d2A3 = 1.0;
59  static constexpr Real d2A4 = 0.0, d2A5 = 0.0, d2A6 = 3.0, d2A7 = -2.0;
60  static constexpr Real d2A8 = 0.0, d2A9 = 0.0, d2A10 = -3.0, d2A11 = 1.0;
61  static constexpr Real d2A12 = 0.0, d2A13 = 0.0, d2A14 = 1.0, d2A15 = 0.0;
62 
63  static constexpr Real d3A0 = 0.0, d3A1 = 0.0, d3A2 = 0.0, d3A3 = -1.0;
64  static constexpr Real d3A4 = 0.0, d3A5 = 0.0, d3A6 = 0.0, d3A7 = 3.0;
65  static constexpr Real d3A8 = 0.0, d3A9 = 0.0, d3A10 = 0.0, d3A11 = -3.0;
66  static constexpr Real d3A12 = 0.0, d3A13 = 0.0, d3A14 = 0.0, d3A15 = 1.0;
67 
68  std::shared_ptr<Vector<Real, OffloadAllocator<Real>>> spline_coefs_;
69 
70  int NumParams;
73  Real Y, dY, d2Y;
74  // Stores the derivatives w.r.t. coefs
75  // of the u, du/dr, and d2u/dr2
76  std::vector<TinyVector<Real, 3>> SplineDerivs;
77  std::vector<Real> Parameters;
78  std::vector<std::string> ParameterNames;
79  std::string elementType, pairType;
80  std::string fileName;
81 
82  bool notOpt;
83  bool periodic;
84 
85  ///constructor
86  BsplineFunctor(const std::string& my_name, Real cusp = 0.0)
87  : OptimizableFunctorBase(my_name), NumParams(0), CuspValue(cusp), notOpt(false), periodic(true)
88  {
89  cutoff_radius = 0.0;
90  }
91 
92  OptimizableFunctorBase* makeClone() const override { return new BsplineFunctor(*this); }
93 
94  void setCusp(Real c) override { CuspValue = c; }
95 
96  void setPeriodic(bool p) override { periodic = p; }
97 
98  /// return the max allowed beginning index to access spline coefficients
99  int getMaxIndex() const { return spline_coefs_->size() - 4; }
100 
101  void resize(int n)
102  {
103  NumParams = n;
104  int numCoefs = NumParams + 4;
105  int numKnots = numCoefs - 2;
106  DeltaR = cutoff_radius / (Real)(numKnots - 1);
107  DeltaRInv = 1.0 / DeltaR;
108  Parameters.resize(n);
109  spline_coefs_ = std::make_shared<Vector<Real, OffloadAllocator<Real>>>(numCoefs);
110  SplineDerivs.resize(numCoefs);
111  }
112 
113  /** reset coefs from Parameters
114  */
115  void reset() override
116  {
117  const int numCoefs = NumParams + 4;
118  const int numKnots = numCoefs - 2;
119  DeltaR = cutoff_radius / (Real)(numKnots - 1);
120  DeltaRInv = 1.0 / DeltaR;
121  auto& coefs = *spline_coefs_;
122  for (int i = 0; i < coefs.size(); i++)
123  coefs[i] = 0.0;
124  // Ensure that cusp conditions is satisfied at the origin
125  coefs[1] = Parameters[0];
126  coefs[2] = Parameters[1];
127  coefs[0] = Parameters[1] - 2.0 * DeltaR * CuspValue;
128  for (int i = 2; i < Parameters.size(); i++)
129  coefs[i + 1] = Parameters[i];
130  coefs.updateTo();
131  }
132 
133  /** compute value, first and second derivatives for [iStart, iEnd) pairs
134  * @param iat the source particle that should be avoided (self pairs)
135  * @param iStart starting particle index
136  * @param iEnd ending particle index
137  * @param _distArray distance arrUay
138  * @param _valArray u(r_j) for j=[iStart,iEnd)
139  * @param _gradArray du(r_j)/dr /r_j for j=[iStart,iEnd)
140  * @param _lapArray d2u(r_j)/dr2 for j=[iStart,iEnd)
141  * @param distArrayCompressed temp storage to filter r_j < cutoff_radius
142  * @param distIndices temp storage for the compressed index
143  */
144  void evaluateVGL(const int iat,
145  const int iStart,
146  const int iEnd,
147  const REAL* _distArray,
148  REAL* restrict _valArray,
149  REAL* restrict _gradArray,
150  REAL* restrict _laplArray,
151  REAL* restrict distArrayCompressed,
152  int* restrict distIndices) const;
153 
154  /** compute value, gradient and laplacian for target particles
155  * This more than just a batched call of evaluateVGL
156  * @param iat the source particle that should be avoided (self pairs)
157  * @param num_groups the number of source particle groups
158  * @param functors for the num_groups of source particles
159  * @param n_src the number of source particles
160  * @param grp_ids the group ids of the n_src source particles
161  * @param nw batch size (number of walkers)
162  * @param mw_vgl return resutls. Multi walker value, gradient and laplacian [nw][1(v)+DIM(g)+1(l)]
163  * @param n_padded the padded size of source particles
164  * @param mw_dist Multi walker distance table [nw][1(distance)+DIM(displacements)][n_padded]
165  * @param mw_cur_allu Multi walker value, first and second derivatives of pair potentials [nw][DIM][n_padded]. if mw_cur_allu is dual space, only update device side.
166  * @param transfer_buffer temporary transfer buffer.
167  *
168  * If mw_dist is dual space, up-to-date data is assumed on device.
169  * If mw_cur_allu is dual space, data is created on the device and there is no transfer to the host
170  * because it will be consumed by mw_updateVGL on the device.
171  */
172  static void mw_evaluateVGL(const int iat,
173  const int num_groups,
174  const BsplineFunctor* const functors[],
175  const int n_src,
176  const int* grp_ids,
177  const int nw,
178  REAL* mw_vgl, // [nw][DIM+2]
179  const int n_padded,
180  const REAL* mw_dist, // [nw][DIM+1][n_padded]
181  REAL* mw_cur_allu, // [nw][3][n_padded]
182  Vector<char, OffloadPinnedAllocator<char>>& transfer_buffer);
183 
184  /** evaluate sum of the pair potentials for [iStart,iEnd)
185  * @param iat dummy
186  * @param iStart starting particle index
187  * @param iEnd ending particle index
188  * @param _distArray distance arrUay
189  * @param distArrayCompressed temp storage to filter r_j < cutoff_radius
190  * @return \f$\sum u(r_j)\f$ for r_j < cutoff_radius
191  */
192  REAL evaluateV(const int iat,
193  const int iStart,
194  const int iEnd,
195  const REAL* restrict _distArray,
196  REAL* restrict distArrayCompressed) const;
197 
198  /** compute value for target-source particle pair potentials
199  * This more than just a batched call of evaluateV
200  * @param num_groups the number of source particle groups
201  * @param functors for the num_groups of source particles
202  * @param n_src the number of source particles
203  * @param grp_ids the group ids of the n_src source particles
204  * @param nnum_pairs the number of particle pairs
205  * @param ref_at the source particles that should be avoided (self pairs)
206  * @param mw_vgl return resutls. Multi walker value, gradient and laplacian [nw][1(v)+DIM(g)+1(l)]
207  * @param dist_stride the offset of distance pointers between to consecutive walkers
208  * @param mw_dist Multi walker distance table [nw][1(distance)+DIM(displacements)][n_padded]
209  * @param transfer_buffer temporary transfer buffer.
210  *
211  * If mw_dist is dual space, up-to-date data is assumed on device.
212  */
213  static void mw_evaluateV(const int num_groups,
214  const BsplineFunctor* const functors[],
215  const int n_src,
216  const int* grp_ids,
217  const int num_pairs,
218  const int* ref_at,
219  const REAL* mw_dist,
220  const int dist_stride,
221  REAL* mw_vals,
222  Vector<char, OffloadPinnedAllocator<char>>& transfer_buffer);
223 
224  inline static Real evaluate_impl(Real r, const Real* coefs, const Real DeltaRInv, const int max_index)
225  {
226  r *= DeltaRInv;
227  int i;
228  Real t;
229  getSplineBound(r, max_index, i, t);
230 
231  Real sCoef0 = coefs[i + 0];
232  Real sCoef1 = coefs[i + 1];
233  Real sCoef2 = coefs[i + 2];
234  Real sCoef3 = coefs[i + 3];
235 
236  return (sCoef0 * (((A0 * t + A1) * t + A2) * t + A3) + sCoef1 * (((A4 * t + A5) * t + A6) * t + A7) +
237  sCoef2 * (((A8 * t + A9) * t + A10) * t + A11) + sCoef3 * (((A12 * t + A13) * t + A14) * t + A15));
238  }
239 
240  inline Real evaluate(Real r) const
241  {
242  Real u(0);
243  if (r < cutoff_radius)
244  u = evaluate_impl(r, spline_coefs_->data(), DeltaRInv, getMaxIndex());
245  return u;
246  }
247 
248  inline Real evaluate(Real r, Real rinv) { return Y = evaluate(r, dY, d2Y); }
249 
250  inline void evaluateAll(Real r, Real rinv) { Y = evaluate(r, dY, d2Y); }
251 
252  inline static Real evaluate_impl(Real r, const Real* coefs, const Real DeltaRInv, const int max_index, Real& dudr, Real& d2udr2)
253  {
254  r *= DeltaRInv;
255  int i;
256  Real t;
257  getSplineBound(r, max_index, i, t);
258 
259  Real sCoef0 = coefs[i + 0];
260  Real sCoef1 = coefs[i + 1];
261  Real sCoef2 = coefs[i + 2];
262  Real sCoef3 = coefs[i + 3];
263 
264  d2udr2 = DeltaRInv * DeltaRInv *
265  (sCoef0 * (d2A2 * t + d2A3) + sCoef1 * (d2A6 * t + d2A7) + sCoef2 * (d2A10 * t + d2A11) +
266  sCoef3 * (d2A14 * t + d2A15));
267 
268  dudr = DeltaRInv *
269  (sCoef0 * ((dA1 * t + dA2) * t + dA3) + sCoef1 * ((dA5 * t + dA6) * t + dA7) +
270  sCoef2 * ((dA9 * t + dA10) * t + dA11) + sCoef3 * ((dA13 * t + dA14) * t + dA15));
271 
272  Real u = (sCoef0 * (((A0 * t + A1) * t + A2) * t + A3) + sCoef1 * (((A4 * t + A5) * t + A6) * t + A7) +
273  sCoef2 * (((A8 * t + A9) * t + A10) * t + A11) + sCoef3 * (((A12 * t + A13) * t + A14) * t + A15));
274  return u;
275  }
276 
277  inline Real evaluate(Real r, Real& dudr, Real& d2udr2)
278  {
279  Real u(0);
280  dudr = Real(0);
281  d2udr2 = Real(0);
282 
283  if (r < cutoff_radius)
284  u = evaluate_impl(r, spline_coefs_->data(), DeltaRInv, getMaxIndex(), dudr, d2udr2);
285  return u;
286  }
287 
288 
289  inline Real evaluate(Real r, Real& dudr, Real& d2udr2, Real& d3udr3)
290  {
291  if (r >= cutoff_radius)
292  {
293  dudr = d2udr2 = d3udr3 = 0.0;
294  return 0.0;
295  }
296  // Real eps = 1.0e-5;
297  // Real dudr_FD = (evaluate(r+eps)-evaluate(r-eps))/(2.0*eps);
298  // Real d2udr2_FD = (evaluate(r+eps)+evaluate(r-eps)-2.0*evaluate(r))/(eps*eps);
299  // Real d3udr3_FD = (-1.0*evaluate(r+1.0*eps)
300  // +2.0*evaluate(r+0.5*eps)
301  // -2.0*evaluate(r-0.5*eps)
302  // +1.0*evaluate(r-1.0*eps))/(eps*eps*eps);
303  r *= DeltaRInv;
304  int i;
305  Real t;
306  getSplineBound(r, getMaxIndex(), i, t);
307  Real tp[4];
308  tp[0] = t * t * t;
309  tp[1] = t * t;
310  tp[2] = t;
311  tp[3] = 1.0;
312  auto& coefs = *spline_coefs_;
313  d3udr3 = DeltaRInv * DeltaRInv * DeltaRInv *
314  (coefs[i + 0] * (d3A0 * tp[0] + d3A1 * tp[1] + d3A2 * tp[2] + d3A3 * tp[3]) +
315  coefs[i + 1] * (d3A4 * tp[0] + d3A5 * tp[1] + d3A6 * tp[2] + d3A7 * tp[3]) +
316  coefs[i + 2] * (d3A8 * tp[0] + d3A9 * tp[1] + d3A10 * tp[2] + d3A11 * tp[3]) +
317  coefs[i + 3] * (d3A12 * tp[0] + d3A13 * tp[1] + d3A14 * tp[2] + d3A15 * tp[3]));
318  d2udr2 = DeltaRInv * DeltaRInv *
319  (coefs[i + 0] * (d2A0 * tp[0] + d2A1 * tp[1] + d2A2 * tp[2] + d2A3 * tp[3]) +
320  coefs[i + 1] * (d2A4 * tp[0] + d2A5 * tp[1] + d2A6 * tp[2] + d2A7 * tp[3]) +
321  coefs[i + 2] * (d2A8 * tp[0] + d2A9 * tp[1] + d2A10 * tp[2] + d2A11 * tp[3]) +
322  coefs[i + 3] * (d2A12 * tp[0] + d2A13 * tp[1] + d2A14 * tp[2] + d2A15 * tp[3]));
323  dudr = DeltaRInv *
324  (coefs[i + 0] * (dA0 * tp[0] + dA1 * tp[1] + dA2 * tp[2] + dA3 * tp[3]) +
325  coefs[i + 1] * (dA4 * tp[0] + dA5 * tp[1] + dA6 * tp[2] + dA7 * tp[3]) +
326  coefs[i + 2] * (dA8 * tp[0] + dA9 * tp[1] + dA10 * tp[2] + dA11 * tp[3]) +
327  coefs[i + 3] * (dA12 * tp[0] + dA13 * tp[1] + dA14 * tp[2] + dA15 * tp[3]));
328  // if (std::abs(dudr_FD-dudr) > 1.0e-8)
329  // std::cerr << "Error in BsplineFunction: dudr = " << dudr
330  // << " dudr_FD = " << dudr_FD << std::endl;
331  // if (std::abs(d2udr2_FD-d2udr2) > 1.0e-4)
332  // std::cerr << "Error in BsplineFunction: r = " << r << " d2udr2 = " << dudr
333  // << " d2udr2_FD = " << d2udr2_FD << " rcut = " << cutoff_radius << std::endl;
334  // if (std::abs(d3udr3_FD-d3udr3) > 1.0e-4)
335  // std::cerr << "Error in BsplineFunction: r = " << r << " d3udr3 = " << dudr
336  // << " d3udr3_FD = " << d3udr3_FD << " rcut = " << cutoff_radius << std::endl;
337  return (coefs[i + 0] * (A0 * tp[0] + A1 * tp[1] + A2 * tp[2] + A3 * tp[3]) +
338  coefs[i + 1] * (A4 * tp[0] + A5 * tp[1] + A6 * tp[2] + A7 * tp[3]) +
339  coefs[i + 2] * (A8 * tp[0] + A9 * tp[1] + A10 * tp[2] + A11 * tp[3]) +
340  coefs[i + 3] * (A12 * tp[0] + A13 * tp[1] + A14 * tp[2] + A15 * tp[3]));
341  }
342 
343  /** update value, gradient and laplacian for target particles
344  * It serves multile walkers and handles update in a batched fashion
345  * @param iat the source particle that should be avoided (self pairs)
346  * @param isAccepted accept/reject status
347  * @param num_groups the number of source particle groups
348  * @param functors for the num_groups of source particles
349  * @param n_src the number of source particles
350  * @param grp_ids the group ids of the n_src source particles
351  * @param nw batch size (number of walkers)
352  * @param mw_vgl Multi walker value, gradient and laplacian [nw][1(v)+DIM(g)+1(l)]
353  * @param n_padded the padded size of source particles
354  * @param mw_dist Multi walker distance table [new + old][nw][1(distance)+DIM(displacements)][n_padded]
355  * @param mw_allUat, returned results. Multi walker value, gradient and laplacian of pair potentials [nw][1(v)+DIM(g)+1(l)][n_padded]
356  * @param mw_cur_allu Multi walker value, first and second derivatives of pair potentials [nw][DIM][n_padded]
357  * @param transfer_buffer temporary transfer buffer
358  *
359  * If mw_dist is dual space, up-to-date data is assumed on device.
360  * If mw_cur_allu is dual space, data on the device is consumed and no transfer is needed.
361  */
362  static void mw_updateVGL(const int iat,
363  const std::vector<bool>& isAccepted,
364  const int num_groups,
365  const BsplineFunctor* const functors[],
366  const int n_src,
367  const int* grp_ids,
368  const int nw,
369  REAL* mw_vgl, // [nw][DIM+2]
370  const int n_padded,
371  const REAL* mw_dist, // [nw][DIM+1][n_padded]
372  REAL* mw_allUat, // [nw][DIM+2][n_padded]
373  REAL* mw_cur_allu, // [nw][3][n_padded]
374  Vector<char, OffloadPinnedAllocator<char>>& transfer_buffer);
375 
376  inline bool evaluateDerivatives(Real r, std::vector<TinyVector<Real, 3>>& derivs) override
377  {
378  if (r >= cutoff_radius)
379  return false;
380  r *= DeltaRInv;
381  int i;
382  Real t;
383  getSplineBound(r, getMaxIndex(), i, t);
384  Real tp[4];
385  tp[0] = t * t * t;
386  tp[1] = t * t;
387  tp[2] = t;
388  tp[3] = 1.0;
389 
391  // d/dp_i u(r)
392  SplineDerivs[i + 0][0] = A0 * tp[0] + A1 * tp[1] + A2 * tp[2] + A3 * tp[3];
393  SplineDerivs[i + 1][0] = A4 * tp[0] + A5 * tp[1] + A6 * tp[2] + A7 * tp[3];
394  SplineDerivs[i + 2][0] = A8 * tp[0] + A9 * tp[1] + A10 * tp[2] + A11 * tp[3];
395  SplineDerivs[i + 3][0] = A12 * tp[0] + A13 * tp[1] + A14 * tp[2] + A15 * tp[3];
396  // d/dp_i du/dr
397  SplineDerivs[i + 0][1] = DeltaRInv * (dA1 * tp[1] + dA2 * tp[2] + dA3 * tp[3]);
398  SplineDerivs[i + 1][1] = DeltaRInv * (dA5 * tp[1] + dA6 * tp[2] + dA7 * tp[3]);
399  SplineDerivs[i + 2][1] = DeltaRInv * (dA9 * tp[1] + dA10 * tp[2] + dA11 * tp[3]);
400  SplineDerivs[i + 3][1] = DeltaRInv * (dA13 * tp[1] + dA14 * tp[2] + dA15 * tp[3]);
401  // d/dp_i d2u/dr2
402  SplineDerivs[i + 0][2] = DeltaRInv * DeltaRInv * (d2A2 * tp[2] + d2A3 * tp[3]);
403  SplineDerivs[i + 1][2] = DeltaRInv * DeltaRInv * (d2A6 * tp[2] + d2A7 * tp[3]);
404  SplineDerivs[i + 2][2] = DeltaRInv * DeltaRInv * (d2A10 * tp[2] + d2A11 * tp[3]);
405  SplineDerivs[i + 3][2] = DeltaRInv * DeltaRInv * (d2A14 * tp[2] + d2A15 * tp[3]);
406 
407  int imin = std::max(i, 1);
408  int imax = std::min(i + 4, NumParams + 1);
409  for (int n = imin; n < imax; ++n)
410  derivs[n - 1] = SplineDerivs[n];
411  derivs[1] += SplineDerivs[0];
412 
413  //Real v[4],dv[4],d2v[4];
414  //v[0] = A[ 0]*tp[0] + A[ 1]*tp[1] + A[ 2]*tp[2] + A[ 3]*tp[3];
415  //v[1] = A[ 4]*tp[0] + A[ 5]*tp[1] + A[ 6]*tp[2] + A[ 7]*tp[3];
416  //v[2] = A[ 8]*tp[0] + A[ 9]*tp[1] + A10*tp[2] + A11*tp[3];
417  //v[3] = A12*tp[0] + A13*tp[1] + A14*tp[2] + A15*tp[3];
418  //// d/dp_i du/dr
419  //dv[0] = DeltaRInv * (dA[ 1]*tp[1] + dA[ 2]*tp[2] + dA[ 3]*tp[3]);
420  //dv[1] = DeltaRInv * (dA[ 5]*tp[1] + dA[ 6]*tp[2] + dA[ 7]*tp[3]);
421  //dv[2] = DeltaRInv * (dA[ 9]*tp[1] + dA10*tp[2] + dA11*tp[3]);
422  //dv[3] = DeltaRInv * (dA13*tp[1] + dA14*tp[2] + dA15*tp[3]);
423  //// d/dp_i d2u/dr2
424  //d2v[0] = DeltaRInv * DeltaRInv * (d2A[ 2]*tp[2] + d2A[ 3]*tp[3]);
425  //d2v[1] = DeltaRInv * DeltaRInv * (d2A[ 6]*tp[2] + d2A[ 7]*tp[3]);
426  //d2v[2] = DeltaRInv * DeltaRInv * (d2A10*tp[2] + d2A11*tp[3]);
427  //d2v[3] = DeltaRInv * DeltaRInv * (d2A14*tp[2] + d2A15*tp[3]);
428 
429  //int imin=std::max(i,1);
430  //int imax=std::min(i+4,NumParams+1)-1;
431  //int n=imin-1, j=imin-i;
432  //while(n<imax && j<4)
433  //{
434  // derivs[n] = TinyVector<Real,3>(v[j],dv[j],d2v[j]);
435  // n++; j++;
436  //}
437  //if(i==0) derivs[1]+= TinyVector<Real,3>(v[0],dv[0],d2v[0]);
438 
439  return true;
440  }
441 
442  inline bool evaluateDerivatives(Real r, std::vector<Real>& derivs) override
443  {
444  if (r >= cutoff_radius)
445  return false;
446  r *= DeltaRInv;
447  int i;
448  Real t;
449  getSplineBound(r, getMaxIndex(), i, t);
450  Real tp[4], v[4];
451  tp[0] = t * t * t;
452  tp[1] = t * t;
453  tp[2] = t;
454  tp[3] = 1.0;
455  v[0] = A0 * tp[0] + A1 * tp[1] + A2 * tp[2] + A3 * tp[3];
456  v[1] = A4 * tp[0] + A5 * tp[1] + A6 * tp[2] + A7 * tp[3];
457  v[2] = A8 * tp[0] + A9 * tp[1] + A10 * tp[2] + A11 * tp[3];
458  v[3] = A12 * tp[0] + A13 * tp[1] + A14 * tp[2] + A15 * tp[3];
459  int imin = std::max(i, 1);
460  int imax = std::min(i + 4, NumParams + 1) - 1;
461  int n = imin - 1, j = imin - i;
462  while (n < imax && j < 4)
463  {
464  derivs[n] = v[j];
465  n++;
466  j++;
467  }
468  if (i == 0)
469  derivs[1] += v[0];
470  return true;
471  }
472 
473  inline Real f(Real r) override
474  {
475  if (r >= cutoff_radius)
476  return 0.0;
477  return evaluate(r);
478  }
479  inline Real df(Real r) override
480  {
481  if (r >= cutoff_radius)
482  return 0.0;
483  Real du, d2u;
484  evaluate(r, du, d2u);
485  return du;
486  }
487 
488 
489  bool put(xmlNodePtr cur) override
490  {
491  ReportEngine PRE("BsplineFunctor", "put(xmlNodePtr)");
492  //CuspValue = -1.0e10;
493  NumParams = 0;
494  //cutoff_radius = 0.0;
495  OhmmsAttributeSet rAttrib;
496  Real radius = -1.0;
497  rAttrib.add(NumParams, "size");
498  rAttrib.add(radius, "rcut");
499  rAttrib.add(radius, "cutoff");
500  rAttrib.put(cur);
501  if (radius < 0.0)
502  if (periodic)
503  {
504  app_log() << " Jastrow cutoff unspecified. Setting to Wigner-Seitz radius = " << cutoff_radius << std::endl;
505  app_log() << std::endl;
506  }
507  else
508  {
509  APP_ABORT(" Jastrow cutoff unspecified. Cutoff must be given when using open boundary conditions");
510  }
511  else if (periodic && radius > cutoff_radius)
512  {
513  if (radius - cutoff_radius > 1e-4)
514  {
515  APP_ABORT(" The Jastrow cutoff specified should not be larger than Wigner-Seitz radius.");
516  }
517  else
518  {
519  app_log() << " The Jastrow cutoff specified is slightly larger than the Wigner-Seitz radius.";
520  app_log() << " Setting to Wigner-Seitz radius = " << cutoff_radius << ".\n";
521  }
522  }
523  else
524  cutoff_radius = radius;
525  if (NumParams == 0)
526  {
527  PRE.error("You must specify a positive number of parameters for the Bspline jastrow function.", true);
528  }
529  app_summary() << " Number of parameters: " << NumParams << std::endl;
530  app_summary() << " Cusp: " << CuspValue << std::endl;
531  app_summary() << " Cutoff radius: " << cutoff_radius << std::endl;
532  resize(NumParams);
533  // Now read coefficents
534  xmlNodePtr xmlCoefs = cur->xmlChildrenNode;
535  while (xmlCoefs != NULL)
536  {
537  std::string cname((const char*)xmlCoefs->name);
538  if (cname == "coefficients")
539  {
540  std::string type("0"), id("0");
541  std::string optimize("yes");
542  OhmmsAttributeSet cAttrib;
543  cAttrib.add(id, "id");
544  cAttrib.add(type, "type");
545  cAttrib.add(optimize, "optimize");
546  cAttrib.put(xmlCoefs);
547  if (type != "Array")
548  {
549  PRE.error("Unknown correlation type " + type + " in BsplineFunctor." + "Resetting to \"Array\"");
550  xmlNewProp(xmlCoefs, (const xmlChar*)"type", (const xmlChar*)"Array");
551  }
552  std::vector<Real> params;
553  putContent(params, xmlCoefs);
554  if (params.size() == NumParams)
555  Parameters = params;
556  else
557  {
558  app_log() << " Changing number of Bspline parameters from " << params.size() << " to " << NumParams
559  << ". Performing fit:\n";
560  // Fit function to new number of parameters
561  const int numPoints = 500;
562  BsplineFunctor<REAL> tmp_func("tmp_func", CuspValue);
563  tmp_func.cutoff_radius = cutoff_radius;
564  tmp_func.resize(params.size());
565  tmp_func.Parameters = params;
566  tmp_func.reset();
567  std::vector<Real> y(numPoints);
568  Matrix<Real> basis(numPoints, NumParams);
569  std::vector<TinyVector<Real, 3>> derivs(NumParams);
570  for (int i = 0; i < numPoints; i++)
571  {
572  Real r = (Real)i / (Real)numPoints * cutoff_radius;
573  y[i] = tmp_func.evaluate(r);
574  evaluateDerivatives(r, derivs);
575  for (int j = 0; j < NumParams; j++)
576  basis(i, j) = derivs[j][0];
577  }
578  resize(NumParams);
579  LinearFit(y, basis, Parameters);
580  app_log() << "New parameters are:\n";
581  for (int i = 0; i < Parameters.size(); i++)
582  app_log() << " " << Parameters[i] << std::endl;
583  }
584  if (optimize == "yes")
585  {
586  notOpt = false;
587  }
588  else
589  {
590  notOpt = true;
591  }
592  for (int i = 0; i < NumParams; i++)
593  {
594  std::stringstream sstr;
595  sstr << id << "_" << i;
597  }
598  int left_pad_space = 5;
599  app_log() << std::endl;
600  myVars.print(app_log(), left_pad_space, true);
601  }
602  xmlCoefs = xmlCoefs->next;
603  }
604  reset();
605  Real zeros = 0;
606  for (int i = 0; i < NumParams; i++)
607  zeros += Parameters[i] * Parameters[i];
608  return zeros > 1.0e-12; //true if Parameters are not zero
609  }
610 
611  void initialize(int numPoints,
612  std::vector<Real>& x,
613  std::vector<Real>& y,
614  REAL cusp,
615  REAL rcut,
616  std::string& id,
617  std::string& optimize)
618  {
619  ReportEngine PRE("BsplineFunctor", "initialize");
620  NumParams = numPoints;
621  cutoff_radius = rcut;
622  CuspValue = cusp;
623  if (NumParams == 0)
624  {
625  PRE.error("You must specify a positive number of parameters for the Bspline jastrow function.", true);
626  }
627  app_log() << "Initializing BsplineFunctor from array. \n";
628  app_log() << " size = " << NumParams << " parameters " << std::endl;
629  app_log() << " cusp = " << CuspValue << std::endl;
630  app_log() << " rcut = " << cutoff_radius << std::endl;
631  resize(NumParams);
632  int npts = x.size();
633  Matrix<Real> basis(npts, NumParams);
634  std::vector<TinyVector<Real, 3>> derivs(NumParams);
635  for (int i = 0; i < npts; i++)
636  {
637  Real r = x[i];
638  if (r > cutoff_radius)
639  {
640  PRE.error("Error in BsplineFunctor::initialize: r > cutoff_radius.", true);
641  }
642  evaluateDerivatives(r, derivs);
643  for (int j = 0; j < NumParams; j++)
644  basis(i, j) = derivs[j][0];
645  }
646  resize(NumParams);
647  LinearFit(y, basis, Parameters);
648  app_log() << "New parameters are:\n";
649  for (int i = 0; i < Parameters.size(); i++)
650  app_log() << " " << Parameters[i] << std::endl;
651 #if !defined(QMC_BUILD_SANDBOX_ONLY)
652  if (optimize == "yes")
653  {
654  // Setup parameter names
655  for (int i = 0; i < NumParams; i++)
656  {
657  std::stringstream sstr;
658  sstr << id << "_" << i;
659  myVars.insert(sstr.str(), (Real)Parameters[i], true, optimize::LOGLINEAR_P);
660  }
661  myVars.print(app_log());
662  }
663  else
664 #endif
665  {
666  notOpt = true;
667  app_log() << "Parameters of BsplineFunctor id:" << id << " are not being optimized.\n";
668  }
669  reset();
670  }
671 
672  void reportStatus(std::ostream& os) override
673  {
674  if (notOpt)
675  return;
676  myVars.print(os);
677  }
678 
679  void checkOutVariables(const opt_variables_type& active) override
680  {
681  if (notOpt)
682  return;
683  myVars.getIndex(active);
684  }
685 
687  {
688  if (notOpt)
689  return;
691  active.insertFrom(myVars);
692  }
693 
694  void resetParametersExclusive(const opt_variables_type& active) override
695  {
696  if (notOpt)
697  return;
698  for (int i = 0; i < Parameters.size(); ++i)
699  {
700  int loc = myVars.where(i);
701  if (loc >= 0)
702  Parameters[i] = std::real(myVars[i] = active[loc]);
703  }
704  reset();
705  }
706 
707  // check if this object has active optimizable parameters
709  {
710  if (notOpt)
711  return false;
712  for (int i = 0; i < Parameters.size(); ++i)
713  {
714  int loc = myVars.where(i);
715  if (loc >= 0)
716  return true;
717  }
718  return false;
719  }
720 };
721 
722 template<typename REAL>
723 inline REAL BsplineFunctor<REAL>::evaluateV(const int iat,
724  const int iStart,
725  const int iEnd,
726  const REAL* restrict _distArray,
727  REAL* restrict distArrayCompressed) const
728 {
729  const Real* restrict distArray = _distArray + iStart;
730 
731  ASSUME_ALIGNED(distArrayCompressed);
732  int iCount = 0;
733  const int iLimit = iEnd - iStart;
734 
735 #pragma vector always
736  for (int jat = 0; jat < iLimit; jat++)
737  {
738  Real r = distArray[jat];
739  // pick the distances smaller than the cutoff and avoid the reference atom
740  if (r < cutoff_radius && iStart + jat != iat)
741  distArrayCompressed[iCount++] = distArray[jat];
742  }
743 
744  Real d = 0.0;
745  auto& coefs = *spline_coefs_;
746  const int max_index = getMaxIndex();
747 #pragma omp simd reduction(+ : d)
748  for (int jat = 0; jat < iCount; jat++)
749  {
750  Real r = distArrayCompressed[jat];
751  r *= DeltaRInv;
752  int i;
753  Real t;
754  getSplineBound(r, max_index, i, t);
755  Real d1 = coefs[i + 0] * (((A0 * t + A1) * t + A2) * t + A3);
756  Real d2 = coefs[i + 1] * (((A4 * t + A5) * t + A6) * t + A7);
757  Real d3 = coefs[i + 2] * (((A8 * t + A9) * t + A10) * t + A11);
758  Real d4 = coefs[i + 3] * (((A12 * t + A13) * t + A14) * t + A15);
759  d += (d1 + d2 + d3 + d4);
760  }
761  return d;
762 }
763 
764 template<typename REAL>
765 inline void BsplineFunctor<REAL>::evaluateVGL(const int iat,
766  const int iStart,
767  const int iEnd,
768  const REAL* _distArray,
769  REAL* restrict _valArray,
770  REAL* restrict _gradArray,
771  REAL* restrict _laplArray,
772  REAL* restrict distArrayCompressed,
773  int* restrict distIndices) const
774 {
775  Real dSquareDeltaRinv = DeltaRInv * DeltaRInv;
776  constexpr Real cOne(1);
777 
778  // START_MARK_FIRST();
779 
780  ASSUME_ALIGNED(distIndices);
781  ASSUME_ALIGNED(distArrayCompressed);
782  int iCount = 0;
783  int iLimit = iEnd - iStart;
784  const REAL* distArray = _distArray + iStart;
785  REAL* valArray = _valArray + iStart;
786  REAL* gradArray = _gradArray + iStart;
787  REAL* laplArray = _laplArray + iStart;
788 
789 #pragma vector always
790  for (int jat = 0; jat < iLimit; jat++)
791  {
792  Real r = distArray[jat];
793  if (r < cutoff_radius && iStart + jat != iat)
794  {
795  distIndices[iCount] = jat;
796  distArrayCompressed[iCount] = r;
797  iCount++;
798  }
799  }
800 
801  auto& coefs = *spline_coefs_;
802  const int max_index = getMaxIndex();
803 #pragma omp simd
804  for (int j = 0; j < iCount; j++)
805  {
806  Real r = distArrayCompressed[j];
807  int iScatter = distIndices[j];
808  Real rinv = cOne / r;
809  r *= DeltaRInv;
810  int iGather;
811  Real t;
812  getSplineBound(r, max_index, iGather, t);
813 
814  Real sCoef0 = coefs[iGather + 0];
815  Real sCoef1 = coefs[iGather + 1];
816  Real sCoef2 = coefs[iGather + 2];
817  Real sCoef3 = coefs[iGather + 3];
818 
819  laplArray[iScatter] = dSquareDeltaRinv *
820  (sCoef0 * (d2A2 * t + d2A3) + sCoef1 * (d2A6 * t + d2A7) + sCoef2 * (d2A10 * t + d2A11) +
821  sCoef3 * (d2A14 * t + d2A15));
822 
823  gradArray[iScatter] = DeltaRInv * rinv *
824  (sCoef0 * ((dA1 * t + dA2) * t + dA3) + sCoef1 * ((dA5 * t + dA6) * t + dA7) +
825  sCoef2 * ((dA9 * t + dA10) * t + dA11) + sCoef3 * ((dA13 * t + dA14) * t + dA15));
826 
827  valArray[iScatter] =
828  (sCoef0 * (((A0 * t + A1) * t + A2) * t + A3) + sCoef1 * (((A4 * t + A5) * t + A6) * t + A7) +
829  sCoef2 * (((A8 * t + A9) * t + A10) * t + A11) + sCoef3 * (((A12 * t + A13) * t + A14) * t + A15));
830  }
831 }
832 
833 extern template struct BsplineFunctor<QMCTraits::RealType>;
834 
835 } // namespace qmcplusplus
836 #endif
Fixed-size array.
Definition: OhmmsTinyMeta.h:30
REAL evaluateV(const int iat, const int iStart, const int iEnd, const REAL *restrict _distArray, REAL *restrict distArrayCompressed) const
evaluate sum of the pair potentials for [iStart,iEnd)
Real evaluate(Real r, Real rinv)
static constexpr Real A1
QMCTraits::RealType real
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
BsplineFunctor class for the Jastrows REAL is the real type used by offload target, it is the correct type for the mw data pointers and is also used to coerce/implicitly convert the Real type inherited OptimizableFunctorBase into that buffer if offload is off this happens too but is just an implementation quirk.
static constexpr Real d2A8
void setIndexDefault()
set default Indices, namely all the variables are active
static constexpr Real dA6
static constexpr Real d2A7
Real evaluate(Real r, Real &dudr, Real &d2udr2)
std::ostream & app_log()
Definition: OutputManager.h:65
std::ostream & app_summary()
Definition: OutputManager.h:63
bool put(xmlNodePtr cur)
assign attributes to the set
Definition: AttributeSet.h:55
static constexpr Real d2A9
void evaluateAll(Real r, Real rinv)
static constexpr Real dA3
static constexpr Real d2A13
OptimizableFunctorBase * makeClone() const override
create a clone of this object
static constexpr Real dA12
static constexpr Real d2A10
static constexpr Real d2A14
Real df(Real r) override
evaluate the first derivative
static constexpr Real A5
static constexpr Real A10
static constexpr Real dA9
static constexpr Real d2A5
std::vector< Real > Parameters
void reportStatus(std::ostream &os) override
print the state, e.g., optimizables
static constexpr Real d3A9
Define a base class for one-dimensional functions with optimizable variables.
static constexpr Real A6
static constexpr Real A12
static constexpr Real A0
static constexpr Real d3A10
int getMaxIndex() const
return the max allowed beginning index to access spline coefficients
static constexpr Real A7
static constexpr Real d3A6
static constexpr Real d3A5
T min(T a, T b)
static constexpr Real d3A14
static void mw_evaluateVGL(const int iat, const int num_groups, const BsplineFunctor *const functors[], const int n_src, const int *grp_ids, const int nw, REAL *mw_vgl, const int n_padded, const REAL *mw_dist, REAL *mw_cur_allu, Vector< char, OffloadPinnedAllocator< char >> &transfer_buffer)
compute value, gradient and laplacian for target particles This more than just a batched call of eval...
static constexpr Real d3A7
static constexpr Real d2A2
static void mw_updateVGL(const int iat, const std::vector< bool > &isAccepted, const int num_groups, const BsplineFunctor *const functors[], const int n_src, const int *grp_ids, const int nw, REAL *mw_vgl, const int n_padded, const REAL *mw_dist, REAL *mw_allUat, REAL *mw_cur_allu, Vector< char, OffloadPinnedAllocator< char >> &transfer_buffer)
update value, gradient and laplacian for target particles It serves multile walkers and handles updat...
BsplineFunctor(const std::string &my_name, Real cusp=0.0)
constructor
void setCusp(Real c) override
empty virtual function to help builder classes
static constexpr Real dA7
static void mw_evaluateV(const int num_groups, const BsplineFunctor *const functors[], const int n_src, const int *grp_ids, const int num_pairs, const int *ref_at, const REAL *mw_dist, const int dist_stride, REAL *mw_vals, Vector< char, OffloadPinnedAllocator< char >> &transfer_buffer)
compute value for target-source particle pair potentials This more than just a batched call of evalua...
static constexpr Real dA10
std::vector< std::string > ParameterNames
void insert(const std::string &vname, real_type v, bool enable=true, int type=OTHER_P)
Definition: VariableSet.h:133
Final class and should not be derived.
class to handle a set of attributes of an xmlNode
Definition: AttributeSet.h:24
static constexpr Real d3A0
declaration of ProgressReportEngine
OptimizableFunctorBase::real_type Real
static constexpr Real d3A8
static constexpr Real d3A4
void checkInVariablesExclusive(opt_variables_type &active) override
check in variational parameters to the global list of parameters used by the optimizer.
Real evaluate(Real r, Real &dudr, Real &d2udr2, Real &d3udr3)
static constexpr Real d2A3
class to handle a set of variables that can be modified during optimizations
Definition: VariableSet.h:49
int where(int i) const
return the locator of the i-th Index
Definition: VariableSet.h:90
static constexpr Real d2A15
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
static constexpr Real d3A15
std::vector< TinyVector< Real, 3 > > SplineDerivs
static constexpr Real dA8
OMPallocator is an allocator with fused device and dualspace allocator functionality.
static constexpr Real d2A1
void resetParametersExclusive(const opt_variables_type &active) override
reset the parameters during optimizations.
Base class for any functor with optimizable parameters.
bool evaluateDerivatives(Real r, std::vector< Real > &derivs) override
static constexpr Real d3A3
bool putContent(T &a, xmlNodePtr cur)
replaces a&#39;s value with the first "element" in the "string" returned by XMLNodeString{cur}.
Definition: libxmldefs.h:88
static constexpr Real dA11
static constexpr Real dA0
void initialize(int numPoints, std::vector< Real > &x, std::vector< Real > &y, REAL cusp, REAL rcut, std::string &id, std::string &optimize)
static constexpr Real A3
Declaraton of Vector<T,Alloc> Manage memory through Alloc directly and allow referencing an existing ...
static constexpr Real dA1
bool put(xmlNodePtr cur) override
process xmlnode and registers variables to optimize
static Real evaluate_impl(Real r, const Real *coefs, const Real DeltaRInv, const int max_index, Real &dudr, Real &d2udr2)
void error(const std::string &msg, bool fatal=false)
static constexpr Real d3A1
void checkOutVariables(const opt_variables_type &active) override
check out variational optimizable variables
static constexpr Real dA5
static constexpr Real dA4
static Real evaluate_impl(Real r, const Real *coefs, const Real DeltaRInv, const int max_index)
void evaluateVGL(const int iat, const int iStart, const int iEnd, const REAL *_distArray, REAL *restrict _valArray, REAL *restrict _gradArray, REAL *restrict _laplArray, REAL *restrict distArrayCompressed, int *restrict distIndices) const
compute value, first and second derivatives for [iStart, iEnd) pairs
static constexpr Real d3A13
static constexpr Real A11
static constexpr Real dA2
static constexpr Real d2A0
static constexpr Real A2
static constexpr Real d2A6
static constexpr Real A4
static constexpr Real d2A11
#define ASSUME_ALIGNED(x)
void insertFrom(const VariableSet &input)
insert a VariableSet to the list
Definition: VariableSet.cpp:37
void getSplineBound(const T x, const int nmax, int &ind, TRESIDUAL &dx)
break x into the integer part and residual part and apply bounds
Definition: SplineBound.hpp:37
Real f(Real r) override
evaluate the value at r
static constexpr Real d3A11
static constexpr Real dA14
void setPeriodic(bool p) override
empty virtual function to help builder classes
Real evaluate(Real r) const
static constexpr Real A13
bool evaluateDerivatives(Real r, std::vector< TinyVector< Real, 3 >> &derivs) override
void add(PDT &aparam, const std::string &aname, std::vector< PDT > candidate_values={}, TagStatus status=TagStatus::OPTIONAL)
add a new attribute
Definition: AttributeSet.h:42
void print(std::ostream &os, int leftPadSpaces=0, bool printHeader=false) const
optimize::VariableSet::real_type real_type
typedef for real values
int getIndex(const std::string &vname) const
return the Index vaule for the named parameter
static constexpr Real d2A12
static constexpr Real d3A2
void LinearFit(std::vector< T > &y, Matrix< T > &A, std::vector< T > &coefs)
Definition: LinearFit.h:28
static constexpr Real A8
std::shared_ptr< Vector< Real, OffloadAllocator< Real > > > spline_coefs_
void reset() override
reset coefs from Parameters
static constexpr Real d2A4
static constexpr Real dA13
static constexpr Real A15
static constexpr Real A9
opt_variables_type myVars
set of variables to be optimized
static constexpr Real d3A12
static constexpr Real dA15
static constexpr Real A14