48 #include <Xyce_config.h>
51 #include <N_UTL_Math.h>
53 #if( defined HAVE_FLOAT_H && defined HAVE__ISNAN_AND__FINITE_SUPPORT )
55 #define isnan(x) _isnan(x)
56 #define isinf(x) (!_finite(x))
100 const double turnpt = -exp(-1.), c1 = 1.5, c2 = .75;
101 double r, r2, r3, s, mach_eps, relerr = 1., diff;
115 if( x == 0. )
return;
116 if( x < (1-c2) ) w = x*(1.-x + c1*x*x);
125 w = x*(1.0-x + c1*x*x);
126 xi = log(1.0-x + c1*x*x) - w;
131 if( diff < 0.0 ) diff = -diff;
132 w = -1 + sqrt(2.0*exp(1.))*sqrt(x-turnpt);
133 if( diff == 0.0 )
return;
146 while( relerr > mach_eps && i<maxit)
151 s = 6.*(w+1.0)*(w+1.0);
152 w = w * ( 1.0 + r + r2/(2.0*( w+1.0)) - (2. * w -1.0)*r3/s );
153 if( w * x < 0.0 ) w = -w;
164 if(relerr < 0.0 ) relerr = -relerr;
167 if( i == maxit ) ierr = 2;
183 if(vnew > vold) vnew = std::min(vnew,(3.0 * vold) + 2.0);
186 if (vnew < 3.5) vnew = std::max(vnew,2.0);
191 if(vnew > vold) vnew = std::min(vnew, 4.0);
192 else vnew = std::max(vnew,-0.5);
215 if((vnew > vcrit) && (fabs(vnew - vold) > (vt + vt)))
219 arg = 1 + (vnew - vold) / vt;
223 vnew = vold + vt * log(arg);
232 vnew = vt *log(vnew/vt);
265 if((vnew > vcrit) && (fabs(vnew - vold) > (vt + vt)))
269 arg = (vnew - vold) / vt;
273 vnew = vold + vt * (2+log(arg-2));
277 vnew = vold - vt*(2+log(2-arg));
282 vnew = vt *log(vnew/vt);
338 #ifdef Xyce_FETLIM_NAN_CHECK
346 vtsthi = fabs(2*(vold-vto))+2;
347 vtstlo = vtsthi/2 +2;
360 if(-delv >vtstlo) vnew = vold - vtstlo;
364 vnew = std::max(vnew,vto+2.0);
370 if(delv >= vtsthi) vnew = vold + vtsthi;
379 vnew = std::max(vnew,vto-0.5);
384 vnew = std::min(vnew,vto+4.0);
393 if(-delv >vtsthi) vnew = vold - vtsthi;
400 if(delv >vtstlo) vnew = vold + vtstlo;
432 register double *cgs,
433 register double *cgd,
434 register double *cgb,
457 else if (vgbt <= -phi/2)
459 *cgb = -vgbt*cox/phi;
463 *cgb = -vgbt*cox/phi;
464 *cgs = cox/(7.5e-1*phi)*vgbt+cox/1.5;
468 vdbsat = vdsat-(vgs1-vgb1);
476 vddif = 2.0*vdbsat-vdb;
477 vddif1 = vdbsat-vdb-1.0e-12;
478 vddif2 = vddif*vddif;
479 *cgd = cox*(1.0-vdbsat*vdbsat/vddif2)/1.5;
480 *cgs = cox*(1.0-vddif1*vddif1/vddif2)/1.5;
489 else if (vgbt <= -phi/2)
491 *cgb += -vgbt*cox/phi;
495 *cgb += -vgbt*cox/phi;
496 *cgs += cox/(7.5e-1*phi)*vgbt+cox/1.5;
500 vdbsat = vdsat0-(vgs0-vgb0);
508 vddif = 2.0*vdbsat-vdb;
509 vddif1 = vdbsat-vdb-1.0e-12;
510 vddif2 = vddif*vddif;
511 *cgd += cox*(1.0-vdbsat*vdbsat/vddif2)/1.5;
512 *cgs += cox*(1.0-vddif1*vddif1/vddif2)/1.5;
516 *cgs = *cgs *.5 + covlgs;
517 *cgd = *cgd *.5 + covlgd;
518 *cgb = *cgb *.5 + covlgb;
563 else if (vgst <= -phi/2)
565 capgb = -vgst*cox/(2*phi);
571 capgb = -vgst*cox/(2*phi);
572 capgs = vgst*cox/(1.5*phi)+cox/3;
587 vddif = 2.0*vdsat-vds;
589 vddif2 = vddif*vddif;
590 capgd = cox*(1.0-vdsat*vdsat/vddif2)/3;
591 capgs = cox*(1.0-vddif1*vddif1/vddif2)/3;
641 double vdenom, vdenom3;
658 else if (vgst <= -phi/2)
666 dcapgbdvgs=-1.0*cox/(2.0*phi);
672 dcapgsdvgs=cox/(1.5*phi);
678 dcapgbdvgs=-1.0*cox/(2.0*phi);
701 vdenom3=vdenom*vdenom*vdenom;
703 dcapgsdvgs=4.0/3.0*cox*vgdt*vgdt/vdenom3;
705 dcapgsdvgd=-4.0/3.0*cox*vgst*vgdt/vdenom3;
706 dcapgddvgs=-4.0/3.0*cox*vgst*vgdt/vdenom3;
708 dcapgddvgd=4.0/3.0*cox*vgst*vgst/vdenom3;
740 double & noise,
double & lnNoise,
741 const int type,
const double param,
const double temp)
746 noise = 2.0 *
CONSTQ * fabs(param);
747 lnNoise = log( std::max(noise,
N_MINLOG) );
752 lnNoise = log( std::max(noise,
N_MINLOG) );
770 void DeviceSupport::cap (
771 register CKTcircuit *ckt,
818 gcg = (cggb+cbgb)*ckt->CKTag[1];
819 gcd = (cgdb+cbdb)*ckt->CKTag[1];
820 gcs = (cgsb+cbsb)*ckt->CKTag[1];
822 gcgxs = -(1-xqc)*gcg;
824 gcdxs = -(1-xqc)*gcd;
826 gcsxs = -(1-xqc)*gcs;
827 *gcdgb = gcgxd-covlgd*ckt->CKTag[1];
828 *gcddb = gcdxd+(capbd+covlgd)*ckt->CKTag[1];
830 *gcsgb = gcgxs-covlgs*ckt->CKTag[1];
832 *gcssb = gcsxs+(capbs+covlgs)*ckt->CKTag[1];
833 *gcggb = (cggb+covlgd+covlgs+covlgb)*ckt->CKTag[1];
834 *gcgdb = (cgdb-covlgd)*ckt->CKTag[1];
835 *gcgsb = (cgsb-covlgs)*ckt->CKTag[1];
836 *gcbgb = (cbgb-covlgb)*ckt->CKTag[1];
837 *gcbdb = (cbdb-capbd)*ckt->CKTag[1];
838 *gcbsb = (cbsb-capbs)*ckt->CKTag[1];
845 qgate = qgate+qgd+qgs+qgb;
847 *qdrn = xqc*qchan-qgd;
848 *qsrc = (1-xqc)*qchan-qgs;
856 double DeviceSupport::pred
869 xfact = ckt->CKTdelta/ckt->CKTdeltaOld[1];
870 return( ( (1+xfact) * *(ckt->CKTstate1+loct) ) -
871 ( xfact * *(ckt->CKTstate2+loct) ) );
892 if (min <= 0.0) min = 0.3;
893 return ( vds * (alpha*(1.0-min) + min) );
941 (
double vgst,
double alpha,
double vgstConst)
943 return ((alpha)*vgst + (1.0-alpha)*vgstConst);
956 double val =
u.RandomDouble();
962 double interval = 1.0 / numBlocks;
964 for (
int i = 0; i < numBlocks; ++i) {
965 double lowBound = ((double) i) * interval;
966 double highBound = ((double) (i+1)) * interval;
967 if ((val >= lowBound) && (val < highBound)) {
972 return (numBlocks-1);
984 double val =
u.RandomDouble();
999 int retVal =
u.SetSeed( seedIn );
1042 ord =
static_cast<int>( order );
1043 for (i=1 ; i<=ord ; ++i)
1056 ddX += (order-ord)*term;
1058 ans += (order-ord)*term;
1074 double rs,wreturn,xi;
1077 rs=pow(10.0,-order);
1078 lambertw(rs*exp(X+rs),wreturn,ierr,xi);
1086 ddX = wreturn/(1+wreturn)/rs;
1087 return (wreturn/rs);
1108 #if( defined HAVE_NAN_INF_SUPPORT || defined HAVE__ISNAN_AND__FINITE_SUPPORT )
1118 double tol = 1.0e-6;
1121 if (!(x <= tol) && !(x > tol))
1127 if (!(z <= tol) && !(z > tol))
1144 std::vector<double> & x,
1145 std::vector<double> & y,
1146 std::vector<double> & y2)
1154 std::vector<double>
u(n-1,0.0);
1164 for (
int i=1; i<n-1; i++)
1166 sig = (x[i]-x[i-1])/(x[i+1]-x[i-1]);
1167 p = sig*y2[i-1] + 2.0;
1168 y2[i] = (sig-1.0)/p;
1169 u[i] = (y[i+1]-y[i])/(x[i+1]-x[i]) -
1170 (y[i]-y[i-1])/(x[i]-x[i-1]);
1171 u[i] = (6.0*u[i]/(x[i+1]-x[i-1]) - sig*u[i-1])/p;
1174 for (
int l=n-2; l>=0; l--)
1176 y2[l] = y2[l]*y2[l+1]+u[l];
1189 std::vector<double> & xa,
1190 std::vector<double> & ya,
1191 std::vector<double> & y2a,
1207 if (xa[k] > x_position) khi=k;
1211 h = xa[khi] - xa[klo];
1221 a = (xa[khi] - x_position)/h;
1222 b = (x_position - xa[klo])/h;
1224 y_spline = a*ya[klo]+b*ya[khi]+((a*a*a-a)*y2a[klo] + (b*b*b-b)*y2a[khi])*(h*h)/6.0;
1230 if ( (y_spline > ya[klo]) && (y_spline > ya[khi]) )
1232 if (ya[klo] > ya[khi]) y_spline = ya[klo];
1233 else y_spline = ya[khi];
1236 if ( (y_spline < ya[klo]) && (y_spline < ya[khi]) )
1238 if (ya[klo] < ya[khi]) y_spline = ya[klo];
1239 else y_spline = ya[khi];
double pnjlim_new(double vnew, double vold, double vt, double vcrit, int *icheck)
double pnjlim(double vnew, double vold, double vt, double vcrit, int *icheck)
void qmeyer(double vgs, double vgd, double vgb, double von, double vdsat, double &capgs, double &capgd, double &capgb, double phi, double cox)
Pure virtual class to augment a linear system.
double getRandomPerturbation()
double fetlim(double vnew, double vold, double vto)
int SetSeed(unsigned int seedIn)
double contVgst(double vgst, double alpha, double vgstConst=3.0)
void splint(std::vector< double > &xa, std::vector< double > &ya, std::vector< double > &y2a, double x_position, double &y_spline)
void spline(std::vector< double > &x, std::vector< double > &y, std::vector< double > &y2)
double Xexp(double, double &, double)
int finiteNumberTest(const double x)
void qmeyerderivs(double vgs, double vgd, double vgb, double von, double vdsat, double &dcapgsdvgs, double &dcapgsdvgb, double &dcapgsdvgd, double &dcapgddvgs, double &dcapgddvgb, double &dcapgddvgd, double &dcapgbdvgs, double &dcapgbdvgb, double &dcapgbdvgd, double phi, double cox, int Dtype)
double limvds(double vnew, double vold)
int getGainScaleBlockID(int numBlocks)
void lambertw(double x, double &w, int &ierr, double &xi)
void noiseSupport(double &noise, double &lnNoise, const int type, const double param, const double temp)
double contVds(double vds, double alpha, double min=0.3)
void cmeyer(double vgs0, double vgd0, double vgb0, double von0, double vdsat0, double vgs1, double vgd1, double vgb1, double covlgs, double covlgd, double covlgb, register double *cgs, register double *cgd, register double *cgb, double phi, double cox, double von, double vdsat)