46 #ifndef Xyce_N_DEV_Interpolators_h
47 #define Xyce_N_DEV_Interpolators_h
61 template <
typename ScalarT>
69 virtual void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya){};
72 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
73 const ScalarT & x, ScalarT & y){};
76 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
77 const ScalarT & x, ScalarT & dydx){};
80 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
81 const ScalarT & x, ScalarT & ypp){};
84 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
85 const ScalarT & a,
const ScalarT & b, ScalarT & result){};
89 const std::vector<ScalarT> & xa,
96 const ScalarT & ai,
const ScalarT & bi,
const ScalarT & ci,
97 const ScalarT & di,
const ScalarT & xi,
const ScalarT & a,
131 template <
typename ScalarT>
134 const std::vector<ScalarT> & xa,
139 size_t ilo = index_lo;
140 size_t ihi = index_hi;
143 size_t i = (ihi + ilo)/2;
167 template <
typename ScalarT>
178 const ScalarT r1 = a - xi;
179 const ScalarT r2 = b - xi;
180 const ScalarT r12 = r1 + r2;
181 const ScalarT bterm = 0.5 * bi * r12;
182 const ScalarT cterm = (1.0 / 3.0) * ci * (r1 * r1 + r2 * r2 + r1 * r2);
183 const ScalarT dterm = 0.25 * di * r12 * (r1 * r1 + r2 * r2);
184 return (b - a) * (ai + bterm + cterm + dterm);
194 template <
typename ScalarT>
200 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya);
202 void clear () {
b.clear();
c.clear();
d.clear();
_m.clear(); };
205 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
206 const ScalarT & x, ScalarT & y);
209 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
210 const ScalarT & x, ScalarT & dydx);
213 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
214 const ScalarT & x, ScalarT & ypp);
217 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
218 const ScalarT & a,
const ScalarT &
b, ScalarT & result);
221 const std::vector<ScalarT> & xa,
222 std::vector<ScalarT> &
b,
223 std::vector<ScalarT> &
c,
224 std::vector<ScalarT> &
d,
225 std::vector<ScalarT> & m);
228 std::vector<ScalarT>
b;
229 std::vector<ScalarT>
c;
230 std::vector<ScalarT>
d;
231 std::vector<ScalarT>
_m;
252 template <
typename ScalarT>
254 const std::vector<ScalarT> & xa,
255 std::vector<ScalarT> & b,
256 std::vector<ScalarT> & c,
257 std::vector<ScalarT> & d,
258 std::vector<ScalarT> & m)
261 size_t size = xa.size();
263 for (i = 0; i < (size - 1); i++)
265 const ScalarT NE = fabs (m[i + 3] - m[i+2]) + fabs (m[i + 1] - m[i]);
274 const ScalarT h_i = xa[i + 1] - xa[i];
275 const ScalarT NE_next = fabs (m[i + 4] - m[i + 3]) + fabs (m[i+2] - m[i + 1]);
276 const ScalarT alpha_i = fabs (m[i + 1] - m[i]) / NE;
285 alpha_ip1 = fabs (m[i+2] - m[i + 1]) / NE_next;
286 tL_ip1 = (1.0 - alpha_ip1) * m[i+2] + alpha_ip1 * m[i + 3];
288 b[i] = (1.0 - alpha_i) * m[i + 1] + alpha_i * m[i+2];
289 c[i] = (3.0 * m[i+2] - 2.0 * b[i] - tL_ip1) / h_i;
290 d[i] = (b[i] + tL_ip1 - 2.0 * m[i+2]) / (h_i * h_i);
307 template <
typename ScalarT>
309 const std::vector<ScalarT> & xa,
310 const std::vector<ScalarT> & ya)
312 size_t size = xa.size();
314 if (b.size() != size) b.resize(size);
315 if (c.size() != size) c.resize(size);
316 if (d.size() != size) d.resize(size);
317 if (_m.size() != size+4) _m.resize(size+4);
319 for (
int i = 0; i <= size - 2; i++)
321 _m[i+2] = (ya[i + 1] - ya[i]) / (xa[i + 1] - xa[i]);
325 _m[0] = 3.0 * _m[2] - 2.0 * _m[3];
326 _m[1] = 2.0 * _m[2] - _m[3];
327 _m[size + 1] = 2.0 * _m[size] - _m[size-1];
328 _m[size + 2] = 3.0 * _m[size] - 2.0 * _m[size-1];
330 calc (xa, b, c, d, _m);
341 template <
typename ScalarT>
343 const std::vector<ScalarT> & xa,
344 const std::vector<ScalarT> & ya,
348 size_t size = xa.size();
349 size_t index = this->binarySearch (xa, x, 0, size - 1);
351 const ScalarT x_lo = xa[index];
352 const ScalarT delx = x - x_lo;
353 y = ya[index] + delx * (b[index] + delx * (c[index] + d[index] * delx));
365 template <
typename ScalarT>
367 const std::vector<ScalarT> & xa,
368 const std::vector<ScalarT> & ya,
372 size_t size = xa.size();
373 size_t index = this->binarySearch (xa, x, 0, size - 1);
375 ScalarT x_lo = xa[index];
376 ScalarT delx = x - x_lo;
377 dydx = b[index] + delx * (2.0 * c[index] + 3.0 * d[index] * delx);
389 template <
typename ScalarT>
391 const std::vector<ScalarT> & xa,
392 const std::vector<ScalarT> & ya,
396 size_t size = xa.size();
397 size_t index = this->binarySearch (xa, x, 0, size - 1);
399 const ScalarT x_lo = xa[index];
400 const ScalarT delx = x - x_lo;
401 ypp = 2.0 * c[index] + 6.0 * d[index] * delx;
413 template <
typename ScalarT>
415 const std::vector<ScalarT> & xa,
416 const std::vector<ScalarT> & ya,
421 size_t size = xa.size();
422 size_t index_a = this->binarySearch (xa, ai, 0, size - 1);
423 size_t index_b = this->binarySearch (xa, bi, 0, size - 1);
427 for(
size_t i=index_a; i<=index_b; i++)
429 const ScalarT x_hi = xa[i + 1];
430 const ScalarT x_lo = xa[i];
431 const ScalarT y_lo = ya[i];
432 const ScalarT dx = x_hi - x_lo;
435 if (i == index_a || i == index_b)
437 ScalarT x1 = (i == index_a) ? ai : x_lo;
438 ScalarT x2 = (i == index_b) ? bi : x_hi;
439 result += this->integ_eval (y_lo, b[i], c[i], d[i], x_lo, x1, x2);
443 result += dx * (y_lo + dx*(0.5*b[i] + dx*(c[i]/3.0 + 0.25*d[i]*dx)));
462 template <
typename ScalarT>
468 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya);
473 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
474 const ScalarT & x, ScalarT & y);
477 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
478 const ScalarT & x, ScalarT & dydx);
481 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
482 const ScalarT & x, ScalarT & ypp);
486 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
487 const ScalarT & a,
const ScalarT & b, ScalarT & result) {};
490 std::vector<ScalarT>
y2;
503 template <
typename ScalarT>
505 (
const std::vector<ScalarT> & xa,
506 const std::vector<ScalarT> & ya)
508 if (y2.size() != xa.size())
510 y2.resize(xa.size());
513 ScalarT p=0; ScalarT qn=0; ScalarT sig=0; ScalarT un=0;
514 int n = y2.size(); std::vector <ScalarT> u(n-1,0.0);
524 for (
int i=1; i<n-1; i++)
526 sig = (xa[i]-xa[i-1])/(xa[i+1]-xa[i-1]);
527 p = sig*y2[i-1] + 2.0;
529 u[i] = (ya[i+1]-ya[i])/(xa[i+1]-xa[i]) -
530 (ya[i]-ya[i-1])/(xa[i]-xa[i-1]);
531 u[i] = (6.0*u[i]/(xa[i+1]-xa[i-1]) - sig*u[i-1])/p;
534 for (
int l=n-2; l>=0; l--)
536 y2[l] = y2[l]*y2[l+1]+u[l];
550 template <
typename ScalarT>
552 const std::vector<ScalarT> & xa,
553 const std::vector<ScalarT> & ya,
554 const ScalarT & x_position,
560 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
561 int k = 0;
int klo = 0;
int khi = n-1;
565 if (xa[k] > x_position) khi=k;
568 h = xa[khi] - xa[klo];
575 ScalarT h0 = xa[1]-xa[0];
576 ScalarT dx = x_position - xa[0];
577 ScalarT dydx = (ya[1]-ya[0])/h0 - h0*y2[0]/3.0 - h0*y2[1]/6.0;
578 y_spline = ya[0] + dx * dydx;
582 ScalarT h1 = xa[n-1]-xa[n-2];
583 ScalarT dx = x_position - xa[n-1];
584 ScalarT dydx = (ya[n-1]-ya[n-2])/h1 + h1*y2[n-2]/6.0 + h1*y2[n-1]/3.0;
585 y_spline = ya[n-1] + dx * dydx;
590 a = (xa[khi] - x_position)/h;
591 b = (x_position - xa[klo])/h;
593 y_spline = a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2[klo] + (b*b*b-b)*y2[khi])*(h*h)/6.0;
607 template <
typename ScalarT>
609 const std::vector<ScalarT> & xa,
610 const std::vector<ScalarT> & ya,
611 const ScalarT & x_position,
612 ScalarT & dydx_spline)
617 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
618 int k = 0;
int klo = 0;
int khi = n-1;
622 if (xa[k] > x_position) khi=k;
625 h = xa[khi] - xa[klo];
632 ScalarT h0 = xa[1]-xa[0];
633 dydx_spline = (ya[1]-ya[0])/h0 - h0*y2[0]/3.0 - h0*y2[1]/6.0;
637 ScalarT h1 = xa[n-1]-xa[n-2];
638 dydx_spline = (ya[n-1]-ya[n-2])/h1 + h1*y2[n-2]/6.0 + h1*y2[n-1]/3.0;
643 a = (xa[khi] - x_position)/h;
644 b = (x_position - xa[klo])/h;
647 dydx_spline = (ya[khi]-ya[klo])/h - ((3*a*a-1)*y2[klo] - (3*b*b-1)*y2[khi])*h/6.0;
661 template <
typename ScalarT>
663 const std::vector<ScalarT> & xa,
664 const std::vector<ScalarT> & ya,
665 const ScalarT & x_position,
671 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
672 int k = 0;
int klo = 0;
int khi = n-1;
676 if (xa[k] > x_position) khi=k;
679 h = xa[khi] - xa[klo];
694 a = (xa[khi] - x_position)/h;
695 b = (x_position - xa[klo])/h;
698 ypp = a*y2[klo] + b*y2[khi];
709 template <
typename ScalarT>
715 void init (
const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya) {};
720 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
721 const ScalarT & x, ScalarT & y);
724 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
725 const ScalarT & x, ScalarT & dydx);
728 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
729 const ScalarT & x, ScalarT & ypp);
732 const std::vector<ScalarT> & xa,
const std::vector<ScalarT> & ya,
733 const ScalarT & a,
const ScalarT & b, ScalarT & result);
748 template <
typename ScalarT>
750 const std::vector<ScalarT> & xa,
751 const std::vector<ScalarT> & ya,
758 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
759 int k = 0;
int klo = 0;
int khi = n-1;
763 if (xa[k] > x) khi=k;
766 h = xa[khi] - xa[klo];
781 ScalarT dx = x - xa[klo];
782 ScalarT ya0 = ya[khi] - ya[klo];
783 y = (dx/h) * ya0 + ya[klo];
795 template <
typename ScalarT>
797 const std::vector<ScalarT> & xa,
798 const std::vector<ScalarT> & ya,
805 ScalarT h = 0.0; ScalarT a = 0.0; ScalarT b = 0.0;
806 int k = 0;
int klo = 0;
int khi = n-1;
810 if (xa[k] > x) khi=k;
813 h = xa[khi] - xa[klo];
828 ScalarT dx = xa[khi] - xa[klo];
829 ScalarT dy = ya[khi] - ya[klo];
842 template <
typename ScalarT>
844 const std::vector<ScalarT> & xa,
845 const std::vector<ScalarT> & ya,
860 template <
typename ScalarT>
862 const std::vector<ScalarT> & xa,
863 const std::vector<ScalarT> & ya,
869 int size = xa.size();
870 int index_a = this->binarySearch (xa, a, 0, size - 1);
871 int index_b = this->binarySearch (xa, b, 0, size - 1);
877 for(
int i=index_a; i<=index_b; i++)
879 const ScalarT x_hi = xa[i + 1];
880 const ScalarT x_lo = xa[i];
881 const ScalarT y_lo = ya[i];
882 const ScalarT y_hi = ya[i + 1];
883 const ScalarT dx = x_hi - x_lo;
887 if (i == index_a || i == index_b)
889 ScalarT x1 = (i == index_a) ? a : x_lo;
890 ScalarT x2 = (i == index_b) ? b : x_hi;
891 const ScalarT D = (y_hi-y_lo)/dx;
892 result += (x2-x1) * (y_lo + 0.5*D*((x2-x_lo)+(x1-x_lo)));
896 result += 0.5 * dx * (y_lo + y_hi);