QMCPACK
OneDimQuinticSpline.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: Miguel Morales, moralessilva2@llnl.gov, Lawrence Livermore National Laboratory
8 // Jeremy McMinnis, jmcminis@gmail.com, University of Illinois at Urbana-Champaign
9 // Mark A. Berrill, berrillma@ornl.gov, Oak Ridge National Laboratory
10 //
11 // File created by: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
12 //////////////////////////////////////////////////////////////////////////////////////
13 
14 
15 #ifndef QMCPLUSPLUS_GRID_FUNCTOR_QUINTIC_SPLINE_H
16 #define QMCPLUSPLUS_GRID_FUNCTOR_QUINTIC_SPLINE_H
17 
19 #include "Numerics/SplineSolvers.h"
20 
21 namespace qmcplusplus
22 {
23 /*
24  * Perform One-Dimensional Quintic Spline Interpolation.
25  */
26 
27 template<class Td, class Tg = Td, class CTd = Vector<Td>, class CTg = Vector<Tg>>
28 class OneDimQuinticSpline : public OneDimGridFunctor<Td, Tg, CTd, CTg>
29 {
30 public:
34  using data_type = typename base_type::data_type;
35  using grid_type = typename base_type::grid_type;
36 
37  using base_type::d2Y;
38  using base_type::dY;
39  using base_type::m_grid;
40  using base_type::m_Y;
41  using base_type::Y;
42 
48 
49  using base_type::NumNodes;
50 
56 
57  OneDimQuinticSpline(std::unique_ptr<grid_type> gt = std::unique_ptr<grid_type>()) : base_type(std::move(gt)) {}
58 
59  template<class VV>
60  OneDimQuinticSpline(std::unique_ptr<grid_type> gt, const VV& nv)
61  : base_type(std::move(gt)), first_deriv(0.0), last_deriv(0.0)
62  {
63  int n = nv.size();
64  m_Y.resize(nv.size());
65  m_Y2.resize(nv.size());
66  std::copy(nv.begin(), nv.end(), m_Y.data());
67  B.resize(n);
68  D.resize(n);
69  E.resize(n);
70  F.resize(n);
71  }
72 
73  void set(Vector<Td>& data)
74  {
75  int n = data.size();
76  m_Y.resize(n);
77  m_Y = data;
78  m_Y2.resize(n);
79  B.resize(n);
80  D.resize(n);
81  E.resize(n);
82  F.resize(n);
83  }
84 
86 
89  {
90  m_Y2.resize(a.m_Y2.size());
91  m_Y2 = a.m_Y2;
92  ConstValue = a.ConstValue;
93  r_min = a.r_min;
94  r_max = a.r_max;
95  first_deriv = a.first_deriv;
96  last_deriv = a.last_deriv;
97  B.resize(a.B.size());
98  B = a.B;
99  D.resize(a.D.size());
100  D = a.D;
101  E.resize(a.E.size());
102  E = a.E;
103  F.resize(a.F.size());
104  F = a.F;
105  }
106 
107 private:
108  inline Td quinticInterpolate(Td cL, Td a, Td b, Td c, Td d, Td e, Td f) const
109  {
110  return a + cL * (b + cL * (c + cL * (d + cL * (e + cL * f))));
111  }
112 
113  inline Td quinticInterpolateSecondDeriv(Td cL, Td a, Td b, Td c, Td d, Td e, Td f, Td& du, Td& d2u) const
114  {
115  du = b + cL * (2.0 * c + cL * (3.0 * d + cL * (4.0 * e + cL * f * 5.0)));
116  d2u = 2.0 * c + cL * (6.0 * d + cL * (12.0 * e + cL * f * 20.0));
117  return a + cL * (b + cL * (c + cL * (d + cL * (e + cL * f))));
118  }
119 
120  inline Td quinticInterpolateThirdDeriv(Td cL, Td a, Td b, Td c, Td d, Td e, Td f, Td& du, Td& d2u, Td& d3u) const
121  {
122  du = b + cL * (2.0 * c + cL * (3.0 * d + cL * (4.0 * e + cL * f * 5.0)));
123  d2u = 2.0 * c + cL * (6.0 * d + cL * (12.0 * e + cL * f * 20.0));
124  d3u = 6.0 * d + cL * (24.0 * e + cL * f * 60.0);
125  return a + cL * (b + cL * (c + cL * (d + cL * (e + cL * f))));
126  }
127 
128 public:
129  inline value_type splint(point_type r) const override
130  {
131  if (r < r_min)
132  {
133  return m_Y[0] + first_deriv * (r - r_min);
134  }
135  else if (r >= r_max)
136  {
137  return ConstValue;
138  }
139  Td cL;
140  int Loc = m_grid->getIndexAndDistanceFromGridPoint(r, cL);
141  return quinticInterpolate(cL, m_Y[Loc], B[Loc], m_Y2[Loc], D[Loc], E[Loc], F[Loc]);
142  }
143 
144 
145  inline value_type splint(point_type r, value_type& du, value_type& d2u) const override
146  {
147  if (r < r_min)
148  {
149  return m_Y[0] + first_deriv * (r - r_min);
150  }
151  else if (r >= r_max)
152  {
153  return ConstValue;
154  }
155  Td cL;
156  int Loc = m_grid->getIndexAndDistanceFromGridPoint(r, cL);
157  return quinticInterpolateSecondDeriv(cL, m_Y[Loc], B[Loc], m_Y2[Loc], D[Loc], E[Loc], F[Loc], du, d2u);
158  }
159 
161  {
162  if (r < r_min)
163  {
164  return m_Y[0] + first_deriv * (r - r_min);
165  }
166  else if (r >= r_max)
167  {
168  return ConstValue;
169  }
170  Td cL;
171  int Loc = m_grid->getIndexAndDistanceFromGridPoint(r, cL);
172  return quinticInterpolateThirdDeriv(cL, m_Y[Loc], B[Loc], m_Y2[Loc], D[Loc], E[Loc], F[Loc], du, d2u, d3u);
173  }
174 
175  inline void spline(int imin, value_type yp1, int imax, value_type ypn) override
176  {
177  first_deriv = yp1;
178  last_deriv = ypn;
179  r_min = m_grid->r(imin);
180  r_max = m_grid->r(imax);
181  int npts(this->size());
182  m_Y2.resize(npts);
183  B.resize(npts);
184  D.resize(npts);
185  E.resize(npts);
186  F.resize(npts);
187  m_Y2 = 0.0;
188  B = 0.0;
189  D = 0.0;
190  E = 0.0;
191  F = 0.0;
192  QuinticSplineSolve(npts - imin, m_grid->data() + imin, m_Y.data() + imin, B.data() + imin, m_Y2.data() + imin,
193  D.data() + imin, E.data() + imin, F.data() + imin);
194  ConstValue = m_Y[imax];
195  }
196 
197  inline void spline() override { spline(0, 0.0, m_grid->size() - 1, 0.0); }
198 };
199 
200 
201 } // namespace qmcplusplus
202 #endif
value_type f(point_type r)
Evaluate the function and its derivatives, store the derivatives.
CTd data_type
the type of the containers Y, dY and d2Y
helper functions for EinsplineSetBuilder
Definition: Configuration.h:43
value_type * data()
return the grid data
Implement One-Dimensional function on a radial grid.
value_type splint(point_type r) const override
int NumNodes
the number of nodes
void copy(const Array< T1, 3 > &src, Array< T2, 3 > &dest)
Definition: Blitz.h:639
An abstract base class to implement a One-Dimensional grid.
Td value_type
the type of the value on a grid
OneDimQuinticSpline(std::unique_ptr< grid_type > gt, const VV &nv)
value_type Y
store the value of the function
void QuinticSplineSolve(int N, const Tg *X, T *Y, T *B, T *C, T *D, T *E, T *F)
template function: note that the range of data is [0,n) instead of [1,n] solve the linear system for ...
Definition: SplineSolvers.h:78
value_type d2Y
store the second derivative of the function
value_type splint(point_type r, value_type &du, value_type &d2u) const override
OneDimGridBase< Tg, CTg > grid_type
the grid type
int size() const
return the number of data points
Td quinticInterpolateThirdDeriv(Td cL, Td a, Td b, Td c, Td d, Td e, Td f, Td &du, Td &d2u, Td &d3u) const
value_type dY
store the derivative of the function
OneDimQuinticSpline< Td, Tg, CTd, CTg > * makeClone() const
Td quinticInterpolateSecondDeriv(Td cL, Td a, Td b, Td c, Td d, Td e, Td f, Td &du, Td &d2u) const
value_type splint(point_type r, value_type &du, value_type &d2u, value_type &d3u) const
Td quinticInterpolate(Td cL, Td a, Td b, Td c, Td d, Td e, Td f) const
Tg point_type
the type of the grid value
OneDimQuinticSpline(std::unique_ptr< grid_type > gt=std::unique_ptr< grid_type >())
void spline(int imin, value_type yp1, int imax, value_type ypn) override
point_type r(int i) const
return the grid point at index i
std::unique_ptr< grid_type > m_grid
pointer to the radial grid
data_type m_Y
data for the function on the grid