QMCPACK
HybridRepCenterOrbitals.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) 2019 QMCPACK developers.
6 //
7 // File developed by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
8 //
9 // File created by: Ye Luo, yeluo@anl.gov, Argonne National Laboratory
10 //
11 //////////////////////////////////////////////////////////////////////////////////////
12 
13 /** @file HybridRepCenterOrbitals.h
14  *
15  * Hybrid representation atomic centered orbitals
16  */
17 #ifndef QMCPLUSPLUS_HYBRIDREP_CENTER_ORBITALS_H
18 #define QMCPLUSPLUS_HYBRIDREP_CENTER_ORBITALS_H
19 
20 #include "Particle/DistanceTable.h"
23 #include "spline2/MultiBspline1D.hpp"
25 #include "hdf/hdf_archive.h"
26 
27 namespace qmcplusplus
28 {
29 template<class BSPLINESPO>
31 
32 template<typename ST>
34 {
35 public:
36  static const int D = 3;
37  using AtomicSplineType = typename bspline_traits<ST, 1>::SplineType;
38  using AtomicBCType = typename bspline_traits<ST, 1>::BCType;
39  using AtomicSingleSplineType = UBspline_1d_d;
41  using value_type = ST;
42 
44 
45 private:
46  // near core cutoff
47  ST rmin;
48  // far from core cutoff, rmin_sqrt>=rmin
52  int NumBands, Npad;
54  const int lmax, lm_tot;
58  ///1D spline of radial functions of all the orbitals
59  std::shared_ptr<MultiBspline1D<ST>> SplineInst;
60  ///coef copy for orbital rotation
61  std::shared_ptr<std::vector<ST>> coef_copy_;
62 
64 
65 public:
66  AtomicOrbitals(int Lmax) : lmax(Lmax), lm_tot((Lmax + 1) * (Lmax + 1)), Ylm(Lmax)
67  {
68  r_power_minus_l.resize(lm_tot);
69  l_vals.resize(lm_tot);
70  for (int l = 0; l <= lmax; l++)
71  for (int m = -l; m <= l; m++)
72  l_vals[l * (l + 1) + m] = l;
73  rmin = std::exp(std::log(std::numeric_limits<ST>::min()) / std::max(Lmax, 1));
74  rmin = std::max(rmin, std::numeric_limits<ST>::epsilon());
75  rmin_sqrt = std::max(rmin, std::sqrt(std::numeric_limits<ST>::epsilon()));
76  }
77 
78  // accessing functions, const only
79  ST getCutoff() const { return cutoff; }
80  ST getCutoffBuffer() const { return cutoff_buffer; }
81  ST getSplineRadius() const { return spline_radius; }
83  int getSplineNpoints() const { return spline_npoints; }
84  int getLmax() const { return lmax; }
85  const PointType& getCenterPos() const { return center_pos; }
86 
87  inline void resizeStorage(size_t Nb)
88  {
89  NumBands = Nb;
90  Npad = getAlignedSize<ST>(Nb);
91  localV.resize(Npad * lm_tot);
92  localG.resize(Npad * lm_tot);
93  localL.resize(Npad * lm_tot);
94  create_spline();
95  }
96 
97  void bcast_tables(Communicate* comm) { chunked_bcast(comm, SplineInst->getSplinePtr()); }
98 
99  void gather_tables(Communicate* comm, std::vector<int>& offset)
100  {
101  gatherv(comm, SplineInst->getSplinePtr(), Npad, offset);
102  }
103 
104  template<typename PT, typename VT>
105  inline void set_info(const PT& R,
106  const VT& cutoff_in,
107  const VT& cutoff_buffer_in,
108  const VT& spline_radius_in,
109  const VT& non_overlapping_radius_in,
110  const int spline_npoints_in)
111  {
112  center_pos[0] = R[0];
113  center_pos[1] = R[1];
114  center_pos[2] = R[2];
115  cutoff = cutoff_in;
116  cutoff_buffer = cutoff_buffer_in;
117  spline_radius = spline_radius_in;
118  spline_npoints = spline_npoints_in;
119  non_overlapping_radius = non_overlapping_radius_in;
120  BaseN = spline_npoints + 2;
121  }
122 
123  inline void create_spline()
124  {
125  AtomicBCType bc;
126  bc.lCode = FLAT;
127  bc.rCode = NATURAL;
128  Ugrid grid;
129  grid.start = 0.0;
130  grid.end = spline_radius;
131  grid.num = spline_npoints;
132  SplineInst = std::make_shared<MultiBspline1D<ST>>();
133  SplineInst->create(grid, bc, lm_tot * Npad);
134  }
135 
136  inline size_t getSplineSizeInBytes() const { return SplineInst->sizeInByte(); }
137 
138  inline void flush_zero() { SplineInst->flush_zero(); }
139 
140  inline void set_spline(AtomicSingleSplineType* spline, int lm, int ispline)
141  {
142  SplineInst->copy_spline(spline, lm * Npad + ispline, 0, BaseN);
143  }
144 
146  {
147  einspline_engine<AtomicSplineType> bigtable(SplineInst->getSplinePtr());
148  int lmax_in = 0, spline_npoints_in = 0;
149  ST spline_radius_in;
150  if (!h5f.readEntry(lmax_in, "l_max") || lmax_in != lmax)
151  return false;
152  if (!h5f.readEntry(spline_radius_in, "spline_radius") || spline_radius_in != spline_radius)
153  return false;
154  if (!h5f.readEntry(spline_npoints_in, "spline_npoints") || spline_npoints_in != spline_npoints)
155  return false;
156  return h5f.readEntry(bigtable, "radial_spline");
157  }
158 
160  {
161  bool success = true;
162  success = success && h5f.writeEntry(spline_radius, "spline_radius");
163  success = success && h5f.writeEntry(spline_npoints, "spline_npoints");
164  success = success && h5f.writeEntry(lmax, "l_max");
165  success = success && h5f.writeEntry(center_pos, "position");
166  einspline_engine<AtomicSplineType> bigtable(SplineInst->getSplinePtr());
167  success = success && h5f.writeEntry(bigtable, "radial_spline");
168  return success;
169  }
170 
171  //evaluate only V
172  template<typename VV>
173  inline void evaluate_v(const ST& r, const PointType& dr, VV& myV)
174  {
175  if (r > std::numeric_limits<ST>::epsilon())
176  Ylm.evaluateV(dr[0] / r, dr[1] / r, dr[2] / r);
177  else
178  Ylm.evaluateV(0, 0, 1);
179  const ST* restrict Ylm_v = Ylm[0];
180 
181  constexpr ST czero(0);
182  ST* restrict val = myV.data();
183  ST* restrict local_val = localV.data();
184  std::fill(myV.begin(), myV.end(), czero);
185 
186  SplineInst->evaluate(r, localV);
187 
188  for (size_t lm = 0; lm < lm_tot; lm++)
189  {
190 #pragma omp simd aligned(val, local_val : QMC_SIMD_ALIGNMENT)
191  for (size_t ib = 0; ib < myV.size(); ib++)
192  val[ib] += Ylm_v[lm] * local_val[ib];
193  local_val += Npad;
194  }
195  }
196 
197  template<typename DISPL, typename VM>
198  inline void evaluateValues(const DISPL& Displacements, const int center_idx, const ST& r, VM& multi_myV)
199  {
200  if (r <= std::numeric_limits<ST>::epsilon())
201  Ylm.evaluateV(0, 0, 1);
202  const ST* restrict Ylm_v = Ylm[0];
203 
204  const size_t m = multi_myV.cols();
205  constexpr ST czero(0);
206  std::fill(multi_myV.begin(), multi_myV.end(), czero);
207  SplineInst->evaluate(r, localV);
208 
209  for (int ivp = 0; ivp < Displacements.size(); ivp++)
210  {
211  PointType dr = Displacements[ivp][center_idx];
212  if (r > std::numeric_limits<ST>::epsilon())
213  Ylm.evaluateV(-dr[0] / r, -dr[1] / r, -dr[2] / r);
214 
215  ST* restrict val = multi_myV[ivp];
216  ST* restrict local_val = localV.data();
217  for (size_t lm = 0; lm < lm_tot; lm++)
218  {
219 #pragma omp simd aligned(val, local_val : QMC_SIMD_ALIGNMENT)
220  for (size_t ib = 0; ib < m; ib++)
221  val[ib] += Ylm_v[lm] * local_val[ib];
222  local_val += Npad;
223  }
224  }
225  }
226 
227  //evaluate VGL
228  template<typename VV, typename GV>
229  inline void evaluate_vgl(const ST& r, const PointType& dr, VV& myV, GV& myG, VV& myL)
230  {
231  ST drx, dry, drz, rhatx, rhaty, rhatz, rinv;
232  if (r > rmin)
233  {
234  rinv = 1.0 / r;
235  }
236  else
237  {
238  rinv = 0;
239  }
240  drx = dr[0];
241  dry = dr[1];
242  drz = dr[2];
243  rhatx = drx * rinv;
244  rhaty = dry * rinv;
245  rhatz = drz * rinv;
246 
247  Ylm.evaluateVGL(drx, dry, drz);
248  const ST* restrict Ylm_v = Ylm[0];
249  const ST* restrict Ylm_gx = Ylm[1];
250  const ST* restrict Ylm_gy = Ylm[2];
251  const ST* restrict Ylm_gz = Ylm[3];
252 
253  ST* restrict g0 = myG.data(0);
254  ST* restrict g1 = myG.data(1);
255  ST* restrict g2 = myG.data(2);
256  constexpr ST czero(0), cone(1), chalf(0.5);
257  std::fill(myV.begin(), myV.end(), czero);
258  std::fill(g0, g0 + Npad, czero);
259  std::fill(g1, g1 + Npad, czero);
260  std::fill(g2, g2 + Npad, czero);
261  std::fill(myL.begin(), myL.end(), czero);
262  ST* restrict val = myV.data();
263  ST* restrict lapl = myL.data();
264  ST* restrict local_val = localV.data();
265  ST* restrict local_grad = localG.data();
266  ST* restrict local_lapl = localL.data();
267 
268  SplineInst->evaluate_vgl(r, localV, localG, localL);
269 
270  if (r > rmin_sqrt)
271  {
272  // far from core
273  r_power_minus_l[0] = cone;
274  ST r_power_temp = cone;
275  for (int l = 1; l <= lmax; l++)
276  {
277  r_power_temp *= rinv;
278  for (int m = -l, lm = l * l; m <= l; m++, lm++)
279  r_power_minus_l[lm] = r_power_temp;
280  }
281 
282  for (size_t lm = 0; lm < lm_tot; lm++)
283  {
284  const ST& l_val = l_vals[lm];
285  const ST& r_power = r_power_minus_l[lm];
286  const ST Ylm_rescale = Ylm_v[lm] * r_power;
287  const ST rhat_dot_G = (rhatx * Ylm_gx[lm] + rhaty * Ylm_gy[lm] + rhatz * Ylm_gz[lm]) * r_power;
288 #pragma omp simd aligned(val, g0, g1, g2, lapl, local_val, local_grad, local_lapl : QMC_SIMD_ALIGNMENT)
289  for (size_t ib = 0; ib < myV.size(); ib++)
290  {
291  const ST local_v = local_val[ib];
292  const ST local_g = local_grad[ib];
293  const ST local_l = local_lapl[ib];
294  // value
295  const ST Vpart = l_val * rinv * local_v;
296  val[ib] += Ylm_rescale * local_v;
297 
298  // grad
299  const ST factor1 = local_g * Ylm_rescale;
300  const ST factor2 = local_v * r_power;
301  const ST factor3 = -Vpart * Ylm_rescale;
302  g0[ib] += factor1 * rhatx + factor2 * Ylm_gx[lm] + factor3 * rhatx;
303  g1[ib] += factor1 * rhaty + factor2 * Ylm_gy[lm] + factor3 * rhaty;
304  g2[ib] += factor1 * rhatz + factor2 * Ylm_gz[lm] + factor3 * rhatz;
305 
306  // laplacian
307  lapl[ib] += (local_l + (local_g * (2 - l_val) - Vpart) * rinv) * Ylm_rescale + (local_g - Vpart) * rhat_dot_G;
308  }
309  local_val += Npad;
310  local_grad += Npad;
311  local_lapl += Npad;
312  }
313  }
314  else if (r > rmin)
315  {
316  // the possibility of reaching here is very very low
317  std::cout << "Warning: an electron is very close to an ion, distance=" << r << " be careful!" << std::endl;
318  // near core, kill divergence in the laplacian
319  r_power_minus_l[0] = cone;
320  ST r_power_temp = cone;
321  for (int l = 1; l <= lmax; l++)
322  {
323  r_power_temp *= rinv;
324  for (int m = -l, lm = l * l; m <= l; m++, lm++)
325  r_power_minus_l[lm] = r_power_temp;
326  }
327 
328  for (size_t lm = 0; lm < lm_tot; lm++)
329  {
330  const ST& l_val = l_vals[lm];
331  const ST& r_power = r_power_minus_l[lm];
332  const ST Ylm_rescale = Ylm_v[lm] * r_power;
333  const ST rhat_dot_G = (Ylm_gx[lm] * rhatx + Ylm_gy[lm] * rhaty + Ylm_gz[lm] * rhatz) * r_power * r;
334 #pragma omp simd aligned(val, g0, g1, g2, lapl, local_val, local_grad, local_lapl : QMC_SIMD_ALIGNMENT)
335  for (size_t ib = 0; ib < myV.size(); ib++)
336  {
337  const ST local_v = local_val[ib];
338  const ST local_g = local_grad[ib];
339  const ST local_l = local_lapl[ib];
340  // value
341  const ST Vpart = Ylm_rescale * local_v;
342  val[ib] += Vpart;
343 
344  // grad
345  const ST factor1 = local_g * Ylm_rescale;
346  const ST factor2 = local_v * r_power;
347  const ST factor3 = -l_val * Vpart * rinv;
348  g0[ib] += factor1 * rhatx + factor2 * Ylm_gx[lm] + factor3 * rhatx;
349  g1[ib] += factor1 * rhaty + factor2 * Ylm_gy[lm] + factor3 * rhaty;
350  g2[ib] += factor1 * rhatz + factor2 * Ylm_gz[lm] + factor3 * rhatz;
351 
352  // laplacian
353  lapl[ib] += local_l * (cone - chalf * l_val) * (3 * Ylm_rescale + rhat_dot_G);
354  }
355  local_val += Npad;
356  local_grad += Npad;
357  local_lapl += Npad;
358  }
359  }
360  else
361  {
362  std::cout << "Warning: an electron is on top of an ion!" << std::endl;
363  // strictly zero
364 
365 #pragma omp simd aligned(val, lapl, local_val, local_lapl : QMC_SIMD_ALIGNMENT)
366  for (size_t ib = 0; ib < myV.size(); ib++)
367  {
368  // value
369  val[ib] = Ylm_v[0] * local_val[ib];
370 
371  // laplacian
372  lapl[ib] = local_lapl[ib] * static_cast<ST>(3) * Ylm_v[0];
373  }
374  local_val += Npad;
375  local_grad += Npad;
376  local_lapl += Npad;
377  if (lm_tot > 0)
378  {
379  //std::cout << std::endl;
380  for (size_t lm = 1; lm < 4; lm++)
381  {
382 #pragma omp simd aligned(g0, g1, g2, local_grad : QMC_SIMD_ALIGNMENT)
383  for (size_t ib = 0; ib < myV.size(); ib++)
384  {
385  const ST local_g = local_grad[ib];
386  // grad
387  g0[ib] += local_g * Ylm_gx[lm];
388  g1[ib] += local_g * Ylm_gy[lm];
389  g2[ib] += local_g * Ylm_gz[lm];
390  }
391  local_grad += Npad;
392  }
393  }
394  }
395  }
396 
397  template<typename VV, typename GV, typename HT>
398  void evaluate_vgh(const ST& r, const PointType& dr, VV& myV, GV& myG, HT& myH)
399  {
400  //Needed to do tensor product here
401  APP_ABORT("AtomicOrbitals::evaluate_vgh");
402  }
403 
405  {
406  const auto spline_ptr = SplineInst->getSplinePtr();
407  const auto coefs_tot_size = spline_ptr->coefs_size;
408  coef_copy_ = std::make_shared<std::vector<ST>>(coefs_tot_size);
409  std::copy_n(spline_ptr->coefs, coefs_tot_size, coef_copy_->begin());
410  }
411 
412  template<typename VM>
413  void applyRotation(const VM& rot_mat, bool use_stored_copy)
414  {
415  // SplineInst is a MultiBspline. See src/spline2/MultiBspline.hpp
416  const auto spline_ptr = SplineInst->getSplinePtr();
417  assert(spline_ptr != nullptr);
418  const auto spl_coefs = spline_ptr->coefs;
419  const auto Nsplines = spline_ptr->num_splines; // May include padding
420  const auto coefs_tot_size = spline_ptr->coefs_size;
421  const auto BasisSetSize = coefs_tot_size / Nsplines;
422  const auto TrueNOrbs = rot_mat.size1(); // == Nsplines - padding
423 
424  if (!use_stored_copy)
425  {
426  assert(coef_copy_ != nullptr);
427  std::copy_n(spl_coefs, coefs_tot_size, coef_copy_->begin());
428  }
429 
430  // There are TrueNOrb splines for every l,m pair, and also padding
431 #ifdef QMC_COMPLEX
432  for (size_t lidx = 0; lidx < lm_tot; lidx++)
433  for (size_t i = 0; i < BasisSetSize; i++)
434  for (size_t j = 0; j < TrueNOrbs; j++)
435  {
436  const auto cur_elem = i * Nsplines + lidx * Npad + 2 * j;
437  ST newval_r{0.};
438  ST newval_i{0.};
439  for (size_t k = 0; k < TrueNOrbs; k++)
440  {
441  const auto index = i * Nsplines + lidx * Npad + 2 * k;
442  ST zr = (*coef_copy_)[index];
443  ST zi = (*coef_copy_)[index + 1];
444  ST wr = rot_mat[k][j].real();
445  ST wi = rot_mat[k][j].imag();
446  newval_r += zr * wr - zi * wi;
447  newval_i += zr * wi + zi * wr;
448  }
449  spl_coefs[cur_elem] = newval_r;
450  spl_coefs[cur_elem + 1] = newval_i;
451  }
452 #else
453  for (size_t lidx = 0; lidx < lm_tot; lidx++)
454  for (size_t i = 0; i < BasisSetSize; i++)
455  for (size_t j = 0; j < TrueNOrbs; j++)
456  {
457  const auto cur_elem = i * Nsplines + lidx * Npad + j;
458  ST newval{0.};
459  for (size_t k = 0; k < TrueNOrbs; k++)
460  {
461  const auto index = i * Nsplines + lidx * Npad + k;
462  newval += (*coef_copy_)[index] * rot_mat[k][j];
463  }
464  spl_coefs[cur_elem] = newval;
465  }
466 #endif
467  }
468 };
469 
470 template<typename ST>
472 {
473 public:
474  static const int D = 3;
477  using PosType = typename DistanceTable::PosType;
478 
479  enum class Region
480  {
481  INSIDE, // within the buffer shell
482  BUFFER, // in the buffer region
483  INTER // interstitial area
484  };
485 
487  {
488  ///r from distance table
490  ///dr from distance table
492  ///for APBC
494  /// region of the location
496  ///smooth function value
498  ///smooth function first derivative
500  ///smooth function second derivative
502  };
503 
504 private:
505  ///atomic centers
506  std::vector<AtomicOrbitals<ST>> AtomicCenters;
507  ///table index
509  ///mapping supercell to primitive cell
510  std::vector<int> Super2Prim;
511  ///smoothing schemes
512  enum class smoothing_schemes
513  {
514  CONSISTENT = 0,
515  SMOOTHALL,
517  } smooth_scheme;
518  /// smoothing function
520 
521  /// select a region (within the buffer shell, in the buffer, interstitial region) and compute the smoothing function if in the buffer.
522  inline void selectRegionAndComputeSmoothing(const ST& cutoff_buffer,
523  const ST& cutoff,
524  LocationSmoothingInfo& info) const
525  {
526  const RealType r = info.dist_r;
527  if (r < cutoff_buffer)
528  info.region = Region::INSIDE;
529  else if (r < cutoff)
530  {
531  constexpr RealType cone(1);
532  const RealType scale = cone / (cutoff - cutoff_buffer);
533  const RealType x = (r - cutoff_buffer) * scale;
534  info.f = smoothing(smooth_func_id, x, info.df_dr, info.d2f_dr2);
535  info.df_dr *= scale;
536  info.d2f_dr2 *= scale * scale;
537  info.region = Region::BUFFER;
538  }
539  else
540  info.region = Region::INTER;
541  }
542 
543 public:
545 
547  {
548  for (auto& atomic_center : AtomicCenters)
549  atomic_center.storeParamsBeforeRotation();
550  }
551 
552  template<typename VM>
553  void applyRotation(const VM& rot_mat, bool use_stored_copy)
554  {
555  for (auto& atomic_center : AtomicCenters)
556  atomic_center.applyRotation(rot_mat, use_stored_copy);
557  }
558 
559  void set_info(const ParticleSet& ions, ParticleSet& els, const std::vector<int>& mapping)
560  {
562  Super2Prim = mapping;
563  }
564 
565  inline void resizeStorage(size_t Nb)
566  {
567  size_t SplineCoefsBytes = 0;
568 
569  for (int ic = 0; ic < AtomicCenters.size(); ic++)
570  {
571  AtomicCenters[ic].resizeStorage(Nb);
572  SplineCoefsBytes += AtomicCenters[ic].getSplineSizeInBytes();
573  }
574 
575  app_log() << "MEMORY " << SplineCoefsBytes / (1 << 20) << " MB allocated "
576  << "for the atomic radial splines in hybrid orbital representation" << std::endl;
577  }
578 
580  {
581  for (int ic = 0; ic < AtomicCenters.size(); ic++)
583  }
584 
585  void gather_atomic_tables(Communicate* comm, std::vector<int>& offset)
586  {
587  if (comm->size() == 1)
588  return;
589  for (int ic = 0; ic < AtomicCenters.size(); ic++)
590  AtomicCenters[ic].gather_tables(comm, offset);
591  }
592 
593  inline void flush_zero()
594  {
595  for (int ic = 0; ic < AtomicCenters.size(); ic++)
597  }
598 
600  {
601  bool success = true;
602  size_t ncenter;
603 
604  try
605  {
606  h5f.push("atomic_centers", false);
607  }
608  catch (...)
609  {
610  success = false;
611  }
612  success = success && h5f.readEntry(ncenter, "number_of_centers");
613  if (!success)
614  return success;
615  if (ncenter != AtomicCenters.size())
616  success = false;
617  // read splines of each center
618  for (int ic = 0; ic < AtomicCenters.size(); ic++)
619  {
620  std::ostringstream gname;
621  gname << "center_" << ic;
622  try
623  {
624  h5f.push(gname.str().c_str(), false);
625  }
626  catch (...)
627  {
628  success = false;
629  }
630  success = success && AtomicCenters[ic].read_splines(h5f);
631  h5f.pop();
632  }
633  h5f.pop();
634  return success;
635  }
636 
638  {
639  bool success = true;
640  int ncenter = AtomicCenters.size();
641  try
642  {
643  h5f.push("atomic_centers", true);
644  }
645  catch (...)
646  {
647  success = false;
648  }
649  success = success && h5f.writeEntry(ncenter, "number_of_centers");
650  // write splines of each center
651  for (int ic = 0; ic < AtomicCenters.size(); ic++)
652  {
653  std::ostringstream gname;
654  gname << "center_" << ic;
655  try
656  {
657  h5f.push(gname.str().c_str(), true);
658  }
659  catch (...)
660  {
661  success = false;
662  }
663  success = success && AtomicCenters[ic].write_splines(h5f);
664  h5f.pop();
665  }
666  h5f.pop();
667  return success;
668  }
669 
670  template<typename Cell>
671  inline int get_bc_sign(const PointType& r,
672  const PointType& r_image,
673  const Cell& PrimLattice,
674  TinyVector<int, D>& HalfG) const
675  {
676  int bc_sign = 0;
677  PointType shift_unit = PrimLattice.toUnit(r - r_image);
678  for (int i = 0; i < D; i++)
679  {
680  ST img = round(shift_unit[i]);
681  bc_sign += HalfG[i] * (int)img;
682  }
683  return bc_sign;
684  }
685 
686  //evaluate only V
687  template<typename VV>
688  inline void evaluate_v(const ParticleSet& P, const int iat, VV& myV, LocationSmoothingInfo& info)
689  {
690  const auto& ei_dist = P.getDistTableAB(myTableID);
691  const int center_idx = ei_dist.get_first_neighbor(iat, info.dist_r, info.dist_dr, P.getActivePtcl() == iat);
692  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
693  selectRegionAndComputeSmoothing(myCenter.getCutoffBuffer(), myCenter.getCutoff(), info);
694  if (info.region != Region::INTER)
695  {
696  PointType dr(-info.dist_dr[0], -info.dist_dr[1], -info.dist_dr[2]);
697  info.r_image = myCenter.getCenterPos() + dr;
698  myCenter.evaluate_v(info.dist_r, dr, myV);
699  }
700  }
701 
702  /* check if the batched algorithm is safe to operate
703  * @param VP virtual particle set
704  * @return true if it is safe
705  *
706  * When the reference electron in the NLPP evaluation has a distance larger than the non overlapping radius of the reference center.
707  * Some qudrature points may get its SPOs evaluated from the nearest center which is not the reference center.
708  * The batched algorthm forces the evaluation on the reference center and introduce some error.
709  * In this case, the non-batched algorithm should be used.
710  */
712  {
713  const int center_idx = VP.refSourcePtcl;
714  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
715  return VP.getRefPS().getDistTableAB(myTableID).getDistRow(VP.refPtcl)[center_idx] <
716  myCenter.getNonOverlappingRadius();
717  }
718 
719  // C2C, C2R cases
720  template<typename VM>
721  inline void evaluateValuesC2X(const VirtualParticleSet& VP, VM& multi_myV, LocationSmoothingInfo& info)
722  {
723  const int center_idx = VP.refSourcePtcl;
724  info.dist_r = VP.getRefPS().getDistTableAB(myTableID).getDistRow(VP.refPtcl)[center_idx];
725  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
726  selectRegionAndComputeSmoothing(myCenter.getCutoffBuffer(), myCenter.getCutoff(), info);
727  if (info.region != Region::INTER)
728  myCenter.evaluateValues(VP.getDistTableAB(myTableID).getDisplacements(), center_idx, info.dist_r, multi_myV);
729  }
730 
731  // R2R case
732  template<typename VM, typename Cell, typename SV>
733  inline void evaluateValuesR2R(const VirtualParticleSet& VP,
734  const Cell& PrimLattice,
735  TinyVector<int, D>& HalfG,
736  VM& multi_myV,
737  SV& bc_signs,
738  LocationSmoothingInfo& info)
739  {
740  const int center_idx = VP.refSourcePtcl;
741  info.dist_r = VP.getRefPS().getDistTableAB(myTableID).getDistRow(VP.refPtcl)[center_idx];
742  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
743  selectRegionAndComputeSmoothing(myCenter.getCutoffBuffer(), myCenter.getCutoff(), info);
744  if (info.region != Region::INTER)
745  {
746  const auto& displ = VP.getDistTableAB(myTableID).getDisplacements();
747  for (int ivp = 0; ivp < VP.getTotalNum(); ivp++)
748  bc_signs[ivp] = get_bc_sign(VP.R[ivp], myCenter.getCenterPos() - displ[ivp][center_idx], PrimLattice, HalfG);
749  myCenter.evaluateValues(displ, center_idx, info.dist_r, multi_myV);
750  }
751  }
752 
753  //evaluate only VGL
754  template<typename VV, typename GV>
755  inline void evaluate_vgl(const ParticleSet& P, const int iat, VV& myV, GV& myG, VV& myL, LocationSmoothingInfo& info)
756  {
757  const auto& ei_dist = P.getDistTableAB(myTableID);
758  const int center_idx = ei_dist.get_first_neighbor(iat, info.dist_r, info.dist_dr, P.getActivePtcl() == iat);
759  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
760  selectRegionAndComputeSmoothing(myCenter.getCutoffBuffer(), myCenter.getCutoff(), info);
761  if (info.region != Region::INTER)
762  {
763  const PointType dr(-info.dist_dr[0], -info.dist_dr[1], -info.dist_dr[2]);
764  info.r_image = myCenter.getCenterPos() + dr;
765  myCenter.evaluate_vgl(info.dist_r, dr, myV, myG, myL);
766  }
767  }
768 
769  //evaluate only VGH
770  template<typename VV, typename GV, typename HT>
771  inline void evaluate_vgh(const ParticleSet& P, const int iat, VV& myV, GV& myG, HT& myH, LocationSmoothingInfo& info)
772  {
773  const auto& ei_dist = P.getDistTableAB(myTableID);
774  const int center_idx = ei_dist.get_first_neighbor(iat, info.dist_r, info.dist_dr, P.getActivePtcl() == iat);
775  auto& myCenter = AtomicCenters[Super2Prim[center_idx]];
776  selectRegionAndComputeSmoothing(myCenter.getCutoffBuffer(), myCenter.getCutoff(), info);
777  if (info.region != Region::INTER)
778  {
779  const PointType dr(-info.dist_dr[0], -info.dist_dr[1], -info.dist_dr[2]);
780  info.r_image = myCenter.getCenterPos() + dr;
781  myCenter.evaluate_vgh(info.dist_r, dr, myV, myG, myH);
782  }
783  }
784 
785  // interpolate buffer region, value only
786  template<typename VV>
787  inline void interpolate_buffer_v(VV& psi, const VV& psi_AO, const RealType f) const
788  {
789  constexpr RealType cone(1);
790  for (size_t i = 0; i < psi.size(); i++)
791  psi[i] = psi_AO[i] * f + psi[i] * (cone - f);
792  }
793 
794  // interpolate buffer region, value, gradients and laplacian
795  template<typename VV, typename GV>
796  inline void interpolate_buffer_vgl(VV& psi,
797  GV& dpsi,
798  VV& d2psi,
799  const VV& psi_AO,
800  const GV& dpsi_AO,
801  const VV& d2psi_AO,
802  const LocationSmoothingInfo& info) const
803  {
804  constexpr RealType cone(1), ctwo(2);
805  const RealType rinv(1.0 / info.dist_r);
806  auto& dist_dr = info.dist_dr;
807  auto& f = info.f;
808  auto& df_dr = info.df_dr;
809  auto& d2f_dr2 = info.d2f_dr2;
811  for (size_t i = 0; i < psi.size(); i++)
812  { // psi, dpsi, d2psi are all consistent
813  d2psi[i] = d2psi_AO[i] * f + d2psi[i] * (cone - f) + df_dr * rinv * ctwo * dot(dpsi[i] - dpsi_AO[i], dist_dr) +
814  (psi_AO[i] - psi[i]) * (d2f_dr2 + ctwo * rinv * df_dr);
815  dpsi[i] = dpsi_AO[i] * f + dpsi[i] * (cone - f) + df_dr * rinv * dist_dr * (psi[i] - psi_AO[i]);
816  psi[i] = psi_AO[i] * f + psi[i] * (cone - f);
817  }
819  for (size_t i = 0; i < psi.size(); i++)
820  {
821  d2psi[i] = d2psi_AO[i] * f + d2psi[i] * (cone - f);
822  dpsi[i] = dpsi_AO[i] * f + dpsi[i] * (cone - f);
823  psi[i] = psi_AO[i] * f + psi[i] * (cone - f);
824  }
826  for (size_t i = 0; i < psi.size(); i++)
827  { // dpsi, d2psi are consistent but psi is not.
828  d2psi[i] = d2psi_AO[i] * f + d2psi[i] * (cone - f) + df_dr * rinv * ctwo * dot(dpsi[i] - dpsi_AO[i], dist_dr);
829  dpsi[i] = dpsi_AO[i] * f + dpsi[i] * (cone - f);
830  psi[i] = psi_AO[i] * f + psi[i] * (cone - f);
831  }
832  else
833  throw std::runtime_error("Unknown smooth scheme!");
834  }
835 
836  template<class BSPLINESPO>
838 };
839 
840 extern template class AtomicOrbitals<float>;
841 extern template class AtomicOrbitals<double>;
842 extern template class HybridRepCenterOrbitals<float>;
843 extern template class HybridRepCenterOrbitals<double>;
844 } // namespace qmcplusplus
845 #endif
void evaluateValuesR2R(const VirtualParticleSet &VP, const Cell &PrimLattice, TinyVector< int, D > &HalfG, VM &multi_myV, SV &bc_signs, LocationSmoothingInfo &info)
Index_t getActivePtcl() const
return active particle id
Definition: ParticleSet.h:260
QMCTraits::RealType RealType
Definition: DistanceTable.h:44
std::vector< AtomicOrbitals< ST > > AtomicCenters
atomic centers
void interpolate_buffer_vgl(VV &psi, GV &dpsi, VV &d2psi, const VV &psi_AO, const GV &dpsi_AO, const VV &d2psi_AO, const LocationSmoothingInfo &info) const
std::vector< T, aligned_allocator< T > > aligned_vector
bool is_VP_batching_safe(const VirtualParticleSet &VP) const
const ParticleSet & getRefPS() const
ParticleSet this object refers to.
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
const DistRow & getDistRow(int iel) const
return a row of distances for a given target particle
int get_bc_sign(const PointType &r, const PointType &r_image, const Cell &PrimLattice, TinyVector< int, D > &HalfG) const
std::ostream & app_log()
Definition: OutputManager.h:65
const std::vector< DisplRow > & getDisplacements() const
return full table displacements
void applyRotation(const VM &rot_mat, bool use_stored_copy)
constexpr std::complex< float > czero
Definition: BLAS.hpp:51
For distance tables of virtual particle (VP) sets constructed based on this table, whether full table is needed on host The corresponding DT of VP need to set MW_EVALUATE_RESULT_NO_TRANSFER_TO_HOST accordingly.
constexpr std::complex< float > cone
Definition: BLAS.hpp:50
int refSourcePtcl
Reference source particle, used when onSphere=true.
A ParticleSet that handles virtual moves of a selected particle of a given physical ParticleSet Virtu...
aligned_vector< ST > vContainer_type
int refPtcl
Reference particle.
enum qmcplusplus::HybridRepCenterOrbitals::smoothing_schemes smooth_scheme
void gather_atomic_tables(Communicate *comm, std::vector< int > &offset)
class to handle hdf file
Definition: hdf_archive.h:51
bool write_splines(hdf_archive &h5f)
typename bspline_traits< ST, 1 >::BCType AtomicBCType
typename AtomicOrbitals< SPLINEBASE::DataType >::PointType PointType
void set_info(const PT &R, const VT &cutoff_in, const VT &cutoff_buffer_in, const VT &spline_radius_in, const VT &non_overlapping_radius_in, const int spline_npoints_in)
smoothing_functions smooth_func_id
smoothing function
void evaluateVGL(T x, T y, T z)
makes a table of and their gradients up to Lmax.
int size() const
return the number of tasks
Definition: Communicate.h:118
void evaluate_vgl(const ST &r, const PointType &dr, VV &myV, GV &myG, VV &myL)
A proxy class to the quantum ParticleSet.
T min(T a, T b)
void set_info(const ParticleSet &ions, ParticleSet &els, const std::vector< int > &mapping)
const DistanceTableAB & getDistTableAB(int table_ID) const
get a distance table by table_ID and dyanmic_cast to DistanceTableAB
Wrapping information on parallelism.
Definition: Communicate.h:68
int addTable(const ParticleSet &psrc, DTModes modes=DTModes::ALL_OFF)
add a distance table
Specialized paritlce class for atomistic simulations.
Definition: ParticleSet.h:55
std::shared_ptr< std::vector< ST > > coef_copy_
coef copy for orbital rotation
SoaSphericalTensor< ST > Ylm
void evaluate_v(const ParticleSet &P, const int iat, VV &myV, LocationSmoothingInfo &info)
void evaluateValuesC2X(const VirtualParticleSet &VP, VM &multi_myV, LocationSmoothingInfo &info)
void gather_tables(Communicate *comm, std::vector< int > &offset)
std::shared_ptr< MultiBspline1D< ST > > SplineInst
1D spline of radial functions of all the orbitals
bool read_splines(hdf_archive &h5f)
void evaluate_vgh(const ParticleSet &P, const int iat, VV &myV, GV &myG, HT &myH, LocationSmoothingInfo &info)
ParticlePos R
Position.
Definition: ParticleSet.h:79
void evaluate_vgl(const ParticleSet &P, const int iat, VV &myV, GV &myG, VV &myL, LocationSmoothingInfo &info)
void selectRegionAndComputeSmoothing(const ST &cutoff_buffer, const ST &cutoff, LocationSmoothingInfo &info) const
select a region (within the buffer shell, in the buffer, interstitial region) and compute the smoothi...
#define APP_ABORT(msg)
Widely used but deprecated fatal error macros from legacy code.
Definition: AppAbort.h:27
MakeReturn< UnaryNode< FnExp, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t exp(const Vector< T1, C1 > &l)
void bcast_tables(Communicate *comm)
T smoothing(smoothing_functions func_id, T x, T &dx, T &d2x)
QMCTraits::PosType PosType
Definition: DistanceTable.h:45
void interpolate_buffer_v(VV &psi, const VV &psi_AO, const RealType f) const
void applyRotation(const VM &rot_mat, bool use_stored_copy)
void push(const std::string &gname, bool createit=true)
push a group to the group stack
MakeReturn< UnaryNode< FnLog, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t log(const Vector< T1, C1 > &l)
void evaluateV(T x, T y, T z, T *Ylm) const
compute Ylm
MakeReturn< UnaryNode< FnSqrt, typename CreateLeaf< Vector< T1, C1 > >::Leaf_t > >::Expression_t sqrt(const Vector< T1, C1 > &l)
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
const PointType & getCenterPos() const
void evaluate_v(const ST &r, const PointType &dr, VV &myV)
Tensor< typename BinaryReturn< T1, T2, OpMultiply >::Type_t, D > dot(const AntiSymTensor< T1, D > &lhs, const AntiSymTensor< T2, D > &rhs)
std::vector< int > Super2Prim
mapping supercell to primitive cell
void set_spline(AtomicSingleSplineType *spline, int lm, int ispline)
General HybridRepSetReader to handle any unitcell.
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 gatherv(T *sb, T *rb, int n, IT &counts, IT &displ, int dest)
virtual int get_first_neighbor(IndexType iat, RealType &r, PosType &dr, bool newpos) const =0
find the first nearest neighbor
typename bspline_traits< ST, 1 >::SplineType AtomicSplineType
void evaluate_vgh(const ST &r, const PointType &dr, VV &myV, GV &myG, HT &myH)
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
void evaluateValues(const DISPL &Displacements, const int center_idx, const ST &r, VM &multi_myV)