45 #include <Xyce_config.h>
62 #include <N_ERH_ErrorMgr.h>
64 #include <N_LAS_Matrix.h>
65 #include <N_LAS_Vector.h>
75 .setDescription(
"Area scaling value (scales IS, ISR, IKF, RS, CJ0, and IBV)");
83 .setDescription(
"Device temperature");
88 .setDescription(
"Initial voltage drop across device set to zero");
92 .setDescription(
"Option to solve diode equations with the Lambert-W function");
100 .setDescription(
"Saturation current")
101 .setAnalyticSensitivityAvailable(
true)
108 .setDescription(
"Saturation current")
109 .setAnalyticSensitivityAvailable(
true)
116 .setDescription(
"Parasitic resistance")
117 .setAnalyticSensitivityAvailable(
true)
122 .setOriginalValueStored(
true)
123 .setDescription(
"Emission coefficient")
124 .setAnalyticSensitivityAvailable(
true)
130 .setDescription(
"Recombination current parameter (level 2)")
131 .setAnalyticSensitivityAvailable(
true)
136 .setDescription(
"Emission coefficient for ISR (level 2)")
137 .setAnalyticSensitivityAvailable(
true)
143 .setDescription(
"High-injection \"knee\" current (level 2)")
144 .setAnalyticSensitivityAvailable(
true)
150 .setDescription(
"Transit time")
151 .setAnalyticSensitivityAvailable(
true)
158 .setDescription(
"Zero-bias p-n depletion capacitance")
159 .setAnalyticSensitivityAvailable(
true)
167 .setDescription(
"Zero-bias p-n depletion capacitance")
168 .setAnalyticSensitivityAvailable(
true)
175 .setDescription(
"Zero-bias p-n depletion capacitance")
176 .setAnalyticSensitivityAvailable(
true)
182 .setDescription(
"Potential for p-n junction")
183 .setAnalyticSensitivityAvailable(
true)
188 .setDescription(
"Grading parameter for p-n junction")
189 .setAnalyticSensitivityAvailable(
true)
195 .setDescription(
"Bandgap voltage (barrier height)")
196 .setAnalyticSensitivityAvailable(
true)
201 .setDescription(
"IS temperature exponent")
202 .setAnalyticSensitivityAvailable(
true)
208 .setDescription(
"IKF temperature coefficient (linear) (level 2)")
209 .setAnalyticSensitivityAvailable(
true)
215 .setDescription(
"BV temperature coefficient (linear) (level 2)");
220 .setDescription(
"BV temperature coefficient (quadratic) (level 2)");
225 .setDescription(
"RS temperature coefficient (linear) (level 2)");
230 .setDescription(
"RS temperature coefficient (quadratic) (level 2)");
234 .setDescription(
"Forward-bias depletion capacitance coefficient")
235 .setAnalyticSensitivityAvailable(
true)
242 .setDescription(
"Reverse breakdown \"knee\" voltage")
243 .setAnalyticSensitivityAvailable(
true)
251 .setDescription(
"Reverse breakdown \"knee\" voltage")
252 .setAnalyticSensitivityAvailable(
true)
258 .setDescription(
"Reverse breakdown \"knee\" current")
259 .setAnalyticSensitivityAvailable(
true)
264 .setDescription(
"Reverse current fitting factor")
265 .setAnalyticSensitivityAvailable(
true)
270 .setDescription(
"Reverse breakdown ideality factor (level 2)")
271 .setAnalyticSensitivityAvailable(
true)
277 .setDescription(
"Low-level reverse breakdown \"knee\" current (level 2)")
278 .setAnalyticSensitivityAvailable(
true)
283 .setDescription(
"Low-level reverse breakdown ideality factor (level 2)")
284 .setAnalyticSensitivityAvailable(
true)
290 .setAnalyticSensitivityAvailable(
true)
295 .setDescription(
"Flicker noise coefficient")
296 .setAnalyticSensitivityAvailable(
true)
301 .setDescription(
"Flicker noise exponent")
302 .setAnalyticSensitivityAvailable(
true)
344 :
DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
349 Temp(getDeviceOptions().temp.getImmutableValue<double>()),
351 InitCondGiven(false),
381 APosEquPosNodeOffset(-1),
382 APosEquPriNodeOffset(-1),
383 ANegEquNegNodeOffset(-1),
384 ANegEquPriNodeOffset(-1),
385 APriEquPosNodeOffset(-1),
386 APriEquNegNodeOffset(-1),
387 APriEquPriNodeOffset(-1),
389 fPosEquPosNodePtr(0),
390 fPosEquPriNodePtr(0),
391 fNegEquNegNodePtr(0),
392 fNegEquPriNodePtr(0),
393 fPriEquPosNodePtr(0),
394 fPriEquNegNodePtr(0),
395 fPriEquPriNodePtr(0),
396 qPosEquPosNodePtr(0),
397 qPosEquPriNodePtr(0),
398 qNegEquNegNodePtr(0),
399 qNegEquPriNodePtr(0),
400 qPriEquPosNodePtr(0),
401 qPriEquNegNodePtr(0),
402 qPriEquPriNodePtr(0),
440 if (!
given(
"LAMBERTW"))
480 const std::vector<int> & extLIDVecRef)
485 #ifdef Xyce_DEBUG_DEVICE
488 Xyce::dout() << std::endl << section_divider << std::endl;
489 Xyce::dout() <<
"In Instance::register LIDs\n\n";
490 Xyce::dout() <<
"name = " <<
getName() << std::endl;
491 Xyce::dout() <<
"number of internal variables: " <<
numIntVars << std::endl;
492 Xyce::dout() <<
"number of external variables: " <<
numExtVars << std::endl;
514 #ifdef Xyce_DEBUG_DEVICE
517 Xyce::dout() <<
"\nSolution and RHS variables:\n";
518 Xyce::dout() <<
"\nli_Pos = ";
519 Xyce::dout().width(4);
520 Xyce::dout() <<
li_Pos << std::endl;
522 Xyce::dout() <<
"\nli_Neg = ";
523 Xyce::dout().width(4);
524 Xyce::dout() <<
li_Neg << std::endl;
526 Xyce::dout() <<
"\nli_Pri = ";
527 Xyce::dout().width(4);
528 Xyce::dout() <<
li_Pri << std::endl;
535 #ifdef Xyce_DEBUG_DEVICE
538 Xyce::dout() <<
"\nEnd of Instance::register LIDs\n";
539 Xyce::dout() << section_divider << std::endl;
592 const std::vector<int> & stoLIDVecRef )
604 #ifdef Xyce_DEBUG_DEVICE
607 Xyce::dout() <<
"li_storevd = " <<
li_storevd;
624 if( storeNameMap.empty () )
627 if( loadLeadCurrent )
663 std::vector<int> map;
664 std::vector< std::vector<int> > map2;
699 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
754 double Cd_Jdxp = 0.0;
755 Cd_Jdxp = -(
Cd ) * Vd_diff;
806 double Gd_Jdxp = 0.0;
807 Gd_Jdxp = -(
Gd ) * Vd_diff;
919 bool bsuccess =
true;
968 double VteR = NR * Vt;
998 if ((*flagSolVectorPtr)[
li_Pos] == 0 ||
999 (*flagSolVectorPtr)[
li_Neg] == 0 ||
1000 (*flagSolVectorPtr)[
li_Pri] == 0)
1039 double Vdtmp = -( BV +
Vd );
1056 #ifdef Xyce_DEBUG_DEVICE
1059 Xyce::dout() << Xyce::section_divider << std::endl;
1060 Xyce::dout() <<
"Instance::updateIntermediateVars " <<
getName()<<std::endl;
1074 if (
Vd >= -3.0 * Vte)
1090 Vrs = (
Id +
Icd)*RS;
1095 if (
Vd >= -3.0 * Vte)
1118 if(
Vd >= -3.0 * Vte) IRfactor = 1.0;
1119 else IRfactor =
tIRF;
1122 if (
Vd >= -3.0 * Vte)
1124 double arg1 =
Vd / Vte;
1126 double evd = exp(arg1);
1130 #ifdef Xyce_DEBUG_DEVICE
1133 Xyce::dout() <<
"Normal exponential regime." << std::endl;
1134 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1135 Xyce::dout() <<
" Vte = " << Vte << std::endl;
1136 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1137 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1146 double arg = 3.0 * Vte / (
Vd *
CONSTe);
1147 arg = arg * arg * arg;
1150 #ifdef Xyce_DEBUG_DEVICE
1153 Xyce::dout() <<
"Linear reverse bias regime." << std::endl;
1154 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1155 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1156 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1157 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1167 double evrev = exp(arg1);
1169 #ifdef Xyce_BREAKDOWN_ORIGINAL
1176 arg2=arg2*arg2*arg2;
1177 double Isat_tBrkdwnV=Isat*(1-arg2);
1182 #ifdef Xyce_DEBUG_DEVICE
1185 Xyce::dout() <<
"Reverse breakdown regime." << std::endl;
1186 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1187 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1188 Xyce::dout() <<
" Id = " << Id << std::endl;
1189 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1199 #ifdef Xyce_DEBUG_DEVICE
1202 Xyce::dout() <<
" Level 2 diode code " << std::endl;
1208 if(
Vd >= -3.0*Vte) IRfactor=1.0;
1209 else IRfactor =
tIRF;
1212 if (
Vd >= -3.0 * Vte)
1214 double arg1 =
Vd / Vte;
1216 double evd = exp(arg1);
1223 Irec = IsatR * (evd - 1.0);
1224 Gd2 = IsatR*evd/VteR;
1231 DKhi = 0.5*Khi*Gd1/(
tIKF+Inorm);
1241 Id = Inorm*Khi + Irec*Kgen;
1242 Gd = Gd1*Khi + Inorm*DKhi + Gd2*Kgen + Irec*DKgen;
1243 #ifdef Xyce_DEBUG_DEVICE
1246 Xyce::dout() <<
"L2 Normal exponential regime." << std::endl;
1247 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1248 Xyce::dout() <<
" Vte = " << Vte << std::endl;
1249 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1250 Xyce::dout() <<
" Irec= " << Irec << std::endl;
1251 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1252 Xyce::dout() <<
" Gd1 = " << Gd1 << std::endl;
1253 Xyce::dout() <<
" Gd2 = " << Gd2 << std::endl;
1254 Xyce::dout() <<
" Khi = " << Khi << std::endl;
1255 Xyce::dout() <<
" Kgen=" << Kgen << std::endl;
1256 Xyce::dout() <<
"DKgen=" <<DKgen << std::endl;
1264 double arg = 3.0 * Vte / (
Vd *
CONSTe);
1265 arg = arg * arg * arg;
1268 #ifdef Xyce_DEBUG_DEVICE
1271 Xyce::dout() <<
"L2 Linear reverse bias regime." << std::endl;
1272 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1273 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1274 Xyce::dout() <<
" Id = " <<
Id << std::endl;
1275 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1285 double evrev = exp(arg1);
1287 #ifdef Xyce_BREAKDOWN_ORIGINAL
1294 arg2=arg2*arg2*arg2;
1295 double Isat_tBrkdwnV=Isat*(1-arg2);
1299 #ifdef Xyce_DEBUG_DEVICE
1302 Xyce::dout() <<
"L2 Reverse breakdown regime." << std::endl;
1303 Xyce::dout() <<
" Vd = " <<
Vd << std::endl;
1304 Xyce::dout() <<
" tBrkdwnV = " <<
tBrkdwnV << std::endl;
1305 Xyce::dout() <<
" Id = " << Id << std::endl;
1306 Xyce::dout() <<
" Gd = " <<
Gd << std::endl;
1324 double arg1 = -M * log(arg);
1326 double sarg = exp(arg1);
1329 Qd = TT *
Id +
tJctPot * Czero * (1.0 - arg * sarg) / (1.0 - M);
1330 Cd = TT *
Gd + Czero * sarg;
1334 double Czof2 = Czero / F2;
1335 double MotJctPot = M /
tJctPot;
1339 Czof2 * (F3 * (
Vc -
tDepCap) + (0.5 * MotJctPot) *
1342 Cd = TT *
Gd + Czof2 * (F3 + MotJctPot *
Vc);
1344 #ifdef Xyce_DEBUG_DEVICE
1347 Xyce::dout() <<
"Qd = " <<
Qd << std::endl;
1348 Xyce::dout() <<
"Cd = " <<
Qd << std::endl;
1358 #ifdef Xyce_DEBUG_DEVICE
1361 Xyce::dout() << Xyce::section_divider << std::endl;
1381 double xfc = log( 1.0 -
model_.
FC );
1383 if( temp != -999.0 )
Temp = temp;
1391 double pbfact = -2.0*vt*(1.5*log(fact2)+
CONSTQ*arg);
1397 double pbfact1 = -2.0*vtnom*(1.5*log(fact1)+
CONSTQ*arg1);
1399 double pbo = (
model_.
VJ-pbfact1)/fact1;
1400 double gmaold = (
model_.
VJ-pbo)/pbo;
1407 double gmanew = (
tJctPot-pbo)/pbo;
1436 tempBV =
model_.
BV*(1 + (Temp-TNOM)*
1455 #ifdef Xyce_BREAKDOWN_ORIGINAL
1473 double reltol = 1.0e-3;
1476 double IRfactor =
tIRF;
1479 if( cbv < IRfactor*tSatCur*tempBV/vt )
1481 cbv = IRfactor*tSatCur*tempBV/vt;
1486 double tol = reltol*cbv;
1487 xbv = tempBV-vt*log(1.0+cbv/(IRfactor*tSatCur));
1488 for(
int i = 0; i < 25; ++i )
1490 xbv = tempBV-vt*log(cbv/(IRfactor*tSatCur)+1.0-xbv/vt);
1491 xcbv = IRfactor*tSatCur*(exp((tempBV-xbv)/vt)-1.0+xbv/vt);
1492 if(fabs(xcbv-cbv)<=tol)
break;
1500 double IRFactor=
tIRF;
1506 const int ITER_COUNT_MAX=8;
1509 double arg1=3.0*vte/(
CONSTe*tempBV);
1510 arg1=arg1*arg1*arg1;
1511 cthreshlow=tSatCur*IRFactor*(1-arg1);
1513 exp(-1.0*(3.0*vte-tempBV)/vte);
1515 if(cbv >= cthreshhigh)
1521 else if(cbv <= cthreshlow)
1534 for(iter_count=0; iter_count < ITER_COUNT_MAX; iter_count++)
1536 arg2=3.0*vte/(
CONSTe*xbv);
1537 arg2=arg2*arg2*arg2;
1538 xbv=tempBV-vte*log(cbv/(tSatCur*IRFactor))+vte *
1556 #ifdef Xyce_DEBUG_DEVICE
1559 Xyce::dout() << Xyce::section_divider << std::endl;
1560 Xyce::dout() <<
"Instance::UpdateTemperature" <<
getName() <<std::endl;
1561 Xyce::dout() <<
" IS = " <<
model_.
IS << std::endl;
1562 Xyce::dout() <<
" vtnom = " << vtnom << std::endl;
1563 Xyce::dout() <<
" xfc = " << xfc << std::endl;
1564 Xyce::dout() <<
" TNOM = " << TNOM << std::endl;
1565 Xyce::dout() <<
" vt = " << vt << std::endl;
1566 Xyce::dout() <<
" fact2 = " << fact2 << std::endl;
1567 Xyce::dout() <<
" egfet = " << egfet << std::endl;
1568 Xyce::dout() <<
" arg = " << arg << std::endl;
1569 Xyce::dout() <<
" pbfact = " << pbfact << std::endl;
1570 Xyce::dout() <<
" egfet1 = " << egfet1 << std::endl;
1571 Xyce::dout() <<
" arg1 = " << arg1 << std::endl;
1572 Xyce::dout() <<
" fact1 = " << fact1 << std::endl;
1573 Xyce::dout() <<
" pbfact1 = " << pbfact1 << std::endl;
1574 Xyce::dout() <<
" pbo = " << pbo << std::endl;
1575 Xyce::dout() <<
" gmaold = " << gmaold << std::endl;
1576 Xyce::dout() <<
" gmanew = " << gmanew << std::endl;
1577 Xyce::dout() <<
" tJctCap = " <<
tJctCap << std::endl;
1578 Xyce::dout() <<
" tJctPot = " <<
tJctPot << std::endl;
1579 Xyce::dout() <<
" tSatCur = " << tSatCur << std::endl;
1580 Xyce::dout() <<
" tF1 = " <<
tF1 << std::endl;
1581 Xyce::dout() <<
" tDepCap = " <<
tDepCap << std::endl;
1582 Xyce::dout() <<
" vte = " << vte << std::endl;
1583 Xyce::dout() <<
" tempBV = " << tempBV << std::endl;
1584 Xyce::dout() <<
" tVcrit = " <<
tVcrit << std::endl;
1585 Xyce::dout() <<
" tRS = " <<
tRS << std::endl;
1586 Xyce::dout() <<
" tCOND = " <<
tCOND << std::endl;
1587 Xyce::dout() <<
" tIRF = " <<
tIRF << std::endl;
1588 Xyce::dout() <<
" tBrkdwnV= " <<
tBrkdwnV << std::endl;
1657 double arg1 = (
Vd + Isat*RS)/Vte;
1659 double evd = exp(arg1);
1660 double lambWArg = Isat*RS*evd/Vte;
1666 Id = -Isat+Vte*(lambWReturn)/RS;
1667 Gd = lambWReturn / ((1 + lambWReturn)*RS);
1686 double FF2 = (1/2 - FF1)*(-2);
1687 double arg = Vte/RS;
1688 double arg1 = (Isat/arg - 3);
1689 double arg2 = FF1*arg1;
1691 double evd = exp(arg2);
1692 double lambWArg = Isat*evd/arg;
1698 #ifdef Xyce_DEBUG_DEVICE
1702 Xyce::dout() <<
"Safe LambertW return" << std::endl;
1704 Xyce::dout() <<
"LambertW argument not in domain" << std::endl;
1706 Xyce::dout() <<
"Arithmetic problems with LambertW" << std::endl;
1710 Id = -Isat*FF1 + FF2*lambWReturn*arg;
1712 double GdFF1 = 1/(-3.0*Vte +
tBrkdwnV);
1713 double GdFF2 = 2 * GdFF1;
1714 double GdW = arg*lambWReturn*GdFF1*arg1/(1 + lambWReturn);
1715 Gd = -Isat*GdFF1 + GdFF2*arg*lambWReturn + FF2*GdW;
1717 #ifdef Xyce_DEBUG_DEVICE
1720 Xyce::dout() <<
"lambWArg = " << lambWArg << std::endl;
1721 Xyce::dout() <<
"lambWError = " << lambWError << std::endl;
1722 Xyce::dout() <<
"lambWReturn= " << lambWReturn << std::endl;
1723 Xyce::dout() <<
"Id = " <<
Id << std::endl;
1724 Xyce::dout() <<
"Gd = " <<
Gd << std::endl;
1725 Xyce::dout() <<
"Using lambertwReverseBias" << std::endl;
1793 double evd = exp(arg1);
1794 double lambWArg = Isat*RS*evd/Vte;
1800 Id = -Vte*lambWReturn/RS;
1801 Gd = lambWReturn / ((1 + lambWReturn)*RS);
1819 if(
M > 0.9 )
M = 0.9;
1822 if(
EG < 0.1 )
EG = 0.1;
1825 if(
FC > 0.95 )
FC = 0.95;
1832 double xfc = log(1.0-
FC);
1833 F2 = exp((1.0+
M)*xfc);
1834 F3 = 1.0-
FC*(1.0+
M);
1850 std::vector<Instance*>::iterator iter;
1854 for (iter=first; iter!=last; ++iter)
1856 (*iter)->processParams();
1874 :
DeviceModel(MB, configuration.getModelParameters(), factory_block),
1926 std::string bad_parameters;
1929 bad_parameters +=
" ISR";
1931 bad_parameters +=
" NR";
1933 bad_parameters +=
" IKF";
1935 bad_parameters +=
" NBV";
1937 bad_parameters +=
" IBVL";
1939 bad_parameters +=
" NBVL";
1941 bad_parameters +=
" TIKF";
1943 bad_parameters +=
" TBV1";
1945 bad_parameters +=
" TBV2";
1947 bad_parameters +=
" TRS1";
1949 bad_parameters +=
" TRS2";
1950 if (!bad_parameters.empty())
1952 UserError0(*
this) <<
"Illegal parameter(s) given for level 1 diode:" << bad_parameters;
1970 std::vector<Instance*>::iterator iterI;
1975 for (iterI = firstI; iterI != lastI; ++iterI)
1992 std::vector<Instance*>::const_iterator iter;
1998 os <<
" name model name Parameters" << std::endl;
1999 for (i=0, iter=first; iter!=last; ++iter, ++i)
2001 os <<
" " << i <<
": " << (*iter)->getName() <<
" ";
2005 os <<
"AREA = " << (*iter)->Area << std::endl;
2006 os <<
" IC = " << (*iter)->InitCond << std::endl;
2007 os <<
"TEMP = " << (*iter)->Temp << std::endl;
2008 os <<
" off = " << (*iter)->off << std::endl;
2034 for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
2053 bool bsuccess =
true;
2064 bsuccess = bsuccess && btmp;
2078 bool Master::loadDAEVectors (
double * solVec,
double * fVec,
double *qVec,
double * bVec,
double * storeLeadF,
double * storeLeadQ)
2098 double Cd_Jdxp = -( di.
Cd ) * Vd_diff;
2099 double Gd_Jdxp = -( di.
Gd ) * Vd_diff;
2103 dFdxdVp[di.
li_Neg] += Gd_Jdxp;
2104 dFdxdVp[di.
li_Pri] -= Gd_Jdxp;
2108 dQdxdVp[di.
li_Neg] += Cd_Jdxp;
2109 dQdxdVp[di.
li_Pri] -= Cd_Jdxp;
2138 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2182 .registerDevice(
"d", 1)
2183 .registerDevice(
"d", 2)
2184 .registerModelType(
"d", 1)
2185 .registerModelType(
"d", 2);
2203 template <
typename ScalarT>
2215 if( M > 0.9 ) M = 0.9;
2218 if( EG < 0.1 ) EG = 0.1;
2221 if( FC > 0.95 ) FC = 0.95;
2228 ScalarT xfc = log(1.0-FC);
2229 F2 = exp((1.0+M)*xfc);
2230 F3 = 1.0-FC*(1.0+M);
2243 template <
typename ScalarT>
2246 const double & temp,
2264 const ScalarT & TNOM,
2266 const ScalarT & CJO,
2271 const ScalarT & XTI,
2273 const ScalarT & COND,
2274 const ScalarT & IRF,
2276 const ScalarT & IKF,
2277 const ScalarT & TIKF,
2278 const ScalarT & ISR,
2279 const ScalarT & IBV,
2282 const bool & BVGiven,
2284 const ScalarT & TBV1,
2285 const ScalarT & TBV2,
2286 const ScalarT & TRS1,
2287 const ScalarT & TRS2,
2294 ScalarT KoverQ =
static_cast<ScalarT
>(
CONSTKoverQ);
2296 ScalarT Eg0 =
static_cast<ScalarT
>(
CONSTEg0);
2298 ScalarT betaEg =
static_cast<ScalarT
>(
CONSTbetaEg);
2299 ScalarT boltz =
static_cast<ScalarT
>(
CONSTboltz);
2300 ScalarT Q =
static_cast<ScalarT
>(
CONSTQ);
2301 ScalarT Eg300 =
static_cast<ScalarT
>(
CONSTEg300);
2302 ScalarT root2 =
static_cast<ScalarT
>(
CONSTroot2);
2303 ScalarT e =
static_cast<ScalarT
>(
CONSTe);
2305 ScalarT vtnom = KoverQ * TNOM;
2307 ScalarT xfc = log( 1.0 - FC );
2309 if( temp != -999.0 ) Temp = temp;
2312 ScalarT vt = KoverQ * Temp;
2313 ScalarT fact2 = Temp / REFTEMP;
2314 ScalarT egfet = Eg0 - (alphaEg*Temp*Temp)/(Temp+betaEg);
2315 ScalarT arg = -egfet/(2.0*boltz*Temp) +
2316 Eg300/(boltz*(REFTEMP+REFTEMP));
2317 ScalarT pbfact = -2.0*vt*(1.5*log(fact2)+Q*arg);
2318 ScalarT egfet1 = Eg0 - (alphaEg*TNOM*TNOM)/
2320 ScalarT arg1 = -egfet1/(2.0*boltz*TNOM) +
2321 Eg300/(2.0*boltz*REFTEMP);
2322 ScalarT fact1 = TNOM/REFTEMP;
2323 ScalarT pbfact1 = -2.0*vtnom*(1.5*log(fact1)+Q*arg1);
2325 ScalarT pbo = (VJ-pbfact1)/fact1;
2326 ScalarT gmaold = (VJ-pbo)/pbo;
2329 (1.0+M*(4.0e-4*(TNOM-REFTEMP) -gmaold));
2331 tJctPot = pbfact+fact2*pbo;
2333 ScalarT gmanew = (tJctPot-pbo)/pbo;
2335 tJctCap *= 1.0 + M*(4.0e-4*(Temp-REFTEMP)-gmanew);
2337 tSatCur = IS*exp(((Temp/TNOM)-1.0)*
2339 XTI/N*log(Temp/TNOM));
2341 tF1 = tJctPot*(1.0-exp((1.0-M)*xfc))/(1.0-M);
2343 tDepCap = FC*tJctPot;
2348 tVcrit = vte*log(vte/(root2*tSatCur));
2351 tIRF = IRF*pow(fact2,1.6);
2356 tSatCurR = ISR*exp((Temp/TNOM - 1.0)*
2358 XTI/NR*log(Temp/TNOM));
2360 tIKF = IKF*(1 + TIKF*(Temp-TNOM));
2362 tempBV = BV*(1 + (Temp-TNOM)*
2363 ( TBV1 + TBV2*(Temp-TNOM) ));
2365 tRS = RS*(1 + (Temp-TNOM)*
2366 ( TRS1 + TRS2*(Temp-TNOM) ));
2369 if(tRS != 0.0) tCOND = 1.0/tRS;
2371 tJctPot = (VJ - egfet1)*fact2 - 3*vt*log(fact2) + egfet;
2373 tJctCap = CJO/(1.0 +
2374 M*(4.0e-4*(Temp-TNOM) + (1-tJctPot/VJ)));
2381 #ifdef Xyce_BREAKDOWN_ORIGINAL
2399 double reltol = 1.0e-3;
2402 double IRfactor = tIRF;
2405 if( cbv < IRfactor*tSatCur*tempBV/vt )
2407 cbv = IRfactor*tSatCur*tempBV/vt;
2412 double tol = reltol*cbv;
2413 xbv = tempBV-vt*log(1.0+cbv/(IRfactor*tSatCur));
2414 for(
int i = 0; i < 25; ++i )
2416 xbv = tempBV-vt*log(cbv/(IRfactor*tSatCur)+1.0-xbv/vt);
2417 xcbv = IRfactor*tSatCur*(exp((tempBV-xbv)/vt)-1.0+xbv/vt);
2418 if(fabs(xcbv-cbv)<=tol)
break;
2426 ScalarT IRFactor=tIRF;
2430 ScalarT cthreshhigh;
2432 const int ITER_COUNT_MAX=8;
2435 ScalarT arg1=3.0*vte/(e*tempBV);
2436 arg1=arg1*arg1*arg1;
2437 cthreshlow=tSatCur*IRFactor*(1-arg1);
2438 cthreshhigh=tSatCur*IRFactor*(1-1.0/(e*e*e)) *
2439 exp(-1.0*(3.0*vte-tempBV)/vte);
2441 if(cbv >= cthreshhigh)
2447 else if(cbv <= cthreshlow)
2460 for(iter_count=0; iter_count < ITER_COUNT_MAX; iter_count++)
2462 arg2=3.0*vte/(e*xbv);
2463 arg2=arg2*arg2*arg2;
2464 xbv=tempBV-vte*log(cbv/(tSatCur*IRFactor))+vte *
2493 template <
typename ScalarT>
2498 const ScalarT & Vpp,
2503 const ScalarT & Temp,
2504 const ScalarT & tJctCap,
2505 const ScalarT & tJctPot,
2506 const ScalarT & tDepCap,
2507 const ScalarT & tF1,
2508 const ScalarT & tSatCur,
2509 const ScalarT & tSatCurR,
2510 const ScalarT & tVcrit,
2511 const ScalarT & tRS,
2512 const ScalarT & tCOND,
2513 const ScalarT & tIRF,
2514 const ScalarT & tIKF,
2515 const ScalarT & tBrkdwnV,
2518 const ScalarT & Area,
2519 const int & lambertWFlag,
2520 const double & gmin,
2546 bool bsuccess =
true;
2561 ScalarT Isat = tSatCur * Area;
2562 ScalarT IsatR = tSatCurR * Area;
2563 ScalarT KoverQ =
static_cast<ScalarT
>(
CONSTKoverQ);
2564 ScalarT Vt = KoverQ * Temp;
2565 ScalarT Vte = N * Vt;
2566 ScalarT VteR = NR * Vt;
2568 Gspr = tCOND * Area;
2577 if (lambertWFlag == 1)
2579 if (Vd >= -3.0 * Vte)
2581 lambertWCurrent(Isat, Vte, tRS);
2584 else if ( !tBrkdwnV || (Vd >= -tBrkdwnV) )
2586 lambertWLinearReverseBias(Isat, Vte, tRS);
2591 lambertWBreakdownCurrent(Isat, Vte, tRS);
2595 Vrs = (Id + Icd)*tRS;
2598 else if (lambertWFlag == 2)
2600 if (Vd >= -3.0 * Vte)
2602 lambertWCurrent(Isat, Vte, 1.0e-15);
2605 else if ( !tBrkdwnV || (Vd >= -tBrkdwnV) )
2607 lambertWLinearReverseBias(Isat, Vte, 1.0e-15);
2612 lambertWBreakdownCurrent(Isat, Vte, 1.0e-15);
2624 if(Vd >= -3.0 * Vte) IRfactor = 1.0;
2625 else IRfactor = tIRF;
2628 if (Vd >= -3.0 * Vte)
2630 ScalarT arg1 = Vd / Vte;
2632 ScalarT evd = exp(arg1);
2634 Id = Isat * (evd - 1.0) + gmin * Vd;
2635 Gd = Isat * evd / Vte + gmin;
2638 else if(!tBrkdwnV || (Vd >= -tBrkdwnV))
2640 ScalarT arg = 3.0 * Vte / (Vd *
CONSTe);
2641 arg = arg * arg * arg;
2642 Id = -Isat * (1.0 + arg) + gmin * Vd;
2643 Gd = Isat * 3.0 * arg / Vd + gmin;
2648 ScalarT arg1 = -(tBrkdwnV + Vd) / Vte;
2650 ScalarT evrev = exp(arg1);
2652 #ifdef Xyce_BREAKDOWN_ORIGINAL
2653 Id = -Isat * evrev + gmin * Vd;
2654 Gd = Isat * evrev / Vte + gmin;
2658 ScalarT arg2=3.0*Vte/(
CONSTe*tBrkdwnV);
2659 arg2=arg2*arg2*arg2;
2660 ScalarT Isat_tBrkdwnV=Isat*(1-arg2);
2661 Id = -Isat_tBrkdwnV * evrev + gmin * Vd;
2662 Gd = Isat_tBrkdwnV * evrev / Vte + gmin;
2673 if(Vd >= -3.0*Vte) IRfactor=1.0;
2674 else IRfactor = tIRF;
2677 if (Vd >= -3.0 * Vte)
2679 ScalarT arg1 = Vd / Vte;
2681 ScalarT evd = exp(arg1);
2682 Inorm = Isat * (evd - 1.0) + gmin * Vd;
2683 Gd1 = Isat*evd/Vte + gmin;
2688 Irec = IsatR * (evd - 1.0);
2689 Gd2 = IsatR*evd/VteR;
2695 Khi = sqrt(tIKF/(tIKF+Inorm));
2696 DKhi = 0.5*Khi*Gd1/(tIKF+Inorm);
2702 Kgen = sqrt( pow(((1-Vd/tJctPot)*(1-Vd/tJctPot) + 0.005),M) );
2703 DKgen = -M*(1-Vd/tJctPot)/(tJctPot*Kgen);
2706 Id = Inorm*Khi + Irec*Kgen;
2707 Gd = Gd1*Khi + Inorm*DKhi + Gd2*Kgen + Irec*DKgen;
2710 else if(!tBrkdwnV || (Vd >= -tBrkdwnV))
2712 ScalarT arg = 3.0 * Vte / (Vd *
CONSTe);
2713 arg = arg * arg * arg;
2714 Id = -Isat * (1.0 + arg) + gmin * Vd;
2715 Gd = Isat * 3.0 * arg / Vd + gmin;
2720 ScalarT arg1 = -(tBrkdwnV + Vd) / Vte;
2722 ScalarT evrev = exp(arg1);
2724 #ifdef Xyce_BREAKDOWN_ORIGINAL
2725 Id = -Isat * evrev + gmin * Vd;
2726 Gd = Isat * evrev / Vte + gmin;
2730 ScalarT arg2=3.0*Vte/(
CONSTe*tBrkdwnV);
2731 arg2=arg2*arg2*arg2;
2732 ScalarT Isat_tBrkdwnV=Isat*(1-arg2);
2733 Id = -Isat_tBrkdwnV * evrev + gmin * Vd;
2734 Gd = Isat_tBrkdwnV * evrev / Vte + gmin;
2745 ScalarT Czero = tJctCap * Area;
2749 ScalarT arg = 1.0 - Vc / tJctPot;
2750 ScalarT arg1 = -M * log(arg);
2752 ScalarT sarg = exp(arg1);
2755 Qd = TT * Id + tJctPot * Czero * (1.0 - arg * sarg) / (1.0 - M);
2756 Cd = TT * Gd + Czero * sarg;
2760 ScalarT Czof2 = Czero / F2;
2761 ScalarT MotJctPot = M / tJctPot;
2764 Qd = TT * Id + Czero * tF1 +
2765 Czof2 * (F3 * (Vc - tDepCap) + (0.5 * MotJctPot) *
2766 (Vc * Vc - tDepCap * tDepCap));
2768 Cd = TT * Gd + Czof2 * (F3 + MotJctPot * Vc);
2788 template <
typename ScalarT>
2795 const ScalarT & Vpp,
2799 const ScalarT & tVcrit,
2800 const ScalarT & Vte,
2808 const ScalarT & currVd_old,
2809 const ScalarT & nextVd_old,
2811 const double InitCond,
2812 const bool InitCondGiven,
2815 int & newtonIterOld,
2817 const bool dotICapplies,
2820 const int & newtonIter,
2821 const bool initJctFlag,
2822 const bool voltageLimiterFlag,
2823 const bool dcopFlag,
2824 const bool locaEnabledFlag
2834 if (newtonIter == 0)
2837 if (initJctFlag && voltageLimiterFlag && !dotICapplies)
2860 if (!(dcopFlag)|| (locaEnabledFlag && dcopFlag))
2862 Vd_old = currVd_old;
2867 Vd_old = nextVd_old;
2872 if (voltageLimiterFlag)
2876 if (newtonIter >= 0)
2879 if (BVGiven && (Vd <
Xycemin(0.0, -BV + 10.0 * Vte)))
2881 double Vdtmp = -( BV + Vd );
2882 Vdtmp = devSupport.
pnjlim(Vdtmp, -(Vd_old+BV), Vte, tVcrit, &ichk);
2886 Vd = devSupport.
pnjlim(Vd, Vd_old, Vte, tVcrit, &ichk);
2888 if (ichk) origFlag =
false;
2893 if (newtonIter != 0 && newtonIter != newtonIterOld)
2895 newtonIterOld = newtonIter;
2909 const std::string &name,
2910 std::vector<double> & dfdp,
2911 std::vector<double> & dqdp,
2912 std::vector<double> & dbdp,
2913 std::vector<int> & Findices,
2914 std::vector<int> & Qindices,
2915 std::vector<int> & Bindices
2919 const Model & mod = *(
dynamic_cast<const Model *
> (e1));
2923 dfdp.resize(3*sizeInstance);
2924 dqdp.resize(3*sizeInstance);
2925 Findices.resize(3*sizeInstance);
2926 Qindices.resize(3*sizeInstance);
2961 std::string paramName = ExtendedString( name ).toUpper();
2963 if (paramName==
"VJ") { VJ.diff(0,1); }
2964 else if (paramName==
"CJO") { CJO.diff(0,1); }
2965 else if (paramName==
"CJ") { CJO.diff(0,1); }
2966 else if (paramName==
"CJ0") { CJO.diff(0,1); }
2967 else if (paramName==
"M") { M.diff(0,1); }
2968 else if (paramName==
"N") { N.diff(0,1); }
2969 else if (paramName==
"IS") { IS.diff(0,1); }
2970 else if (paramName==
"JS") { IS.diff(0,1); }
2971 else if (paramName==
"EG") { EG.diff(0,1); }
2972 else if (paramName==
"XTI") { XTI.diff(0,1); }
2973 else if (paramName==
"RS") { RS.diff(0,1); }
2974 else if (paramName==
"COND") { COND.diff(0,1); }
2975 else if (paramName==
"IRF") { IRF.diff(0,1); }
2976 else if (paramName==
"NR") { NR.diff(0,1); }
2977 else if (paramName==
"IKF") { IKF.diff(0,1); }
2978 else if (paramName==
"TIKF") { TIKF.diff(0,1); }
2979 else if (paramName==
"ISR") { ISR.diff(0,1); }
2980 else if (paramName==
"IBV") { IBV.diff(0,1); }
2981 else if (paramName==
"IBVL") { IBVL.diff(0,1); }
2982 else if (paramName==
"NBV") { NBV.diff(0,1); }
2983 else if (paramName==
"NBVL") { NBVL.diff(0,1); }
2984 else if (paramName==
"BV") { BV.diff(0,1); }
2985 else if (paramName==
"VB") { BV.diff(0,1); }
2986 else if (paramName==
"TT") { TT.diff(0,1); }
2987 else if (paramName==
"FC") { FC.diff(0,1); }
2988 else if (paramName==
"KF") { KF.diff(0,1); }
2989 else if (paramName==
"AF") { AF.diff(0,1); }
2990 else if (paramName==
"TNOM") { TNOM.diff(0,1); }
2992 else if (paramName==
"TBV1") { TBV1.diff(0,1); }
2993 else if (paramName==
"TBV2") { TBV2.diff(0,1); }
2994 else if (paramName==
"TRS1") { TRS1.diff(0,1); }
2995 else if (paramName==
"TRS2") { TRS2.diff(0,1); }
3001 for (std::vector<Instance *>::const_iterator in = mod.
instanceContainer.begin();
3004 double * solVec = (*in)->extData.nextSolVectorRawPtr;
3006 fadType Vpp = solVec[(*in)->li_Pri];
3007 fadType Vn = solVec[(*in)->li_Neg];
3008 fadType Vp = solVec[(*in)->li_Pos];
3031 Temp, tJctCap, tJctPot, tDepCap, tF1, tSatCur, tSatCurR,
3032 tVcrit, tRS, tCOND, tIRF, tIKF, tBrkdwnV,
3033 TNOM, VJ, CJO, M, N, IS, EG, XTI, RS, COND, IRF,
3034 NR, IKF, TIKF, ISR, IBV, BV,
3036 TBV1, TBV2, TRS1, TRS2, FC,
3050 Temp, tJctCap, tJctPot, tDepCap, tF1,
3051 tSatCur, tSatCurR, tVcrit, tRS, tCOND,
3052 tIRF, tIKF, tBrkdwnV,
3054 Area, (*in)->lambertWFlag, (*in)->getDeviceOptions().gmin,
3056 M, BV, IBV, NBV, IBVL, NBVL, N, NR, TT, F2, F3,
3059 Id, Gd, Qd, Cd, Gspr
3066 fadType Ir = Gspr * (Vp - Vpp);
3067 dfdp[iPos] -= -Ir.dx(0);
3068 dfdp[iNeg] -= Id.dx(0);
3069 dfdp[iPri] -= (-Id.dx(0) + Ir.dx(0));
3072 dqdp[iNeg] -= Qd.dx(0);
3073 dqdp[iPri] -= -Qd.dx(0);
3075 Findices[iPos] = (*in)->li_Pos;
3076 Findices[iNeg] = (*in)->li_Neg;
3077 Findices[iPri] = (*in)->li_Pri;
3079 Qindices[iPos] = (*in)->li_Pos;
3080 Qindices[iNeg] = (*in)->li_Neg;
3081 Qindices[iPri] = (*in)->li_Pri;