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: Jeongnim Kim, jeongnim.kim@gmail.com, University of Illinois at Urbana-Champaign
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_LINEAR_SPLINE_H
16 #define QMCPLUSPLUS_GRID_FUNCTOR_LINEAR_SPLINE_H
17 
18 #include "Numerics/OneDimGridFunctor.h"
19 //#define USE_MEMORYSAVEMODE
20 
21 namespace qmcplusplus
22 {
23 /** Perform One-Dimensional linear spline Interpolation.
24  *
25  * Only valid with linear grid.
26  * @todo Have to prevent OneDimLinearSpline<T> being used with other than
27  * linear grid!!
28  */
29 template<class Td, class Tg = Td, class CTd = Vector<Td>, class CTg = Vector<Tg>>
30 class OneDimLinearSpline : public OneDimGridFunctor<Td, Tg, CTd, CTg>
31 {
32 public:
33   typedef OneDimGridFunctor<Td, Tg, CTd, CTg> base_type;
34   typedef typename base_type::value_type value_type;
35   typedef typename base_type::point_type point_type;
36   typedef typename base_type::data_type data_type;
37   typedef typename base_type::grid_type grid_type;
38 
39   using base_type::d2Y;
40   using base_type::dY;
41   using base_type::GridManager;
42   using base_type::m_grid;
43   using base_type::m_Y;
44   using base_type::Y;
45   //using base_type::FirstAddress;
46 
47   int First;
48   int Last;
49   value_type ConstValue;
50   point_type r_min;
51   point_type r_max;
52   point_type delta;
53   point_type delta_inv;
54   data_type m_Y1;
55 
base_type(gt)56   OneDimLinearSpline(grid_type* gt = 0) : base_type(gt), r_min(0), r_max(0)
57   {
58     if (gt)
59     {
60       r_min = gt->rmin();
61       r_max = gt->rmax();
62     }
63   }
64 
OneDimLinearSpline(point_type ri,point_type rf)65   OneDimLinearSpline(point_type ri, point_type rf) : base_type(0), r_min(ri), r_max(rf) {}
66 
67   template<class VV>
base_type(gt)68   OneDimLinearSpline(grid_type* gt, const VV& nv, bool pbc = false) : base_type(gt)
69   {
70     if (gt)
71     {
72       r_min = gt->rmin();
73       r_max = gt->rmax();
74     }
75     assign(nv.begin(), nv.end());
76   }
77 
makeClone()78   OneDimLinearSpline<Td, Tg, CTd, CTg>* makeClone() const { return new OneDimLinearSpline<Td, Tg, CTd, CTg>(*this); }
79 
80   template<class IT>
assign(IT d_first,IT d_last)81   void assign(IT d_first, IT d_last)
82   {
83     m_Y.resize(d_last - d_first);
84     copy(d_first, d_last, m_Y.data());
85     delta = (r_max - r_min) / static_cast<point_type>(m_Y.size() - 1);
86     //r_min=m_grid->rmin();
87     //r_max=m_grid->rmax();
88     //delta=m_grid->dh();
89     delta_inv = 1.0 / delta;
90   }
91 
92 
rmax()93   inline point_type rmax() const { return r_max; }
94 
95   /** evaluate the value at r
96    * @param r value on a grid
97    * @return value obtained by cubic-spline
98    *
99    * Performance may be tunned: define USE_MEMORYSAVEMODE
100    * to evaluate the coefficients instead of using aux. arrays
101    */
splint(point_type r)102   inline value_type splint(point_type r) const override
103   {
104     if (r >= r_max)
105       return ConstValue;
106     int k = static_cast<int>((r - r_min) * delta_inv);
107 #if defined(USE_MEMORYSAVEMODE)
108     return m_Y[k] + (m_Y[k + 1] - m_Y[k]) * (r * delta_inv - k);
109 #else
110     return m_Y[k] + m_Y1[k] * (r - (*m_grid)[k]);
111 #endif
112   }
113 
114   //template<class IT1, class IT2>
115   //void assign(IT1 g_first, IT1 g_last, IT2 d_first, IT2 d_last)
116   //{
117   //  if(m_grid ==0)
118   //  {
119   //    NumericalGrid<Td> *agrid=new NumericalGrid<Td>;
120   //    agrid->assign(g_first,g_last);
121   //    m_grid=agrid;
122   //  }
123   //  assign(d_first,d_last);
124   //}
125 
126 
127   //  /** evaluate the value at r using a binary search on a grid
128   //   * @param r distance
129   //   */
130   //  inline value_type splintNG(point_type r) const
131   //  {
132   //    if(r>=r_max) return ConstValue;
133   //    int k=m_grid->getIndex(r);
134   //    //int k = static_cast<int>((r-r_min)*delta_inv);
135   //#if defined(USE_MEMORYSAVEMODE)
136   //    return m_Y[k]+(m_Y[k+1]-m_Y[k])*(r*delta_inv-k);
137   //#else
138   //    return m_Y[k]+m_Y1[k]*(r-(*m_grid)[k]);
139   //#endif
140   //  }
141 
142   /** evaluate the index and the linear coefficient
143    * @param r distance
144    * @param k return index
145    * @param rfrac (r-floor(r/delta))/delta
146    */
locate(point_type r,int & k,point_type & rfrac)147   inline void locate(point_type r, int& k, point_type& rfrac)
148   {
149     k     = static_cast<int>((r - r_min) * delta_inv);
150     rfrac = r * delta_inv - k;
151   }
152 
153   /** evaluate the value at r=(k + rfrac)*delta
154    */
f(int k,point_type rfrac)155   inline value_type f(int k, point_type rfrac) { return m_Y[k] * (1.0 - rfrac) + m_Y[k + 1] * rfrac; }
156 
157   /** evaluate the value at r
158    * @param r value on a grid
159    * @param du first derivative (assigned)
160    * @param d2u second derivative (assigned)
161    * @return value obtained by cubic-spline
162    */
splint(point_type r,value_type & du,value_type & d2u)163   inline value_type splint(point_type r, value_type& du, value_type& d2u) const override
164   {
165     std::cerr << "  OneDimLinearSpline cannot be used for derivates." << std::endl;
166     return 0.0;
167   }
168 
169   /** evaluate the spline coefficients
170    * @param imin index of the first valid grid
171    * @param yp1 first derivative at imin grid point
172    * @param imax index of the last valid grid
173    * @param ypn first derivative at imax grid point
174    *
175    */
spline(int imin,value_type yp1,int imax,value_type ypn)176   inline void spline(int imin, value_type yp1, int imax, value_type ypn)
177   {
178     int npts(imax - imin + 1);
179     First = imin;
180     Last  = imax;
181     m_Y1.resize(npts);
182     //r_min=m_grid->r(imin);
183     //r_max=m_grid->r(imax);
184     for (int i = imin; i < imax - 1; i++)
185     {
186       m_Y1[i] = (m_Y[i + 1] - m_Y[i]) / ((*m_grid)[i + 1] - (*m_grid)[i]);
187       //m_Y1[i]= (m_Y[i+1]-m_Y[i])*delta_inv;
188     }
189     m_Y1[imax] = 0.0;
190     ConstValue = m_Y[imax];
191   }
192 
spline()193   inline void spline() { spline(0, 0.0, this->size() - 1, 0.0); }
194 };
195 
196 } // namespace qmcplusplus
197 #endif
198