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