1 /* $Id: d_mos2.model,v 26.133 2009/11/26 04:58:04 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 *------------------------------------------------------------------
22 * mos model equations: spice level 2 equivalent
29 #include "l_denoise.h"
31 /*--------------------------------------------------------------------------*/
38 dev_type BUILT_IN_MOS;
39 inherit BUILT_IN_MOS123;
42 double mjsw "" default=.33;
43 double tox "" default=1e-7;
44 double cox "" final_default="P_EPS_OX/tox";
45 double vto "" final_default=0.0;
46 double gamma "" final_default=0.0;
47 double phi "" final_default=0.6;
48 int mos_level "back-annotate for diode" name=DIODElevel
49 print_test="mos_level != LEVEL" default=LEVEL;
52 double kp "transconductance parameter"
53 name=KP final_default=2e-5
54 print_test="!calc_kp" calc_print_test="calc_kp";
55 double nfs_cm "fast surface state density"
57 double vmax "max drift velocity of carriers"
59 double neff "total channel charge coefficient"
60 name=NEFf default=1.0 positive
61 print_test="neff != 1.0 || lambda == NA";
62 double ucrit_cm "critical field mobility degradation"
63 name=UCRit default=1e4
64 print_test="ucrit_cm != 1e4 || uexp != NA";
65 double uexp "critical field exponent in mob.deg."
67 double utra "transverse field coefficient (not used)"
68 name=UTRa default=NA print_test=false;
69 double delta "width effect on threshold voltage"
70 name=DELta default=0.0;
72 calculated_parameters {
73 double nfs "" calculate="nfs_cm*ICM2M2";
74 double ucrit "" calculate="ucrit_cm*ICM2M";
75 bool calc_kp "" default=false;
76 double alpha "" calculate="((nsub != NA)
77 ? (2. * P_EPS_SI) / (P_Q * nsub)
79 double xd "coeffDepLayWidth" calculate="sqrt(alpha)";
80 double xwb "" calculate="((nsub != NA)
83 double vbp "" calculate="ucrit * P_EPS_SI / cox";
84 double cfsox "" calculate="P_Q * nfs / cox";
87 if (!has_good_value(tox)) {
97 phi = (2. * P_K_Q) * tnom_k * log(nsub/NI);
100 error(((!_sim->is_first_expand()) ? (bDEBUG) : (bWARNING)),
101 long_label() + ": calculated phi too small, using .1\n");
107 gamma = sqrt(2. * P_EPS_SI * P_Q * nsub) / cox;
111 double phi_ms = (tpg == gtMETAL)
112 ? polarity * (-.05 - (egap + polarity * phi) / 2.)
113 : -(tpg * egap + phi) / 2.;
114 double vfb = phi_ms - polarity * P_Q * nss / cox;
115 vto = vfb + phi + gamma * sqrt(phi);
122 calculated_parameters {
123 double relxj "" calculate="((m->xj != NA && m->xj > 0)
126 double eta_1 "" calculate="((cgate != 0)
127 ? M_PI_4 * P_EPS_SI * m->delta / cgate * l_eff
129 double eta "" calculate="eta_1 + 1.";
130 double eta_2 "" calculate="eta / 2.";
133 temperature_dependent {
134 calculated_parameters {
135 double vt "" calculate="temp * P_K_Q";
136 double phi "" calculate="m->phi*tempratio + (-2*vt*(1.5*log(tempratio)+P_Q*(arg)))";
137 double sqrt_phi "" calculate="sqrt(phi)";
138 double phi_sqrt_phi "" calculate="phi * sqrt_phi";
139 double beta "" calculate="(m->kp / tempratio4) * s->w_eff / s->l_eff";
140 double uo "" calculate="m->uo * tempratio4";
141 double vbi "" calculate="(fixzero(
142 (m->vto - m->gamma * sqrt(m->phi)
143 +.5*(m->egap-egap) + m->polarity* .5 * (phi-m->phi)), m->phi))";
146 double temp = d->_sim->_temp_c + P_CELSIUS0;
147 double tempratio = temp / m->tnom_k; // ratio
148 double tempratio4 = tempratio * sqrt(tempratio);
149 double kt = temp * P_K;
150 double egap = 1.16 - (7.02e-4*temp*temp) / (temp+1108.);
151 double arg = (m->egap*tempratio - egap) / (2*kt);
154 /*-----------------------------------------------------------------------*/
156 #define short_channel (m->xj != NOT_INPUT && m->xj > 0.)
157 #define do_subthreshold (m->nfs != 0.)
158 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
159 trace0(d->long_label().c_str());
160 trace3("", d->vds, d->vgs, d->vbs);
161 assert(m->tnom_k > 0);
162 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
163 d->reverse_if_needed();
164 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
165 double v_phi_s = t->phi - d->vbs;
166 double sarg, dsarg_dvbs, d2sdb2, sarg3;
169 sarg = sqrt(v_phi_s);
170 dsarg_dvbs = -.5 / sarg;
171 d2sdb2 = .5 * dsarg_dvbs / v_phi_s;
173 trace3("sb-ok", sarg, v_phi_s, dsarg_dvbs);
175 if (OPT::mosflags & 01000) {
176 sarg = t->sqrt_phi / (1. + .5 * d->vbs / t->phi);
177 dsarg_dvbs = -.5 * sarg * sarg / t->phi_sqrt_phi;
178 d2sdb2 = -dsarg_dvbs * sarg / t->phi_sqrt_phi;
180 trace3("***sb-reversed(01000)***", sarg, v_phi_s, dsarg_dvbs);
183 / (1. + .5 * d->vbs / t->phi
184 + .375 * d->vbs * d->vbs / (t->phi * t->phi));
185 dsarg_dvbs = (-.5 * sarg * sarg / t->phi_sqrt_phi)
186 * (1. + 1.5 * d->vbs / t->phi);
187 d2sdb2 = (-dsarg_dvbs * sarg / t->phi_sqrt_phi)
188 - (.75 * sarg / (t->phi_sqrt_phi * t->phi))
189 * (2. * d->vbs * dsarg_dvbs + sarg);
191 trace3("***sb-reversed(00000)***", sarg, v_phi_s, dsarg_dvbs);
195 sarg3 = sarg*sarg*sarg;
197 assert(dsarg_dvbs < 0.);
198 assert(up_order(-1/t->phi, d2sdb2, 1/t->phi));
199 trace2("", d2sdb2, sarg3);
201 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
202 double barg, dbarg_dvbs, d2bdb2;
204 double vbd = d->vbs - d->vds;
205 double v_phi_d = t->phi - vbd;
207 barg = sqrt(v_phi_d);
208 dbarg_dvbs = -.5 / barg;
209 d2bdb2 = .5 * dbarg_dvbs / v_phi_d;
211 trace4("db-ok", barg, v_phi_d, dbarg_dvbs, d2bdb2);
213 if (OPT::mosflags & 01000) {
214 barg = t->sqrt_phi / (1. + .5 * vbd / t->phi);
215 dbarg_dvbs = -.5 * barg * barg / t->phi_sqrt_phi;
216 d2bdb2 = -dbarg_dvbs * barg / t->phi_sqrt_phi;
218 trace4("***db-reversed(00000)***",barg, v_phi_d, dbarg_dvbs, d2bdb2);
221 / (1. + .5 * vbd / t->phi
222 + .375 * vbd * vbd / (t->phi * t->phi));
223 dbarg_dvbs = (-.5 * barg * barg / t->phi_sqrt_phi)
224 * (1. + 1.5 * vbd / t->phi);
225 d2bdb2 = (-dbarg_dvbs * barg / t->phi_sqrt_phi)
226 - (.75 * barg / (t->phi_sqrt_phi * t->phi))
227 * (2. * vbd * dbarg_dvbs + barg);
228 trace4("***db-reversed(00000)***",barg, v_phi_d, dbarg_dvbs, d2bdb2);
233 assert(dbarg_dvbs < 0.);
234 assert(up_order(-1/t->phi, d2bdb2, 1/t->phi));
236 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
237 double gamma_s, dgamma_s_dvds, dgamma_s_dvbs, dgddb2;
240 double argxd = 1. + 2. * barg * m->xd / m->xj;
242 double argd = sqrt(argxd);
243 trace2("", argxd, argd);
245 double alpha_d = s->relxj * (argd - 1.);
246 double dalpha_d_dvds = m->xd / (4. * s->l_eff * argd * barg);
247 double dalpha_d_dvbs = -dalpha_d_dvds;
248 trace3("", alpha_d, dalpha_d_dvds, dalpha_d_dvbs);
250 double argxs = 1. + 2. * sarg * m->xd / m->xj;
252 double args = sqrt(argxs);
253 trace2("", argxs, args);
255 double alpha_s = s->relxj * (args - 1.);
256 double dalpha_s_dvbs = -m->xd / (4. * s->l_eff * args * sarg);
257 trace2("", alpha_s, dalpha_s_dvbs);
259 gamma_s = m->gamma * (1. - alpha_s - alpha_d);
260 dgamma_s_dvds = -m->gamma * dalpha_d_dvds;
261 dgamma_s_dvbs = -m->gamma * (dalpha_d_dvbs + dalpha_s_dvbs);
263 double dasdb2=-m->xd*(d2sdb2+dsarg_dvbs*dsarg_dvbs*m->xd/(m->xj*argxs))
265 double daddb2=-m->xd*(d2bdb2+dbarg_dvbs*dbarg_dvbs*m->xd/(m->xj*argxd))
267 dgddb2 = -.5 * m->gamma * (dasdb2 + daddb2);
269 if (gamma_s <= 0. && m->gamma > 0.) {
271 error(bTRACE, d->long_label() + ": gamma is negative\n");
272 error(bTRACE, "+ gamma_s=%g, alpha_s=%g, alpha_d=%g\n",
273 gamma_s, alpha_s, alpha_d);
275 trace4("no short chan", gamma_s, dgamma_s_dvds, dgamma_s_dvds, dgddb2);
278 dgamma_s_dvds = dgamma_s_dvbs = 0.;
280 trace4("short channel", gamma_s, dgamma_s_dvds, dgamma_s_dvds, dgddb2);
283 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
284 /* von, subthreshold, cutoff, vgst */
285 double vc, vc_eta, dvon_dvbs;
286 double xn, vtxn, dxn_dvbs; /* subthreshold only */
288 double vbin = t->vbi + s->eta_1 * v_phi_s;
289 d->von = vbin + gamma_s * sarg;
290 dvon_dvbs = -s->eta_1 + dgamma_s_dvbs * sarg + gamma_s * dsarg_dvbs;
291 trace3("guess", vbin, d->von, dvon_dvbs);
293 if (do_subthreshold) {
294 double cdonco = -(gamma_s*dsarg_dvbs + dgamma_s_dvbs*sarg) + s->eta_1;
295 xn = 1. + m->cfsox + cdonco;
297 dxn_dvbs = 2. * dgamma_s_dvbs * dsarg_dvbs
298 + gamma_s * d2sdb2 + dgddb2 * sarg;
299 trace3("do_sub", xn, vtxn, dxn_dvbs);
302 dvon_dvbs += t->vt * dxn_dvbs;
303 d->vgst = d->vgs - d->von;
304 trace3("", d->von, dvon_dvbs, d->vgst);
306 d->subthreshold = (d->vgs < d->von);
309 xn = vtxn = dxn_dvbs = 0.;
310 d->vgst = d->vgs - d->von;
311 trace3("no_sub", xn, vtxn, dxn_dvbs);
312 trace3("", d->von, dvon_dvbs, d->vgst);
314 d->subthreshold = false;
315 d->cutoff = (d->vgs < d->von);
317 trace0("***** cut off *****");
319 d->gmf = d->gmr = 0.;
321 d->gmbf = d->gmbr = 0.;
325 double vgsx = (d->subthreshold) ? d->von : d->vgs;
327 vc_eta = vc / s->eta;
328 trace3("", vgsx, vc, vc_eta);
330 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
332 double ufact, duf_dvgs, duf_dvds, duf_dvbs, ueff;
334 if (m->uexp != NOT_INPUT && d->vgst > m->vbp) {
335 ufact = pow(m->vbp/d->vgst, m->uexp);
336 duf_dvgs = -ufact * m->uexp / d->vgst;
337 duf_dvds = 0.; /* wrong, but as per spice2 */
338 duf_dvbs = dvon_dvbs * ufact * m->uexp / d->vgst;
339 trace4("calc ufact", ufact, duf_dvgs, duf_dvds, duf_dvbs);
342 duf_dvgs = duf_dvds = duf_dvbs = 0.;
343 trace4("def ufact", ufact, duf_dvgs, duf_dvds, duf_dvbs);
345 ueff = t->uo * ufact; /* ???? */
346 trace2("", ufact, ueff);
348 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
349 /* vdsat according to Baum's Theory of scattering velocity saturation */
350 int use_vmax = m->vmax != NOT_INPUT;
352 double gammad = gamma_s / s->eta;
353 double v1 = vc_eta + v_phi_s;
355 double xv = m->vmax * s->l_eff / ueff;
356 double a1 = gammad * (4./3.);
357 double b1 = -2. * (v1+xv);
358 double c1 = -2. * gammad * xv; /* end of scope */
359 double d1 = 2.*v1*(v2+xv) - v2*v2 - (4./3.)*gammad*sarg3;
360 double a = -b1; /* xv, v1, v2, sarg3 */
361 double b = a1 * c1 - 4. * d1;
362 double C = -d1 * (a1*a1 - 4.*b1) - c1*c1;
363 double r = -a*a / 3. + b;
364 double r3 = r*r*r; /* r */
365 double S = 2. * a*a*a / 27. - a*b / 3. + C; /* b, c */
367 double p = s2 / 4. + r3 / 27.; /* r */
369 if (p < 0.) { /* p */
370 double ro = pow((-r3 / 27), (1./6.)); /* s2, r3 */
371 double fi = atan(-2. * sqrt(-p) / S);
372 y3 = 2. * ro * cos(fi/3.) - a / 3.;
375 double p3 = pow((fabs(-S/2.+p2)), (1./3.));
376 double p4 = pow((fabs(-S/2.-p2)), (1./3.)); /* s */
377 y3 = p3 + p4 - a / 3.; /* a */
383 if (a1*a1 / 4. - b1 + y3 < 0. && y3*y3 / 4. - d1 < 0.) {
386 "%s: internal error: a3,b4, a1=%g, b1=%g, y3=%g, d1=%g\n",
387 d->long_label().c_str(), a1, b1, y3, d1);
389 double a3 = sqrt(a1*a1 / 4. - b1 + y3);
390 double b3 = sqrt(y3*y3 / 4. - d1);
391 for (int i = 0; i < 4; i++) {
392 static const double sig1[4] = {1., -1., 1., -1.};
393 static const double sig2[4] = {1., 1., -1., -1.};
394 double a4 = a1 / 2. + sig1[i] * a3;
395 double b4 = y3 / 2. + sig2[i] * b3; /* y3 */
396 double delta4 = a4*a4 / 4. - b4;
398 double sd4 = sqrt(delta4);
399 x4[iknt++] = - a4 / 2. + sd4;
400 x4[iknt++] = - a4 / 2. - sd4; /* i */
407 for (int j = 0; j < iknt; j++) { /* iknt */
409 double poly4 = x4[j]*x4[j]*x4[j]*x4[j]/* ~= 0, used as check */
410 + a1 * x4[j]*x4[j]*x4[j] /* roundoff error not */
411 + b1 * x4[j]*x4[j] /* propagated, so ok */
413 + d1; /* a1, b1, c1, d1 */
414 if (fabs(poly4) <= 1e-6) {
416 if (root_count <= 1) { /* xvalid = min(x4[j]) */
419 if (x4[j] <= xvalid) {
420 xvalid=x4[j]; /* x4[], j */
427 if (root_count <= 0) { /* root_count */
428 error(bTRACE, d->long_label() + ": Baum's theory rejected\n");
431 trace1("use_vmax rejected", d->vdsat);
433 d->vdsat = xvalid*xvalid - v_phi_s;
434 trace1("use_vmax", d->vdsat);
438 trace1("!use_vmax", d->vdsat);
440 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
441 /* vdsat according to Grove-Frohman equation */
442 double dvdsat_dvgs = NOT_VALID;
443 double dvdsat_dvbs = NOT_VALID;
446 double argv = vc_eta + v_phi_s;
448 double gammad = gamma_s / s->eta;
449 double gammd2 = gammad * gammad;
450 double arg1 = sqrt(1. + 4. * argv / gammd2);
451 d->vdsat = vc_eta + gammd2 * (1.-arg1) / 2.;
452 dvdsat_dvgs = (1. - 1./arg1) / s->eta;
453 dvdsat_dvbs = (gammad * (1.-arg1) + 2.*argv / (gammad*arg1))
454 / s->eta * dgamma_s_dvbs
455 + 1./arg1 + s->eta_1 * dvdsat_dvgs;
456 trace3("!use_vmax,gamma>0,argv>0",d->vdsat,dvdsat_dvgs,dvdsat_dvbs);
460 dvdsat_dvgs = dvdsat_dvbs = 0.;
461 error(bTRACE, d->long_label() + ": argv is negative\n");
462 trace2("argv<0", argv, vc);
463 trace3("!use_vmax,gamma>0,argv<=0",d->vdsat,dvdsat_dvgs,dvdsat_dvbs);
469 trace3("!use_vmax, gamma<=0", d->vdsat, dvdsat_dvgs, dvdsat_dvbs);
472 /* dvdsat_dvgs, dvdsat_dvbs deferred */
473 trace3("use_vmax", d->vdsat, dvdsat_dvgs, dvdsat_dvbs);
475 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
478 "%s: calculated vdsat (%g) < 0. using vdsat = 0.\n",
479 d->long_label().c_str(), d->vdsat);
482 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
483 double bsarg, dbsarg_dvbs;
485 double vbdsat = d->vbs - d->vdsat;
487 double v_phi_ds = t->phi - vbdsat;
488 bsarg = sqrt(v_phi_ds);
489 dbsarg_dvbs = -.5 / bsarg;
490 trace3("vbdsat <= 0", vbdsat, bsarg, dbsarg_dvbs);
492 bsarg = t->sqrt_phi / (1. + .5 * vbdsat / t->phi);
493 dbsarg_dvbs = -.5 * bsarg * bsarg / t->phi_sqrt_phi;
495 trace3("vbdsat > 0", vbdsat, bsarg, dbsarg_dvbs);
498 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
499 /* local dvdsat_dvgs, dvdsat_dvbs maybe */
502 double bodys = bsarg*bsarg*bsarg - sarg3;
504 2. * gamma_s * (bsarg*bsarg*dbsarg_dvbs - sarg*sarg*dsarg_dvbs);
505 double argv = vc_eta - d->vdsat;
506 double vqchan = argv - gamma_s * bsarg;
507 double dqdsat = -1. + gamma_s * dbsarg_dvbs;
508 double vl = m->vmax * s->l_eff;
509 double dfunds = vl * dqdsat - ueff * vqchan;
510 double dfundg = (vl - ueff * d->vdsat) / s->eta;
511 double dfundb = -vl * (1. + dqdsat - s->eta_1 / s->eta)
512 + ueff * (gdbdvs - dgamma_s_dvbs * bodys / 1.5) / s->eta;
513 dvdsat_dvgs = -dfundg / dfunds;
514 dvdsat_dvbs = -dfundb / dfunds;
515 trace2("use_vmax", dvdsat_dvgs, dvdsat_dvbs);
517 /* dvdsat_dvgs, dvdsat_dvbs already set */
518 trace2("!use_vmax", dvdsat_dvgs, dvdsat_dvbs);
520 assert(dvdsat_dvgs != NOT_VALID);
521 assert(dvdsat_dvbs != NOT_VALID);
523 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
524 double dl_dvgs, dl_dvds, dl_dvbs, clfact;
527 if (m->lambda == NOT_INPUT) {
530 double xdv = m->xd / sqrt(m->neff);
531 double xlv = m->vmax * xdv / (2. * ueff);
532 double argv = d->vds - d->vdsat;
536 double xls = sqrt(xlv*xlv + argv);
537 double dl = (xls-xlv) * xdv;
538 /* lambda = dl / (s->l_eff * d->vds); */
539 clfact = (1. - dl / s->l_eff);
540 dldsat = xdv / (2. * xls * s->l_eff);
542 double argv = (d->vds - d->vdsat) / 4.;
543 double sargv = sqrt(1. + argv*argv);
544 if (argv + sargv >= 0.) {
545 double dl = m->xd * sqrt(argv + sargv);
546 /* lambda = dl / (s->l_eff * d->vds); */
547 clfact = (1. - dl / s->l_eff);
548 /* dldsat = lambda * d->vds / (8. * sargv); */
549 dldsat = dl / (s->l_eff * 8. * sargv);
556 "%s: internal error: vds(%g) < vdsat(%g)\n",
557 d->long_label().c_str(), d->vds, d->vdsat);
560 dl_dvgs = dvdsat_dvgs * dldsat;
562 dl_dvbs = dvdsat_dvbs * dldsat;
564 /* lambda = m->lambda; */
565 clfact = (1. - m->lambda * d->vds);
566 dl_dvgs = dl_dvbs = 0.;
567 dl_dvds = -m->lambda;
570 /* clfact = (1. - lambda * d->vds); */
571 if (clfact < m->xwb/s->l_eff) {
572 double leff = m->xwb / (2. - (clfact * s->l_eff / m->xwb));
573 double dfact = (leff * leff) / (m->xwb * m->xwb);
574 clfact = leff / s->l_eff;
579 }else{ /* vds <= 0. */
582 dl_dvgs = dl_dvds = dl_dvbs = 0.;
583 trace1("*** vds < 0 ***", d->vds);
585 trace4("", dl_dvgs, dl_dvds, dl_dvbs, clfact);
587 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
588 /* ids, gmf, gds, gmbf */
590 d->saturated = (d->vds > d->vdsat);
591 double vdsx = (d->saturated) ? d->vdsat : d->vds;
592 double bargx = (d->saturated) ? bsarg : barg;
593 double body = bargx*bargx*bargx - sarg3;
594 double expg = (d->subthreshold) ? exp(d->vgst / vtxn) : 1.;
595 trace4("", vdsx, bargx, body, expg);
597 trace3("", t->beta, ufact, clfact);
598 double beta = t->beta * ufact / clfact;
600 beta * ((vc - s->eta_2 * vdsx) * vdsx - (2./3.) * gamma_s * body);
601 trace4("", beta, vc, (s->eta*vdsx), (gamma_s*bargx));
602 double didvds = beta * (vc - s->eta * vdsx - gamma_s * bargx);
603 fixzero(&didvds, ids_on);
604 trace4("", beta, ids_on, didvds, d->saturated);
606 d->ids = ids_on * expg;
608 d->gmf = beta * vdsx;
609 d->gmf += ids_on * (duf_dvgs/ufact - dl_dvgs/clfact);
611 d->gmf += didvds * dvdsat_dvgs;
613 if (d->subthreshold) {
614 d->gmf = ids_on / vtxn;
616 d->gmf += didvds * dvdsat_dvgs;
621 d->gds = (d->saturated) ? 0.: didvds;
622 d->gds += ids_on * (duf_dvds/ufact - dl_dvds/clfact);
624 d->gds -= beta * (2./3.) * body * dgamma_s_dvds;
626 if (d->subthreshold) {
627 double dxndvd = dgamma_s_dvds * dsarg_dvbs;
628 double dodvds = dgamma_s_dvds * sarg + t->vt * dxndvd;
629 double gmw = d->ids * d->vgst / (vtxn * xn);
631 d->gds -= d->gmf * dodvds + gmw * dxndvd;
634 d->gmbf = beta * (s->eta_1 * vdsx - gamma_s * (sarg - bargx));
635 d->gmbf += ids_on * (duf_dvbs/ufact - dl_dvbs/clfact);
637 d->gmbf -= beta * (2./3.) * body * dgamma_s_dvbs;
640 d->gmbf += didvds * dvdsat_dvbs;
642 if (d->subthreshold) {
643 double gmw = d->ids * d->vgst / (vtxn * xn);
644 d->gmbf += beta * dvon_dvbs * vdsx;
646 d->gmbf -= d->gmf * dvon_dvbs + gmw * dxn_dvbs;
648 trace4("", d->ids, d->gmf, d->gds, d->gmbf);
654 d->gmf = d->gmbf = 0;
656 d->gmr = d->gmbr = 0.;
660 /*--------------------------------------------------------------------------*/
661 /*--------------------------------------------------------------------------*/