1/* $Id: d_mos7.model,v 26.132 2009/11/24 04:26:37 al Exp $ -*- C++ -*-
2 * Copyright (C) 2001 Albert Davis
3 * Author: Albert Davis <aldavis@gnu.org>
4 *
5 * This file is part of "Gnucap", the Gnu Circuit Analysis Package
6 *
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)
10 * any later version.
11 *
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.
16 *
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
20 * 02110-1301, USA.
21 *------------------------------------------------------------------
22 * Berkeley BSIM3v3.1 model
23 * Derived from Spice3f4,Copyright 1990 Regents of the University of California
24 * Author: 1991 JianHui Huang and Min-Chie Jeng.
25 * Recoded for Gnucap model compiler, Al Davis, 2000
26 */
27h_headers {
28#include "d_mos_base.h"
29}
30cc_headers {
31#include "l_compar.h"
32#include "l_denoise.h"
33}
34/*--------------------------------------------------------------------------*/
35/*
36  from diode
37      no fc???
38      double bulkJctPotential
39	"Source/drain junction built-in potential"
40	name=PB default=1.0;
41      double unitAreaJctCap
42	"Source/drain bottom junction capacitance per unit area"
43	name=CJ default=5.0E-4;
44      double bulkJctBotGradingCoeff
45	"Source/drain bottom junction capacitance grading coefficient"
46	name=MJ default=0.5;
47      double sidewallJctPotential
48	"Source/drain sw junction capacitance built in potential"
49	name=PBSW default=1.0;
50      double unitLengthSidewallJctCap
51	"Source/drain sw junction capacitance per unit periphery"
52	name=CJSW default=5.0E-10;
53      double bulkJctSideGradingCoeff
54	"Source/drain sw junction capacitance grading coefficient"
55	name=MJSW default=0.33;
56      double kf "Flicker noise coefficient"
57	name=KF default=0.0;
58      double af "Flicker noise exponent"
59	name=AF default=1.0;
60
61  from mos_base
62      no is???
63      double jctSatCurDensity
64	"Source/drain junction reverse saturation current density"
65	name=JS default=1.0E-4;
66      double sheetResistance "Source-drain sheet resistance"
67	name=RSH default=0.0;
68      no rd???
69      no rs???
70      no cbd???
71      no cbs???
72      double cgso "Gate-source overlap capacitance per width"
73        "CGSO default=NA;
74      double cgdo "Gate-drain overlap capacitance per width"
75	name=CGDO default=NA;
76      double cgbo "Gate-bulk overlap capacitance per length"
77	name=CGBO default=NA;
78 */
79model BUILT_IN_MOS7 {
80  level 7
81  public_keys {
82    nmos7 polarity=pN;
83    pmos7 polarity=pP;
84  }
85  dev_type BUILT_IN_MOS;
86  inherit BUILT_IN_MOS_BASE;
87  independent {
88    override {
89      double mjsw "" final_default=.33;
90      double pb "" final_default=1.0 quiet_min=0.1;
91      double pbsw "" final_default=pb quiet_min=0.1;
92      double cjo "" default=5.0E-4;
93      double cgdo "" final_default="(((dlc != NA) && (dlc > 0.0))
94	  ? dlc * cox - cgdl.nom()
95	  : 0.6 * xj.nom() * cox)";
96      double cgso "" final_default="(((dlc != NA) && (dlc > 0.0))
97	  ? dlc * cox - cgsl.nom()
98	  : 0.6 * xj.nom() * cox)";
99      double cgbo "" final_default="((dwc != NA)
100	  ? 2.0 * dwc  * cox
101	  : 2.0 * Wint * cox)";
102      /* assumes cg?? final_default is BEFORE d?c final_default */
103      int cmodel "CMODEL" print_test="cmodel!=1"
104	calculate="((!cmodel)?1:cmodel)";
105      bool needs_isub "" calculate="(alpha0.nom()!=0.)";
106      int mos_level "back-annotate for diode" name=DIODElevel
107	print_test="mos_level != LEVEL" default=LEVEL;
108    }
109    raw_parameters {
110      int capMod "Capacitance model selector (0, 1, 2, other?)"
111	name=CAPMOD default=2;
112      int nqsMod "Non-quasi-static model selector (0, !0)"
113	name=NQSMOD default=0;
114      int mobMod "Mobility model selector (1,2,3,other?)"
115	name=MOBMOD default=1;
116      int noiMod "Noise model selector (not used)"
117	name=NOIMOD default=1;
118      int paramChk "Model parameter checking selector (not used)"
119	name=PARAMCHK default=0;
120      int binUnit "Bin unit selector (1, !1)"
121	name=BINUNIT default=1;
122      double version "parameter for model version (not used)"
123	name=VERSION default=3.1;
124      double tox "Gate oxide thickness in meters"
125	name=TOX default=150.0e-10;
126
127      double xpart "Channel charge partitioning"
128	name=XPART default=0.0;
129
130      double jctSidewallSatCurDensity
131	"Sidewall junction reverse saturation current density"
132	name=JSW default=0.0;
133      double mjswg
134	"Source/drain (gate side) sw junction capacitance grading coefficient"
135	name=MJSWG default=NA final_default=mjsw;
136      double pbswg
137	"Source/drain (gate side) sw junction capacitance built in potential"
138	name=PBSWG default=NA final_default=pbsw quiet_min=0.1;
139      double unitLengthGateSidewallJctCap
140	"Source/drain (gate side) sidewall junction capacitance per unit width"
141	name=CJSWG default=NA final_default=cjsw;
142      double jctEmissionCoeff
143	"Source/drain junction emission coefficient"
144	name=NJ default=1.0;
145      double jctTempExponent
146	"Junction current temperature exponent"
147	name=XTI default=3.0;
148
149      double Lint "Length reduction parameter" name=LINT default=0.0;
150      double Ll   "Length reduction parameter" name=LL default=0.0;
151      double Lln  "Length reduction parameter" name=LLN default=1.0;
152      double Lw   "Length reduction parameter" name=LW default=0.0;
153      double Lwn  "Length reduction parameter" name=LWN default=1.0;
154      double Lwl  "Length reduction parameter" name=LWL default=0.0;
155
156      double Wint "Width reduction parameter" name=WINT default=0.0;
157      double Wl   "Width reduction parameter" name=WL default=0.0;
158      double Wln  "Width reduction parameter" name=WLN default=1.0;
159      double Ww   "Width reduction parameter" name=WW default=0.0;
160      double Wwn  "Width reduction parameter" name=WWN default=1.0;
161      double Wwl  "Width reduction parameter" name=WWL default=0.0;
162
163      double dwc "Delta W for C-V model"
164	name=DWC default=NA final_default=Wint;
165      double dlc "Delta L for C-V model"
166	name=DLC default=NA final_default=Lint;
167
168      double noia "Flicker noise parameter, oxide trap density A"
169	name=NOIA default=NA final_default="(polarity==pN) ? 1e20 : 9.9e18";
170      double noib "Flicker noise parameter, oxide trap density B"
171	name=NOIB default=NA final_default="(polarity==pN) ? 5e4 : 2.4e3";
172      double noic "Flicker noise parameter, oxide trap density C"
173	name=NOIC default=NA final_default="(polarity==pN) ?-1.4e-12 :1.4e-12";
174      double em "Flicker noise parameter V/m"
175	name=EM default=4.1e7;
176      double ef "Flicker noise frequency exponent"
177	name=EF default=1.0;
178    }
179    calculated_parameters {
180      double cox;
181      double factor1 "" calculate="sqrt(tox * P_EPS_SI / P_EPS_OX)";
182      double vt_at_tnom "" calculate="tnom_k * P_K_Q";
183      double ni "" calculate="(1.45e10 * (tnom_k / 300.15)
184	 * sqrt(tnom_k / 300.15)
185	 * exp(21.5565981 - egap / (2.0 * vt_at_tnom)))";
186    }
187    code_pre {
188      //tox = std::max(tox, 1e-20);
189      cox = 3.453133e-11 / tox;
190    }
191    code_post {
192      if (npeak.has_good_value() && npeak.nom() > 1.0e20) {
193	npeak.set_nom(npeak.nom() * 1.0e-6);
194      }
195      if (ngate.has_good_value() && ngate.nom() > 1.0e23) {
196	ngate.set_nom(ngate.nom() * 1.0e-6);
197      }
198    }
199  }
200  size_dependent {
201    raw_parameters {
202      double cdsc "Drain/Source and channel coupling capacitance Q/V/m^2"
203	name=CDSC default=2.4e-4;
204      double cdscb "Body-bias dependence of cdsc Q/V/m^2"
205	name=CDSCB default=0.0;
206      double cdscd "Drain-bias dependence of cdsc Q/V/m^2"
207	name=CDSCD default=0.0;
208      double cit "Interface state capacitance Q/V/m^2"
209	name=CIT default=0.0;
210      double nfactor "Subthreshold swing Coefficient"
211	name=NFACTOR default=1;
212      double xj "Junction depth in meters"
213	name=XJ default=.15e-6;
214      double vsat "Saturation velocity at tnom m/s"
215	name=VSAT default=8.0e4;
216      double at "Temperature coefficient of vsat m/s"
217	name=AT default=3.3e4;
218      double a0 "Non-uniform depletion width effect coefficient."
219	name=A0 default=1.0;
220      double ags "Gate bias  coefficient of Abulk."
221	name=AGS default=0.0;
222      double a1 "Non-saturation effect coefficient"
223	name=A1 default=0.0;
224      double a2 "Non-saturation effect coefficient"
225	name=A2 default=1.0;
226      double keta
227	"Body-bias coefficient of non-uniform depletion width effect. 1/v"
228	name=KETA default=-0.047;
229      double nsub "Substrate doping concentration 1/cm3"
230	name=NSUB default=6.0e16;
231      double npeak "Channel doping concentration 1/cm3"
232	name=NCH default=NA;
233      double ngate "Poly-gate doping concentration 1/cm3"
234	name=NGATE default=0.0;
235      double gamma1 "Vth body coefficient"
236	name=GAMMA1 default=NA;
237      double gamma2 "Vth body coefficient"
238	name=GAMMA2 default=NA;
239      double vbx "Vth transition body Voltage"
240	name=VBX default=NA;
241      double vbm "Maximum body voltage"
242	name=VBM default=-3.0;
243
244      double xt "Doping depth"
245	name=XT default=1.55e-7;
246      double k1 "Bulk effect coefficient 1"
247	name=K1 default=NA;
248      double kt1 "Temperature coefficient of Vth"
249	name=KT1 default=-0.11;
250      double kt1l "Temperature coefficient of Vth"
251	name=KT1L default=0.0;
252      double kt2 "Body-coefficient of kt1"
253	name=KT2 default=0.022;
254      double k2 "Bulk effect coefficient 2"
255	name=K2 default=NA;
256      double k3 "Narrow width effect coefficient"
257	name=K3 default=80.0;
258      double k3b "Body effect coefficient of k3"
259	name=K3B default=0.0;
260      double w0 "Narrow width effect parameter"
261	name=W0 default=2.5e-6;
262      double nlx "Lateral non-uniform doping effect"
263	name=NLX default=1.74e-7;
264      double dvt0 "Short channel effect coeff. 0"
265	name=DVT0 default=2.2;
266      double dvt1 "Short channel effect coeff. 1"
267	name=DVT1 default=0.53;
268      double dvt2 "Short channel effect coeff. 2 1/v"
269	name=DVT2 default=-0.032;
270      double dvt0w "Narrow Width coeff. 0"
271	name=DVT0W default=0.0;
272      double dvt1w "Narrow Width effect coeff. 1"
273	name=DVT1W default=5.3e6;
274      double dvt2w "Narrow Width effect coeff. 2"
275	name=DVT2W default=-0.032;
276      double drout "DIBL coefficient of output resistance"
277	name=DROUT default=0.56;
278      double dsub "DIBL coefficient in the subthreshold region"
279	name=DSUB default=NA final_default="drout";
280      double vth0 "Threshold voltage"
281	name=VTH0 default=NA final_default=NA;
282      double ua1 "Temperature coefficient of ua m/v"
283	name=UA1 default=4.31e-9;
284      double ua "Linear gate dependence of mobility m/v"
285	name=UA default=2.25e-9;
286      double ub1 "Temperature coefficient of ub (m/V)**2"
287	name=UB1 default=-7.61e-18;
288      double ub "Quadratic gate dependence of mobility (m/V)**2"
289	name=UB default=5.87e-19;
290      double uc1 "Temperature coefficient of uc"
291	name=UC1 default=NA
292	final_default="((m->mobMod==3) ? -0.056 : -0.056e-9)";
293      double uc "Body-bias dependence of mobility"
294	name=UC default=NA
295	final_default="((m->mobMod==3) ? -0.0465 : -0.0465e-9)";
296      double u0 "Low-field mobility at Tnom"
297	name=U0 default=NA
298	final_default="((m->polarity == pN) ? 0.067 : 0.025)";
299      double ute "Temperature coefficient of mobility"
300	name=UTE default=-1.5;
301      double voff "Threshold voltage offset"
302	name=VOFF default=-0.08;
303
304      double delta "Effective Vds parameter"
305	name=DELTA default=0.01;
306      double rdsw  "Source-drain resistance per width"
307	name=RDSW default=0.0;
308      double prwg "Gate-bias effect on parasitic resistance"
309	name=PRWG default=0.0;
310      double prwb "Body-effect on parasitic resistance"
311	name=PRWB default=0.0;
312      double prt "Temperature coefficient of parasitic resistance"
313	name=PRT default=0.0;
314      double eta0 "Subthreshold region DIBL coefficient"
315	name=ETA0 default=0.08;
316      double etab "Subthreshold region DIBL coefficient 1/v"
317	name=ETAB default=-0.07;
318      double pclm "Channel length modulation Coefficient"
319	name=PCLM default=1.3;
320      double pdibl1 "Drain-induced barrier lowering coefficient"
321	name=PDIBLC1 default=.39;
322      double pdibl2 "Drain-induced barrier lowering coefficient"
323	name=PDIBLC2 default=0.0086;
324      double pdiblb "Body-effect on drain-induced barrier lowering 1/v"
325	name=PDIBLCB default=0.0;
326      double pscbe1 "Substrate current body-effect coefficient"
327	name=PSCBE1 default=4.24e8;
328      double pscbe2 "Substrate current body-effect coefficient"
329	name=PSCBE2 default=1.0e-5;
330      double pvag "Gate dependence of output resistance parameter"
331	name=PVAG default=0.0;
332
333      double wr "Width dependence of rds"
334	name=WR default=1.0;
335      double dwg "Width reduction parameter"
336	name=DWG default=0.0;
337      double dwb "Width reduction parameter"
338	name=DWB default=0.0;
339      double b0 "Abulk narrow width parameter"
340	name=B0 default=0.0;
341      double b1 "Abulk narrow width parameter"
342	name=B1 default=0.0;
343
344      double alpha0 "substrate current model parameter"
345	name=ALPHA0 default=0.0;
346      double beta0 "substrate current model parameter"
347	name=BETA0 default=30.0;
348
349      /* CV model */
350      double elm "Non-quasi-static Elmore Constant Parameter"
351	name=ELM default=5.0;
352      double vfbcv "Flat Band Voltage parameter for capmod=0 only"
353	name=VFBCV default=-1.0;
354      double cgsl "New C-V model parameter"
355	name=CGSL default=0.0;
356      double cgdl "New C-V model parameter"
357	name=CGDL default=0.0;
358      double ckappa "New C-V model parameter"
359	name=CKAPPA default=0.6;
360      double cf "Fringe capacitance parameter"
361	name=CF default=NA
362	final_default="2.0 * P_EPS_OX / M_PI * log(1.0 + 0.4e-6 / m->tox)";
363      double clc "Vdsat parameter for C-V model"
364	name=CLC default=0.1e-6;
365      double cle "Vdsat parameter for C-V model"
366	name=CLE default=0.6;
367    }
368    calculated_parameters {
369      double dl;
370      double dlc;
371      double dw;
372      double dwc;
373
374      double leff; /* BUG:: why not reuse from super */
375      double weff;
376      double leffCV;
377      double weffCV;
378
379      double abulkCVfactor "" calculate="1.0 + pow((clc / leff), cle)";
380
381      double cgso "" calculate="(m->cgso + cf) * weffCV";
382      double cgdo "" calculate="(m->cgdo + cf) * weffCV";
383      double cgbo "" calculate="m->cgbo * leffCV";
384
385      double litl "" calculate="sqrt(3.0 * xj * m->tox)";
386    }
387    code_pre {
388      {
389	double T0 = pow(c->l_in, m->Lln);
390	double T1 = pow(c->w_in, m->Lwn);
391	double tmp1 = m->Ll / T0 + m->Lw / T1 + m->Lwl / (T0 * T1);
392	dl = m->Lint + tmp1;
393	dlc = m->dlc + tmp1;
394      }
395      {
396	double T2 = pow(c->l_in, m->Wln);
397	double T3 = pow(c->w_in, m->Wwn);
398	double tmp2 = m->Wl / T2 + m->Ww / T3 + m->Wwl / (T2 * T3);
399	dw = m->Wint + tmp2;
400	dwc = m->dwc + tmp2;
401      }
402
403      leff = c->l_in - 2.0 * dl;
404      weff = c->w_in - 2.0 * dw;
405      leffCV = c->l_in - 2.0 * dlc;
406      weffCV = c->w_in - 2.0 * dwc;
407      cgate = m->cox * w_eff * l_eff; /* BUG:: not adjusted values?? */
408      double L = leff;
409      double W = weff;
410      if (m->binUnit == 1) {
411	L /= MICRON2METER;
412	W /= MICRON2METER;
413      }
414    }
415    code_post {
416      if (u0 > 1.0) {
417	u0 /= 1.0e4;
418      }
419      if (m->npeak.nom() == NA) {
420	if (m->gamma1.nom() != NA) {
421	  double T0 = gamma1 * m->cox;
422	  npeak = 3.021E22 * T0 * T0;
423	}else{
424	  npeak = 1.7e17;
425	}
426      }
427      if (m->k1.nom() != NA && m->k2.nom() != NA) {
428	if (m->k1.nom() == NA) {
429	  k1 = 0.53;
430	}
431	if (m->k2.nom() == NA) {
432	  k2 = -0.0186;
433	}
434      }else{
435	vbm = -std::abs(vbm);
436	if (m->gamma1.nom() == NA) {
437	  gamma1 = 5.753e-12 * sqrt(npeak) / m->cox;
438	}
439	if (m->gamma2.nom() == NA) {
440	  gamma2 = 5.753e-12 * sqrt(nsub) / m->cox;
441	}
442      }
443    }
444  }
445  temperature_dependent {
446    calculated_parameters {
447      double temp;
448      double tempratio "" calculate="temp / m->tnom_k";
449      double tempratio_1 "" calculate="tempratio - 1";
450      double vtm "vtm" calculate="temp * P_K_Q";
451      double ua;
452      double ub;
453      double uc;
454      double u0temp;
455      double vsattemp;
456      double rds0;
457      double phi;
458      double sqrtPhi;
459      double phis3;
460      double Xdep0;
461      double vbi;
462      double cdep0;
463      double k1;
464      double k2;
465      double vbsc;
466      double vth0;
467      double vfb;
468      double theta0vb0;
469      double thetaRout;
470    }
471    code_pre {
472      temp = d->_sim->_temp_c + P_CELSIUS0;
473      double egap = 1.16 - 7.02e-4 * temp * temp / (temp + 1108.0);
474    }
475    code_post {
476      double jctTempSatCurDensity;
477      double jctSidewallTempSatCurDensity;
478      if (temp != m->tnom_k) {
479	double T0 = m->egap / m->vt_at_tnom - egap / vtm + m->jctTempExponent
480	  * log(temp / m->tnom_k);
481	double T1 = exp(T0 / m->jctEmissionCoeff);
482	jctTempSatCurDensity = m->js * T1;
483	jctSidewallTempSatCurDensity = m->jctSidewallSatCurDensity * T1;
484      }else{
485	jctTempSatCurDensity = m->js;
486	jctSidewallTempSatCurDensity = m->jctSidewallSatCurDensity;
487      }
488      if (jctTempSatCurDensity < 0.0) {
489	jctTempSatCurDensity = 0.0;
490      }
491      if (jctSidewallTempSatCurDensity < 0.0) {
492	jctSidewallTempSatCurDensity = 0.0;
493      }
494      {
495	double T0 = (tempratio - 1.0);
496	ua = s->ua + s->ua1 * T0;
497	ub = s->ub + s->ub1 * T0;
498	uc = s->uc + s->uc1 * T0;
499	u0temp = s->u0 * pow(tempratio, s->ute);
500	vsattemp = s->vsat - s->at * T0;
501	rds0 = (s->rdsw + s->prt * T0) / pow(s->weff * 1E6, s->wr);
502      }
503      phi = 2.0 * m->vt_at_tnom * log(s->npeak / m->ni);
504      sqrtPhi = sqrt(phi);
505      phis3 = sqrtPhi * phi;
506      Xdep0 = sqrt(2.0 * P_EPS_SI / (P_Q * s->npeak * 1.0e6)) * sqrtPhi;
507      vbi = m->vt_at_tnom * log(1.0e20 * s->npeak / (m->ni * m->ni));
508      cdep0 = sqrt(P_Q * P_EPS_SI * s->npeak * 1.0e6 / 2.0 / phi);
509
510      if (m->k1.nom() != NA && m->k2.nom() != NA) {
511	k2 = s->k2;
512	k1 = s->k1;
513      }else{
514	double vbx = (m->vbx.nom() == NA)
515	  ? -std::abs(phi - 7.7348e-4 * s->npeak * s->xt * s->xt)
516	  : -std::abs(s->vbx);
517	double T0 = s->gamma1 - s->gamma2;
518	double T1 = sqrt(phi - vbx) - sqrtPhi;
519	double T2 = sqrt(phi * (phi - s->vbm)) - phi;
520	k2 = T0 * T1 / (2.0 * T2 + s->vbm);
521	k1 = s->gamma2 - 2.0 * k2 * sqrt(phi - s->vbm);
522      }
523      if (k2 < 0.) {
524	double T0 = 0.5 * k1 / k2;
525	vbsc = to_range(-30.0, (0.9 * (phi - T0 * T0)), -3.0);
526      }else{
527	vbsc = -30.0;
528      }
529      vbsc = std::min(vbsc, s->vbm);
530      if (s->vth0 == NA) {
531	vfb = -1.0;
532	vth0 = m->polarity * (vfb + phi + k1 * sqrtPhi);
533      }else{
534	vth0 = s->vth0;
535	vfb = m->polarity * vth0 - phi - k1 * sqrtPhi;
536      }
537      trace3("", s->vth0, vth0, vfb);
538      {
539	double T1 = sqrt(P_EPS_SI / P_EPS_OX * m->tox * Xdep0);
540	double T0 = exp(-0.5 * s->dsub * s->leff / T1);
541	theta0vb0 = (T0 + 2.0 * T0 * T0);
542
543	T0 = exp(-0.5 * s->drout * s->leff / T1);
544	double T2 = (T0 + 2.0 * T0 * T0);
545	thetaRout = s->pdibl1 * T2 + s->pdibl2;
546      }
547    }
548  }
549  /*-----------------------------------------------------------------------*/
550  tr_eval {
551    trace3("", d->vds, d->vgs, d->vbs);
552    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
553    const double EXP_THRESHOLD = 34.0;
554    const double MIN_EXP = 1.713908431e-15;
555    const double MAX_EXP = 5.834617425e14;
556    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
557    d->reverse_if_needed();
558    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
559    double Vbseff, dVbseff_dVb;
560    {
561      double T0 = d->vbs - t->vbsc - 0.001;
562      double T1 = sqrt(T0 * T0 - 0.004 * t->vbsc);
563      trace3("", t->vbsc, T0, T1);
564      Vbseff = t->vbsc + 0.5 * (T0 + T1);
565      dVbseff_dVb = 0.5 * (1.0 + T0 / T1);
566      trace2("raw", Vbseff, dVbseff_dVb);
567
568      fixzero(&Vbseff, t->vbsc);
569      if (Vbseff < d->vbs) {	// From Spice, to fix numeric problems
570	untested();		// inadequately.  Above fixzero should do a
571	Vbseff = d->vbs;	// better job, but I left this in case.
572      }
573    }
574    trace2("fixed", Vbseff, dVbseff_dVb);
575    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
576    double Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb;
577    if (Vbseff > 0.0) {
578      untested();
579      d->sbfwd = true;
580      double T0 = t->phi / (t->phi + Vbseff);
581      Phis = t->phi * T0;
582      dPhis_dVb = -T0 * T0;
583      sqrtPhis = t->phis3 / (t->phi + 0.5 * Vbseff);
584      dsqrtPhis_dVb = -0.5 * sqrtPhis * sqrtPhis / t->phis3;
585      trace0("bs-fwd-bias");
586    }else{
587      d->sbfwd = false;
588      Phis = t->phi - Vbseff;
589      dPhis_dVb = -1.0;
590      sqrtPhis = sqrt(Phis);
591      dsqrtPhis_dVb = -0.5 / sqrtPhis;
592      trace0("bs-normal");
593    }
594    trace4("", Phis, dPhis_dVb, sqrtPhis, dsqrtPhis_dVb);
595    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
596    double Xdep = t->Xdep0 * sqrtPhis / t->sqrtPhi;
597    double dXdep_dVb = (t->Xdep0 / t->sqrtPhi) * dsqrtPhis_dVb;
598    trace2("", Xdep, dXdep_dVb);
599    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
600    double Theta0, dTheta0_dVb;
601    {
602      double lt1, dlt1_dVb;
603      {
604	double T3 = sqrt(Xdep);
605	double T0 = s->dvt2 * Vbseff;
606	double T1, T2;
607	if (T0 >= - 0.5) {
608	  T1 = 1.0 + T0;
609	  T2 = s->dvt2;
610	  trace4("", T0, T1, T2, T3);
611	}else{
612	  untested();
613	  /* Added to avoid any discontinuity problems caused by dvt2 */
614	  double T4 = 1.0 / (3.0 + 8.0 * T0);
615	  T1 = (1.0 + 3.0 * T0) * T4;
616	  T2 = s->dvt2 * T4 * T4;
617	  trace4("dvd2 fix", T0, T1, T2, T3);
618	}
619	lt1 = m->factor1 * T3 * T1;
620	dlt1_dVb = m->factor1 * (0.5 / T3 * T1 * dXdep_dVb + T3 * T2);
621      }
622      trace2("", lt1, dlt1_dVb);
623
624      double T0 = -0.5 * s->dvt1 * s->leff / lt1;
625      if (T0 > -EXP_THRESHOLD) {
626	double T1 = exp(T0);
627	Theta0 = T1 * (1.0 + 2.0 * T1);
628	double dT1_dVb = -T0 / lt1 * T1 * dlt1_dVb;
629	dTheta0_dVb = (1.0 + 4.0 * T1) * dT1_dVb;
630	trace2("T0 > -ET", Theta0, dTheta0_dVb);
631      }else{
632	double T1 = MIN_EXP;
633	Theta0 = T1 * (1.0 + 2.0 * T1);
634	dTheta0_dVb = 0.0;
635	trace2("T0 < -ET", Theta0, dTheta0_dVb);
636      }
637    }
638    trace2("", Theta0, dTheta0_dVb);
639    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
640    double dVth_dVb, dVth_dVd; // d->von
641    {
642      double V0 = t->vbi - t->phi;
643      double T2, dT2_dVb;
644      {
645	double ltw, dltw_dVb;
646	{
647	  double t3 = sqrt(Xdep);
648	  double t0 = s->dvt2w * Vbseff;
649	  double t1, t2;
650	  if (t0 >= - 0.5) {
651	    t1 = 1.0 + t0;
652	    t2 = s->dvt2w;
653	  }else{
654	    untested();
655	    /* Added to avoid any discontinuity problems caused by dvt2w */
656	    double t4 = 1.0 / (3.0 + 8.0 * t0);
657	    t1 = (1.0 + 3.0 * t0) * t4;
658	    t2 = s->dvt2w * t4 * t4;
659	  }
660	  trace4("", t0, t1, t2, t3);
661	  ltw = m->factor1 * t3 * t1;
662	  dltw_dVb = m->factor1 * (0.5 / t3 * t1 * dXdep_dVb + t3 * t2);
663	}
664	trace2("", ltw, dltw_dVb);
665	double T0 = -0.5 * s->dvt1w * s->weff * s->leff / ltw;
666	if (T0 > -EXP_THRESHOLD) {
667	  double T1 = exp(T0);
668	  T2 = T1 * (1.0 + 2.0 * T1);
669	  double dT1_dVb = -T0 / ltw * T1 * dltw_dVb;
670	  dT2_dVb = (1.0 + 4.0 * T1) * dT1_dVb;
671	}else{
672	  double T1 = MIN_EXP;
673	  T2 = T1 * (1.0 + 2.0 * T1);
674	  dT2_dVb = 0.0;
675	}
676	T0 = s->dvt0w * T2;
677	T2 = T0 * V0;
678	dT2_dVb = s->dvt0w * dT2_dVb * V0;
679      }
680      trace3("", V0, T2, dT2_dVb);
681      double T0 = sqrt(1.0 + s->nlx / s->leff);
682      double T1 = t->k1 * (T0 - 1.0) * t->sqrtPhi
683	+ (s->kt1 + s->kt1l / s->leff + s->kt2 * Vbseff) * t->tempratio_1;
684      double tmp2 = m->tox * t->phi / (s->weff + s->w0);
685
686      double T3 = s->eta0 + s->etab * Vbseff;
687      trace4("", T0, T1, tmp2, T3);
688      double T4;
689      if (T3 < 1.0e-4) {
690	untested();
691	/* avoid  discontinuity problems caused by etab */
692	double T9 = 1.0 / (3.0 - 2.0e4 * T3);
693	T3 = (2.0e-4 - T3) * T9;
694	T4 = T9 * T9;
695	trace3("", T9, T3, T4);
696      }else{
697	T4 = 1.0;
698	trace1("", T4);
699      }
700      double thetavth = s->dvt0 * Theta0;
701      double Delt_vth = thetavth * V0;
702      double dDelt_vth_dVb = s->dvt0 * dTheta0_dVb * V0;
703      trace4("", thetavth, t->theta0vb0, Delt_vth, dDelt_vth_dVb);
704      double dDIBL_Sft_dVd = T3 * t->theta0vb0;
705      double DIBL_Sft = dDIBL_Sft_dVd * d->vds;
706      trace2("", dDIBL_Sft_dVd, DIBL_Sft);
707
708      trace4("", t->vth0, t->k1, sqrtPhis, t->sqrtPhi);
709      trace4("", t->k2, Vbseff, Delt_vth, T2);
710      trace4("", s->k3, s->k3b, Vbseff, tmp2);
711      trace2("", T1, DIBL_Sft);
712      double Vth = m->polarity * t->vth0 + t->k1 * (sqrtPhis - t->sqrtPhi)
713	- t->k2 * Vbseff - Delt_vth - T2 + (s->k3 + s->k3b * Vbseff) * tmp2
714	+ T1 - DIBL_Sft;
715      d->von = Vth;
716
717      dVth_dVb = t->k1 * dsqrtPhis_dVb - t->k2 - dDelt_vth_dVb - dT2_dVb
718	+ s->k3b * tmp2 - s->etab * d->vds * t->theta0vb0 * T4
719	+ s->kt2 * t->tempratio_1;
720      dVth_dVd = -dDIBL_Sft_dVd;
721    }
722    trace3("", d->von, dVth_dVb, dVth_dVd);
723    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
724    /* Calculate n */
725    double n, dn_dVb, dn_dVd;
726    {
727      double tmp2 = s->nfactor * P_EPS_SI / Xdep;
728      double tmp3 = s->cdsc + s->cdscb * Vbseff + s->cdscd * d->vds;
729      double tmp4 = (tmp2 + tmp3 * Theta0 + s->cit) / m->cox;
730      trace3("", tmp2, tmp3, tmp4);
731      if (tmp4 >= -0.5) {
732	n = 1.0 + tmp4;
733	dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb
734		  + s->cdscb * Theta0) / m->cox;
735	dn_dVd = s->cdscd * Theta0 / m->cox;
736	trace3("n", n, dn_dVb, dn_dVd);
737      }else{
738	/* avoid  discontinuity problems caused by tmp4 */
739	double T0 = 1.0 / (3.0 + 8.0 * tmp4);
740	n = (1.0 + 3.0 * tmp4) * T0;
741	T0 *= T0;
742	dn_dVb = (-tmp2 / Xdep * dXdep_dVb + tmp3 * dTheta0_dVb
743		  + s->cdscb * Theta0) / m->cox * T0;
744	dn_dVd = s->cdscd * Theta0 / m->cox * T0;
745	trace3("n disc", n, dn_dVb, dn_dVd);
746      }
747    }
748    trace3("", n, dn_dVb, dn_dVd);
749    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
750    /* Poly Gate Si Depletion Effect */
751    double Vgs_eff, dVgs_eff_dVg;
752    {
753      double T0 = t->vfb + t->phi;
754      trace2("Poly", t->vfb, t->phi);
755      trace3("", s->ngate, d->vgs, T0);
756      if ((s->ngate > 1.e18) && (s->ngate < 1.e25) && (d->vgs > T0)) {
757	/* added to avoid the problem caused by ngate */
758	double T1 = 1.0e6 * P_Q * P_EPS_SI * s->ngate / (m->cox * m->cox);
759	double T4 = sqrt(1.0 + 2.0 * (d->vgs - T0) / T1);
760	double T2 = T1 * (T4 - 1.0);
761	double T3 = 0.5 * T2 * T2 / T1; /* T3 = Vpoly */
762	double T7 = 1.12 - T3 - 0.05;
763	double T6 = sqrt(T7 * T7 + 0.224);
764	double T5 = 1.12 - 0.5 * (T7 + T6);
765	Vgs_eff = d->vgs - T5;
766	dVgs_eff_dVg = 1.0 - (0.5 - 0.5 / T4) * (1.0 + T7 / T6);
767	trace2("><", Vgs_eff, dVgs_eff_dVg);
768      }else{
769	Vgs_eff = d->vgs;
770	dVgs_eff_dVg = 1.0;
771	trace2("const", Vgs_eff, dVgs_eff_dVg);
772      }
773    }
774    trace2("", Vgs_eff, dVgs_eff_dVg);
775    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
776    /* Effective Vgst (Vgsteff) Calculation */
777    double /*Vgsteff,*/ dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb, Vgst2Vtm;
778    double VgstNVt, ExpVgst; // d->vgst
779    {
780      double Vgst = Vgs_eff - d->von;
781      double T10 = 2.0 * n * t->vtm;
782      VgstNVt = Vgst / T10;
783      double ExpArg = (2.0 * s->voff - Vgst) / T10;
784      trace4("", Vgst, T10, VgstNVt, ExpArg);
785
786      /* MCJ: Very small Vgst */
787      if (VgstNVt > EXP_THRESHOLD) {
788	d->vgst = Vgst;
789	dVgsteff_dVg = dVgs_eff_dVg;
790	dVgsteff_dVd = -dVth_dVd;
791	dVgsteff_dVb = -dVth_dVb;
792	ExpVgst = NOT_VALID;
793	trace4(">>", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb);
794      }else if (ExpArg > EXP_THRESHOLD) {
795	double T0 = (Vgst - s->voff) / (n * t->vtm);
796	ExpVgst = exp(T0);
797	d->vgst = t->vtm * t->cdep0 / m->cox * ExpVgst;
798	dVgsteff_dVg = d->vgst / (n * t->vtm);
799	dVgsteff_dVd = -dVgsteff_dVg * (dVth_dVd + T0 * t->vtm * dn_dVd);
800	dVgsteff_dVb = -dVgsteff_dVg * (dVth_dVb + T0 * t->vtm * dn_dVb);
801	dVgsteff_dVg *= dVgs_eff_dVg;
802	trace4(">", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb);
803      }else{
804	ExpVgst = exp(VgstNVt);
805	double T1 = T10 * log(1.0 + ExpVgst);
806	double dT1_dVg = ExpVgst / (1.0 + ExpVgst);
807	double dT1_dVb = -dT1_dVg * (dVth_dVb + Vgst / n * dn_dVb)
808		      + T1 / n * dn_dVb;
809	double dT1_dVd = -dT1_dVg * (dVth_dVd + Vgst / n * dn_dVd)
810		      + T1 / n * dn_dVd;
811
812	double dT2_dVg = -m->cox / (t->vtm * t->cdep0)
813		      * exp(ExpArg);
814	double T2 = 1.0 - T10 * dT2_dVg;
815	double dT2_dVd = -dT2_dVg * (dVth_dVd - 2.0 * t->vtm * ExpArg * dn_dVd)
816		      + (T2 - 1.0) / n * dn_dVd;
817	double dT2_dVb = -dT2_dVg * (dVth_dVb - 2.0 * t->vtm * ExpArg * dn_dVb)
818		      + (T2 - 1.0) / n * dn_dVb;
819
820	d->vgst = T1 / T2;
821	double T3 = T2 * T2;
822	dVgsteff_dVg = (T2 * dT1_dVg - T1 * dT2_dVg) / T3 * dVgs_eff_dVg;
823	dVgsteff_dVd = (T2 * dT1_dVd - T1 * dT2_dVd) / T3;
824	dVgsteff_dVb = (T2 * dT1_dVb - T1 * dT2_dVb) / T3;
825	trace4("<", d->vgst, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb);
826      }
827      Vgst2Vtm = d->vgst + 2.0 * t->vtm;
828      trace3("", d->vgst, t->vtm, Vgst2Vtm);
829    }
830    trace1("", d->vgst);
831    trace4("", dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb, Vgst2Vtm);
832    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
833    /* Calculate Effective Channel Geometry */
834    double Weff, dWeff_dVg, dWeff_dVb;
835    {
836      double T9 = sqrtPhis - t->sqrtPhi;
837      Weff = s->weff - 2.0 * (s->dwg * d->vgst + s->dwb * T9);
838      dWeff_dVg = -2.0 * s->dwg;
839      dWeff_dVb = -2.0 * s->dwb * dsqrtPhis_dVb;
840
841      if (Weff < 2.0e-8) {
842	/* to avoid the discontinuity problem due to Weff*/
843	double T0 = 1.0 / (6.0e-8 - 2.0 * Weff);
844	Weff = 2.0e-8 * (4.0e-8 - Weff) * T0;
845	T0 *= T0 * 4.0e-16;
846	dWeff_dVg *= T0;
847	dWeff_dVb *= T0;
848	trace3("Weff fix", Weff, dWeff_dVg, dWeff_dVb);
849      }
850    }
851    trace3("", Weff, dWeff_dVg, dWeff_dVb);
852    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
853    double Rds, dRds_dVg, dRds_dVb;
854    {
855      double T9 = sqrtPhis - t->sqrtPhi;
856      double T0 = s->prwg * d->vgst + s->prwb * T9;
857      if (T0 >= -0.9) {
858	Rds = t->rds0 * (1.0 + T0);
859	dRds_dVg = t->rds0 * s->prwg;
860	dRds_dVb = t->rds0 * s->prwb * dsqrtPhis_dVb;
861      }else{
862	/* to avoid the discontinuity problem due to prwg and prwb*/
863	double T1 = 1.0 / (17.0 + 20.0 * T0);
864	Rds = t->rds0 * (0.8 + T0) * T1;
865	T1 *= T1;
866	dRds_dVg = t->rds0 * s->prwg * T1;
867	dRds_dVb = t->rds0 * s->prwb * dsqrtPhis_dVb * T1;
868	trace3("Rds fix", T9, T0, T1);
869	trace3("Rds fix", Rds, dRds_dVg, dRds_dVb);
870      }
871    }
872    trace3("", Rds, dRds_dVg, dRds_dVb);
873    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
874    /* Calculate Abulk */
875    double Abulk0, dAbulk0_dVb, dAbulk_dVg, Abulk, dAbulk_dVb;
876    {
877      double T1 = 0.5 * t->k1 / sqrtPhis;
878      double dT1_dVb = -T1 / sqrtPhis * dsqrtPhis_dVb;
879
880      double T9 = sqrt(s->xj * Xdep);
881      double tmp1 = s->leff + 2.0 * T9;
882      double T5 = s->leff / tmp1;
883      double tmp2 = s->a0 * T5;
884      double tmp3 = s->weff + s->b1;
885      double tmp4 = s->b0 / tmp3;
886      double T2 = tmp2 + tmp4;
887      double dT2_dVb = -T9 / tmp1 / Xdep * dXdep_dVb;
888      double T6 = T5 * T5;
889      double T7 = T5 * T6;
890
891      Abulk0 = 1.0 + T1 * T2;
892      dAbulk0_dVb = T1 * tmp2 * dT2_dVb + T2 * dT1_dVb;
893
894      double T8 = s->ags * s->a0 * T7;
895      dAbulk_dVg = -T1 * T8;
896      Abulk = Abulk0 + dAbulk_dVg * d->vgst;
897      dAbulk_dVb = dAbulk0_dVb - T8 * d->vgst * (dT1_dVb + 3.0 * T1 * dT2_dVb);
898
899      trace2("1", Abulk0, dAbulk0_dVb);
900      trace3("1", dAbulk_dVg, Abulk, dAbulk_dVb);
901
902      if (Abulk0 < 0.1) {
903	/* added to avoid the problems caused by Abulk0 */
904	double t9 = 1.0 / (3.0 - 20.0 * Abulk0);
905	Abulk0 = (0.2 - Abulk0) * t9;
906	dAbulk0_dVb *= t9 * t9;
907	trace2("2", Abulk0, dAbulk0_dVb);
908      }
909      if (Abulk < 0.1) {
910	/* added to avoid the problems caused by Abulk */
911	double t9 = 1.0 / (3.0 - 20.0 * Abulk);
912	Abulk = (0.2 - Abulk) * t9;
913	dAbulk_dVb *= t9 * t9;
914	trace3("2", dAbulk_dVg, Abulk, dAbulk_dVb);
915      }
916
917      double T0, dT0_dVb;
918      {
919	double t2 = s->keta * Vbseff;
920	if (t2 >= -0.9) {
921	  T0 = 1.0 / (1.0 + t2);
922	  dT0_dVb = -s->keta * T0 * T0;
923	  trace3("", t2, T0, dT0_dVb);
924	}else{
925	  /* added to avoid the problems caused by Keta */
926	  double t1 = 1.0 / (0.8 + T2);
927	  T0 = (17.0 + 20.0 * T2) * t1;
928	  dT0_dVb = -s->keta * t1 * t1;
929	  trace3("keta fix", T2, T0, dT0_dVb);
930	}
931      }
932      dAbulk_dVg *= T0;
933      dAbulk_dVb = dAbulk_dVb * T0 + Abulk * dT0_dVb;
934      dAbulk0_dVb = dAbulk0_dVb * T0 + Abulk0 * dT0_dVb;
935      Abulk *= T0;
936      Abulk0 *= T0;
937    }
938    trace2("", Abulk0, dAbulk0_dVb);
939    trace3("", dAbulk_dVg, Abulk, dAbulk_dVb);
940    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
941    /* Mobility calculation */
942    double ueff, dueff_dVg, dueff_dVd, dueff_dVb;
943    {
944      double Denomi, dDenomi_dVg, dDenomi_dVd, dDenomi_dVb;
945      {
946	double T5;
947	if (m->mobMod == 1) {
948	  double T0 = d->vgst + d->von + d->von;
949	  double T2 = t->ua + t->uc * Vbseff;
950	  double T3 = T0 / m->tox;
951	  T5 = T3 * (T2 + t->ub * T3);
952	  dDenomi_dVg = (T2 + 2.0 * t->ub * T3) / m->tox;
953	  dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd;
954	  dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + t->uc * T3;
955	}else if (m->mobMod == 2) {
956	  T5 = d->vgst / m->tox
957	    * (t->ua + t->uc * Vbseff + t->ub * d->vgst / m->tox);
958	  dDenomi_dVg = (t->ua + t->uc * Vbseff + 2.0 * t->ub * d->vgst / m->tox)
959	    / m->tox;
960	  dDenomi_dVd = 0.0;
961	  dDenomi_dVb = d->vgst * t->uc / m->tox;
962	}else{
963	  double T0 = d->vgst + d->von + d->von;
964	  double T2 = 1.0 + t->uc * Vbseff;
965	  double T3 = T0 / m->tox;
966	  double T4 = T3 * (t->ua + t->ub * T3);
967	  T5 = T4 * T2;
968	  dDenomi_dVg = (t->ua + 2.0 * t->ub * T3) * T2 / m->tox;
969	  dDenomi_dVd = dDenomi_dVg * 2.0 * dVth_dVd;
970	  dDenomi_dVb = dDenomi_dVg * 2.0 * dVth_dVb + t->uc * T4;
971	}
972	if (T5 >= -0.8) {
973	  Denomi = 1.0 + T5;
974	}else{
975	  /* Added to avoid the discontinuity problem caused by ua and ub*/
976	  double t9 = 1.0 / (7.0 + 10.0 * T5);
977	  Denomi = (0.6 + T5) * t9;
978	  t9 *= t9;
979	  dDenomi_dVg *= t9;
980	  dDenomi_dVd *= t9;
981	  dDenomi_dVb *= t9;
982	}
983      }
984      ueff = t->u0temp / Denomi;
985      double t9 = -ueff / Denomi;
986      dueff_dVg = t9 * dDenomi_dVg;
987      dueff_dVd = t9 * dDenomi_dVd;
988      dueff_dVb = t9 * dDenomi_dVb;
989    }
990    trace4("", ueff, dueff_dVg, dueff_dVd, dueff_dVb);
991    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
992    double Esat, EsatL, dEsatL_dVg, dEsatL_dVd, dEsatL_dVb;
993    {
994      Esat = 2.0 * t->vsattemp / ueff;
995      EsatL = Esat * s->leff;
996      double T0 = -EsatL /ueff;
997      dEsatL_dVg = T0 * dueff_dVg;
998      dEsatL_dVd = T0 * dueff_dVd;
999      dEsatL_dVb = T0 * dueff_dVb;
1000    }
1001    trace2("", Esat, EsatL);
1002    trace3("", dEsatL_dVg, dEsatL_dVd, dEsatL_dVb);
1003    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1004    double Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb; // d->vdsat
1005    double Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd;
1006    {
1007      double WVCoxRds;
1008      {
1009	double WVCox = Weff * t->vsattemp * m->cox;
1010	WVCoxRds = WVCox * Rds;
1011      }
1012      trace1("", WVCoxRds);
1013
1014      double Lambda, dLambda_dVg;
1015      {
1016	if (s->a1 == 0.0) {
1017	  Lambda = s->a2;
1018	  dLambda_dVg = 0.0;
1019	}else if (s->a1 > 0.0) {
1020	  /* avoid discontinuity problem caused by s->a1 and s->a2 (Lambda) */
1021	  double T0 = 1.0 - s->a2;
1022	  double T1 = T0 - s->a1 * d->vgst - 0.0001;
1023	  double T2 = sqrt(T1 * T1 + 0.0004 * T0);
1024	  Lambda = s->a2 + T0 - 0.5 * (T1 + T2);
1025	  dLambda_dVg = 0.5 * s->a1 * (1.0 + T1 / T2);
1026	}else{
1027	  double T1 = s->a2 + s->a1 * d->vgst - 0.0001;
1028	  double T2 = sqrt(T1 * T1 + 0.0004 * s->a2);
1029	  Lambda = 0.5 * (T1 + T2);
1030	  dLambda_dVg = 0.5 * s->a1 * (1.0 + T1 / T2);
1031	}
1032      }
1033      trace2("", Lambda, dLambda_dVg);
1034
1035      double tmp2, tmp3;
1036      if (Rds > 0) {
1037	tmp2 = dRds_dVg / Rds + dWeff_dVg / Weff;
1038	tmp3 = dRds_dVb / Rds + dWeff_dVb / Weff;
1039      }else{
1040	tmp2 = dWeff_dVg / Weff;
1041	tmp3 = dWeff_dVb / Weff;
1042      }
1043      trace2("", tmp2, tmp3);
1044
1045      //double Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb; // d->vdsat
1046      double tmp1;
1047      {
1048	if ((Rds == 0.0) && (Lambda == 1.0)) {
1049	  double T0 = 1.0 / (Abulk * EsatL + Vgst2Vtm);
1050	  tmp1 = 0.0;
1051	  double T1 = T0 * T0;
1052	  double T2 = Vgst2Vtm * T0;
1053	  double T3 = EsatL * Vgst2Vtm;
1054	  Vdsat = T3 * T0;
1055	  double dT0_dVg = -(Abulk * dEsatL_dVg + EsatL * dAbulk_dVg + 1.0)*T1;
1056	  double dT0_dVd = -(Abulk * dEsatL_dVd) * T1;
1057	  double dT0_dVb = -(Abulk * dEsatL_dVb + dAbulk_dVb * EsatL) * T1;
1058	  dVdsat_dVg = T3 * dT0_dVg + T2 * dEsatL_dVg + EsatL * T0;
1059	  dVdsat_dVd = T3 * dT0_dVd + T2 * dEsatL_dVd;
1060	  dVdsat_dVb = T3 * dT0_dVb + T2 * dEsatL_dVb;
1061	}else{
1062	  tmp1 = dLambda_dVg / (Lambda * Lambda);
1063	  double T9 = Abulk * WVCoxRds;
1064	  double T8 = Abulk * T9;
1065	  double T7 = Vgst2Vtm * T9;
1066	  double T6 = Vgst2Vtm * WVCoxRds;
1067	  double T0 = 2.0 * Abulk * (T9 - 1.0 + 1.0 / Lambda);
1068	  double dT0_dVg = 2.0 * (T8 * tmp2 - Abulk * tmp1
1069			+ (2.0 * T9 + 1.0 / Lambda - 1.0) * dAbulk_dVg);
1070	  double dT0_dVb = 2.0 * (T8 * (2.0 / Abulk * dAbulk_dVb + tmp3)
1071				  + (1.0 / Lambda - 1.0) * dAbulk_dVb);
1072	  //double dT0_dVd = 0.0;
1073
1074	  double T1 = Vgst2Vtm * (2.0 / Lambda - 1.0) + Abulk * EsatL + 3.0*T7;
1075	  double dT1_dVg = (2.0 / Lambda - 1.0) - 2.0 * Vgst2Vtm * tmp1
1076	    + Abulk * dEsatL_dVg + EsatL * dAbulk_dVg
1077	    + 3.0 * (T9 + T7 * tmp2 + T6 * dAbulk_dVg);
1078	  double dT1_dVb = Abulk * dEsatL_dVb + EsatL * dAbulk_dVb
1079	    + 3.0 * (T6 * dAbulk_dVb + T7 * tmp3);
1080	  double dT1_dVd = Abulk * dEsatL_dVd;
1081
1082	  double T2 = Vgst2Vtm * (EsatL + 2.0 * T6);
1083	  double dT2_dVg = EsatL + Vgst2Vtm * dEsatL_dVg
1084	    + T6 * (4.0 + 2.0 * Vgst2Vtm * tmp2);
1085	  double dT2_dVb = Vgst2Vtm * (dEsatL_dVb + 2.0 * T6 * tmp3);
1086	  double dT2_dVd = Vgst2Vtm * dEsatL_dVd;
1087
1088	  double T3 = sqrt(T1 * T1 - 2.0 * T0 * T2);
1089	  Vdsat = (T1 - T3) / T0;
1090	  dVdsat_dVg = (dT1_dVg - (T1 * dT1_dVg - dT0_dVg * T2
1091				- T0 * dT2_dVg) / T3 - Vdsat * dT0_dVg) / T0;
1092	  dVdsat_dVb = (dT1_dVb - (T1 * dT1_dVb - dT0_dVb * T2
1093				- T0 * dT2_dVb) / T3 - Vdsat * dT0_dVb) / T0;
1094	  dVdsat_dVd = (dT1_dVd - (T1 * dT1_dVd - T0 * dT2_dVd) / T3) / T0;
1095	}
1096	d->vdsat = Vdsat;
1097	d->saturated = (d->vds >= d->vdsat);
1098      }
1099      trace1("", tmp1);
1100      trace4("d->vdsat", Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb);
1101
1102      // double Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd;
1103      {
1104	double tmp4 = 1.0 - 0.5 * Abulk * Vdsat / Vgst2Vtm;
1105	double T9 = WVCoxRds * d->vgst;
1106	double T8 = T9 / Vgst2Vtm;
1107	double T0 = EsatL + Vdsat + 2.0 * T9 * tmp4;
1108	double T7 = 2.0 * WVCoxRds * tmp4;
1109	double dT0_dVg = dEsatL_dVg + dVdsat_dVg + T7 * (1.0 + tmp2 * d->vgst)
1110	  - T8 * (Abulk * dVdsat_dVg - Abulk * Vdsat / Vgst2Vtm
1111		  + Vdsat * dAbulk_dVg);
1112	double dT0_dVb = dEsatL_dVb + dVdsat_dVb + T7 * tmp3 * d->vgst
1113	  - T8 * (dAbulk_dVb * Vdsat + Abulk * dVdsat_dVb);
1114	double dT0_dVd = dEsatL_dVd + dVdsat_dVd - T8 * Abulk * dVdsat_dVd;
1115	T9 = WVCoxRds * Abulk;
1116	double T1 = 2.0 / Lambda - 1.0 + T9;
1117	double dT1_dVg = -2.0 * tmp1 +  WVCoxRds * (Abulk * tmp2 + dAbulk_dVg);
1118	double dT1_dVb = dAbulk_dVb * WVCoxRds + T9 * tmp3;
1119	Vasat = T0 / T1;
1120	dVasat_dVg = (dT0_dVg - Vasat * dT1_dVg) / T1;
1121	dVasat_dVb = (dT0_dVb - Vasat * dT1_dVb) / T1;
1122	dVasat_dVd = dT0_dVd / T1;
1123      }
1124      trace4("", Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd);
1125    }
1126    trace1("", d->vdsat);
1127    trace4("", Vdsat, dVdsat_dVg, dVdsat_dVd, dVdsat_dVb);
1128    trace4("", Vasat, dVasat_dVg, dVasat_dVb, dVasat_dVd);
1129    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1130    /* Effective Vds (Vdseff) Calculation */
1131    double Vdseff, diffVds, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb;
1132    {
1133      double T1 = Vdsat - d->vds - s->delta;
1134      double dT1_dVg = dVdsat_dVg;
1135      double dT1_dVd = dVdsat_dVd - 1.0;
1136      double dT1_dVb = dVdsat_dVb;
1137      trace4("", T1, dT1_dVg, dT1_dVd, dT1_dVb);
1138
1139      double T2 = sqrt(T1 * T1 + 4.0 * s->delta * Vdsat);
1140      double T0 = T1 / T2;
1141      double T3 = 2.0 * s->delta / T2;
1142      trace3("", T2, T0, T3);
1143      double dT2_dVg = T0 * dT1_dVg + T3 * dVdsat_dVg;
1144      double dT2_dVd = T0 * dT1_dVd + T3 * dVdsat_dVd;
1145      double dT2_dVb = T0 * dT1_dVb + T3 * dVdsat_dVb;
1146      trace3("", dT2_dVg, dT2_dVd, dT2_dVb);
1147
1148      Vdseff      = Vdsat - 0.5 * (T1 + T2);
1149      dVdseff_dVg = dVdsat_dVg - 0.5 * (dT1_dVg + dT2_dVg);
1150      dVdseff_dVd = dVdsat_dVd - 0.5 * (dT1_dVd + dT2_dVd);
1151      dVdseff_dVb = dVdsat_dVb - 0.5 * (dT1_dVb + dT2_dVb);
1152      trace4("raw", Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb);
1153
1154      fixzero(&Vdseff,      Vdsat);
1155      fixzero(&dVdseff_dVg, dVdsat_dVg);
1156      fixzero(&dVdseff_dVd, dVdsat_dVd);
1157      fixzero(&dVdseff_dVb, dVdsat_dVb);
1158      /* Added to eliminate non-zero Vdseff at Vds=0.0 */
1159      if (d->vds == 0.0) {
1160	assert(Vdseff == 0.0);
1161	assert(dVdseff_dVg == 0.0);
1162	assert(dVdseff_dVb == 0.0);
1163      }
1164      if (Vdseff > d->vds) {	// From Spice, to fix numeric problems.
1165	trace2("numeric problems", Vdseff, d->vds);
1166	Vdseff = d->vds;
1167      }
1168      trace4("fixed", Vdseff, dVdseff_dVg, dVdseff_dVd, dVdseff_dVb);
1169
1170      diffVds = d->vds - Vdseff;
1171      trace2("", Vdseff, diffVds);
1172    }
1173    trace2("", Vdseff, diffVds);
1174    trace3("", dVdseff_dVg, dVdseff_dVd, dVdseff_dVb);
1175    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1176    /* Calculate Ids */
1177    double Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb;
1178    {
1179      double Va, dVa_dVg, dVa_dVd, dVa_dVb;
1180      {
1181	double VACLM, dVACLM_dVg, dVACLM_dVb, dVACLM_dVd;
1182	if ((s->pclm > 0.0) && (diffVds > 1.0e-10)) {
1183	  double T0 = 1.0 / (s->pclm * Abulk * s->litl);
1184	  double dT0_dVb = -T0 / Abulk * dAbulk_dVb;
1185	  double dT0_dVg = -T0 / Abulk * dAbulk_dVg;
1186	  double T2 = d->vgst / EsatL;
1187	  double T1 = s->leff * (Abulk + T2);
1188	  double dT1_dVg = s->leff * ((1.0-T2*dEsatL_dVg)/EsatL + dAbulk_dVg);
1189	  double dT1_dVb = s->leff * (dAbulk_dVb - T2 * dEsatL_dVb / EsatL);
1190	  double dT1_dVd = -T2 * dEsatL_dVd / Esat;
1191	  double T9 = T0 * T1;
1192	  VACLM = T9 * diffVds;
1193	  dVACLM_dVg = T0 * dT1_dVg * diffVds - T9 * dVdseff_dVg
1194	    + T1 * diffVds * dT0_dVg;
1195	  dVACLM_dVb = (dT0_dVb*T1 + T0*dT1_dVb) * diffVds - T9 * dVdseff_dVb;
1196	  dVACLM_dVd = T0 * dT1_dVd * diffVds + T9 * (1.0 - dVdseff_dVd);
1197	}else{
1198	  VACLM = MAX_EXP;
1199	  dVACLM_dVd = dVACLM_dVg = dVACLM_dVb = 0.0;
1200	}
1201	trace4("", VACLM, dVACLM_dVg, dVACLM_dVb, dVACLM_dVd);
1202
1203	double VADIBL, dVADIBL_dVg, dVADIBL_dVb, dVADIBL_dVd;
1204	if (t->thetaRout > 0.0) {
1205	  double T8 = Abulk * Vdsat;
1206	  double T0 = Vgst2Vtm * T8;
1207	  double dT0_dVg = Vgst2Vtm * Abulk * dVdsat_dVg + T8
1208	    + Vgst2Vtm * Vdsat * dAbulk_dVg;
1209	  double dT0_dVb = Vgst2Vtm * (dAbulk_dVb*Vdsat + Abulk*dVdsat_dVb);
1210	  double dT0_dVd = Vgst2Vtm * Abulk * dVdsat_dVd;
1211	  double T1 = Vgst2Vtm + T8;
1212	  double dT1_dVg = 1.0 + Abulk * dVdsat_dVg + Vdsat * dAbulk_dVg;
1213	  double dT1_dVb = Abulk * dVdsat_dVb + dAbulk_dVb * Vdsat;
1214	  double dT1_dVd = Abulk * dVdsat_dVd;
1215	  double T9 = T1 * T1;
1216	  double T2 = t->thetaRout;
1217	  VADIBL = (Vgst2Vtm - T0 / T1) / T2;
1218	  dVADIBL_dVg = (1.0 - dT0_dVg / T1 + T0 * dT1_dVg / T9) / T2;
1219	  dVADIBL_dVb = (-dT0_dVb / T1 + T0 * dT1_dVb / T9) / T2;
1220	  dVADIBL_dVd = (-dT0_dVd / T1 + T0 * dT1_dVd / T9) / T2;
1221
1222	  double T7 = s->pdiblb * Vbseff;
1223	  if (T7 >= -0.9) {
1224	    double T3 = 1.0 / (1.0 + T7);
1225	    VADIBL *= T3;
1226	    dVADIBL_dVg *= T3;
1227	    dVADIBL_dVb = (dVADIBL_dVb - VADIBL * s->pdiblb) * T3;
1228	    dVADIBL_dVd *= T3;
1229	  }else{
1230	    /* Added to avoid the discontinuity problem caused by pdiblcb */
1231	    double T4 = 1.0 / (0.8 + T7);
1232	    double T3 = (17.0 + 20.0 * T7) * T4;
1233	    dVADIBL_dVg *= T3;
1234	    dVADIBL_dVb = dVADIBL_dVb * T3 - VADIBL * s->pdiblb * T4 * T4;
1235	    dVADIBL_dVd *= T3;
1236	    VADIBL *= T3;
1237	  }
1238	}else{
1239	  VADIBL = MAX_EXP;
1240	  dVADIBL_dVd = dVADIBL_dVg = dVADIBL_dVb = 0.0;
1241	}
1242	trace4("", VADIBL, dVADIBL_dVg, dVADIBL_dVb, dVADIBL_dVd);
1243
1244	double T8 = s->pvag / EsatL;
1245	double T9 = T8 * d->vgst;
1246	double T0, dT0_dVg, dT0_dVb, dT0_dVd;
1247	if (T9 > -0.9) {
1248	  T0 = 1.0 + T9;
1249	  dT0_dVg = T8 * (1.0 - d->vgst * dEsatL_dVg / EsatL);
1250	  dT0_dVb = -T9 * dEsatL_dVb / EsatL;
1251	  dT0_dVd = -T9 * dEsatL_dVd / EsatL;
1252	}else{
1253	  /* Added to avoid the discontinuity problems caused by pvag */
1254	  double T1 = 1.0 / (17.0 + 20.0 * T9);
1255	  T0 = (0.8 + T9) * T1;
1256	  T1 *= T1;
1257	  dT0_dVg = T8 * (1.0 - d->vgst * dEsatL_dVg / EsatL) * T1;
1258	  T9 *= T1 / EsatL;
1259	  dT0_dVb = -T9 * dEsatL_dVb;
1260	  dT0_dVd = -T9 * dEsatL_dVd;
1261	}
1262	double tmp1 = VACLM * VACLM;
1263	double tmp2 = VADIBL * VADIBL;
1264	double tmp3 = VACLM + VADIBL;
1265
1266	double T1 = VACLM * VADIBL / tmp3;
1267	tmp3 *= tmp3;
1268	double dT1_dVg = (tmp1 * dVADIBL_dVg + tmp2 * dVACLM_dVg) / tmp3;
1269	double dT1_dVd = (tmp1 * dVADIBL_dVd + tmp2 * dVACLM_dVd) / tmp3;
1270	double dT1_dVb = (tmp1 * dVADIBL_dVb + tmp2 * dVACLM_dVb) / tmp3;
1271
1272	Va = Vasat + T0 * T1;
1273	dVa_dVg = dVasat_dVg + T1 * dT0_dVg + T0 * dT1_dVg;
1274	dVa_dVd = dVasat_dVd + T1 * dT0_dVd + T0 * dT1_dVd;
1275	dVa_dVb = dVasat_dVb + T1 * dT0_dVb + T0 * dT1_dVb;
1276      }
1277      trace4("", Va, dVa_dVg, dVa_dVd, dVa_dVb);
1278
1279      double Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb;
1280      {
1281	double gche, dgche_dVg, dgche_dVd, dgche_dVb;
1282	{
1283	  double beta, dbeta_dVg, dbeta_dVd, dbeta_dVb;
1284	  {
1285	    double CoxWovL = m->cox * Weff / s->leff;
1286	    beta = ueff * CoxWovL;
1287	    dbeta_dVg = CoxWovL * dueff_dVg + beta * dWeff_dVg / Weff;
1288	    dbeta_dVd = CoxWovL * dueff_dVd;
1289	    dbeta_dVb = CoxWovL * dueff_dVb + beta * dWeff_dVb / Weff;
1290	  }
1291	  trace4("", beta, dbeta_dVg, dbeta_dVd, dbeta_dVb);
1292
1293	  double fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb;
1294	  {
1295	    double T0 = 1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm;
1296	    double dT0_dVg = -0.5 * (Abulk * dVdseff_dVg
1297		- Abulk * Vdseff / Vgst2Vtm + Vdseff * dAbulk_dVg) / Vgst2Vtm;
1298	    double dT0_dVd = -0.5 * Abulk * dVdseff_dVd / Vgst2Vtm;
1299	    double dT0_dVb = -0.5 * (Abulk*dVdseff_dVb + dAbulk_dVb*Vdseff)
1300	      / Vgst2Vtm;
1301	    fgche1 = d->vgst * T0;
1302	    dfgche1_dVg = d->vgst * dT0_dVg + T0;
1303	    dfgche1_dVd = d->vgst * dT0_dVd;
1304	    dfgche1_dVb = d->vgst * dT0_dVb;
1305	  }
1306	  trace4("", fgche1, dfgche1_dVg, dfgche1_dVd, dfgche1_dVb);
1307
1308	  double fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb;
1309	  {
1310	    double T9 = Vdseff / EsatL;
1311	    fgche2 = 1.0 + T9;
1312	    dfgche2_dVg = (dVdseff_dVg - T9 * dEsatL_dVg) / EsatL;
1313	    dfgche2_dVd = (dVdseff_dVd - T9 * dEsatL_dVd) / EsatL;
1314	    dfgche2_dVb = (dVdseff_dVb - T9 * dEsatL_dVb) / EsatL;
1315	  }
1316	  trace4("", fgche2, dfgche2_dVg, dfgche2_dVd, dfgche2_dVb);
1317
1318	  gche = beta * fgche1 / fgche2;
1319	  dgche_dVg = (beta * dfgche1_dVg + fgche1 * dbeta_dVg
1320		       - gche * dfgche2_dVg) / fgche2;
1321	  dgche_dVd = (beta * dfgche1_dVd + fgche1 * dbeta_dVd
1322		       - gche * dfgche2_dVd) / fgche2;
1323	  dgche_dVb = (beta * dfgche1_dVb + fgche1 * dbeta_dVb
1324		       - gche * dfgche2_dVb) / fgche2;
1325	}
1326	trace4("", gche, dgche_dVg, dgche_dVd, dgche_dVb);
1327
1328	double T0 = 1.0 + gche * Rds;
1329	double T9 = Vdseff / T0;
1330	Idl = gche * T9;
1331	dIdl_dVg = (gche * dVdseff_dVg + T9 * dgche_dVg) / T0
1332	  - Idl * gche / T0 * dRds_dVg;
1333	dIdl_dVd = (gche * dVdseff_dVd + T9 * dgche_dVd) / T0;
1334	dIdl_dVb = (gche*dVdseff_dVb + T9*dgche_dVb - Idl*dRds_dVb*gche) / T0;
1335      }
1336      trace4("", Idl, dIdl_dVg, dIdl_dVd, dIdl_dVb);
1337
1338      double T9 =  diffVds / Va;
1339      double T0 =  1.0 + T9;
1340      Idsa = Idl * T0;
1341      dIdsa_dVg = T0 * dIdl_dVg - Idl * (dVdseff_dVg + T9 * dVa_dVg) / Va;
1342      dIdsa_dVd = T0 * dIdl_dVd + Idl * (1.0 - dVdseff_dVd - T9*dVa_dVd) / Va;
1343      dIdsa_dVb = T0 * dIdl_dVb - Idl * (dVdseff_dVb + T9 * dVa_dVb) / Va;
1344    }
1345    trace4("", Idsa, dIdsa_dVg, dIdsa_dVd, dIdsa_dVb);
1346    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1347    // d->ids, d->gds, d->gmf, d->gmbf
1348    {
1349      double VASCBE, dVASCBE_dVg, dVASCBE_dVd, dVASCBE_dVb;
1350      if (s->pscbe2 > 0.0) {
1351	if (diffVds > s->pscbe1 * s->litl / EXP_THRESHOLD) {
1352	  double T0 =  s->pscbe1 * s->litl / diffVds;
1353	  VASCBE = s->leff * exp(T0) / s->pscbe2;
1354	  double T1 = T0 * VASCBE / diffVds;
1355	  dVASCBE_dVg = T1 * dVdseff_dVg;
1356	  dVASCBE_dVd = -T1 * (1.0 - dVdseff_dVd);
1357	  dVASCBE_dVb = T1 * dVdseff_dVb;
1358	}else{
1359	  VASCBE = MAX_EXP * s->leff/s->pscbe2;
1360	  dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0;
1361	}
1362      }else{
1363	VASCBE = MAX_EXP;
1364	dVASCBE_dVg = dVASCBE_dVd = dVASCBE_dVb = 0.0;
1365      }
1366      double T9 = diffVds / VASCBE;
1367      double T0 = 1.0 + T9;
1368      double Ids = Idsa * T0;
1369      double Gm = T0*dIdsa_dVg - Idsa*(dVdseff_dVg + T9*dVASCBE_dVg) / VASCBE;
1370      double Gds = T0 * dIdsa_dVd
1371	+ Idsa * (1.0 - dVdseff_dVd - T9 * dVASCBE_dVd) / VASCBE;
1372      double Gmb = T0 * dIdsa_dVb
1373	- Idsa * (dVdseff_dVb + T9 * dVASCBE_dVb) / VASCBE;
1374      trace3("", T0, dIdsa_dVb, (T0 * dIdsa_dVb));
1375      trace4("", dVdseff_dVb, T9, dVASCBE_dVb, (dVdseff_dVb + T9*dVASCBE_dVb));
1376      trace3("", Idsa, VASCBE, (Idsa*(dVdseff_dVb+T9*dVASCBE_dVb)/VASCBE));
1377
1378      Gds += Gm * dVgsteff_dVd;
1379      Gmb += Gm * dVgsteff_dVb;
1380      Gm *= dVgsteff_dVg;
1381      Gmb *= dVbseff_dVb;
1382      trace4("", Ids, Gm, Gds, Gmb);
1383      trace0("=========================");
1384
1385      d->gds = Gds;
1386      if (d->reversed) {
1387	d->ids  = -Ids;
1388	d->gmr  = Gm;
1389	d->gmbr = Gmb;
1390	d->gmf = d->gmbf = 0;
1391      }else{
1392	d->ids  = Ids;
1393	d->gmf  = Gm;
1394	d->gmbf = Gmb;
1395	d->gmr = d->gmbr = 0.;
1396      }
1397    }
1398    trace4("", d->ids, d->gds, d->gmf, d->gmbf);
1399    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1400    // d->isub, d->gbbs, d->gbgs, d->gbds
1401    {
1402      /* calculate substrate current Isub */
1403      double Isub, Gbd, Gbb, Gbg;
1404      if ((s->alpha0 <= 0.0) || (s->beta0 <= 0.0)) {
1405	Isub = Gbd = Gbb = Gbg = 0.0;
1406	trace4("no-isub", Isub, Gbd, Gbb, Gbg);
1407      }else{
1408	double T2 = s->alpha0 / s->leff;
1409	double T1, dT1_dVg, dT1_dVd, dT1_dVb;
1410	if (diffVds > s->beta0 / EXP_THRESHOLD) {
1411	  double T0 = -s->beta0 / diffVds;
1412	  T1 = T2 * diffVds * exp(T0);
1413	  double T3 = T1 / diffVds * (T0 - 1.0);
1414	  trace3("", T0, T2, T3);
1415	  dT1_dVg = T3 * dVdseff_dVg;
1416	  dT1_dVd = T3 * (dVdseff_dVd - 1.0);
1417	  dT1_dVb = T3 * dVdseff_dVb;
1418	  trace4("vds > ?", T1, dT1_dVg, dT1_dVd, dT1_dVb);
1419	}else{
1420	  double T3 = T2 * MIN_EXP;
1421	  trace2("", T2, T3);
1422	  T1 = T3 * diffVds;
1423	  dT1_dVg = -T3 * dVdseff_dVg;
1424	  dT1_dVd = T3 * (1.0 - dVdseff_dVd);
1425	  dT1_dVb = -T3 * dVdseff_dVb;
1426	  trace4("vds < ?", T1, dT1_dVg, dT1_dVd, dT1_dVb);
1427	}
1428	Isub = T1 * Idsa;
1429	Gbg = T1 * dIdsa_dVg + Idsa * dT1_dVg;
1430	Gbd = T1 * dIdsa_dVd + Idsa * dT1_dVd;
1431	Gbb = T1 * dIdsa_dVb + Idsa * dT1_dVb;
1432	trace4("raw", Isub, Gbd, Gbb, Gbg);
1433
1434	Gbd += Gbg * dVgsteff_dVd;
1435	Gbb += Gbg * dVgsteff_dVb;
1436	Gbg *= dVgsteff_dVg;
1437	Gbb *= dVbseff_dVb; /* bug fixing */
1438      }
1439      trace4("", Isub, Gbd, Gbb, Gbg);
1440      if (d->reversed) {
1441	d->idb   = Isub;
1442	d->gdbds = Gbd;
1443	d->gdbgs = Gbg;
1444	d->gdbbs = Gbb;
1445	d->isb = d->gsbsd = d->gsbgd = d->gsbbd = 0.;
1446      }else{
1447	d->idb = d->gdbds = d->gdbgs = d->gdbbs = 0.;
1448	d->isb   = Isub;
1449	d->gsbsd = Gbd;
1450	d->gsbgd = Gbg;
1451	d->gsbbd = Gbb;
1452      }
1453      //double d__csub = Isub - (Gbb * Vbseff + Gbd * d->vds + Gbg * d->vgs);
1454    }
1455    trace4("", d->isub, d->gbbs, d->gbgs, d->gbds);
1456    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1457    /* Calculate Qinv for Noise analysis */
1458    {
1459      //double T1 = d->vgst * (1.0 - 0.5 * Abulk * Vdseff / Vgst2Vtm);
1460      //double d__qinv = -m->cox * Weff * s->leff * T1;
1461    }
1462    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1463    // ends line 2020 (finished)
1464    // d->qgate, d->qdrn, d->qbulk
1465    // d->cggb, d->cgsb, d->cgdb
1466    // d->cdgb, d->cdsb, d->cddb
1467    // d->cbgb, d->cbsb, d->cbdb
1468    {
1469      const bool ChargeComputationNeeded = true;
1470      trace2("", m->xpart, m->capMod);
1471      if ((m->xpart < 0) || (!ChargeComputationNeeded)) {
1472	d->qgate = d->qdrn = d->qbulk = 0.0;
1473	d->cggb = d->cgsb = d->cgdb = 0.0;
1474	d->cdgb = d->cdsb = d->cddb = 0.0;
1475	d->cbgb = d->cbsb = d->cbdb = 0.0;
1476	trace0("xpart < 0 || no charge computation");
1477      }else if (m->capMod == 0) {
1478	// block ends 1710 this 1454
1479	trace0("begin capMod == 0 (mos7)");
1480	if (Vbseff < 0.0) {  // redefinition
1481	  Vbseff = d->vbs;
1482	  dVbseff_dVb = 1.0;
1483	}else{
1484	  Vbseff = t->phi - Phis;
1485	  dVbseff_dVb = -dPhis_dVb;
1486	}
1487	trace1("old value replaced", dVth_dVb);
1488	double Vfb = s->vfbcv; // possible improper redefinition later
1489	double Vth = Vfb + t->phi + t->k1 * sqrtPhis;
1490	dVth_dVb = t->k1 * dsqrtPhis_dVb; // redefinition
1491	double Vgst = Vgs_eff - Vth;
1492	//double dVgst_dVb = -dVth_dVb;
1493	//double dVgst_dVg = dVgs_eff_dVg;
1494	double CoxWL = m->cox * s->weffCV * s->leffCV;
1495	double Arg1 = Vgs_eff - Vbseff - Vfb;
1496	trace3("", Vfb, Vth, dVth_dVb);
1497	trace3("", Vgst, CoxWL, Arg1);
1498
1499	// ends 1618 this 1328
1500	if (Arg1 <= 0.0) {
1501	  trace0("Arg1 <= 0.0");
1502
1503	  d->qgate = CoxWL * Arg1;
1504	  d->cggb = CoxWL * dVgs_eff_dVg;
1505	  d->cgdb = 0.0;
1506	  d->cgsb = CoxWL * (dVbseff_dVb - dVgs_eff_dVg);
1507
1508	  d->qbulk = -d->qgate;
1509	  d->cbgb = -CoxWL * dVgs_eff_dVg;
1510	  d->cbdb = 0.0;
1511	  d->cbsb = -d->cgsb;
1512
1513	  d->qdrn = 0.0;
1514	  d->cdgb = 0.0;
1515	  d->cddb = 0.0;
1516	  d->cdsb = 0.0;
1517	}else if (Vgst <= 0.0) {
1518	  trace0("Vgst <= 0.0");
1519	  double T1 = 0.5 * t->k1;
1520	  double T2 = sqrt(T1 * T1 + Arg1);
1521	  double T0 = CoxWL * T1 / T2;
1522
1523	  d->qgate = CoxWL * t->k1 * (T2 - T1);
1524	  d->cggb = T0 * dVgs_eff_dVg;
1525	  d->cgdb = 0.0;
1526	  d->cgsb = T0 * (dVbseff_dVb - dVgs_eff_dVg);
1527
1528	  d->qbulk = -d->qgate;
1529	  d->cbgb = -d->cggb;
1530	  d->cbdb = 0.0;
1531	  d->cbsb = -d->cgsb;
1532
1533	  d->qdrn = 0.0;
1534	  d->cdgb = 0.0;
1535	  d->cddb = 0.0;
1536	  d->cdsb = 0.0;
1537	}else{
1538	  trace0("!(Arg1 <= 0.0 || Vgst <= 0.0)");
1539	  double One_Third_CoxWL = CoxWL / 3.0;
1540	  double Two_Third_CoxWL = 2.0 * One_Third_CoxWL;
1541	  // redefine Vdsat, dVdsat_dVg, dVdsat_dVb
1542	  {
1543	    double AbulkCV = Abulk0 * s->abulkCVfactor;
1544	    double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb;
1545	    Vdsat = Vgst / AbulkCV;
1546	    dVdsat_dVg = dVgs_eff_dVg / AbulkCV;
1547	    dVdsat_dVb = - (Vdsat * dAbulkCV_dVb + dVth_dVb)/ AbulkCV;
1548	  }
1549	  if (m->xpart > 0.5) {
1550	    /* 0/100 Charge petition model */
1551	    if (d->vds >= Vdsat) {
1552	      /* saturation region */
1553	      double T1 = Vdsat / 3.0;
1554	      double T2 = -One_Third_CoxWL * dVdsat_dVb;
1555	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1);
1556	      d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg;
1557	      d->cgsb = -(d->cggb + T2);
1558	      d->cgdb = 0.0;
1559
1560	      double T2a = -Two_Third_CoxWL * Vgst;
1561	      double T3 = -(T2 + Two_Third_CoxWL * dVth_dVb);
1562	      d->qbulk = -(d->qgate + T2a);
1563	      d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg);
1564	      d->cbsb = -(d->cbgb + T3);
1565	      d->cbdb = 0.0;
1566
1567	      d->qdrn = 0.0;
1568	      d->cdgb = 0.0;
1569	      d->cddb = 0.0;
1570	      d->cdsb = 0.0;
1571	    }else{
1572	      /* linear region */
1573	      double Alphaz = Vgst / Vdsat;
1574	      double T1 = 2.0 * Vdsat - d->vds;
1575	      double T2 = d->vds / (3.0 * T1);
1576	      double T3 = T2 * d->vds;
1577	      double T9 = 0.25 * CoxWL;
1578	      double T4 = T9 * Alphaz;
1579	      double T7 = 2.0 * d->vds - T1 - 3.0 * T3;
1580	      double T8 = T3 - T1 - 2.0 * d->vds;
1581	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds-T3));
1582	      double T10 = T4 * T8;
1583	      d->qdrn = T4 * T7;
1584	      d->qbulk = -(d->qgate + d->qdrn + T10);
1585
1586	      double T5 = T3 / T1;
1587	      d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg;
1588	      double T11 = -CoxWL * T5 * dVdsat_dVb;
1589	      d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5);
1590	      d->cgsb = -(d->cggb + T11 + d->cgdb);
1591
1592	      double T6 = 1.0 / Vdsat;
1593	      double dAlphaz_dVg = T6 * (1.0 - Alphaz * dVdsat_dVg);
1594	      double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb);
1595	      T7 = T9 * T7;
1596	      T8 = T9 * T8;
1597	      T9 = 2.0 * T4 * (1.0 - 3.0 * T5);
1598	      d->cdgb = (T7 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg;
1599	      double T12 = T7 * dAlphaz_dVb - T9 * dVdsat_dVb;
1600	      d->cddb = T4 * (3.0 - 6.0 * T2 - 3.0 * T5);
1601	      d->cdsb = -(d->cdgb + T12 + d->cddb);
1602
1603	      T9 = 2.0 * T4 * (1.0 + T5);
1604	      T10 = (T8 * dAlphaz_dVg - T9 * dVdsat_dVg) * dVgs_eff_dVg;
1605	      T11 = T8 * dAlphaz_dVb - T9 * dVdsat_dVb;
1606	      T12 = T4 * (2.0 * T2 + T5 - 1.0);
1607	      double T0 = -(T10 + T11 + T12);
1608	      d->cbgb = -(d->cggb + d->cdgb + T10);
1609	      d->cbdb = -(d->cgdb + d->cddb + T12);
1610	      d->cbsb = -(d->cgsb + d->cdsb + T0);
1611	    }
1612	  }else if (m->xpart < 0.5) {
1613	    /* 40/60 Charge petition model */
1614	    if (d->vds >= Vdsat) {
1615	      /* saturation region */
1616	      double T1 = Vdsat / 3.0;
1617	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1);
1618	      double T2 = -Two_Third_CoxWL * Vgst;
1619	      d->qbulk = -(d->qgate + T2);
1620	      d->qdrn = 0.4 * T2;
1621
1622	      d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg;
1623	      T2 = -One_Third_CoxWL * dVdsat_dVb;
1624	      d->cgsb = -(d->cggb + T2);
1625	      d->cgdb = 0.0;
1626
1627	      double T3 = 0.4 * Two_Third_CoxWL;
1628	      d->cdgb = -T3 * dVgs_eff_dVg;
1629	      d->cddb = 0.0;
1630	      double T4 = T3 * dVth_dVb;
1631	      d->cdsb = -(T4 + d->cdgb);
1632
1633	      d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg);
1634	      T3 = -(T2 + Two_Third_CoxWL * dVth_dVb);
1635	      d->cbsb = -(d->cbgb + T3);
1636	      d->cbdb = 0.0;
1637	    }else{
1638	      /* linear region  */
1639	      double T1 = 2.0 * Vdsat - d->vds;
1640	      double T2 = d->vds / (3.0 * T1);
1641	      double T3 = T2 * d->vds;
1642	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds - T3));
1643	      double T5 = T3 / T1;
1644	      d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg;
1645	      double tmp = -CoxWL * T5 * dVdsat_dVb;
1646	      d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5);
1647	      d->cgsb = -(d->cggb + d->cgdb + tmp);
1648
1649	      double T6 = 1.0 / Vdsat;
1650	      double Alphaz      =  T6 * Vgst;
1651	      double dAlphaz_dVg =  T6 * (1.0 - Alphaz * dVdsat_dVg);
1652	      double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb);
1653	      T6 = 8.0 * Vdsat * Vdsat - 6.0 * Vdsat * d->vds
1654		+ 1.2 * d->vds * d->vds;
1655	      double T8 = T2 / T1;
1656	      double T7 = d->vds - T1 - T8 * T6;
1657	      double T9 = 0.25 * CoxWL;
1658	      double T4 = T9 * Alphaz;
1659	      d->qdrn = T4 * T7;
1660	      T7 *= T9;
1661	      tmp = T8 / T1;
1662	      double tmp1 = T4 * (2.0 - 4.0 * tmp * T6
1663			   + T8 * (16.0 * Vdsat - 6.0 * d->vds));
1664	      d->cdgb = (T7 * dAlphaz_dVg - tmp1 * dVdsat_dVg) * dVgs_eff_dVg;
1665	      double T10 = T7 * dAlphaz_dVb - tmp1 * dVdsat_dVb;
1666	      d->cddb = T4 * (2.0 - (1.0 / (3.0 * T1 * T1) + 2.0 * tmp) * T6
1667			      + T8 * (6.0 * Vdsat - 2.4 * d->vds));
1668	      d->cdsb = -(d->cdgb + T10 + d->cddb);
1669
1670	      T7 = 2.0 * (T1 + T3);
1671	      d->qbulk = -(d->qgate - T4 * T7);
1672	      T7 *= T9;
1673	      double T0 = 4.0 * T4 * (1.0 - T5);
1674	      double T12 = (-T7 * dAlphaz_dVg - d->cdgb - T0 * dVdsat_dVg)
1675		* dVgs_eff_dVg;
1676	      double T11 = -T7 * dAlphaz_dVb - T10 - T0 * dVdsat_dVb;
1677	      T10 = -4.0 * T4 * (T2 - 0.5 + 0.5 * T5) - d->cddb;
1678	      tmp = -(T10 + T11 + T12);
1679	      d->cbgb = -(d->cggb + d->cdgb + T12);
1680	      d->cbdb = -(d->cgdb + d->cddb + T11);
1681	      d->cbsb = -(d->cgsb + d->cdsb + tmp);
1682	      trace3("0,40/60,lin", T10, T11, T12);
1683	      trace3("0,40/60,lin", d->cbgb, d->cbdb, d->cbsb);
1684	    }
1685	  }else{
1686	    /* 50/50 partitioning */
1687	    if (d->vds >= Vdsat) {
1688	      /* saturation region */
1689	      double T1 = Vdsat / 3.0;
1690	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - T1);
1691	      double T2 = -Two_Third_CoxWL * Vgst;
1692	      d->qbulk = -(d->qgate + T2);
1693	      d->qdrn = 0.5 * T2;
1694
1695	      T2 = -One_Third_CoxWL * dVdsat_dVb;
1696	      d->cggb = One_Third_CoxWL * (3.0 - dVdsat_dVg) * dVgs_eff_dVg;
1697	      d->cgsb = -(d->cggb + T2);
1698	      d->cgdb = 0.0;
1699
1700	      double T4 = One_Third_CoxWL * dVth_dVb;
1701	      d->cdgb = -One_Third_CoxWL * dVgs_eff_dVg;
1702	      d->cddb = 0.0;
1703	      d->cdsb = -(T4 + d->cdgb);
1704
1705	      double T3 = -(T2 + Two_Third_CoxWL * dVth_dVb);
1706	      d->cbgb = -(d->cggb - Two_Third_CoxWL * dVgs_eff_dVg);
1707	      d->cbsb = -(d->cbgb + T3);
1708	      d->cbdb = 0.0;
1709	    }else{
1710	      /* linear region */
1711	      double T1 = 2.0 * Vdsat - d->vds;
1712	      double T2 = d->vds / (3.0 * T1);
1713	      double T3 = T2 * d->vds;
1714	      double T5 = T3 / T1;
1715	      double tmp = -CoxWL * T5 * dVdsat_dVb;
1716	      d->qgate = CoxWL * (Vgs_eff - Vfb - t->phi - 0.5 * (d->vds-T3));
1717	      d->cggb = CoxWL * (1.0 - T5 * dVdsat_dVg) * dVgs_eff_dVg;
1718	      d->cgdb = CoxWL * (T2 - 0.5 + 0.5 * T5);
1719	      d->cgsb = -(d->cggb + d->cgdb + tmp);
1720
1721	      double T6 = 1.0 / Vdsat;
1722	      double Alphaz =       T6 * Vgst;
1723	      double dAlphaz_dVg =  T6 * (1.0 - Alphaz * dVdsat_dVg);
1724	      double dAlphaz_dVb = -T6 * (dVth_dVb + Alphaz * dVdsat_dVb);
1725
1726	      double T9 = 0.25 * CoxWL;
1727	      double T4 = T9 * Alphaz;
1728	      double T7 = T1 + T3;
1729	      d->qdrn = -T4 * T7;
1730	      d->qbulk = - (d->qgate + d->qdrn + d->qdrn);
1731
1732	      T7 *= T9;
1733	      double T0 = T4 * (2.0 * T5 - 2.0);
1734	      double T12 = T0 * dVdsat_dVb - T7 * dAlphaz_dVb;
1735	      d->cdgb = (T0 * dVdsat_dVg - T7 * dAlphaz_dVg) * dVgs_eff_dVg;
1736	      d->cddb = T4 * (1.0 - 2.0 * T2 - T5);
1737	      d->cdsb = -(d->cdgb + T12 + d->cddb);
1738
1739	      d->cbgb = -(d->cggb + 2.0 * d->cdgb);
1740	      d->cbdb = -(d->cgdb + 2.0 * d->cddb);
1741	      d->cbsb = -(d->cgsb + 2.0 * d->cdsb);
1742	    }
1743	  }
1744	} // begins 1328 this 1618
1745	trace0("end capMod == 0");
1746	// end of else if (m->capMod == 0) line 1454 this 1709
1747      }else{
1748	trace0("begin capMod != 0 (mos7)");
1749	assert(m->capMod != 0);
1750	double qsrc;
1751	double VbseffCV, dVbseffCV_dVb;
1752	if (Vbseff < 0.0) {
1753	  VbseffCV = Vbseff;
1754	  dVbseffCV_dVb = 1.0;
1755	}else{
1756	  VbseffCV = t->phi - Phis;
1757	  dVbseffCV_dVb = -dPhis_dVb;
1758	}
1759	trace2("", VbseffCV, dVbseffCV_dVb);
1760
1761	//double Vth = d->von; // possibly wrong value -- scope problem
1762	double Vfb = d->von - t->phi - t->k1 * sqrtPhis;
1763	double dVfb_dVb = 0.;//////dVth_dVb - t->k1 * dsqrtPhis_dVb;
1764	double dVfb_dVd = 0.;//////dVth_dVd;
1765
1766	//double Vgst = Vgs_eff - d->von;
1767
1768	//trace3("", d->vgst, Vgst, VgstNVt);
1769	trace2("", n, t->vtm);
1770
1771	double Vgsteff;
1772	{
1773	  if ((VgstNVt > -EXP_THRESHOLD) && (VgstNVt < EXP_THRESHOLD)) {
1774	    trace0("VgstNVt in range");
1775	    assert(ExpVgst != NOT_VALID);
1776	    ExpVgst *= ExpVgst;
1777	    ExpVgst = exp(VgstNVt); ////// test
1778	    trace1("", ExpVgst);
1779	    Vgsteff = n * t->vtm * log(1.0 + ExpVgst);
1780	    dVgsteff_dVg = ExpVgst / (1.0 + ExpVgst);
1781	    dVgsteff_dVd = -dVgsteff_dVg
1782	      * (dVth_dVd + (Vgs_eff - d->von) / n * dn_dVd)
1783	      + Vgsteff / n * dn_dVd;
1784	    dVgsteff_dVb = -dVgsteff_dVg
1785	      * (dVth_dVb + (Vgs_eff - d->von) / n * dn_dVb)
1786	      + Vgsteff / n * dn_dVb;
1787	    dVgsteff_dVg *= dVgs_eff_dVg;
1788	  }else{
1789	    Vgsteff = d->vgst;
1790	  }
1791	}
1792	trace4("", Vgsteff, dVgsteff_dVg, dVgsteff_dVd, dVgsteff_dVb);
1793
1794	double CoxWL = m->cox * s->weffCV * s->leffCV;
1795	// redundant??
1796
1797	if (m->capMod == 1) {
1798	  double Cgg, Cgd, Cgb;
1799	  {
1800	    double Arg1 = Vgs_eff - VbseffCV - Vfb - Vgsteff;
1801	    if (Arg1 <= 0.0) {
1802	      d->qgate = CoxWL * Arg1;
1803	      Cgg = CoxWL * (dVgs_eff_dVg - dVgsteff_dVg);
1804	      Cgd = -CoxWL * (dVfb_dVd + dVgsteff_dVd);
1805	      Cgb = -CoxWL * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb);
1806	    }else{
1807	      double T0 = 0.5 * t->k1;
1808	      double T1 = sqrt(T0 * T0 + Arg1);
1809	      double T2 = CoxWL * T0 / T1;
1810	      d->qgate = CoxWL * t->k1 * (T1 - T0);
1811	      Cgg = T2 * (dVgs_eff_dVg - dVgsteff_dVg);
1812	      Cgd = -T2 * (dVfb_dVd + dVgsteff_dVd);
1813	      Cgb = -T2 * (dVfb_dVb + dVbseffCV_dVb + dVgsteff_dVb);
1814	    }
1815	  }
1816	  d->qbulk = -d->qgate;
1817	  double Cbg = -Cgg;
1818	  double Cbd = -Cgd;
1819	  double Cbb = -Cgb;
1820
1821	  double AbulkCV = Abulk0 * s->abulkCVfactor;
1822	  double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb;
1823
1824	  double Csg, Csb, Csd;
1825	  {
1826	    double VdsatCV = Vgsteff / AbulkCV;
1827	    if (VdsatCV < d->vds) {
1828	      double One_Third_CoxWL = CoxWL / 3.0;
1829	      double Two_Third_CoxWL = 2.0 * One_Third_CoxWL;
1830	      double dVdsatCV_dVg = 1.0 / AbulkCV;
1831	      double dVdsatCV_dVb = -VdsatCV * dAbulkCV_dVb / AbulkCV;
1832	      {
1833		double T0 = Vgsteff - VdsatCV / 3.0;
1834		double dT0_dVg = 1.0 - dVdsatCV_dVg / 3.0;
1835		double dT0_dVb = -dVdsatCV_dVb / 3.0;
1836		d->qgate += CoxWL * T0;
1837		double Cgg1 = CoxWL * dT0_dVg;
1838		double Cgb1 = CoxWL * dT0_dVb + Cgg1 * dVgsteff_dVb;
1839		double Cgd1 = Cgg1 * dVgsteff_dVd;
1840		Cgg1 *= dVgsteff_dVg;
1841		Cgg += Cgg1;
1842		Cgb += Cgb1;
1843		Cgd += Cgd1;
1844	      }
1845	      {
1846		double T0 = VdsatCV - Vgsteff;
1847		double dT0_dVg = dVdsatCV_dVg - 1.0;
1848		double dT0_dVb = dVdsatCV_dVb;
1849		d->qbulk += One_Third_CoxWL * T0;
1850		double Cbg1 = One_Third_CoxWL * dT0_dVg;
1851		double Cbb1 = One_Third_CoxWL * dT0_dVb + Cbg1 * dVgsteff_dVb;
1852		double Cbd1 = Cbg1 * dVgsteff_dVd;
1853		Cbg1 *= dVgsteff_dVg;
1854		Cbg += Cbg1;
1855		Cbb += Cbb1;
1856		Cbd += Cbd1;
1857	      }
1858	      double T0;
1859	      if (m->xpart > 0.5) {
1860		T0 = -Two_Third_CoxWL;
1861	      }else if (m->xpart < 0.5) {
1862		T0 = -0.4 * CoxWL;
1863	      }else{
1864		T0 = -One_Third_CoxWL;
1865	      }
1866	      qsrc = T0 * Vgsteff;
1867	      Csg = T0 * dVgsteff_dVg;
1868	      Csb = T0 * dVgsteff_dVb;
1869	      Csd = T0 * dVgsteff_dVd;
1870	      Cgb *= dVbseff_dVb;
1871	      Cbb *= dVbseff_dVb;
1872	      Csb *= dVbseff_dVb;
1873	    }else{
1874	      double T0 = AbulkCV * d->vds;
1875	      double T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1.e-20);
1876	      double Cgg1, Cgb1, Cgd1, Cbg1, Cbb1, Cbd1;
1877	      {
1878		double T2 = d->vds / T1;
1879		double T3 = T0 * T2;
1880		double dT3_dVg = -12.0 * T2 * T2 * AbulkCV;
1881		double dT3_dVd = 6.0 * T0 * (4.0*Vgsteff - T0) / T1 / T1 - 0.5;
1882		double dT3_dVb = 12.0 * T2 * T2 * dAbulkCV_dVb * Vgsteff;
1883
1884		d->qgate += CoxWL * (Vgsteff - 0.5 * d->vds + T3);
1885		Cgg1 = CoxWL * (1.0 + dT3_dVg);
1886		Cgb1 = CoxWL * dT3_dVb + Cgg1 * dVgsteff_dVb;
1887		Cgd1 = CoxWL * dT3_dVd + Cgg1 * dVgsteff_dVd;
1888		Cgg1 *= dVgsteff_dVg;
1889		Cgg += Cgg1;
1890		Cgb += Cgb1;
1891		Cgd += Cgd1;
1892
1893		d->qbulk += CoxWL * (1.0 - AbulkCV) * (0.5 * d->vds - T3);
1894		Cbg1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVg);
1895		Cbb1 = -CoxWL * ((1.0 - AbulkCV) * dT3_dVb
1896				 + (0.5 * d->vds - T3) * dAbulkCV_dVb)
1897		  + Cbg1 * dVgsteff_dVb;
1898		Cbd1 = -CoxWL * (1.0 - AbulkCV) * dT3_dVd
1899		  + Cbg1 * dVgsteff_dVd;
1900		Cbg1 *= dVgsteff_dVg;
1901		Cbg += Cbg1;
1902		Cbb += Cbb1;
1903		Cbd += Cbd1;
1904	      }
1905	      if (m->xpart > 0.5) {
1906		/* 0/100 Charge petition model */
1907		T1 = T1 + T1;
1908		qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - T0 * T0 / T1);
1909		Csg = -CoxWL * (0.5 + 24.0 * T0 * d->vds / T1 / T1 * AbulkCV);
1910		Csb = -CoxWL * (0.25 * d->vds * dAbulkCV_dVb
1911			  - 12.0 * T0 * d->vds / T1 / T1 * (4.0 * Vgsteff - T0)
1912				* dAbulkCV_dVb) + Csg * dVgsteff_dVb;
1913		Csd = -CoxWL * (0.25 * AbulkCV - 12.0 * AbulkCV * T0
1914				/ T1 / T1 * (4.0 * Vgsteff - T0))
1915		  + Csg * dVgsteff_dVd;
1916		Csg *= dVgsteff_dVg;
1917	      }else if (m->xpart < 0.5) {
1918		/* 40/60 Charge petition model */
1919		T1 = T1 / 12.0;
1920		double T2 = 0.5 * CoxWL / (T1 * T1);
1921		double T3 = Vgsteff * (2.0 * T0 * T0 / 3.0
1922				       + Vgsteff * (Vgsteff - 4.0 * T0 / 3.0))
1923		  - 2.0 * T0 * T0 * T0 / 15.0;
1924		qsrc = -T2 * T3;
1925		double T4 = 4.0 / 3.0 * Vgsteff * (Vgsteff-T0) + 0.4 * T0 * T0;
1926		Csg = -2.0 * qsrc / T1
1927		  - T2 * (Vgsteff * (3.0 * Vgsteff - 8.0 * T0 / 3.0)
1928			  + 2.0 * T0 * T0 / 3.0);
1929		Csb = (qsrc / T1 * d->vds + T2 * T4 * d->vds) * dAbulkCV_dVb
1930		  + Csg * dVgsteff_dVb;
1931		Csd = (qsrc / T1 + T2 * T4) * AbulkCV + Csg * dVgsteff_dVd;
1932		Csg *= dVgsteff_dVg;
1933	      }else{
1934		/* 50/50 Charge petition model */
1935		qsrc = -0.5 * (d->qgate + d->qbulk);
1936		Csg = -0.5 * (Cgg1 + Cbg1);
1937		Csb = -0.5 * (Cgb1 + Cbb1);
1938		Csd = -0.5 * (Cgd1 + Cbd1);
1939	      }
1940	      Cgb *= dVbseff_dVb;
1941	      Cbb *= dVbseff_dVb;
1942	      Csb *= dVbseff_dVb;
1943	    }
1944	  }
1945	  d->qdrn = -(d->qgate + d->qbulk + qsrc);
1946	  d->cggb = Cgg;
1947	  d->cgsb = -(Cgg + Cgd + Cgb);
1948	  d->cgdb = Cgd;
1949	  d->cdgb = -(Cgg + Cbg + Csg);
1950	  d->cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb);
1951	  d->cddb = -(Cgd + Cbd + Csd);
1952	  d->cbgb = Cbg;
1953	  d->cbsb = -(Cbg + Cbd + Cbb);
1954	  d->cbdb = Cbd;
1955	  trace0("end capMod == 1");
1956	}else if (m->capMod == 2) {
1957	  trace0("begin capMod == 2");
1958	  double Qac0, dQac0_dVg, dQac0_dVd, dQac0_dVb;
1959	  double Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb;
1960	  {
1961	    double Vfbeff, dVfbeff_dVd, dVfbeff_dVg, dVfbeff_dVb;
1962	    {
1963	      const double DELTA_3 = 0.02;
1964	      double V3 = Vfb - Vgs_eff + VbseffCV - DELTA_3;
1965	      double T0, T2;
1966	      if (Vfb <= 0.0) {
1967		T0 = sqrt(V3 * V3 - 4.0 * DELTA_3 * Vfb);
1968		T2 = -DELTA_3 / T0;
1969	      }else{
1970		T0 = sqrt(V3 * V3 + 4.0 * DELTA_3 * Vfb);
1971		T2 = DELTA_3 / T0;
1972	      }
1973	      double T1 = 0.5 * (1.0 + V3 / T0);
1974	      Vfbeff = Vfb - 0.5 * (V3 + T0);
1975	      dVfbeff_dVd = (1.0 - T1 - T2) * dVfb_dVd;
1976	      dVfbeff_dVg = T1 * dVgs_eff_dVg;
1977	      dVfbeff_dVb = (1.0 - T1 - T2) * dVfb_dVb - T1 * dVbseffCV_dVb;
1978	    }
1979	    trace3("", Vfbeff, dVfbeff_dVg, dVfbeff_dVb);
1980	    trace1("", dVfbeff_dVd);
1981
1982	    //double Qac0, dQac0_dVg, dQac0_dVd, dQac0_dVb;
1983	    {
1984	      Qac0 = CoxWL * (Vfbeff - Vfb);
1985	      dQac0_dVg = CoxWL * dVfbeff_dVg;
1986	      dQac0_dVd = CoxWL * (dVfbeff_dVd - dVfb_dVd);
1987	      dQac0_dVb = CoxWL * (dVfbeff_dVb - dVfb_dVb);
1988	    }
1989
1990	    //double Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb;
1991	    {
1992	      double T0 = 0.5 * t->k1;
1993	      double T3 = Vgs_eff - Vfbeff - VbseffCV - Vgsteff;
1994	      double T1, T2;
1995	      if (t->k1 == 0.0) {
1996		T1 = 0.0;
1997		T2 = 0.0;
1998	      }else if (T3 < 0.0) {
1999		T1 = T0 + T3 / t->k1;
2000		T2 = CoxWL;
2001	      }else{
2002		T1 = sqrt(T0 * T0 + T3);
2003		T2 = CoxWL * T0 / T1;
2004	      }
2005	      Qsub0 = CoxWL * t->k1 * (T1 - T0);
2006	      dQsub0_dVg = T2 * (dVgs_eff_dVg - dVfbeff_dVg - dVgsteff_dVg);
2007	      dQsub0_dVd = -T2 * (dVfbeff_dVd + dVgsteff_dVd);
2008	      dQsub0_dVb = -T2 * (dVfbeff_dVb +dVbseffCV_dVb +dVgsteff_dVb);
2009	    }
2010	  }
2011	  trace3("", Qac0, dQac0_dVg, dQac0_dVb);
2012	  trace1("", dQac0_dVd);
2013	  trace4("", Qsub0, dQsub0_dVg, dQsub0_dVd, dQsub0_dVb);
2014
2015	  double AbulkCV = Abulk0 * s->abulkCVfactor;
2016	  double dAbulkCV_dVb = s->abulkCVfactor * dAbulk0_dVb;
2017	  trace2("", AbulkCV, dAbulkCV_dVb);
2018
2019	  double VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb;
2020	  {
2021	    const double DELTA_4 = 0.02;
2022	    double VdsatCV = Vgsteff / AbulkCV;
2023	    double V4 = VdsatCV - d->vds - DELTA_4;
2024	    double T0 = sqrt(V4 * V4 + 4.0 * DELTA_4 * VdsatCV);
2025	    VdseffCV = VdsatCV - 0.5 * (V4 + T0);
2026	    double T1 = 0.5 * (1.0 + V4 / T0);
2027	    double T2 = DELTA_4 / T0;
2028	    double T3 = (1.0 - T1 - T2) / AbulkCV;
2029	    dVdseffCV_dVg = T3;
2030	    dVdseffCV_dVd = T1;
2031	    dVdseffCV_dVb = -T3 * VdsatCV * dAbulkCV_dVb;
2032	  }
2033	  trace4("", VdseffCV, dVdseffCV_dVg, dVdseffCV_dVd, dVdseffCV_dVb);
2034
2035	  double T0 = AbulkCV * VdseffCV;
2036	  double T1 = 12.0 * (Vgsteff - 0.5 * T0 + 1e-20);
2037	  trace2("", T0, T1);
2038
2039	  double Cgg1, Cgd1, Cgb1, Cbg1, Cbd1, Cbb1;
2040	  // also 1st estimate of d->qgate, d->qbulk
2041	  {
2042	    double T2 = VdseffCV / T1;
2043	    double T3 = T0 * T2;
2044	    double T4 = (1.0 - 12.0 * T2 * T2 * AbulkCV);
2045	    double T5 = (6.0 * T0 * (4.0 * Vgsteff - T0) / (T1 * T1) - 0.5);
2046	    double T6 = 12.0 * T2 * T2 * Vgsteff;
2047	    d->qgate = CoxWL * (Vgsteff - 0.5 * VdseffCV + T3);
2048	    Cgg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg);
2049	    Cgd1 = CoxWL * T5 * dVdseffCV_dVd + Cgg1 * dVgsteff_dVd;
2050	    Cgb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb)
2051	      + Cgg1 * dVgsteff_dVb;
2052	    Cgg1 *= dVgsteff_dVg;
2053
2054	    double T7 = 1.0 - AbulkCV;
2055	    d->qbulk = CoxWL * T7 * (0.5 * VdseffCV - T3);
2056	    T4 = -T7 * (T4 - 1.0);
2057	    T5 = -T7 * T5;
2058	    T6 = -(T7 * T6 + (0.5 * VdseffCV - T3));
2059	    Cbg1 = CoxWL * (T4 + T5 * dVdseffCV_dVg);
2060	    Cbd1 = CoxWL * T5 * dVdseffCV_dVd + Cbg1 * dVgsteff_dVd;
2061	    Cbb1 = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb)
2062	      + Cbg1 * dVgsteff_dVb;
2063	    Cbg1 *= dVgsteff_dVg;
2064	  }
2065	  trace3("", Cgg1, Cgd1, Cgb1);
2066	  trace3("", Cbg1, Cbd1, Cbb1);
2067	  trace2("2-1", d->qgate, d->qbulk);
2068
2069	  double Csg, Csd, Csb;
2070	  trace1("", m->xpart);
2071	  if (m->xpart > 0.5) {
2072	    trace0("0/100 Charge petition model");
2073	    T1 = T1 + T1;
2074	    qsrc = -CoxWL * (0.5 * Vgsteff + 0.25 * T0 - T0 * T0 / T1);
2075	    double T7 = (4.0 * Vgsteff - T0) / (T1 * T1);
2076	    double T4 = -(0.5 + 24.0 * T0 * T0 / (T1 * T1));
2077	    double T5 = -(0.25 * AbulkCV - 12.0 * AbulkCV * T0 * T7);
2078	    double T6 = -(0.25 * VdseffCV - 12.0 * T0 * VdseffCV * T7);
2079	    Csg = CoxWL * (T4 + T5 * dVdseffCV_dVg);
2080	    Csd = CoxWL * T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd;
2081	    Csb = CoxWL * (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb)
2082	      + Csg * dVgsteff_dVb;
2083	    Csg *= dVgsteff_dVg;
2084	  }else if (m->xpart < 0.5) {
2085	    trace0("40/60 Charge petition model");
2086	    T1 = T1 / 12.0;
2087	    double T2 = 0.5 * CoxWL / (T1 * T1);
2088	    double T3 = Vgsteff * (2.0 * T0 * T0 / 3.0 + Vgsteff
2089				   * (Vgsteff - 4.0 * T0 / 3.0))
2090	      - 2.0 * T0 * T0 * T0 / 15.0;
2091	    qsrc = -T2 * T3;
2092	    double T7 = 4.0 / 3.0 * Vgsteff * (Vgsteff - T0) + 0.4 * T0 * T0;
2093	    double T4 = -2.0 * qsrc / T1
2094	      - T2 * (Vgsteff * (3.0 * Vgsteff - 8.0 * T0 / 3.0)
2095		      + 2.0 * T0 * T0 / 3.0);
2096	    double T5 = (qsrc / T1 + T2 * T7) * AbulkCV;
2097	    double T6 = (qsrc / T1 * VdseffCV + T2 * T7 * VdseffCV);
2098	    Csg = (T4 + T5 * dVdseffCV_dVg);
2099	    Csd = T5 * dVdseffCV_dVd + Csg * dVgsteff_dVd;
2100	    Csb = (T5 * dVdseffCV_dVb + T6 * dAbulkCV_dVb)
2101	      + Csg * dVgsteff_dVb;
2102	    Csg *= dVgsteff_dVg;
2103	  }else{
2104	    trace0("50/50 Charge petition model");
2105	    qsrc = -0.5 * (d->qgate + d->qbulk);
2106	    Csg = -0.5 * (Cgg1 + Cbg1);
2107	    Csb = -0.5 * (Cgb1 + Cbb1);
2108	    Csd = -0.5 * (Cgd1 + Cbd1);
2109	  }
2110	  trace4("", Csg, Csd, Csb, qsrc);
2111
2112	  d->qgate += Qac0 + Qsub0;
2113	  d->qbulk -= (Qac0 + Qsub0);
2114	  d->qdrn = -(d->qgate + d->qbulk + qsrc);
2115	  trace3("2-2", d->qgate, d->qbulk, d->qdrn);
2116
2117	  double Cgg = dQac0_dVg + dQsub0_dVg + Cgg1;
2118	  double Cgd = dQac0_dVd + dQsub0_dVd + Cgd1;
2119	  double Cgb = dQac0_dVb + dQsub0_dVb + Cgb1;
2120	  trace3("", Cgg, Cgd, Cgb);
2121
2122	  double Cbg = Cbg1 - dQac0_dVg - dQsub0_dVg;
2123	  double Cbd = Cbd1 - dQac0_dVd - dQsub0_dVd;
2124	  double Cbb = Cbb1 - dQac0_dVb - dQsub0_dVb;
2125	  trace3("", Cbg, Cbd, Cbb);
2126
2127	  Cgb *= dVbseff_dVb;
2128	  Cbb *= dVbseff_dVb;
2129	  Csb *= dVbseff_dVb;
2130	  trace3("adjusted", Cgb, Cbb, Csb);
2131
2132	  d->cggb = Cgg;
2133	  d->cgsb = -(Cgg + Cgd + Cgb);
2134	  d->cgdb = Cgd;
2135	  d->cdgb = -(Cgg + Cbg + Csg);
2136	  d->cdsb = (Cgg + Cgd + Cgb + Cbg + Cbd + Cbb + Csg + Csd + Csb);
2137	  d->cddb = -(Cgd + Cbd + Csd);
2138	  d->cbgb = Cbg;
2139	  d->cbsb = -(Cbg + Cbd + Cbb);
2140	  d->cbdb = Cbd;
2141	  trace0("end capMod == 2");
2142	}else{
2143	  error(bDANGER, "illegal capmod = %d\n", int(m->capMod));
2144	  d->qbulk = d->qgate = NOT_VALID;
2145	}
2146
2147	/* Non-quasi-static Model */
2148	double tconst;
2149	if (m->nqsMod) {
2150	  //  d->gtau
2151	  double qcheq = -d->qbulk - d->qgate;
2152	  double T0 = s->leffCV * s->leffCV;
2153	  tconst = t->u0temp * s->elm / CoxWL / T0;
2154	  if (qcheq == 0.0) {
2155	    tconst = 0.0;
2156	  }else if (qcheq < 0.0) {
2157	    tconst = -tconst;
2158	  }else{
2159	  }
2160	  double gtau_drift = std::abs(tconst * qcheq);
2161	  double gtau_diff = 16.0 * t->u0temp * t->vtm / T0;
2162	  d->gtau =  gtau_drift + gtau_diff;
2163	  d->cqgb = -(d->cggb + d->cbgb);
2164	  d->cqdb = -(d->cgdb + d->cbdb);
2165	  d->cqsb = -(d->cgsb + d->cbsb);
2166	  d->cqbb = d->cggb +d->cgdb +d->cgsb +d->cbgb +d->cbdb +d->cbsb;
2167
2168	  d->qbulk = d->qgate = d->qdrn = qsrc = 0.0;
2169	  d->cggb = d->cgsb = d->cgdb = 0.0;
2170	  d->cdgb = d->cdsb = d->cddb = 0.0;
2171	  d->cbgb = d->cbsb = d->cbdb = 0.0;
2172#if 0
2173	  *(ckt->CKTstate0 + d->qcheq) = qcheq;
2174	  if (ckt->CKTmode & MODEINITTRAN)
2175	    *(ckt->CKTstate1 + d->qcheq) = *(ckt->CKTstate0 + d->qcheq);
2176	  error = NIintegrate(ckt, &geq, &ceq, 0.0, d->qcheq);
2177	  if (error) return (error);
2178#endif
2179	}else{
2180	  d->gtau = 0.0;
2181	  d->cqgb = d->cqdb = d->cqsb = d->cqbb = 0.0;
2182	}
2183      }
2184    }
2185    trace0("mos7");
2186    trace3("", d->qgate, d->qdrn, d->qbulk);
2187    trace3("", d->cggb, d->cgsb, d->cgdb);
2188    trace3("", d->cdgb, d->cdsb, d->cddb);
2189    trace3("", d->cbgb, d->cbsb, d->cbdb);
2190
2191    trace2("", d->ids, d->gds);
2192    trace4("", d->gmf, d->gmr, d->gmbf, d->gmbr);
2193    trace4("", d->isub, d->gbbs, d->gbgs, d->gbds);
2194    trace4("", d->qgate, d->cggb, d->cgsb, d->cgdb);
2195    trace4("", d->qdrn, d->cdgb, d->cdsb, d->cddb);
2196    trace4("", d->qbulk, d->cbgb, d->cbsb, d->cbdb);
2197    trace1("", d->gtau);
2198    trace4("", d->cqgb, d->cqsb, d->cqdb, d->cqbb);
2199    trace1("", d->tconst);
2200    trace2("", d->cgb, d->qgb);
2201    trace2("", d->qgd, d->cgd);
2202    trace2("", d->qgs, d->cgs);
2203    trace3("", d->vgs, d->vds, d->vbs);
2204    trace3("", d->vdsat, d->vgst, d->von);
2205  }
2206}
2207/*--------------------------------------------------------------------------*/
2208/*--------------------------------------------------------------------------*/
2209