QMCPACK
MultiFunctorAdapter.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) 2016 Jeongnim Kim and QMCPACK developers.
6 //
7 // File developed by:
8 //
9 // File created by: Jeongnim Kim, jeongnim.kim@intel.com, Intel Corp.
10 //////////////////////////////////////////////////////////////////////////////////////
11 
12 
13 #ifndef QMCPLUSPLUS_SOA_MULTIANALYTICFUNCTOR_BUILDER_H
14 #define QMCPLUSPLUS_SOA_MULTIANALYTICFUNCTOR_BUILDER_H
15 
16 #include "Configuration.h"
19 #include "Message/MPIObjectBase.h"
20 #include "ModernStringUtils.hpp"
21 #include "hdf/hdf_archive.h"
22 
23 namespace qmcplusplus
24 {
25 /** generic functor that computes a set of 1D functors
26  * @tparam FN analytic functor, SlaterCombo<T>, GaussianCombo<T>
27  *
28  * Analytic functors are light and no state but not efficient.
29  * Only for benchmarking.
30  */
31 template<typename FN>
33 {
34  using RealType = typename FN::real_type;
36  using single_type = FN;
41 
42  MultiFunctorAdapter() = default;
44  {
45  Rnl.reserve(other.Rnl.size());
46  for (size_t i = 0; i < other.Rnl.size(); ++i)
47  Rnl.push_back(std::make_unique<single_type>(*other.Rnl[i]));
48  }
49 
50  inline RealType rmax() const
51  {
52  //Another magic r_max
53  constexpr RealType r0(100);
54  return r0;
55  }
56 
57  inline void evaluate(RealType r, RealType* restrict u)
58  {
59  for (size_t i = 0, n = Rnl.size(); i < n; ++i)
60  u[i] = Rnl[i]->f(r);
61  }
62 
63  /**
64  * @brief evaluate for multiple electrons and multiple pbc images
65  *
66  * r is assumed to be up-to-date on the device before entering this function, and
67  * u needs to be updated on the device before exiting this function
68  *
69  * Eventually, all computation should be done on the device to avoid transfers, but
70  * for now this is all done on the host
71  *
72  * @param [in] r electron distances [Nelec, Npbc]
73  * @param [out] u value of all radial functions at all electron distances [Nelec, Npbc, nRnl]
74  * @param Rmax evaluate to zero for any distance greater than or equal to Rmax
75  */
76  inline void batched_evaluate(OffloadArray2D& r, OffloadArray3D& u, RealType Rmax) const
77  {
78  r.updateFrom(); // TODO: remove after offload and make r const
79 
80  const size_t nElec = r.size(0);
81  const size_t Nxyz = r.size(1); // number of PBC images
82  assert(nElec == u.size(0));
83  assert(Nxyz == u.size(1));
84  const size_t nRnl = u.size(2); // number of splines
85  const size_t nR = nElec * Nxyz; // total number of positions to evaluate
86 
87  for (size_t i_e = 0; i_e < nElec; i_e++)
88  for (size_t i_xyz = 0; i_xyz < Nxyz; i_xyz++)
89  if (r(i_e, i_xyz) >= Rmax)
90  for (size_t i = 0, n = Rnl.size(); i < n; ++i)
91  u(i_e, i_xyz, i) = 0.0;
92  else
93  for (size_t i = 0, n = Rnl.size(); i < n; ++i)
94  u(i_e, i_xyz, i) = Rnl[i]->f(r(i_e, i_xyz));
95 
96  u.updateTo(); // TODO: remove after offload
97  }
98 
99  /**
100  * @brief evaluate value, first deriv, second deriv for multiple electrons and multiple pbc images
101  *
102  * r is assumed to be up-to-date on the device before entering this function, and
103  * vgl needs to be updated on the device before exiting this function
104  *
105  * Eventually, all computation should be done on the device to avoid transfers, but
106  * for now this is all done on the host
107  *
108  * @param [in] r electron distances [Nelec, Npbc]
109  * @param [out] vgl val/d1/d2 of all radial functions at all electron distances [3(val,d1,d2), Nelec, Npbc, nRnl]
110  * @param Rmax radial function and derivs will evaluate to zero for any distance greater than or equal to Rmax
111  */
112  inline void batched_evaluateVGL(OffloadArray2D& r, OffloadArray4D& vgl, RealType Rmax) const
113  {
114  r.updateFrom(); // TODO: remove when eval is offloaded
115  const size_t nElec = r.size(0);
116  const size_t Nxyz = r.size(1); // number of PBC images
117  assert(3 == vgl.size(0));
118  assert(nElec == vgl.size(1));
119  assert(Nxyz == vgl.size(2));
120  const size_t nRnl = vgl.size(3); // number of primitives
121  const size_t nR = nElec * Nxyz; // total number of positions to evaluate
122  assert(nRnl == Rnl.size());
123 
124  auto* r_ptr = r.data();
125  auto* u_ptr = vgl.data_at(0, 0, 0, 0);
126  auto* du_ptr = vgl.data_at(1, 0, 0, 0);
127  auto* d2u_ptr = vgl.data_at(2, 0, 0, 0);
128 
129  for (size_t ir = 0; ir < nR; ir++)
130  {
131  // TODO: once this is offloaded, maybe better to just avoid branching and keep values past Rmax
132  if (r_ptr[ir] >= Rmax)
133  {
134  for (size_t i = 0; i < nRnl; ++i)
135  {
136  u_ptr[ir * nRnl + i] = 0.0;
137  du_ptr[ir * nRnl + i] = 0.0;
138  d2u_ptr[ir * nRnl + i] = 0.0;
139  }
140  }
141  else
142  {
143  const RealType r = r_ptr[ir];
144  const RealType rinv = RealType(1) / r;
145  for (size_t i = 0; i < nRnl; ++i)
146  {
147  Rnl[i]->evaluateAll(r, rinv);
148  u_ptr[ir * nRnl + i] = Rnl[i]->Y;
149  du_ptr[ir * nRnl + i] = Rnl[i]->dY;
150  d2u_ptr[ir * nRnl + i] = Rnl[i]->d2Y;
151  }
152  }
153  }
154  vgl.updateTo(); // TODO: remove when eval is offloaded
155  }
156 
157  inline void evaluate(RealType r, RealType* restrict u, RealType* restrict du, RealType* restrict d2u)
158  {
159  const RealType rinv = RealType(1) / r;
160  for (size_t i = 0, n = Rnl.size(); i < n; ++i)
161  {
162  Rnl[i]->evaluateAll(r, rinv);
163  u[i] = Rnl[i]->Y;
164  du[i] = Rnl[i]->dY;
165  d2u[i] = Rnl[i]->d2Y;
166  }
167  }
168  inline void evaluate(RealType r,
169  RealType* restrict u,
170  RealType* restrict du,
171  RealType* restrict d2u,
172  RealType* restrict d3u)
173  {
174  const RealType rinv = RealType(1) / r;
175  for (size_t i = 0, n = Rnl.size(); i < n; ++i)
176  {
177  Rnl[i]->evaluateWithThirdDeriv(r, rinv);
178  u[i] = Rnl[i]->Y;
179  du[i] = Rnl[i]->dY;
180  d2u[i] = Rnl[i]->d2Y;
181  d3u[i] = Rnl[i]->d3Y;
182  }
183  }
184 };
185 
186 template<typename COT>
188 
189 template<typename FN, typename SH>
191 {
192 public:
196 
197  ///true, if the RadialOrbitalType is normalized
199  ///orbitals to build
201 
202  ///constructor
204 
205  ///implement functions used by AOBasisBuilder
206  bool addGrid(xmlNodePtr cur, const std::string& rad_type) { return true; }
207  bool addGridH5(hdf_archive& hin) { return true; }
208  bool openNumericalBasisH5(xmlNodePtr cur) { return true; }
209  bool put(xmlNodePtr cur)
210  {
211  const std::string a(lowerCase(getXMLAttributeValue(cur, "normalized")));
212  if (a == "no")
213  Normalized = false;
214  return true;
215  }
216 
217  bool addRadialOrbital(xmlNodePtr cur, const std::string& rad_type, const QuantumNumberType& nlms)
218  {
219  auto radorb = std::make_unique<single_type>(nlms[q_l], Normalized);
220  radorb->putBasisGroup(cur);
221 
222  m_orbitals.RnlID.push_back(nlms);
223  m_orbitals.MultiRnl.Rnl.push_back(std::move(radorb));
224  return true;
225  }
226 
227  bool addRadialOrbitalH5(hdf_archive& hin, const std::string& rad_type, const QuantumNumberType& nlms)
228  {
229  auto radorb = std::make_unique<single_type>(nlms[q_l], Normalized);
230  radorb->putBasisGroupH5(hin, *myComm);
231 
232  m_orbitals.RnlID.push_back(nlms);
233  m_orbitals.MultiRnl.Rnl.push_back(std::move(radorb));
234 
235  return true;
236  }
237 
238  void finalize()
239  {
240  m_orbitals.setRmax(0); //set Rmax
241  }
242 };
243 } // namespace qmcplusplus
244 #endif
void evaluate(RealType r, RealType *restrict u)
std::vector< T, aligned_allocator< T > > aligned_vector
Base class for any object which needs to know about a MPI communicator.
Definition: MPIObjectBase.h:26
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
MultiFunctorAdapter(const MultiFunctorAdapter &other)
Type_t * data_at(const std::array< SIZET, D > &indices)
Definition: OhmmsArray.h:104
Type_t * data()
Definition: OhmmsArray.h:87
Build a set of radial orbitals at the origin.
bool addGrid(xmlNodePtr cur, const std::string &rad_type)
implement functions used by AOBasisBuilder
class to handle hdf file
Definition: hdf_archive.h:51
declaration of MPIObjectBase
generic functor that computes a set of 1D functors
void batched_evaluate(OffloadArray2D &r, OffloadArray3D &u, RealType Rmax) const
evaluate for multiple electrons and multiple pbc images
Wrapping information on parallelism.
Definition: Communicate.h:68
void evaluate(RealType r, RealType *restrict u, RealType *restrict du, RealType *restrict d2u, RealType *restrict d3u)
Communicate * myComm
pointer to Communicate
Definition: MPIObjectBase.h:62
std::string lowerCase(const std::string_view s)
++17
bool addRadialOrbital(xmlNodePtr cur, const std::string &rad_type, const QuantumNumberType &nlms)
size_t size() const
Definition: OhmmsArray.h:57
bool addRadialOrbitalH5(hdf_archive &hin, const std::string &rad_type, const QuantumNumberType &nlms)
aligned_vector< std::unique_ptr< single_type > > Rnl
std::string getXMLAttributeValue(const xmlNodePtr cur, const std::string_view name)
get the value string for attribute name if name is unfound in cur you get an empty string back this i...
void updateFrom(size_t size=0, std::ptrdiff_t offset=0)
Definition: OhmmsArray.h:229
hdf_archive hin
hdf file only for numerical basis h5 file generated by SQD
OHMMS_PRECISION real_type
void evaluate(RealType r, RealType *restrict u, RealType *restrict du, RealType *restrict d2u)
void updateTo(size_t size=0, std::ptrdiff_t offset=0)
Definition: OhmmsArray.h:224
bool Normalized
true, if the RadialOrbitalType is normalized
void batched_evaluateVGL(OffloadArray2D &r, OffloadArray4D &vgl, RealType Rmax) const
evaluate value, first deriv, second deriv for multiple electrons and multiple pbc images ...