46 #ifndef Xyce_N_DEV_Interpolators_h
47 #define Xyce_N_DEV_Interpolators_h
49 #include <N_UTL_Math.h>
63 template <
typename ScalarT>
71 virtual void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya){};
74 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
75 const ScalarT & x, ScalarT & y){};
78 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
79 const ScalarT & x, ScalarT & dydx){};
82 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
83 const ScalarT & x, ScalarT & ypp){};
86 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
87 const ScalarT & a,
const ScalarT & b, ScalarT & result){};
91 const std::vector<ScalarT> & xa,
98 const ScalarT & ai,
const ScalarT & bi,
const ScalarT & ci,
99 const ScalarT & di,
const ScalarT & xi,
const ScalarT & a,
133 template <
typename ScalarT>
136 const std::vector<ScalarT> & xa,
141 size_t ilo = index_lo;
142 size_t ihi = index_hi;
145 size_t i = (ihi + ilo)/2;
169 template <
typename ScalarT>
180 const ScalarT r1 = a - xi;
181 const ScalarT r2 = b - xi;
182 const ScalarT r12 = r1 + r2;
183 const ScalarT bterm = 0.5 * bi * r12;
184 const ScalarT cterm = (1.0 / 3.0) * ci * (r1 * r1 + r2 * r2 + r1 * r2);
185 const ScalarT dterm = 0.25 * di * r12 * (r1 * r1 + r2 * r2);
186 return (b - a) * (ai + bterm + cterm + dterm);
196 template <
typename ScalarT>
202 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya);
204 void clear () {
b.clear();
c.clear();
d.clear();
_m.clear(); };
207 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
208 const ScalarT & x, ScalarT & y);
211 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
212 const ScalarT & x, ScalarT & dydx);
215 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
216 const ScalarT & x, ScalarT & ypp);
219 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
220 const ScalarT & a,
const ScalarT &
b, ScalarT & result);
223 const std::vector<ScalarT> & xa,
224 std::vector<ScalarT> &
b,
225 std::vector<ScalarT> &
c,
226 std::vector<ScalarT> &
d,
227 std::vector<ScalarT> & m);
230 std::vector<ScalarT>
b;
231 std::vector<ScalarT>
c;
232 std::vector<ScalarT>
d;
233 std::vector<ScalarT>
_m;
254 template <
typename ScalarT>
256 const std::vector<ScalarT> & xa,
257 std::vector<ScalarT> & b,
258 std::vector<ScalarT> & c,
259 std::vector<ScalarT> & d,
260 std::vector<ScalarT> & m)
263 size_t size = xa.size();
265 for (i = 0; i < (size - 1); i++)
267 const ScalarT NE = std::fabs (m[i + 3] - m[i+2]) + fabs (m[i + 1] - m[i]);
276 const ScalarT h_i = xa[i + 1] - xa[i];
277 const ScalarT NE_next = std::fabs (m[i + 4] - m[i + 3]) + fabs (m[i+2] - m[i + 1]);
278 const ScalarT alpha_i = std::fabs (m[i + 1] - m[i]) / NE;
287 alpha_ip1 = std::fabs (m[i+2] - m[i + 1]) / NE_next;
288 tL_ip1 = (1.0 - alpha_ip1) * m[i+2] + alpha_ip1 * m[i + 3];
290 b[i] = (1.0 - alpha_i) * m[i + 1] + alpha_i * m[i+2];
291 c[i] = (3.0 * m[i+2] - 2.0 * b[i] - tL_ip1) / h_i;
292 d[i] = (b[i] + tL_ip1 - 2.0 * m[i+2]) / (h_i * h_i);
309 template <
typename ScalarT>
311 const std::vector<ScalarT> & xa,
312 const std::vector<ScalarT> & ya)
314 size_t size = xa.size();
316 if (b.size() != size) b.resize(size);
317 if (c.size() != size) c.resize(size);
318 if (d.size() != size) d.resize(size);
319 if (_m.size() != size+4) _m.resize(size+4);
321 for (
int i = 0; i <= size - 2; i++)
323 _m[i+2] = (ya[i + 1] - ya[i]) / (xa[i + 1] - xa[i]);
327 _m[0] = 3.0 * _m[2] - 2.0 * _m[3];
328 _m[1] = 2.0 * _m[2] - _m[3];
329 _m[size + 1] = 2.0 * _m[size] - _m[size-1];
330 _m[size + 2] = 3.0 * _m[size] - 2.0 * _m[size-1];
332 calc (xa, b, c, d, _m);
343 template <
typename ScalarT>
345 const std::vector<ScalarT> & xa,
346 const std::vector<ScalarT> & ya,
350 size_t size = xa.size();
351 size_t index = this->binarySearch (xa, x, 0, size - 1);
353 const ScalarT x_lo = xa[index];
354 const ScalarT delx = x - x_lo;
355 y = ya[index] + delx * (b[index] + delx * (c[index] + d[index] * delx));
367 template <
typename ScalarT>
369 const std::vector<ScalarT> & xa,
370 const std::vector<ScalarT> & ya,
374 size_t size = xa.size();
375 size_t index = this->binarySearch (xa, x, 0, size - 1);
377 ScalarT x_lo = xa[index];
378 ScalarT delx = x - x_lo;
379 dydx = b[index] + delx * (2.0 * c[index] + 3.0 * d[index] * delx);
391 template <
typename ScalarT>
393 const std::vector<ScalarT> & xa,
394 const std::vector<ScalarT> & ya,
398 size_t size = xa.size();
399 size_t index = this->binarySearch (xa, x, 0, size - 1);
401 const ScalarT x_lo = xa[index];
402 const ScalarT delx = x - x_lo;
403 ypp = 2.0 * c[index] + 6.0 * d[index] * delx;
415 template <
typename ScalarT>
417 const std::vector<ScalarT> & xa,
418 const std::vector<ScalarT> & ya,
423 size_t size = xa.size();
424 size_t index_a = this->binarySearch (xa, ai, 0, size - 1);
425 size_t index_b = this->binarySearch (xa, bi, 0, size - 1);
429 for(
size_t i=index_a; i<=index_b; i++)
431 const ScalarT x_hi = xa[i + 1];
432 const ScalarT x_lo = xa[i];
433 const ScalarT y_lo = ya[i];
434 const ScalarT dx = x_hi - x_lo;
437 if (i == index_a || i == index_b)
439 ScalarT x1 = (i == index_a) ? ai : x_lo;
440 ScalarT x2 = (i == index_b) ? bi : x_hi;
441 result += this->integ_eval (y_lo, b[i], c[i], d[i], x_lo, x1, x2);
445 result += dx * (y_lo + dx*(0.5*b[i] + dx*(c[i]/3.0 + 0.25*d[i]*dx)));
464 template <
typename ScalarT>
470 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya);
475 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
476 const ScalarT & x, ScalarT & y);
479 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
480 const ScalarT & x, ScalarT & dydx);
483 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
484 const ScalarT & x, ScalarT & ypp);
488 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
489 const ScalarT & a,
const ScalarT & b, ScalarT & result) {};
492 std::vector<ScalarT>
y2;
505 template <
typename ScalarT>
507 (
const std::vector<ScalarT> & xa,
508 const std::vector<ScalarT> & ya)
510 if (y2.size() != xa.size())
512 y2.resize(xa.size());
515 ScalarT p=0; ScalarT qn=0; ScalarT sig=0; ScalarT un=0;
516 int n = y2.size(); std::vector <ScalarT> u(n-1,0.0);
526 for (
int i=1; i<n-1; i++)
528 sig = (xa[i]-xa[i-1])/(xa[i+1]-xa[i-1]);
529 p = sig*y2[i-1] + 2.0;
531 u[i] = (ya[i+1]-ya[i])/(xa[i+1]-xa[i]) -
532 (ya[i]-ya[i-1])/(xa[i]-xa[i-1]);
533 u[i] = (6.0*u[i]/(xa[i+1]-xa[i-1]) - sig*u[i-1])/p;
536 for (
int l=n-2; l>=0; l--)
538 y2[l] = y2[l]*y2[l+1]+u[l];
552 template <
typename ScalarT>
554 const std::vector<ScalarT> & xa,
555 const std::vector<ScalarT> & ya,
556 const ScalarT & x_position,
562 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
563 int k = 0;
int klo = 0;
int khi = n-1;
567 if (xa[k] > x_position) khi=k;
570 h = xa[khi] - xa[klo];
577 ScalarT h0 = xa[1]-xa[0];
578 ScalarT dx = x_position - xa[0];
579 ScalarT dydx = (ya[1]-ya[0])/h0 - h0*y2[0]/3.0 - h0*y2[1]/6.0;
580 y_spline = ya[0] + dx * dydx;
584 ScalarT h1 = xa[n-1]-xa[n-2];
585 ScalarT dx = x_position - xa[n-1];
586 ScalarT dydx = (ya[n-1]-ya[n-2])/h1 + h1*y2[n-2]/6.0 + h1*y2[n-1]/3.0;
587 y_spline = ya[n-1] + dx * dydx;
592 a = (xa[khi] - x_position)/h;
593 b = (x_position - xa[klo])/h;
595 y_spline = a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2[klo] + (b*b*b-b)*y2[khi])*(h*h)/6.0;
609 template <
typename ScalarT>
611 const std::vector<ScalarT> & xa,
612 const std::vector<ScalarT> & ya,
613 const ScalarT & x_position,
614 ScalarT & dydx_spline)
619 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
620 int k = 0;
int klo = 0;
int khi = n-1;
624 if (xa[k] > x_position) khi=k;
627 h = xa[khi] - xa[klo];
634 ScalarT h0 = xa[1]-xa[0];
635 dydx_spline = (ya[1]-ya[0])/h0 - h0*y2[0]/3.0 - h0*y2[1]/6.0;
639 ScalarT h1 = xa[n-1]-xa[n-2];
640 dydx_spline = (ya[n-1]-ya[n-2])/h1 + h1*y2[n-2]/6.0 + h1*y2[n-1]/3.0;
645 a = (xa[khi] - x_position)/h;
646 b = (x_position - xa[klo])/h;
649 dydx_spline = (ya[khi]-ya[klo])/h - ((3*a*a-1)*y2[klo] - (3*b*b-1)*y2[khi])*h/6.0;
663 template <
typename ScalarT>
665 const std::vector<ScalarT> & xa,
666 const std::vector<ScalarT> & ya,
667 const ScalarT & x_position,
673 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
674 int k = 0;
int klo = 0;
int khi = n-1;
678 if (xa[k] > x_position) khi=k;
681 h = xa[khi] - xa[klo];
696 a = (xa[khi] - x_position)/h;
697 b = (x_position - xa[klo])/h;
700 ypp = a*y2[klo] + b*y2[khi];
711 template <
typename ScalarT>
717 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya) {};
722 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
723 const ScalarT & x, ScalarT & y);
726 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
727 const ScalarT & x, ScalarT & dydx);
730 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
731 const ScalarT & x, ScalarT & ypp);
734 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
735 const ScalarT & a,
const ScalarT & b, ScalarT & result);
750 template <
typename ScalarT>
752 const std::vector<ScalarT> & xa,
753 const std::vector<ScalarT> & ya,
760 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
761 int k = 0;
int klo = 0;
int khi = n-1;
765 if (xa[k] > x) khi=k;
768 h = xa[khi] - xa[klo];
783 ScalarT dx = x - xa[klo];
784 ScalarT ya0 = ya[khi] - ya[klo];
785 y = (dx/h) * ya0 + ya[klo];
797 template <
typename ScalarT>
799 const std::vector<ScalarT> & xa,
800 const std::vector<ScalarT> & ya,
807 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
808 int k = 0;
int klo = 0;
int khi = n-1;
812 if (xa[k] > x) khi=k;
815 h = xa[khi] - xa[klo];
830 ScalarT dx = xa[khi] - xa[klo];
831 ScalarT dy = ya[khi] - ya[klo];
844 template <
typename ScalarT>
846 const std::vector<ScalarT> & xa,
847 const std::vector<ScalarT> & ya,
862 template <
typename ScalarT>
864 const std::vector<ScalarT> & xa,
865 const std::vector<ScalarT> & ya,
871 int size = xa.size();
872 int index_a = this->binarySearch (xa, a, 0, size - 1);
873 int index_b = this->binarySearch (xa, b, 0, size - 1);
879 for(
int i=index_a; i<=index_b; i++)
881 const ScalarT x_hi = xa[i + 1];
882 const ScalarT x_lo = xa[i];
883 const ScalarT y_lo = ya[i];
884 const ScalarT y_hi = ya[i + 1];
885 const ScalarT dx = x_hi - x_lo;
889 if (i == index_a || i == index_b)
891 ScalarT x1 = (i == index_a) ? a : x_lo;
892 ScalarT x2 = (i == index_b) ? b : x_hi;
893 const ScalarT D = (y_hi-y_lo)/dx;
894 result += (x2-x1) * (y_lo + 0.5*D*((x2-x_lo)+(x1-x_lo)));
898 result += 0.5 * dx * (y_lo + y_hi);
virtual void eval(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &y)
void init(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya)
virtual void eval_deriv(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &dydx)
Pure virtual class to augment a linear system.
void eval_deriv(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &dydx)
void eval_deriv(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &dydx)
virtual void eval_integ(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &a, const ScalarT &b, ScalarT &result)
void eval(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &y)
void eval(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &y)
void eval(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &y)
std::vector< ScalarT > _m
void eval_integ(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &a, const ScalarT &b, ScalarT &result)
void eval_deriv2(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &ypp)
void eval_deriv(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &dydx)
void calc(const std::vector< ScalarT > &xa, std::vector< ScalarT > &b, std::vector< ScalarT > &c, std::vector< ScalarT > &d, std::vector< ScalarT > &m)
void eval_integ(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &a, const ScalarT &b, ScalarT &result)
size_t binarySearch(const std::vector< ScalarT > &xa, const ScalarT &x, size_t index_lo, size_t index_hi)
void init(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya)
void eval_deriv2(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &ypp)
void eval_integ(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &a, const ScalarT &b, ScalarT &result)
void eval_deriv2(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &ypp)
void init(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya)
ScalarT integ_eval(const ScalarT &ai, const ScalarT &bi, const ScalarT &ci, const ScalarT &di, const ScalarT &xi, const ScalarT &a, const ScalarT &b)
virtual void eval_deriv2(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya, const ScalarT &x, ScalarT &ypp)
std::vector< ScalarT > y2
virtual void init(const std::vector< ScalarT > &xa, const std::vector< ScalarT > &ya)