Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_VDMOS.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_VDMOS.C,v $
27 //
28 // Purpose : Implement the Vertical double-diffused power MOSFET
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 02/28/00
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.160 $
40 //
41 // Revision Date : $Date: 2014/05/22 17:40:30 $
42 //
43 // Current Owner : $Author: erkeite $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #include <N_UTL_Misc.h>
49 
50 #ifdef HAVE_CMATH
51 #include <cmath>
52 #else
53 #include <math.h>
54 #endif
55 
56 #ifdef HAVE_CLIMITS
57 #include <climits>
58 #else
59 #include <limits.h>
60 #endif
61 
62 
63 // ---------- Xyce Includes ----------
64 #include <N_DEV_Const.h>
65 #include <N_DEV_DeviceOptions.h>
66 #include <N_DEV_ExternData.h>
67 #include <N_DEV_MatrixLoadData.h>
68 #include <N_DEV_SolverState.h>
69 #include <N_DEV_VDMOS.h>
70 #include <N_DEV_Message.h>
71 #include <N_ERH_ErrorMgr.h>
72 
73 #include <N_DEV_MOSFET1.h>
74 
75 #include <N_LAS_Matrix.h>
76 #include <N_LAS_Vector.h>
77 
78 namespace Xyce {
79 namespace Device {
80 
81 
82 namespace VDMOS {
83 
84 
86 {
87 // Set up map for normal (double) param variables:
88  p.addPar ("L", 0.0, false, ParameterType::NO_DEP,
90  NULL, U_METER, CAT_GEOMETRY, "Channel length");
91 
92  p.addPar ("W", 0.0, false, ParameterType::NO_DEP,
94  NULL, U_METER, CAT_GEOMETRY, "Channel width");
95 
96  p.addPar ("AD", 0.0, false, ParameterType::NO_DEP,
98  NULL, U_METER2, CAT_GEOMETRY, "Drain diffusion area");
99 
100  p.addPar ("AS", 0.0, false, ParameterType::NO_DEP,
102  NULL, U_METER2, CAT_GEOMETRY, "Source diffusion area");
103 
104  p.addPar ("NRD", 1.0, false, ParameterType::NO_DEP,
106  NULL, U_SQUARES, CAT_GEOMETRY, "Multiplier for RSH to yield parasitic resistance of drain");
107 
108  p.addPar ("NRS", 1.0, false, ParameterType::NO_DEP,
110  NULL, U_SQUARES, CAT_GEOMETRY, "Multiplier for RSH to yield parasitic resistance of source");
111 
112  p.addPar ("PD", 0.0, false, ParameterType::NO_DEP,
114  NULL, U_METER, CAT_GEOMETRY, "Drain diffusion perimeter");
115 
116  p.addPar ("PS", 0.0, false, ParameterType::NO_DEP,
118  NULL, U_METER, CAT_GEOMETRY, "Source diffusion perimeter");
119 
120  p.addPar ("M", 1.0, false, ParameterType::NO_DEP,
122  NULL, U_NONE, CAT_CONTROL, "Multiplier for M devices connected in parallel");
123 
124  p.addPar ("TEMP", 0.0, false, ParameterType::TIME_DEP,
126  NULL, STANDARD, CAT_NONE, "Device temperature");
127 }
128 
130 {
131  p.addPar ("L0", 0.0, false, ParameterType::NO_DEP,
132  &VDMOS::Model::l0, NULL,
133  U_METER, CAT_GEOMETRY, "Gate length of nominal device");
134 
135  p.addPar ("W0", 0.0, false, ParameterType::NO_DEP,
136  &VDMOS::Model::w0, NULL,
137  U_METER, CAT_GEOMETRY, "Gate width of nominal device");
138 
139  p.addPar ("VTO", 0.0, false, ParameterType::NO_DEP,
140  &VDMOS::Model::vt0, NULL,
141  U_VOLT, CAT_VOLT, "Zero-bias threshold voltage");
142 
143  p.addPar ("PHI", 0.6, false, ParameterType::NO_DEP,
144  &VDMOS::Model::phi, NULL,
145  U_VOLT, CAT_PROCESS, "Surface potential");
146 
147  p.addPar ("RD", 0.0, false, ParameterType::MIN_RES,
149  U_OHM, CAT_RES, "Drain ohmic resistance");
150 
151  p.addPar ("RG", 0.0, false, ParameterType::NO_DEP,
153  U_OHM, CAT_RES, "Gate ohmic resistance");
154 
155  p.addPar ("RS", 0.0, false, ParameterType::MIN_RES,
157  U_OHM, CAT_RES, "Source ohmic resistance");
158 
159  p.addPar ("CBD", 0.0, false, ParameterType::MIN_CAP,
162  U_FARAD, CAT_CAP, "Zero-bias bulk-drain p-n capacitance");
163 
164  p.addPar ("CBS", 0.0, false, ParameterType::MIN_CAP,
167  U_FARAD, CAT_CAP, "Zero-bias bulk-source p-n capacitance");
168 
169  p.addPar ("TS", 0.0, false, ParameterType::NO_DEP,
172 
173  p.addPar ("IS", 1e-14, false, ParameterType::NO_DEP,
175  U_AMP, CAT_CURRENT, "Bulk p-n saturation current");
176 
177  p.addPar ("PB", 0.8, false, ParameterType::NO_DEP,
179  U_VOLT, CAT_VOLT, "Bulk p-n bottom potential");
180 
181  p.addPar ("CGSO", 0.0, false, ParameterType::NO_DEP,
183  U_FARADMM1, CAT_CAP, "Gate-source overlap capacitance/channel width");
184 
185  p.addPar ("CGDO", 0.0, false, ParameterType::NO_DEP,
187  U_FARADMM1, CAT_CAP, "Gate-drain overlap capacitance/channel width");
188 
189  p.addPar ("CGBO", 0.0, false, ParameterType::NO_DEP,
191  U_FARADMM1, CAT_CAP, "Gate-bulk overlap capacitance/channel length");
192 
193  p.addPar ("RSH", 0.0, false, ParameterType::NO_DEP,
195  U_OHM, CAT_RES, "Drain, source diffusion sheet resistance");
196 
197  p.addPar ("CJ", 0.0, false, ParameterType::NO_DEP,
200  U_FARADMM2, CAT_CAP, "Bulk p-n zero-bias bottom capacitance/area");
201 
202  p.addPar ("MJ", 0.5, false, ParameterType::NO_DEP,
204  U_NONE, CAT_DOPING, "Bulk p-n bottom grading coefficient");
205 
206  p.addPar ("CJSW", 0.0, false, ParameterType::NO_DEP,
209  U_FARADMM2, CAT_CAP, "Bulk p-n zero-bias sidewall capacitance/area");
210 
211  p.addPar ("MJSW", 0.5, false, ParameterType::NO_DEP,
213  U_NONE, CAT_DOPING, "Bulk p-n sidewall grading coefficient");
214 
215  p.addPar ("JS", 0.0, false, ParameterType::NO_DEP,
217  U_AMPMM2, CAT_PROCESS, "Bulk p-n saturation current density");
218 
219  p.addPar ("TOX", 1e-7, false, ParameterType::NO_DEP,
221  U_METER, CAT_GEOMETRY, "Gate oxide thickness");
222 
223  p.addPar ("LD", 0.0, false, ParameterType::NO_DEP,
224  &VDMOS::Model::latDiff, NULL,
225  U_METER, CAT_DOPING, "Lateral diffusion length");
226 
227  p.addPar ("UO", 280., false, ParameterType::NO_DEP,
229  U_CMM2VM1SM1, ParameterCategory(CAT_PROCESS | UNDOCUMENTED), "Surface mobility");
230 
231  p.addPar ("U0", 280., false, ParameterType::NO_DEP,
233  U_CMM2VM1SM1, CAT_PROCESS, "Surface mobility");
234 
235  p.addPar ("FC", 0.5, false, ParameterType::NO_DEP,
237  U_NONE, CAT_CAP, "Coefficient for forward-bias depletion capacitance formula");
238 
239  p.addPar ("NSUB", 0.0, false, ParameterType::NO_DEP,
241  U_CMM3, CAT_DOPING, "Substrate doping density");
242 
243  p.addPar ("NSS", 0.0, false, ParameterType::NO_DEP,
245  U_CMM2, CAT_PROCESS, "Surface state density");
246 
247  p.addPar ("TNOM", 0.0, false, ParameterType::NO_DEP,
248  &VDMOS::Model::tnom, NULL,
249  STANDARD, CAT_NONE, "");
250 
251  p.addPar ("VMAX", 4e+4, false, ParameterType::NO_DEP,
253  U_MSM1, CAT_PROCESS, "Maximum drift velocity for carriers");
254 
255  p.addPar ("XJ", 0.0, false, ParameterType::NO_DEP,
257  U_METER, CAT_GEOMETRY, "Metallurgical junction depth");
258 
259  p.addPar ("LAMBDA", 0.048, false, ParameterType::NO_DEP,
260  &VDMOS::Model::lambda, NULL,
261  U_VOLTM1, CAT_PROCESS, "Output conductance parameter");
262 
263  p.addPar ("DELTA", 5.0, false, ParameterType::NO_DEP,
264  &VDMOS::Model::delta, NULL,
265  U_NONE, CAT_NONE, "Transition width parameter");
266 
267  p.addPar ("ETA", 1.32, false, ParameterType::NO_DEP,
268  &VDMOS::Model::eta, NULL,
269  U_NONE, CAT_NONE, "Subthreshold ideality factor");
270 
271  p.addPar ("M", 4.0, false, ParameterType::NO_DEP,
272  &VDMOS::Model::m, NULL,
273  U_NONE, CAT_CONTROL, "Knee shape parameter");
274 
275  p.addPar ("MC", 3.0, false, ParameterType::NO_DEP,
276  &VDMOS::Model::mc, NULL,
278 
279  p.addPar ("SIGMA0", 0.048, false, ParameterType::NO_DEP,
280  &VDMOS::Model::sigma0, NULL,
281  U_NONE, CAT_NONE, "DIBL parameter");
282 
283  p.addPar ("VSIGMAT", 1.7, false, ParameterType::NO_DEP,
284  &VDMOS::Model::vsigmat, NULL,
285  U_VOLT, CAT_VOLT, "DIBL parameter");
286 
287  p.addPar ("VSIGMA", 0.2, false, ParameterType::NO_DEP,
288  &VDMOS::Model::vsigma, NULL,
289  U_VOLT, CAT_VOLT, "DIBL parameter");
290 
291  p.addPar ("THETA", 0.0, false, ParameterType::NO_DEP,
292  &VDMOS::Model::theta, NULL,
293  U_MVM1, CAT_PROCESS, "Mobility degradation parameter");
294 
295  p.addPar ("GAMMAS0", 0.5, false, ParameterType::NO_DEP,
296  &VDMOS::Model::gammas0, NULL,
297  U_VOLTMH, CAT_NONE, "Body effect constant in front of square root term");
298 
299  p.addPar ("GAMMAL0", 0.0, false, ParameterType::NO_DEP,
300  &VDMOS::Model::gammal0, NULL,
301  U_NONE, CAT_NONE, "Body effect constant in front of linear term");
302 
303  p.addPar ("LGAMMAS", 0.0, false, ParameterType::NO_DEP,
304  &VDMOS::Model::lgammas, NULL,
305  U_VOLTMH, CAT_NONE, "Sensitivity of gS on device length");
306 
307  p.addPar ("WGAMMAS", 0.0, false, ParameterType::NO_DEP,
308  &VDMOS::Model::wgammas, NULL,
309  U_VOLTMH, CAT_NONE, "Sensitivity of gS on device width");
310 
311  p.addPar ("LGAMMAL", 0.0, false, ParameterType::NO_DEP,
312  &VDMOS::Model::lgammal_, NULL,
313  U_NONE, CAT_NONE, "Sensitivity of gL on device length");
314 
315  p.addPar ("WGAMMAL", 0.0, false, ParameterType::NO_DEP,
316  &VDMOS::Model::wgammal, NULL,
317  U_NONE, CAT_NONE, "Sensitivity of gL on device width");
318 
319  p.addPar ("K", 0.0, false, ParameterType::NO_DEP,
320  &VDMOS::Model::k, NULL,
322 
323  p.addPar ("KVT", 0.0, false, ParameterType::NO_DEP,
324  &VDMOS::Model::kvt, NULL,
326 
327  p.addPar ("MDTEMP", 0.0, false, ParameterType::NO_DEP,
328  &VDMOS::Model::mdtemp, NULL,
330 
331  p.addPar ("KVS", 0.0, false, ParameterType::NO_DEP,
332  &VDMOS::Model::kvs, NULL,
334 
335  p.addPar ("TVS", 0.0, false, ParameterType::NO_DEP,
336  &VDMOS::Model::tvs, NULL,
338 
339  p.addPar ("MTH", 0.0, false, ParameterType::NO_DEP,
340  &VDMOS::Model::mth, NULL,
342 
343  p.addPar ("ARTD", 0.0, false, ParameterType::NO_DEP,
344  &VDMOS::Model::artd, NULL,
346 
347  p.addPar ("BRTD", 0.035, false, ParameterType::NO_DEP,
348  &VDMOS::Model::brtd, NULL,
350 
351  p.addPar ("CRTD", 0.1472, false, ParameterType::NO_DEP,
352  &VDMOS::Model::crtd, NULL,
354 
355  p.addPar ("DRTD", 0.0052, false, ParameterType::NO_DEP,
356  &VDMOS::Model::drtd, NULL,
358 
359  p.addPar ("NRTD", 0.115, false, ParameterType::NO_DEP,
360  &VDMOS::Model::nrtd, NULL,
362 
363  p.addPar ("N2", 1.0, false, ParameterType::NO_DEP,
364  &VDMOS::Model::n2, NULL,
366 
367  p.addPar ("XQC", 0.6, false, ParameterType::NO_DEP,
368  &VDMOS::Model::xqc, NULL,
369  U_NONE, CAT_PROCESS, "Charge partitioning factor");
370 
371  p.addPar ("MCV", 10.0, false, ParameterType::NO_DEP,
372  &VDMOS::Model::mcv, NULL,
373  U_NONE, CAT_GEOMETRY, "Transition width parameter used by the charge partitioning scheme");
374 
375  p.addPar ("VFB", 0.0, false, ParameterType::NO_DEP,
376  &VDMOS::Model::vfb, NULL,
377  U_VOLT, CAT_VOLT, "Flat band voltage");
378 
379  p.addPar ("ALPHA", 0.0, false, ParameterType::NO_DEP,
380  &VDMOS::Model::alpha, NULL,
381  U_NONE, CAT_NONE, "Parameter accounting for the threshold dependence on the channel potential");
382 
383  p.addPar ("LS", 35e-9, false, ParameterType::NO_DEP,
384  &VDMOS::Model::ls, NULL,
386 
387  p.addPar ("RSUB", 0.0, false, ParameterType::NO_DEP,
388  &VDMOS::Model::rsub, NULL,
390 
391  p.addPar ("VP", 0.0, false, ParameterType::NO_DEP,
395 
396  p.addPar ("AI", 2e+9, false, ParameterType::NO_DEP,
397  &VDMOS::Model::ai, NULL,
399 
400  p.addPar ("BI", 8e+8, false, ParameterType::NO_DEP,
401  &VDMOS::Model::bi, NULL,
403 
404  p.addPar ("DELMAX", 0.9, false, ParameterType::NO_DEP,
405  &VDMOS::Model::delmax, NULL,
407 
408  p.addPar ("MD", 2.0, false, ParameterType::NO_DEP,
409  &VDMOS::Model::md, NULL,
411 
412  p.addPar ("DRIFTPARAMA", 0.08, false, ParameterType::NO_DEP,
414  U_OHM, CAT_RES, "Drift region resistance intercept parameter");
415 
416  p.addPar ("DRIFTPARAMB", 0.013, false, ParameterType::NO_DEP,
418  U_OHMPV, CAT_RES, "Drift region resistance slope parameter");
419 
420  p.addPar ("RDSSHUNT", 0.0, false, ParameterType::NO_DEP,
421  &VDMOS::Model::rdsshunt, NULL,
422  U_OHM, CAT_RES, "Drain-source shunt resistance");
423 
424  p.addPar ("D1IS", 1e-14, false, ParameterType::NO_DEP,
426  U_AMP, CAT_CURRENT, "Drain-Source diode saturation current");
427 
428  p.addPar ("D1RS", 0.0, false, ParameterType::NO_DEP,
430  U_OHM, CAT_RES, "Drain-source diode ohmic resistance");
431 
432  p.addPar ("D1N", 1.0, false, ParameterType::NO_DEP,
434  U_NONE, CAT_PROCESS, "Drain-source diode emission coefficient");
435 
436  p.addPar ("D1TT", 0.0, false, ParameterType::NO_DEP,
438  U_SECOND, CAT_PROCESS, "Drain-source diode transit time");
439 
440  p.addPar ("D1CJO", 0.0, false, ParameterType::NO_DEP,
442  U_FARAD, CAT_CAP, "Drain-source diode junction capacitance");
443 
444  p.addPar ("D1VJ", 1.0, false, ParameterType::NO_DEP,
446  U_VOLT, CAT_VOLT, "Drain-source diode junction potential");
447 
448  p.addPar ("D1M", 0.5, false, ParameterType::NO_DEP,
450  U_NONE, CAT_PROCESS, "Drain-source diode grading coefficient");
451 
452  p.addPar ("D1EG", 1.11, false, ParameterType::NO_DEP,
454  U_EV, CAT_PROCESS, "Drain-source diode activation energy");
455 
456  p.addPar ("D1XTI", 3.0, false, ParameterType::NO_DEP,
458  U_NONE, CAT_PROCESS, "Drain-source diode sat. current temperature exponent");
459 
460  p.addPar ("D1FC", 0.5, false, ParameterType::NO_DEP,
462  U_NONE, CAT_CAP, "Drain-source diode forward bias depletion capacitance");
463 
464  p.addPar ("D1BV", 1E99, false, ParameterType::NO_DEP,
467  U_VOLT, CAT_VOLT, "Drain-source diode reverse breakdown voltage");
468 
469  p.addPar ("D1IBV", 1e-3, false, ParameterType::NO_DEP,
471  U_AMP, CAT_CURRENT, "Drain-source diode current at breakdown voltage");
472 
473  p.addPar ("D1IKF", 0.0, false, ParameterType::NO_DEP,
474  &VDMOS::Model::D1DIOikf, NULL,
475  U_AMP, CAT_CURRENT, "Drain-source diode high injection knee currrent");
476 
477  p.addPar ("D1ISR", 0.0, false, ParameterType::NO_DEP,
478  &VDMOS::Model::D1DIOisr, NULL,
479  U_AMP, CAT_CURRENT, "Drain-source diode recombination saturation current");
480 
481  p.addPar ("D1NR", 2.0, false, ParameterType::NO_DEP,
482  &VDMOS::Model::D1DIOnr, NULL,
483  U_NONE, CAT_PROCESS, "Drain-source diode recombination emission coefficient");
484 
485  p.addPar ("D1KF", 0.0, false, ParameterType::NO_DEP,
487  U_NONE, CAT_FLICKER, "Drain-source diode flicker noise coefficient");
488 
489  p.addPar ("D1AF", 1.0, false, ParameterType::NO_DEP,
491  U_NONE, CAT_FLICKER, "Drain-source diode flicker noise exponent");
492 
493  p.addPar ("D1TNOM", 300.15, false, ParameterType::NO_DEP,
495  U_DEGC, CAT_TEMP, "Drain-source diode nominal temperature");
496 
497  // Set up non-double precision variables:
498  p.addPar ("TPG", 1, false, ParameterType::NO_DEP,
499  &VDMOS::Model::gateType, NULL,
500  U_NONE, CAT_MATERIAL, "Gate material type (-1 = same as substrate,"
501  " 0 = aluminum, 1 = opposite of substrate)");
502  p.addPar ("CV", 1, false, ParameterType::NO_DEP,
503  &VDMOS::Model::cv, NULL,
504  U_NONE, CAT_CONTROL, "Charge model storage selector");
505  p.addPar ("CVE", 1, false, ParameterType::NO_DEP,
506  &VDMOS::Model::cve, NULL,
507  U_NONE, CAT_CONTROL, "Meyer-like capacitor model selector");
508  p.addPar ("FPE", 1, false, ParameterType::NO_DEP,
509  &VDMOS::Model::fpe, NULL,
510  U_NONE, CAT_CONTROL, "Charge partitioning scheme selector");
511  p.addPar ("ISUBMOD", 0, false, ParameterType::NO_DEP,
512  &VDMOS::Model::isubmod, NULL,
514 
516 }
517 
518 
519 
520 std::vector< std::vector<int> > Instance::jacStamp_DC_SC_GC;
521 std::vector< std::vector<int> > Instance::jacStamp_DC_GC;
522 std::vector< std::vector<int> > Instance::jacStamp_SC_GC;
523 std::vector< std::vector<int> > Instance::jacStamp_DC_SC;
524 std::vector< std::vector<int> > Instance::jacStamp_GC;
525 std::vector< std::vector<int> > Instance::jacStamp_SC;
526 std::vector< std::vector<int> > Instance::jacStamp_DC;
527 std::vector< std::vector<int> > Instance::jacStamp;
528 
529 std::vector<int> Instance::jacMap_DC_SC_GC;
530 std::vector<int> Instance::jacMap_DC_GC;
531 std::vector<int> Instance::jacMap_SC_GC;
532 std::vector<int> Instance::jacMap_DC_SC;
533 std::vector<int> Instance::jacMap_GC;
534 std::vector<int> Instance::jacMap_SC;
535 std::vector<int> Instance::jacMap_DC;
536 std::vector<int> Instance::jacMap;
537 
538 std::vector< std::vector<int> > Instance::jacMap2_DC_SC_GC;
539 std::vector< std::vector<int> > Instance::jacMap2_DC_GC;
540 std::vector< std::vector<int> > Instance::jacMap2_SC_GC;
541 std::vector< std::vector<int> > Instance::jacMap2_DC_SC;
542 std::vector< std::vector<int> > Instance::jacMap2_GC;
543 std::vector< std::vector<int> > Instance::jacMap2_SC;
544 std::vector< std::vector<int> > Instance::jacMap2_DC;
545 std::vector< std::vector<int> > Instance::jacMap2;
546 
547 // duplicating, but with RD1RS nonzero
548 std::vector< std::vector<int> > Instance::jacStamp_D1C_DC_SC_GC;
549 std::vector< std::vector<int> > Instance::jacStamp_D1C_DC_GC;
550 std::vector< std::vector<int> > Instance::jacStamp_D1C_SC_GC;
551 std::vector< std::vector<int> > Instance::jacStamp_D1C_DC_SC;
552 std::vector< std::vector<int> > Instance::jacStamp_D1C_GC;
553 std::vector< std::vector<int> > Instance::jacStamp_D1C_SC;
554 std::vector< std::vector<int> > Instance::jacStamp_D1C_DC;
555 std::vector< std::vector<int> > Instance::jacStamp_D1C;
556 
557 std::vector<int> Instance::jacMap_D1C_DC_SC_GC;
558 std::vector<int> Instance::jacMap_D1C_DC_GC;
559 std::vector<int> Instance::jacMap_D1C_SC_GC;
560 std::vector<int> Instance::jacMap_D1C_DC_SC;
561 std::vector<int> Instance::jacMap_D1C_GC;
562 std::vector<int> Instance::jacMap_D1C_SC;
563 std::vector<int> Instance::jacMap_D1C_DC;
564 std::vector<int> Instance::jacMap_D1C;
565 
566 std::vector< std::vector<int> > Instance::jacMap2_D1C_DC_SC_GC;
567 std::vector< std::vector<int> > Instance::jacMap2_D1C_DC_GC;
568 std::vector< std::vector<int> > Instance::jacMap2_D1C_SC_GC;
569 std::vector< std::vector<int> > Instance::jacMap2_D1C_DC_SC;
570 std::vector< std::vector<int> > Instance::jacMap2_D1C_GC;
571 std::vector< std::vector<int> > Instance::jacMap2_D1C_SC;
572 std::vector< std::vector<int> > Instance::jacMap2_D1C_DC;
573 std::vector< std::vector<int> > Instance::jacMap2_D1C;
574 
575 //--------------------- Class Model ----------------------------
576 
577 //-----------------------------------------------------------------------------
578 // Function : Model::Model
579 // Purpose :
580 // Special Notes :
581 // Scope : public
582 // Creator : Tom Russo, Component Information and Models
583 // Creation Date : 2/26/01
584 //-----------------------------------------------------------------------------
586  const Configuration & configuration,
587  const ModelBlock & MB,
588  const FactoryBlock & factory_block)
589  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
590  dtype(CONSTNMOS),
591  gateType(0),
592 
593  l0(2e-6),
594  w0(2e-5),
595  tnom(getDeviceOptions().tnom),
596  latDiff(0.0),
597  jctSatCurDensity(0.0),
598  jctSatCur(0.0),
599  drainResistance(0.0),
600  gateResistance(0.0),
601  sourceResistance(0.0),
602  sheetResistance(0.0),
603  gateSourceOverlapCapFactor(0.0),
604  gateDrainOverlapCapFactor(0.0),
605  gateBulkOverlapCapFactor(0.0),
606  oxideCapFactor(0.0),
607  vt0(0.0),
608  capBD(0.0),
609  capBS(0.0),
610  timeScale(0.0),
611  bulkCapFactor(0.0),
612  sideWallCapFactor(0.0),
613  bulkJctPotential(0.0),
614  bulkJctBotGradingCoeff(0.0),
615  bulkJctSideGradingCoeff(0.0),
616  fwdCapDepCoeff(0.0),
617  phi(0.0),
618  gamma(0.0),
619  lambda(0.0),
620  substrateDoping(0.0),
621  surfaceStateDensity(0.0),
622  oxideThickness(0.0),
623  surfaceMobility(0.0),
624  surfaceMobility0(0.0),
625 
626  capBDGiven(0),
627  capBSGiven(0),
628  bulkCapFactorGiven(0),
629  sideWallCapFactorGiven(0),
630  vpGiven(0),
631 
632  maxDriftVel(0.0),
633  junctionDepth(0.0),
634  rdi(0.0),
635  rsi(0.0),
636 
637  delta(5.0),
638  eta(1.32),
639  m(4.0),
640  mc(3.0),
641  sigma0(0.048),
642  vsigmat(1.7),
643  vsigma(0.2),
644  theta(0.0),
645  gammas0(0.5),
646  gammal0(0.0),
647  lgammas(0.0),
648  wgammas(0.0),
649  lgammal_(0.0),
650  wgammal(0.0),
651  kacc(0.0),
652  gb(0.0),
653  knit(0.0),
654  nitd(0.0),
655  nits(0.0),
656  mm(0.5),
657  k(0.0),
658  deltaSqr(0.0),
659  kvt(0.0),
660  mdtemp(0.0),
661  kvs(0.0),
662  tvs(0.0),
663  mth(0.0),
664  artd(0.0),
665  brtd(0.035),
666  crtd(0.1472),
667  drtd(0.0052),
668  nrtd(0.115),
669  n2(1.0),
670 
671  xqc(0.6),
672  mcv(10.0),
673  vfb(0.0),
674  fpe(1),
675  alpha(1.05),
676 
677  cv(1),
678  cve(1),
679  ls(35e-9),
680  rsub(0.0),
681  vp(0.0),
682  ai(2e9),
683  bi(8e8),
684  delmax(0.9),
685  md(2.0),
686  isubmod(0),
687 
688  kaccd(0.0),
689  kaccs(0.0),
690  invm(0.0),
691  invmc(0.0),
692  invmd(0.0),
693 
694  fact1(0.0),
695  vtnom(0.0),
696  egfet1(0.0),
697  pbfact1(0.0),
698 
699  driftParamA(0.08),
700  driftParamB(0.013),
701  rdsshunt(0.0),
702 
703  D1DIOsatCur(0.0),
704  D1DIOresist(0.0),
705  D1DIOconductance(0.0),
706  D1DIOemissionCoeff(0.0),
707  D1DIOtransitTime(0.0),
708  D1DIOjunctionCap(0.0),
709  D1DIOjunctionPot(0.0),
710  D1DIOgradingCoeff(0.0),
711  D1DIOactivationEnergy(0.0),
712  D1DIOsaturationCurrentExp(0.0),
713  D1DIOdepletionCapCoeff(0.0),
714  D1DIObreakdownVoltage(0.0),
715  D1DIObreakdownCurrent(0.0),
716  D1DIOf2(0.0),
717  D1DIOf3(0.0),
718  D1DIOnomTemp(0.0),
719  D1DIOfNcoef(0.0),
720  D1DIOfNexp(0.0),
721  D1DIOikf(0.0),
722  D1DIOisr(0.0),
723  D1DIOnr(0.0),
724  D1DIObreakdownVoltageGiven(0)
725 
726 {
727 
728  if (getType() != "")
729  {
730  if (getType() == "NMOS") {
731  dtype = CONSTNMOS;
732  }
733  else if (getType() == "PMOS") {
734  dtype = CONSTPMOS;
735  }
736  else
737  {
738  UserError0(*this) << "Could not recognize the type for model " << getName();
739  }
740  }
741 
742 
743  // Set params to constant default values:
744  setDefaultParams ();
745 
746  // Set params according to .model line and constant defaults from metadata:
747  setModParams (MB.params);
748 
749  // Set any non-constant parameter defaults:
750  if (!given("TNOM"))
752  if (!given("L0"))
754  if (!given("W0"))
756  if (!given("ALPHA"))
757  alpha = (dtype == CONSTNMOS) ? 1.05 : 1.3;
758  if (capBD != 0)
759  capBDGiven = true;
760  if (capBS != 0)
761  capBSGiven = true;
762 
763  // Calculate any parameters specified as expressions:
764 
766 
767  // calculate dependent (ie computed) params and check for errors:
768  if (given("U0"))
769  {
770  if (given("UO"))
771  UserError0(*this) << "Both uo and u0 have been specified and, which is not allowed";
772  else
773  UserWarning0(*this) << "Surface mobility has been specified as u0 instead of uo, uo is the preferred syntax";
774 
776  }
777 
778  if(eta == 0)
779  {
780  UserError0(*this) << "ETA cannot be zero for level 18";
781  }
782 
783  if(driftParamA == 0 && driftParamB == 0)
784  {
785  UserError0(*this) << "Both driftParamA and driftParamB cannot be zero";
786  }
787 
788  if(cv != 1 && cv != 2)
789  {
790  UserError0(*this) << "Model error: use cv=1 (Meyer's model) or cv=2 (Meyer-like Model)";
791  }
792 
793  if(fpe != 1 && fpe != 2 && fpe != 3)
794  {
795  UserError0(*this) << "Model error: use fpe=1 (and xqc), fpe=2 (and xqc,mcv) or fpe=3";
796  }
797 
798  if(mcv <= 1)
799  {
800  UserError0(*this) << "Model error: charge conservation requires mcv > 1";
801  }
802 
803  if(xqc > 1 || xqc < 0.5)
804  {
805  UserError0(*this) << "Model error: charge conservation requires 0.5 <= xqc <= 1.0";
806  }
807 
808  // New version of VDMOSModel. We have to set lambda to zero
809  if(isubmod) lambda = 0.0;
810 
811  // limit diode #1 parameters
812  // limit grading coeff to max of 0.9
813  if(D1DIOgradingCoeff > 0.9)
814  {
815  UserWarning0(*this) << "grading coefficient too large, limited to 0.9";
816  D1DIOgradingCoeff = 0.9;
817  }
818 
819  // limit activation energy to min of 0.1
820  if(D1DIOactivationEnergy < 0.1)
821  {
822  UserWarning0(*this) << "activation energy too small, limited to 0.1";
823  D1DIOactivationEnergy = 0.1;
824  }
825 
826  // limit depletion cap coeff to max of 0.95
827  if(D1DIOdepletionCapCoeff > 0.95)
828  {
829  UserWarning0(*this) << "coefficient Fc too large, limited to 0.95";
830  D1DIOdepletionCapCoeff = 0.95;
831  }
832 
833  processParams ();
834 
835 #ifdef Xyce_DEBUG_DEVICE
836  if (getDeviceOptions().debugLevel > 0)
837  {
838  Xyce::dout() << " " << std::endl;
839  Xyce::dout() << "l0 " << l0 << std::endl;
840  Xyce::dout() << "w0 " << w0 << std::endl;
841  Xyce::dout() << "vt0 = " << vt0 << std::endl;
842  Xyce::dout() << "gamma = " << gamma << std::endl;
843  Xyce::dout() << "lambda = " << lambda << std::endl;
844  Xyce::dout() << "phi = " << phi << std::endl;
845  Xyce::dout() << "drainResistance = " << drainResistance << std::endl;
846  Xyce::dout() << "gateResistance = " << gateResistance << std::endl;
847  Xyce::dout() << "sourceResistance = " << sourceResistance << std::endl;
848  Xyce::dout() << "capBD = " << capBD << std::endl;
849  Xyce::dout() << "capBS = " << capBS << std::endl;
850  Xyce::dout() << "timeScale = " << timeScale << std::endl;
851  Xyce::dout() << "jctSatCur = " << jctSatCur << std::endl;
852  Xyce::dout() << "bulkJctPotential = " << bulkJctPotential << std::endl;
853  Xyce::dout() << "gateSourceOverlapCapFactor = " << gateSourceOverlapCapFactor << std::endl;
854  Xyce::dout() << "gateDrainOverlapCapFactor = " << gateDrainOverlapCapFactor << std::endl;
855  Xyce::dout() << "gateBulkOverlapCapFactor = " << gateBulkOverlapCapFactor << std::endl;
856  Xyce::dout() << "sheetResistance = " << sheetResistance << std::endl;
857  Xyce::dout() << "bulkCapFactor = " << bulkCapFactor << std::endl;
858  Xyce::dout() << "bulkJctBotGradingCoeff = " << bulkJctBotGradingCoeff << std::endl;
859  Xyce::dout() << "sideWallCapFactor = " << sideWallCapFactor << std::endl;
860  Xyce::dout() << "bulkJctSideGradingCoeff = " << bulkJctSideGradingCoeff << std::endl;
861  Xyce::dout() << "jctSatCurDensity = " << jctSatCurDensity << std::endl;
862  Xyce::dout() << "oxideThickness = " << oxideThickness << std::endl;
863  Xyce::dout() << "oxideCapFactor = " << oxideCapFactor << std::endl;
864  Xyce::dout() << "latDiff = " << latDiff << std::endl;
865  Xyce::dout() << "surfaceMobility = " << surfaceMobility << std::endl;
866  Xyce::dout() << "fwdCapDepCoeff = " << fwdCapDepCoeff << std::endl;
867  Xyce::dout() << "substrateDoping = " << substrateDoping << std::endl;
868  Xyce::dout() << "gateType = " << gateType << std::endl;
869  Xyce::dout() << "surfaceStateDensity = " << surfaceStateDensity << std::endl;
870  Xyce::dout() << "tnom = " << tnom << std::endl;
871  Xyce::dout() << "driftParamA = " << driftParamA << std::endl;
872  Xyce::dout() << "driftParamB = " << driftParamB << std::endl;
873  Xyce::dout() << "rdsshunt = " << rdsshunt << std::endl;
874  }
875 #endif
876 
877 }
878 
879 //-----------------------------------------------------------------------------
880 // Function : Model::~Model
881 // Purpose : destructor
882 // Special Notes :
883 // Scope : public
884 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
885 // Creation Date : 3/16/00
886 //-----------------------------------------------------------------------------
888 {
889  std::vector<Instance*>::iterator iter;
890  std::vector<Instance*>::iterator first = instanceContainer.begin();
891  std::vector<Instance*>::iterator last = instanceContainer.end();
892 
893  for (iter=first; iter!=last; ++iter)
894  {
895  delete (*iter);
896  }
897 
898 }
899 
900 
901 //-----------------------------------------------------------------------------
902 // Function : Model::printOutInstances
903 // Purpose : debugging tool.
904 // Special Notes :
905 // Scope : public
906 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
907 // Creation Date : 4/03/00
908 //-----------------------------------------------------------------------------
909 std::ostream &Model::printOutInstances(std::ostream &os) const
910 {
911  std::vector<Instance*>::const_iterator iter;
912  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
913  std::vector<Instance*>::const_iterator last = instanceContainer.end();
914 
915  int i;
916  os << std::endl;
917  os << " name model name Parameters" << std::endl;
918  for (i=0, iter=first; iter!=last; ++iter, ++i)
919  {
920  os << " " << i << ": " << (*iter)->getName() << "\t";
921  os << getName();
922  os << std::endl;
923  }
924 
925  os << std::endl;
926 
927  return os;
928 }
929 
930 //-----------------------------------------------------------------------------
931 // Function : Model::forEachInstance
932 // Purpose :
933 // Special Notes :
934 // Scope : public
935 // Creator : David Baur
936 // Creation Date : 2/4/2014
937 //-----------------------------------------------------------------------------
938 /// Apply a device instance "op" to all instances associated with this
939 /// model
940 ///
941 /// @param[in] op Operator to apply to all instances.
942 ///
943 ///
944 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
945 {
946  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
947  op(*it);
948 }
949 
950 
951 //-----------------------------------------------------------------------------
952 // Function : Model::processParams
953 // Purpose :
954 // Special Notes :
955 // Scope : public
956 // Creator : pmc
957 // Creation Date : 2/17/2004
958 //-----------------------------------------------------------------------------
960 {
961  double wkfngs(0.0);
962  double wkfng(0.0);
963  double fermig(0.0);
964  double fermis(0.0);
965  double kt1(0.0);
966  double arg1(0.0);
967 
970  kt1 = CONSTboltz * tnom;
971  egfet1 = 1.16-(7.02e-4*tnom*tnom)/(tnom+1108);
972  arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
973  pbfact1= -2*vtnom *(1.5*log(fact1)+CONSTQ*arg1);
974 
975 // assuming silicon - make definition for epsilon of silicon
976 //#define EPSSIL (11.7 * 8.854214871e-12) = CONSTEPSSI (the Xyce value)
977 
978  oxideCapFactor = 3.9 * 8.854214871e-12/oxideThickness;
979  if(given("NSUB"))
980  {
981  if(substrateDoping*1e6 >1.45e16)
982  {
983  if(!given("PHI"))
984  {
985  phi = 2*vtnom* log(substrateDoping*1e6/1.45e16);
986  phi = Xycemax(.1,phi);
987  }
988  fermis = dtype*0.5*phi;
989  wkfng = 3.2;
990  if(gateType != 0)
991  {
992  fermig = dtype *gateType*0.5*egfet1;
993  wkfng = 3.25 + 0.5 * egfet1 - fermig;
994  }
995  wkfngs = wkfng - (3.25 + 0.5 * egfet1 + fermis);
996  gamma = sqrt(2 * 11.70 * 8.854214871e-12 * CONSTQ
998  if(!given("GAMMAS0")) gammas0 = gamma;
999 
1000  if(!given("VTO"))
1001  {
1002  if(!given("NSS")) surfaceStateDensity=0;
1003  if(!given("VFB"))
1004  {
1006  }
1007  vt0 = vfb + dtype * (gamma * sqrt(phi)+ phi);
1008  }
1009  else
1010  {
1011  if(!given("VFB")) vfb = vt0 - dtype * (gamma * sqrt(phi)+ phi);
1012  }
1013  }
1014  else
1015  {
1016  UserError0(*this) << "SubstrateDoping is 0";
1017 
1018  substrateDoping = 0;
1019  }
1020  }
1021 
1022  if(!given("CJ"))
1023  {
1025  /(2*bulkJctPotential));
1026  }
1027  if(!given("VFB"))
1028  {
1029  if(fabs(vfb) < 1e-12) vfb = 1e-12;
1030  else vfb = vfb;
1031  }
1032 
1033  kaccd = kacc/(1+pow(k*nitd,mm));
1034  kaccs = kacc/(1+pow(k*nits,mm));
1035  deltaSqr = delta*delta;
1036 
1037  if(D1DIOresist == 0)
1038  D1DIOconductance = 0;
1039  else
1041 
1042  double D1xfc = log(1-D1DIOdepletionCapCoeff);
1043  D1DIOf2 = exp((1 + D1DIOgradingCoeff)*D1xfc);
1045 
1046  return true;
1047 }
1048 
1049 //----------------------------------------------------------------------------
1050 // Function : Model::processInstanceParams
1051 // Purpose :
1052 // Special Notes :
1053 // Scope : public
1054 // Creator : Dave Shirely, PSSI
1055 // Creation Date : 03/23/06
1056 //----------------------------------------------------------------------------
1058 {
1059 
1060  std::vector<Instance*>::iterator iter;
1061  std::vector<Instance*>::iterator first = instanceContainer.begin();
1062  std::vector<Instance*>::iterator last = instanceContainer.end();
1063 
1064  for (iter=first; iter!=last; ++iter)
1065  {
1066  (*iter)->processParams();
1067  }
1068 
1069  return true;
1070 }
1071 
1072 //------------------ Class Instance ----------------------------
1073 
1074 
1075 //-----------------------------------------------------------------------------
1076 // Function : Instance::Instance
1077 // Purpose : instance block constructor
1078 // Special Notes :
1079 // Scope : public
1080 // Creator : Tom Russo, Component Information and Models
1081 // Creation Date : 3/21/01
1082 //-----------------------------------------------------------------------------
1084  const Configuration & configuration,
1085  const InstanceBlock & IB,
1086  Model & Miter,
1087  const FactoryBlock & factory_block)
1088  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
1089  model_(Miter),
1090  dNode(0),
1091  gNode(0),
1092  sNode(0),
1093  bNode(0),
1094  dNodePrime(0),
1095  sNodePrime(0),
1096  dDriftNode(0),
1097  l(getDeviceOptions().defl),
1098  w(getDeviceOptions().defw),
1099  drainArea(getDeviceOptions().defad),
1100  sourceArea(getDeviceOptions().defas),
1101  drainSquares(1.0),
1102  sourceSquares(1.0),
1103  drainPerimeter(0.0),
1104  sourcePerimeter(0.0),
1105  sourceCond(0.0),
1106  gateCond(0.0),
1107  drainCond(0.0),
1108  draindriftCond(0.0),
1109  vt(0.0),
1110  gammas(0.0),
1111  gammal(0.0),
1112  gchi0(0.0),
1113  vtoo(0.0),
1114  vthLimit(0.0),
1115  numberParallel(1),
1116 
1117  temp(getDeviceOptions().temp.getImmutableValue<double>()),
1118  tSurfMob(0.0),
1119  tPhi(0.0),
1120  tVto(0.0),
1121  tSatCur(0.0),
1122  tSatCurDens(0.0),
1123  tCbd(0.0),
1124  tCbs(0.0),
1125  tCj(0.0),
1126  tCjsw(0.0),
1127  tBulkPot(0.0),
1128  tDepCap(0.0),
1129  tVbi(0.0),
1130 
1131  von(0.0),
1132  vdsat(0.0),
1133  vddsat(0.0),
1134  sourceVcrit(0.0),
1135  drainVcrit(0.0),
1136  draindriftVcrit(0.0),
1137  cd(0.0),
1138  cdd(0.0),
1139  gmbs(0.0),
1140  gm(0.0),
1141  gddd(0.0),
1142  dIdd_dVd(0.0),
1143  gds(0.0),
1144  gdds(0.0),
1145  gdsshunt(0.0),
1146  gbd(0.0),
1147  gbs(0.0),
1148  cbd(0.0),
1149  Cbd(0.0),
1150  Cbdsw(0.0),
1151  cbs(0.0),
1152  Cbs(0.0),
1153  Cbssw(0.0),
1154  f2d(0.0),
1155  f3d(0.0),
1156  f4d(0.0),
1157  f2s(0.0),
1158  f3s(0.0),
1159  f4s(0.0),
1160  mode(1),
1161  mode_low(0.0),
1162  mode_high(0.0),
1163  off(0),
1164  dNodePrimeSet(0),
1165  sNodePrimeSet(0),
1166  limitedFlag(false),
1167  //calculated quantities
1168  EffectiveLength(0),
1169  DrainSatCur(0),
1170  SourceSatCur(0),
1171  GateSourceOverlapCap(0),
1172  GateDrainOverlapCap(0),
1173  GateBulkOverlapCap(0),
1174  OxideCap(0),
1175 
1176  Isource(0.0),
1177  Igate(0.0),
1178  Idrain(0.0),
1179  Idraindrift(0.0),
1180  Irdsshunt(0.0),
1181  Ird1rs(0.0),
1182  mm1(0.0),
1183  dmm1vgs(0.0),
1184  dmm1vds(0.0),
1185  dmm1vbs(0.0),
1186  cdrain(0.0),
1187  cdraindrift(0.0),
1188 
1189  D1DIOoff1(0),
1190  D1DIOarea(1.0),
1191  D1DIOinitCond(0.0),
1192  D1DIOtemp(0.0),
1193  D1DIOtJctPot(0.0),
1194  D1DIOtJctCap(0.0),
1195  D1DIOtDepCap(0.0),
1196  D1DIOtSatCur(0.0),
1197  D1DIOtSatRCur(0.0),
1198  D1DIOtVcrit(0.0),
1199  D1DIOtF1(0.0),
1200  D1DIOtBrkdwnV(0.0),
1201  D1gspr(0.0),
1202  D1gd(0.0),
1203  D1cdeq(0.0),
1204  D1vt(0.0),
1205  D1vte(0.0),
1206  D1capd(0.0),
1207 
1208  D1DIOcapCharge(0.0),
1209  D1DIOcapCurrent(0.0),
1210 
1211  Vd (0.0),
1212  Vs (0.0),
1213  Vg (0.0),
1214  Vb (0.0),
1215  Vdp (0.0),
1216  Vgp (0.0),
1217  Vsp (0.0),
1218  Vdd (0.0),
1219  Vddp (0.0),
1220  Vddd (0.0),
1221  Vdddp (0.0),
1222  Vssp (0.0),
1223  Vbsp (0.0),
1224  Vbdp (0.0),
1225  Vggp (0.0),
1226  Vgpsp (0.0),
1227  Vgpdp (0.0),
1228  Vgpb (0.0),
1229  Vdpsp (0.0),
1230  Vbdd (0.0),
1231  D1vd (0.0),
1232  Capgs (0.0),
1233  Capgdd(0.0),
1234  Capgb (0.0),
1235  Gm (0.0),
1236  Gmbs (0.0),
1237  revsum(0.0),
1238  nrmsum(0.0),
1239 
1240  // solution,rhs vector:
1241  // local indices
1242  li_Drain (-1),
1243  li_DrainPrime (-1),
1244  li_Source (-1),
1245  li_SourcePrime (-1),
1246  li_Gate (-1),
1247  li_GatePrime (-1),
1248  li_Bulk (-1),
1249  li_DrainDrift (-1),
1250  li_D1Prime (-1),
1251 
1252  // jacobian matrix:
1253  // matrix and vector pointers:
1254  // drain row
1255  ADrainEquDrainNodeOffset (-1),
1256  ADrainEquSourceNodeOffset (-1),
1257  ADrainEquDrainDriftNodeOffset (-1),
1258  ADrainEquD1PrimeNodeOffset (-1),
1259  // gate row
1260  AGateEquGateNodeOffset (-1),
1261  AGateEquGatePrimeNodeOffset (-1),
1262  // source row
1263  ASourceEquDrainNodeOffset (-1),
1264  ASourceEquSourceNodeOffset (-1),
1265  ASourceEquSourcePrimeNodeOffset (-1),
1266  // bulk row
1267  ABulkEquBulkNodeOffset (-1),
1268  ABulkEquDrainPrimeNodeOffset (-1),
1269  ABulkEquGatePrimeNodeOffset (-1),
1270  ABulkEquSourcePrimeNodeOffset (-1),
1271  // drain' row
1272  ADrainPrimeEquBulkNodeOffset (-1),
1273  ADrainPrimeEquDrainPrimeNodeOffset (-1),
1274  ADrainPrimeEquGatePrimeNodeOffset (-1),
1275  ADrainPrimeEquSourcePrimeNodeOffset (-1),
1276  ADrainPrimeEquDrainDriftNodeOffset (-1),
1277  // gate' row
1278  AGatePrimeEquGateNodeOffset (-1),
1279  AGatePrimeEquBulkNodeOffset (-1),
1280  AGatePrimeEquDrainPrimeNodeOffset (-1),
1281  AGatePrimeEquGatePrimeNodeOffset (-1),
1282  AGatePrimeEquSourcePrimeNodeOffset (-1),
1283  // source' row
1284  ASourcePrimeEquSourceNodeOffset (-1),
1285  ASourcePrimeEquBulkNodeOffset (-1),
1286  ASourcePrimeEquDrainPrimeNodeOffset (-1),
1287  ASourcePrimeEquGatePrimeNodeOffset (-1),
1288  ASourcePrimeEquSourcePrimeNodeOffset (-1),
1289  // drain drift row
1290  ADrainDriftEquDrainNodeOffset (-1),
1291  ADrainDriftEquDrainPrimeNodeOffset (-1),
1292  ADrainDriftEquDrainDriftNodeOffset (-1),
1293  // D1Prime row
1294  AD1PrimeEquDrainNodeOffset (-1),
1295  AD1PrimeEquSourceNodeOffset (-1),
1296  AD1PrimeEquD1PrimeNodeOffset (-1),
1297 
1299  // F-matrix pointers:
1300  f_DrainEquDrainNodePtr(0),
1301  f_DrainEquSourceNodePtr(0),
1302  f_DrainEquDrainDriftNodePtr(0),
1303  f_DrainEquD1PrimeNodePtr(0),
1304 
1305  f_GateEquGateNodePtr(0),
1306  f_GateEquGatePrimeNodePtr(0),
1307 
1308  f_SourceEquDrainNodePtr(0),
1309  f_SourceEquSourceNodePtr(0),
1310  f_SourceEquSourcePrimeNodePtr(0),
1311  f_SourceEquD1PrimeNodePtr(0),
1312 
1313  f_BulkEquBulkNodePtr(0),
1314  f_BulkEquDrainPrimeNodePtr(0),
1315  f_BulkEquGatePrimeNodePtr(0),
1316  f_BulkEquSourcePrimeNodePtr(0),
1317 
1318  f_DrainPrimeEquBulkNodePtr(0),
1319  f_DrainPrimeEquDrainPrimeNodePtr(0),
1320  f_DrainPrimeEquGatePrimeNodePtr(0),
1321  f_DrainPrimeEquSourcePrimeNodePtr(0),
1322  f_DrainPrimeEquDrainDriftNodePtr(0),
1323 
1324  f_GatePrimeEquGateNodePtr(0),
1325  f_GatePrimeEquBulkNodePtr(0),
1326  f_GatePrimeEquDrainPrimeNodePtr(0),
1327  f_GatePrimeEquGatePrimeNodePtr(0),
1328  f_GatePrimeEquSourcePrimeNodePtr(0),
1329 
1330  f_SourcePrimeEquSourceNodePtr(0),
1331  f_SourcePrimeEquBulkNodePtr(0),
1332  f_SourcePrimeEquDrainPrimeNodePtr(0),
1333  f_SourcePrimeEquGatePrimeNodePtr(0),
1334  f_SourcePrimeEquSourcePrimeNodePtr(0),
1335 
1336  f_DrainDriftEquDrainNodePtr(0),
1337  f_DrainDriftEquDrainPrimeNodePtr(0),
1338  f_DrainDriftEquDrainDriftNodePtr(0),
1339 
1340  f_D1PrimeEquDrainNodePtr(0),
1341  f_D1PrimeEquSourceNodePtr(0),
1342  f_D1PrimeEquD1PrimeNodePtr(0),
1343 
1344  // Q-matrix pointers:
1345  q_DrainEquDrainNodePtr(0),
1346  q_DrainEquSourceNodePtr(0),
1347  q_DrainEquDrainDriftNodePtr(0),
1348  q_DrainEquD1PrimeNodePtr(0),
1349 
1350  q_GateEquGateNodePtr(0),
1351  q_GateEquGatePrimeNodePtr(0),
1352 
1353  q_SourceEquDrainNodePtr(0),
1354  q_SourceEquSourceNodePtr(0),
1355  q_SourceEquSourcePrimeNodePtr(0),
1356  q_SourceEquD1PrimeNodePtr(0),
1357 
1358  q_BulkEquBulkNodePtr(0),
1359  q_BulkEquDrainPrimeNodePtr(0),
1360  q_BulkEquGatePrimeNodePtr(0),
1361  q_BulkEquSourcePrimeNodePtr(0),
1362 
1363  q_DrainPrimeEquBulkNodePtr(0),
1364  q_DrainPrimeEquDrainPrimeNodePtr(0),
1365  q_DrainPrimeEquGatePrimeNodePtr(0),
1366  q_DrainPrimeEquSourcePrimeNodePtr(0),
1367  q_DrainPrimeEquDrainDriftNodePtr(0),
1368 
1369  q_GatePrimeEquGateNodePtr(0),
1370  q_GatePrimeEquBulkNodePtr(0),
1371  q_GatePrimeEquDrainPrimeNodePtr(0),
1372  q_GatePrimeEquGatePrimeNodePtr(0),
1373  q_GatePrimeEquSourcePrimeNodePtr(0),
1374 
1375  q_SourcePrimeEquSourceNodePtr(0),
1376  q_SourcePrimeEquBulkNodePtr(0),
1377  q_SourcePrimeEquDrainPrimeNodePtr(0),
1378  q_SourcePrimeEquGatePrimeNodePtr(0),
1379  q_SourcePrimeEquSourcePrimeNodePtr(0),
1380 
1381  q_DrainDriftEquDrainNodePtr(0),
1382  q_DrainDriftEquDrainPrimeNodePtr(0),
1383  q_DrainDriftEquDrainDriftNodePtr(0),
1384 
1385  q_D1PrimeEquDrainNodePtr(0),
1386  q_D1PrimeEquSourceNodePtr(0),
1387  q_D1PrimeEquD1PrimeNodePtr(0),
1388 #endif
1389 
1390  vbdd(0.0),
1391  vbs(0.0),
1392  vgpdd(0.0),
1393  vgps(0.0),
1394  vdds(0.0),
1395 
1396  vbdd_old(0.0),
1397  vbs_old(0.0),
1398  vgpdd_old(0.0),
1399  vgps_old(0.0),
1400  vdds_old(0.0),
1401  D1vd_old(0.0),
1402 
1403  vbdd_orig(0.0),
1404  vbs_orig(0.0),
1405  vgpdd_orig(0.0),
1406  vgps_orig(0.0),
1407  vdds_orig(0.0),
1408  D1vd_orig(0.0),
1409 
1410  capgs(0.0),
1411  qgs(0.0),
1412  cqgs(0.0),
1413  capgdd(0.0),
1414  qgdd(0.0),
1415  cqgdd(0.0),
1416  capgb(0.0),
1417  qgb(0.0),
1418  cqgb(0.0),
1419  capbd(0.0),
1420  qbd(0.0),
1421  cqbd(0.0),
1422  capbs(0.0),
1423  qbs(0.0),
1424  cqbs(0.0),
1425 
1426  // local indices
1427  li_state_vbdd(-1),
1428  li_state_vbs(-1),
1429  li_state_vgps(-1),
1430  li_state_vdds(-1),
1431  li_state_D1vd(-1),
1432  li_state_qgs(-1),
1433  li_state_qgdd(-1),
1434  li_state_qgb(-1),
1435  li_state_capgs(-1),
1436  li_state_capgdd(-1),
1437  li_state_capgb(-1),
1438  li_state_qbd(-1),
1439  li_state_qbs(-1),
1440  //li_state_cqgs(-1),
1441  //li_state_cqgdd(-1),
1442  //li_state_cqgb(-1),
1443  //li_state_cqbd(-1),
1444  //li_state_cqbs(-1),
1445 
1446  li_state_D1DIOcapCharge(-1),
1447  //li_state_D1DIOcapCurrent(-1),
1448  li_state_von(-1),
1449  li_store_dev_id(-1),
1450  li_store_dev_ig(-1),
1451  li_store_dev_is(-1),
1452  li_store_dev_ib(-1)
1453 {
1454  //numStateVars = 21;
1455  numStateVars = 15;
1456  numExtVars = 4;
1457  numLeadCurrentStoreVars = 4; // drain, gate, source & base lead currents
1458 
1459  devConMap.resize(4);
1460  devConMap[0] = 1;
1461  devConMap[1] = 2;
1462  devConMap[2] = 1;
1463  devConMap[3] = 3;
1464 
1465  if( jacStamp.empty() )
1466  {
1467  // stamp for RS!=0, RD!=0, RG!=0, RD1RS!=0
1468  jacStamp_D1C_DC_SC_GC.resize(9);
1469  jacStamp_D1C_DC_SC_GC[0].resize(4); // Drain row
1470  jacStamp_D1C_DC_SC_GC[0][0]=0; // d-d
1471  jacStamp_D1C_DC_SC_GC[0][1]=2; // d-s
1472  jacStamp_D1C_DC_SC_GC[0][2]=7; // d-dd
1473  jacStamp_D1C_DC_SC_GC[0][3]=8; // d-d1'
1474  jacStamp_D1C_DC_SC_GC[1].resize(2); // Gate row
1475  jacStamp_D1C_DC_SC_GC[1][0]=1; // g-g
1476  jacStamp_D1C_DC_SC_GC[1][1]=5; // g-g'
1477  jacStamp_D1C_DC_SC_GC[2].resize(4); // Source row
1478  jacStamp_D1C_DC_SC_GC[2][0]=0; // s-d
1479  jacStamp_D1C_DC_SC_GC[2][1]=2; // s-s
1480  jacStamp_D1C_DC_SC_GC[2][2]=6; // s-s'
1481  jacStamp_D1C_DC_SC_GC[2][3]=8; // s-d1'
1482  jacStamp_D1C_DC_SC_GC[3].resize(4); // Bulk row
1483  jacStamp_D1C_DC_SC_GC[3][0]=3; // b-b
1484  jacStamp_D1C_DC_SC_GC[3][1]=4; // b-d'
1485  jacStamp_D1C_DC_SC_GC[3][2]=5; // b-g'
1486  jacStamp_D1C_DC_SC_GC[3][3]=6; // b-s'
1487  jacStamp_D1C_DC_SC_GC[4].resize(5); // Drain' row
1488  jacStamp_D1C_DC_SC_GC[4][0]=3; // d'-b
1489  jacStamp_D1C_DC_SC_GC[4][1]=4; // d'-d'
1490  jacStamp_D1C_DC_SC_GC[4][2]=5; // d'-g'
1491  jacStamp_D1C_DC_SC_GC[4][3]=6; // d'-s'
1492  jacStamp_D1C_DC_SC_GC[4][4]=7; // d'-dd
1493  jacStamp_D1C_DC_SC_GC[5].resize(5); // Gate' row
1494  jacStamp_D1C_DC_SC_GC[5][0]=1; // g'-g
1495  jacStamp_D1C_DC_SC_GC[5][1]=3; // g'-b
1496  jacStamp_D1C_DC_SC_GC[5][2]=4; // g'-d'
1497  jacStamp_D1C_DC_SC_GC[5][3]=5; // g'-g'
1498  jacStamp_D1C_DC_SC_GC[5][4]=6; // g'-s'
1499  jacStamp_D1C_DC_SC_GC[6].resize(5); // Source' row
1500  jacStamp_D1C_DC_SC_GC[6][0]=2; // s'-s
1501  jacStamp_D1C_DC_SC_GC[6][1]=3; // s'-b
1502  jacStamp_D1C_DC_SC_GC[6][2]=4; // s'-d'
1503  jacStamp_D1C_DC_SC_GC[6][3]=5; // s'-g'
1504  jacStamp_D1C_DC_SC_GC[6][4]=6; // s'-s'
1505  jacStamp_D1C_DC_SC_GC[7].resize(3); // DrainDrift row
1506  jacStamp_D1C_DC_SC_GC[7][0]=0; // dd-d
1507  jacStamp_D1C_DC_SC_GC[7][1]=4; // dd-d'
1508  jacStamp_D1C_DC_SC_GC[7][2]=7; // dd-dd
1509  jacStamp_D1C_DC_SC_GC[8].resize(3); // D1'pos row
1510  jacStamp_D1C_DC_SC_GC[8][0]=0; // d1'-d
1511  jacStamp_D1C_DC_SC_GC[8][1]=2; // d1'-s
1512  jacStamp_D1C_DC_SC_GC[8][2]=8; // d1'-d1'
1513  jacMap_D1C_DC_SC_GC.clear();
1514 
1515  // First, generate the stamp for when RD1RS is zero --- it will be used
1516  // for all the other calculations for that case.
1517  // When RD1RS is zero, d1' is just S
1521  8, 2, 9);
1522 
1523  // Now do the cases where RD1RS is nonzero, but one of the others is
1527  6, 2, 9); // s' becomes same as s
1531  7, 4, 9); // dd becomes same as d'
1535  5, 1, 9); // g' becomes same as g
1536 
1537  // s' is already same as s here, so dd has become 6 instead of 7, and
1538  // needs to be mapped onto d' (which is still 4)
1541 
1542  // g' is same as g here, making s' 5 instead of 6, map it onto s now:
1545  // g' is same as g here, making dd 6 instead of 7, map it onto d' now:
1548 
1549  // g'=g and s'=s, so dd is 5 instead of 7, map it onto d'
1551  jacStamp_D1C, jacMap_D1C, jacMap2_D1C, 5, 4, 9);
1552 
1553  // Now do the ones where RD1RS is zero, starting from the case where
1554  // everything *but* RD1RS is nonzero. These follow exactly the same
1555  // pattern as above, but starting from _DC_SC_GC instead of _D1C_DC_SC_GC
1556  // This only works out this way because d1' is the last row, and nothing
1557  // gets moved up when it goes away.
1558  // I won't repeat the comments for each block.
1559  // only one row goes away:
1566 
1567  // s'==s already
1569  jacStamp_GC, jacMap_GC, jacMap2_GC, 6, 4, 9);
1570 
1571  // g'=g already
1573  jacStamp_DC, jacMap_DC, jacMap2_DC, 5, 2, 9);
1575  jacStamp_SC, jacMap_SC, jacMap2_SC, 6, 4, 9);
1576 
1577  // s'=s, g'=g already
1579  jacStamp, jacMap, jacMap2, 5, 4, 9);
1580  }
1581 
1582 
1583  // Set params to constant default values:
1584  setDefaultParams ();
1585 
1586  // Set params according to instance line and constant defaults from metadata:
1587  setParams (IB.params);
1588 
1589  // Set any non-constant parameter defaults:
1590  if (!given("TEMP"))
1591  temp = getDeviceOptions().temp.getImmutableValue<double>();
1592  if (!given("L"))
1593  l = model_.l0;
1594  if (!given("W"))
1595  w = model_.w0;
1596 
1597  // Calculate any parameters specified as expressions:
1599 
1600  // calculate dependent (ie computed) params and check for errors:
1601 
1602  // call updateTemp which may change model parameters if
1603  // temperature effects are present
1604  processParams ();
1605 
1606  if(model_.drainResistance != 0)
1607  {
1609  }
1610  else if (model_.given("RSH"))
1611  {
1612  if(model_.sheetResistance != 0)
1613  {
1614  drainCond =
1616  }
1617  else
1618  {
1619  drainCond = 0;
1620  }
1621  }
1622  else
1623  {
1624  drainCond = 0;
1625  }
1626  if(model_.sourceResistance != 0)
1627  {
1629  }
1630  else if (model_.given("RSH"))
1631  {
1632  if(model_.sheetResistance != 0)
1633  {
1634  sourceCond =
1636  }
1637  else
1638  {
1639  sourceCond = 0;
1640  }
1641  }
1642  else
1643  {
1644  sourceCond = 0;
1645  }
1646 
1647  if(model_.given("RG"))
1648  {
1649  if(model_.gateResistance != 0)
1650  {
1652  }
1653  else
1654  {
1655  gateCond = 0;
1656  }
1657  }
1658  else
1659  {
1660  gateCond = 0;
1661  }
1662 
1663  w *= numberParallel;
1664 
1666  if(gddd != 0) gddd = 1.0/gddd;
1667  draindriftCond = gddd;
1668 
1669  if(l - 2 * model_.latDiff <=0)
1670  {
1671  UserError0(*this) << "Effective channel length less than zero.";
1672  }
1673 
1674  // values for diode #1
1675  D1DIOarea = 1;
1676 
1682 
1683  numIntVars = 1 + (((sourceCond == 0.0)?0:1)+((drainCond == 0.0) ? 0:1)
1684  + ((gateCond == 0.0) ? 0:1))
1685  + ((model_.D1DIOconductance == 0.0) ? 0:1);
1686 }
1687 
1688 //-----------------------------------------------------------------------------
1689 // Function : Instance::~Instance
1690 // Purpose : destructor
1691 // Special Notes :
1692 // Scope : public
1693 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1694 // Creation Date : 3/16/00
1695 //-----------------------------------------------------------------------------
1697 {
1698 }
1699 
1700 //-----------------------------------------------------------------------------
1701 // Function : Instance::registerLIDs
1702 // Purpose :
1703 // Special Notes :
1704 // Scope : public
1705 // Creator : Robert Hoekstra, Computational Sciences
1706 // Creation Date : 6/21/02
1707 //-----------------------------------------------------------------------------
1708 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
1709  const std::vector<int> & extLIDVecRef )
1710 {
1711  AssertLIDs(intLIDVecRef.size() == numIntVars);
1712  AssertLIDs(extLIDVecRef.size() == numExtVars);
1713 
1714 #ifdef Xyce_DEBUG_DEVICE
1715  if (getDeviceOptions().debugLevel > 0)
1716  {
1717  Xyce::dout() << section_divider << std::endl;
1718  Xyce::dout() << " In Instance::register LIDs\n\n";
1719  Xyce::dout() << " name = " << getName() << std::endl;
1720  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
1721  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
1722  }
1723 #endif
1724 
1725  // copy over the global ID lists.
1726  intLIDVec = intLIDVecRef;
1727  extLIDVec = extLIDVecRef;
1728 
1729  // now use these lists to obtain the indices into the
1730  // linear algebra entities. This assumes an order.
1731  // For the matrix indices, first do the rows.
1732 
1733  li_Drain = extLIDVec[0];
1734  li_Gate = extLIDVec[1];
1735  li_Source = extLIDVec[2];
1736  li_Bulk = extLIDVec[3];
1737 
1738  int intLoc = 0;
1739  li_DrainPrime = intLIDVec[intLoc++];
1740 
1741  if( gateCond )
1742  li_GatePrime = intLIDVec[intLoc++];
1743  else
1745 
1746  if( sourceCond )
1747  li_SourcePrime = intLIDVec[intLoc++];
1748  else
1750 
1751  if( drainCond )
1752  li_DrainDrift = intLIDVec[intLoc++];
1753  else
1755 
1756  if( model_.D1DIOconductance )
1757  li_D1Prime = intLIDVec[intLoc++];
1758  else
1760 
1761 #ifdef Xyce_DEBUG_DEVICE
1762  if (getDeviceOptions().debugLevel > 0)
1763  {
1764  Xyce::dout() << "\n variable local indices:\n";
1765  Xyce::dout() << " li_Drain = " << li_Drain << std::endl;
1766  Xyce::dout() << " li_Source = " << li_Source << std::endl;
1767  Xyce::dout() << " li_Gate = " << li_Gate << std::endl;
1768  Xyce::dout() << " li_Bulk = " << li_Bulk << std::endl;
1769  Xyce::dout() << " li_DrainPrime = " << li_DrainPrime << std::endl;
1770  Xyce::dout() << " li_GatePrime = " << li_GatePrime << std::endl;
1771  Xyce::dout() << " li_SourcePrime = " << li_SourcePrime << std::endl;
1772  Xyce::dout() << " li_DrainDrift = " << li_DrainDrift << std::endl;
1773  Xyce::dout() << " li_D1Prime = " << li_D1Prime << std::endl;
1774 
1775  Xyce::dout() << section_divider << std::endl;
1776  }
1777 #endif
1778 
1779 }
1780 
1781 //-----------------------------------------------------------------------------
1782 // Function : Instance::getIntNameMap
1783 // Purpose :
1784 // Special Notes :
1785 // Scope : public
1786 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1787 // Creation Date : 05/13/05
1788 //-----------------------------------------------------------------------------
1789 std::map<int,std::string> & Instance::getIntNameMap ()
1790 {
1791  // set up the internal name map, if it hasn't been already.
1792  if (intNameMap.empty ())
1793  {
1794  intNameMap[ li_DrainPrime ] = spiceInternalName(getName(), "drainprime");
1795 
1796  if ( li_GatePrime != li_Gate )
1797  {
1798  intNameMap[ li_GatePrime ] = spiceInternalName(getName(), "gateprime");
1799  }
1800 
1801  if ( li_SourcePrime != li_Source )
1802  {
1803  intNameMap[ li_SourcePrime ] = spiceInternalName(getName(), "sourceprime");
1804  }
1805 
1806  if ( li_DrainDrift != li_DrainPrime )
1807  {
1808  intNameMap[ li_DrainDrift ] = spiceInternalName(getName(), "draindrift");
1809  }
1810 
1811  if ( li_D1Prime != li_Source )
1812  {
1814  }
1815  }
1816 
1817  return intNameMap;
1818 }
1819 
1820 //-----------------------------------------------------------------------------
1821 // Function : Instance::registerStateLIDs
1822 // Purpose :
1823 // Special Notes :
1824 // Scope : public
1825 // Creator : Robert Hoekstra, Computational Sciences
1826 // Creation Date : 6/21/02
1827 //-----------------------------------------------------------------------------
1828 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
1829 {
1830  AssertLIDs(staLIDVecRef.size() == numStateVars);
1831 
1832 #ifdef Xyce_DEBUG_DEVICE
1833  if (getDeviceOptions().debugLevel > 0)
1834  {
1835  Xyce::dout() << std::endl;
1836  Xyce::dout() << section_divider << std::endl;
1837  Xyce::dout() << " In Instance::registerStateLIDs\n\n";
1838  Xyce::dout() << " name = " << getName() << std::endl;
1839  Xyce::dout() << " Number of State LIDs: " << numStateVars << std::endl;
1840  }
1841 #endif
1842 
1843  // Copy over the global ID lists:
1844  staLIDVec = staLIDVecRef;
1845 
1846  int lid=0;
1847  li_state_vbdd = staLIDVec[lid++];
1848  li_state_vbs = staLIDVec[lid++];
1849  li_state_vgps = staLIDVec[lid++];
1850  li_state_vdds = staLIDVec[lid++];
1851  li_state_D1vd = staLIDVec[lid++];
1852 
1853  li_state_qgs = staLIDVec[lid++];
1854  //li_state_cqgs = staLIDVec[lid++];
1855  li_state_qgdd = staLIDVec[lid++];
1856  //li_state_cqgdd = staLIDVec[lid++];
1857  li_state_qgb = staLIDVec[lid++];
1858  //li_state_cqgb = staLIDVec[lid++];
1859 
1860  li_state_capgs = staLIDVec[lid++];
1861  li_state_capgdd = staLIDVec[lid++];
1862  li_state_capgb = staLIDVec[lid++];
1863 
1864  li_state_qbd = staLIDVec[lid++];
1865  //li_state_cqbd = staLIDVec[lid++];
1866  li_state_qbs = staLIDVec[lid++];
1867  //li_state_cqbs = staLIDVec[lid++];
1868 
1870  //li_state_D1DIOcapCurrent = staLIDVec[lid++];
1871 
1872  li_state_von = staLIDVec[lid++];
1873 
1874 #ifdef Xyce_DEBUG_DEVICE
1875  if (getDeviceOptions().debugLevel > 0)
1876  {
1877  Xyce::dout() << " State local indices:" << std::endl;
1878  Xyce::dout() << std::endl;
1879 
1880  Xyce::dout() << " li_state_vbdd = " << li_state_vbdd << "\n";
1881  Xyce::dout() << " li_state_vbs = " << li_state_vbs << "\n";
1882  Xyce::dout() << " li_state_vgps = " << li_state_vgps << "\n";
1883  Xyce::dout() << " li_state_vdds = " << li_state_vdds << "\n";
1884  Xyce::dout() << " li_state_qgs = " << li_state_qgs << "\n";
1885  //Xyce::dout() << " li_state_cqgs = " << li_state_cqgs << "\n";
1886  Xyce::dout() << " li_state_capgs = " << li_state_capgs << "\n";
1887  Xyce::dout() << " li_state_capgdd = " << li_state_capgdd << "\n";
1888  Xyce::dout() << " li_state_capgb = " << li_state_capgb << "\n";
1889  Xyce::dout() << " li_state_qgdd = " << li_state_qgdd << "\n";
1890  //Xyce::dout() << " li_state_cqgdd = " << li_state_cqgdd << "\n";
1891  Xyce::dout() << " li_state_qgb = " << li_state_qgb << "\n";
1892  //Xyce::dout() << " li_state_cqgb = " << li_state_cqgb << "\n";
1893  Xyce::dout() << " li_state_qbs = " << li_state_qbs << "\n";
1894  //Xyce::dout() << " li_state_cqbs = " << li_state_cqbs << "\n";
1895  Xyce::dout() << " li_state_qbd = " << li_state_qbd << "\n";
1896  //Xyce::dout() << " li_state_cqbd = " << li_state_cqbd << "\n";
1897  Xyce::dout() << " li_state_D1DIOcapCharge = " << li_state_D1DIOcapCharge << "\n";
1898  //Xyce::dout() << " li_state_D1DIOcapCurrent = " << li_state_D1DIOcapCurrent << "\n";
1899  Xyce::dout() << " li_state_von = " << li_state_von << "\n";
1900 
1901  Xyce::dout() << std::endl;
1902  Xyce::dout() << section_divider << std::endl;
1903  }
1904 #endif
1905 
1906 }
1907 
1908 
1909 //-----------------------------------------------------------------------------
1910 // Function : Instance::registerStoreLIDs
1911 // Purpose :
1912 // Special Notes :
1913 // Scope : public
1914 // Creator : Richard Schiek, Electrical Systems Modeling
1915 // Creation Date : 4/23/2013
1916 //-----------------------------------------------------------------------------
1917 void Instance::registerStoreLIDs( const std::vector<int> & stoLIDVecRef )
1918 {
1919  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
1920 
1921  // Copy over the global ID lists:
1922  stoLIDVec = stoLIDVecRef;
1923  if( loadLeadCurrent )
1924  {
1925  li_store_dev_id = stoLIDVec[0];
1926  li_store_dev_ig = stoLIDVec[1];
1927  li_store_dev_is = stoLIDVec[2];
1928  li_store_dev_ib = stoLIDVec[3];
1929  }
1930 }
1931 
1932 //-----------------------------------------------------------------------------
1933 // Function : Instance::getStoreNameMap
1934 // Purpose :
1935 // Special Notes :
1936 // Scope : public
1937 // Creator : Richard Schiek, Electrical Systems Modeling
1938 // Creation Date : 4/23/2013
1939 //-----------------------------------------------------------------------------
1940 std::map<int,std::string> & Instance::getStoreNameMap ()
1941 {
1942  // set up the internal name map, if it hasn't been already.
1943  if( loadLeadCurrent && storeNameMap.empty ())
1944  {
1949  }
1950 
1951  return storeNameMap;
1952 }
1953 
1954 //-----------------------------------------------------------------------------
1955 // Function : Instance::jacobianStamp
1956 // Purpose :
1957 // Special Notes :
1958 // Scope : public
1959 // Creator : Robert Hoekstra, Computational Sciences
1960 // Creation Date : 9/3/02
1961 //-----------------------------------------------------------------------------
1962 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
1963 {
1964  if( drainCond != 0.0 && gateCond != 0.0 && sourceCond != 0.0)
1966  else if( drainCond != 0.0 && gateCond != 0.0 && sourceCond == 0.0 )
1968  else if( drainCond == 0.0 && gateCond != 0.0 && sourceCond != 0.0 )
1970  else if( drainCond != 0.0 && gateCond == 0.0 && sourceCond != 0.0 )
1972  else if( drainCond == 0.0 && gateCond != 0.0 && sourceCond == 0.0 )
1974  else if( drainCond != 0.0 && gateCond == 0.0 && sourceCond == 0.0 )
1976  else if( drainCond == 0.0 && gateCond == 0.0 && sourceCond != 0.0 )
1978  else if( drainCond == 0.0 && gateCond == 0.0 && sourceCond == 0.0 )
1980  else
1982 }
1983 
1984 //-----------------------------------------------------------------------------
1985 // Function : Instance::registerJacLIDs
1986 // Purpose :
1987 // Special Notes :
1988 // Scope : public
1989 // Creator : Robert Hoekstra, Computational Sciences
1990 // Creation Date : 9/3/02
1991 //-----------------------------------------------------------------------------
1992 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
1993 {
1994  DeviceInstance::registerJacLIDs( jacLIDVec );
1995  std::vector<int> map;
1996  std::vector< std::vector<int> > map2;
1997  double d1dcond=(model_.D1DIOconductance);
1998  if (gateCond != 0.0)
1999  {
2000  if (drainCond != 0.0)
2001  {
2002  if (sourceCond != 0.0)
2003  {
2004  if (d1dcond != 0)
2005  {
2006  map = jacMap_D1C_DC_SC_GC;
2007  map2 = jacMap2_D1C_DC_SC_GC;
2008  }
2009  else
2010  {
2011  map = jacMap_DC_SC_GC;
2012  map2 = jacMap2_DC_SC_GC;
2013  }
2014  }
2015  else
2016  {
2017  if (d1dcond != 0)
2018  {
2019  map = jacMap_D1C_DC_GC;
2020  map2 = jacMap2_D1C_DC_GC;
2021  }
2022  else
2023  {
2024  map = jacMap_DC_GC;
2025  map2 = jacMap2_DC_GC;
2026  }
2027  }
2028  }
2029  else
2030  {
2031  if (sourceCond != 0.0)
2032  {
2033  if (d1dcond != 0)
2034  {
2035  map = jacMap_D1C_SC_GC;
2036  map2 = jacMap2_D1C_SC_GC;
2037  }
2038  else
2039  {
2040  map = jacMap_SC_GC;
2041  map2 = jacMap2_SC_GC;
2042  }
2043  }
2044  else
2045  {
2046  if (d1dcond != 0)
2047  {
2048  map = jacMap_D1C_GC;
2049  map2 = jacMap2_D1C_GC;
2050  }
2051  else
2052  {
2053  map = jacMap_GC;
2054  map2 = jacMap2_GC;
2055  }
2056  }
2057  }
2058  }
2059  else
2060  {
2061  if (drainCond != 0.0)
2062  {
2063  if (sourceCond != 0.0)
2064  {
2065  if (d1dcond != 0)
2066  {
2067  map = jacMap_D1C_DC_SC;
2068  map2 = jacMap2_D1C_DC_SC;
2069  }
2070  else
2071  {
2072  map = jacMap_DC_SC;
2073  map2 = jacMap2_DC_SC;
2074  }
2075  }
2076  else
2077  {
2078  if (d1dcond != 0)
2079  {
2080  map = jacMap_D1C_DC;
2081  map2 = jacMap2_D1C_DC;
2082  }
2083  else
2084  {
2085  map = jacMap_DC;
2086  map2 = jacMap2_DC;
2087  }
2088  }
2089  }
2090  else
2091  {
2092  if (sourceCond != 0.0)
2093  {
2094  if (d1dcond != 0)
2095  {
2096  map = jacMap_D1C_SC;
2097  map2 = jacMap2_D1C_SC;
2098  }
2099  else
2100  {
2101  map = jacMap_SC;
2102  map2 = jacMap2_SC;
2103  }
2104  }
2105  else
2106  {
2107  if (d1dcond != 0)
2108  {
2109  map = jacMap_D1C;
2110  map2 = jacMap2_D1C;
2111  }
2112  else
2113  {
2114  map = jacMap;
2115  map2 = jacMap2;
2116  }
2117  }
2118  }
2119  }
2120 
2121  ADrainEquDrainNodeOffset = jacLIDVec[map[0]][map2[0][0]];
2122  ADrainEquSourceNodeOffset = jacLIDVec[map[0]][map2[0][1]];
2123  ADrainEquDrainDriftNodeOffset = jacLIDVec[map[0]][map2[0][2]];
2124  ADrainEquD1PrimeNodeOffset = jacLIDVec[map[0]][map2[0][3]];
2125 
2126  AGateEquGateNodeOffset = jacLIDVec[map[1]][map2[1][0]];
2127  AGateEquGatePrimeNodeOffset = jacLIDVec[map[1]][map2[1][1]];
2128 
2129  ASourceEquDrainNodeOffset = jacLIDVec[map[2]][map2[2][0]];
2130  ASourceEquSourceNodeOffset = jacLIDVec[map[2]][map2[2][1]];
2131  ASourceEquSourcePrimeNodeOffset = jacLIDVec[map[2]][map2[2][2]];
2132  ASourceEquD1PrimeNodeOffset = jacLIDVec[map[2]][map2[2][3]];
2133 
2134  ABulkEquBulkNodeOffset = jacLIDVec[map[3]][map2[3][0]];
2135  ABulkEquDrainPrimeNodeOffset = jacLIDVec[map[3]][map2[3][1]];
2136  ABulkEquGatePrimeNodeOffset = jacLIDVec[map[3]][map2[3][2]];
2137  ABulkEquSourcePrimeNodeOffset = jacLIDVec[map[3]][map2[3][3]];
2138 
2139  ADrainPrimeEquBulkNodeOffset = jacLIDVec[map[4]][map2[4][0]];
2140  ADrainPrimeEquDrainPrimeNodeOffset = jacLIDVec[map[4]][map2[4][1]];
2141  ADrainPrimeEquGatePrimeNodeOffset = jacLIDVec[map[4]][map2[4][2]];
2142  ADrainPrimeEquSourcePrimeNodeOffset = jacLIDVec[map[4]][map2[4][3]];
2143  ADrainPrimeEquDrainDriftNodeOffset = jacLIDVec[map[4]][map2[4][4]];
2144 
2145  AGatePrimeEquGateNodeOffset = jacLIDVec[map[5]][map2[5][0]];
2146  AGatePrimeEquBulkNodeOffset = jacLIDVec[map[5]][map2[5][1]];
2147  AGatePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[5]][map2[5][2]];
2148  AGatePrimeEquGatePrimeNodeOffset = jacLIDVec[map[5]][map2[5][3]];
2149  AGatePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[5]][map2[5][4]];
2150 
2151  ASourcePrimeEquSourceNodeOffset = jacLIDVec[map[6]][map2[6][0]];
2152  ASourcePrimeEquBulkNodeOffset = jacLIDVec[map[6]][map2[6][1]];
2153  ASourcePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[6]][map2[6][2]];
2154  ASourcePrimeEquGatePrimeNodeOffset = jacLIDVec[map[6]][map2[6][3]];
2155  ASourcePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[6]][map2[6][4]];
2156 
2157  ADrainDriftEquDrainNodeOffset = jacLIDVec[map[7]][map2[7][0]];
2158  ADrainDriftEquDrainPrimeNodeOffset = jacLIDVec[map[7]][map2[7][1]];
2159  ADrainDriftEquDrainDriftNodeOffset = jacLIDVec[map[7]][map2[7][2]];
2160 
2161  AD1PrimeEquDrainNodeOffset = jacLIDVec[map[8]][map2[8][0]];
2162  AD1PrimeEquSourceNodeOffset = jacLIDVec[map[8]][map2[8][1]];
2163  AD1PrimeEquD1PrimeNodeOffset = jacLIDVec[map[8]][map2[8][2]];
2164 }
2165 
2166 //-----------------------------------------------------------------------------
2167 // Function : Instance::setupPointers
2168 // Purpose :
2169 // Special Notes :
2170 // Scope : public
2171 // Creator : Eric Keiter, SNL
2172 // Creation Date : 12/06/08
2173 //-----------------------------------------------------------------------------
2175 {
2176 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2177  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2178  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2179 
2184 
2187 
2192 
2197 
2203 
2209 
2215 
2219 
2223 
2224 
2225 
2230 
2233 
2238 
2243 
2249 
2255 
2261 
2265 
2269 
2270 
2271 
2272 
2273 #endif
2274 }
2275 
2276 //-----------------------------------------------------------------------------
2277 // Function : Instance::loadDAEQVector
2278 //
2279 // Purpose : Loads the Q-vector contributions for a single
2280 // voltage source instance.
2281 //
2282 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2283 // which the system of equations is represented as:
2284 //
2285 // f(x) = dQ(x)/dt + F(x) + B(t) = 0
2286 //
2287 // The "Q" vector contains charges and fluxes, mostly.
2288 // The voltage source will not make any contributions to Q,
2289 // so this function does nothing.
2290 //
2291 // Scope : public
2292 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2293 // Creation Date : 06/02/05
2294 //-----------------------------------------------------------------------------
2296 {
2297  double * qVec = extData.daeQVectorRawPtr;
2298  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
2299 
2300  double coef_Jdxp(0.0);
2301 
2302  double ceqbs(0.0), ceqbd(0.0), ceqgb(0.0), ceqgs(0.0), ceqgdd(0.0); // 3f5 vars
2303  double Dtype =model_.dtype;
2304 
2305  ceqbs = Dtype*qbs;
2306  ceqbd = Dtype*qbd;
2307  ceqgb = Dtype*qgb;
2308  ceqgs = Dtype*qgs;
2309  ceqgdd = Dtype*qgdd;
2310 
2311  qVec[li_Bulk] += (ceqbs + ceqbd - ceqgb);
2312  qVec[li_DrainPrime] += -(ceqbd + ceqgdd);
2313  qVec[li_GatePrime] += (ceqgs+ceqgdd+ceqgb);
2314  qVec[li_SourcePrime] += (-(ceqbs + ceqgs));
2315  qVec[li_D1Prime] += D1DIOcapCharge;
2316  qVec[li_Drain] += -D1DIOcapCharge;
2317  // voltlim section:
2318  if (!origFlag)
2319  {
2320  // bulk
2321  coef_Jdxp = Dtype*(-Capgb*(vgps-vgps_orig-vbs+vbs_orig)
2322  + (+Capgb)*(vbdd-vbdd_orig)
2323  + (+capbs)*(vbs-vbs_orig));
2324  dQdxdVp[li_Bulk] += coef_Jdxp;
2325 
2326  // drain-prime
2327  coef_Jdxp = Dtype*(-Capgdd*(vgpdd-vgpdd_orig)-capbd*(vbdd-vbdd_orig));
2328  dQdxdVp[li_DrainPrime] += coef_Jdxp;
2329 
2330  // gate-prime
2331  coef_Jdxp = Dtype*(Capgdd*(vgpdd-vgpdd_orig)+Capgs*(vgps-vgps_orig)+
2333  dQdxdVp[li_GatePrime] += coef_Jdxp;
2334 
2335  // source-prime
2336  coef_Jdxp = Dtype*(-Capgs*(vgps-vgps_orig)-capbs*(vbs-vbs_orig));
2337  dQdxdVp[li_SourcePrime] += coef_Jdxp;
2338 
2339  coef_Jdxp = -D1capd*(D1vd-D1vd_orig);
2340  dQdxdVp[li_D1Prime] -= coef_Jdxp;
2341  dQdxdVp[li_Drain] += coef_Jdxp;
2342  }
2343 
2344  if( loadLeadCurrent )
2345  {
2346  double * storeLeadQ = extData.storeLeadCurrQCompRawPtr;
2347 
2348  storeLeadQ[li_store_dev_id] = -D1DIOcapCharge;
2349  storeLeadQ[li_store_dev_is] = 0;
2350  storeLeadQ[li_store_dev_ig] = 0;
2351  storeLeadQ[li_store_dev_ib] = (ceqbs + ceqbd - ceqgb);
2352  // case where optional nodes become external nodes:
2353  if( !gateCond )
2354  {
2355  // G' is G
2356  storeLeadQ[li_store_dev_ig] += (ceqgs+ceqgdd+ceqgb);
2357  }
2358 
2359  if( !sourceCond )
2360  {
2361  // S' is S
2362  storeLeadQ[li_store_dev_is] += (-(ceqbs + ceqgs));
2363  }
2364 
2365  if( !drainCond )
2366  {
2367  // Ddrift is D'
2368  }
2369 
2370  if( !model_.D1DIOconductance )
2371  {
2372  // D1' is S
2373  storeLeadQ[li_store_dev_is] += D1DIOcapCharge;
2374  }
2375  }
2376 
2377  return true;
2378 }
2379 
2380 //-----------------------------------------------------------------------------
2381 // Function : Instance::loadDAEFVector
2382 //
2383 // Purpose : Loads the F-vector contributions for a single
2384 // VDMOS instance.
2385 //
2386 // Special Notes :
2387 //
2388 // Scope : public
2389 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2390 // Creation Date : 06/02/05
2391 //-----------------------------------------------------------------------------
2393 {
2394  double * fVec = extData.daeFVectorRawPtr;
2395  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
2396 
2397  double coef_Jdxp(0.0), gd_Jdxp(0.0);
2398  double gmin1 = getDeviceOptions().gmin;
2399  double Dtype =model_.dtype;
2400 
2401  double ceqbs = Dtype*(cbs+cqbs);
2402  double ceqbd = Dtype*(cbd+cqbd);
2403 
2404  double D1current = Dtype*D1cdeq; // don't add in the capacitor stuff
2405  fVec[li_Drain] += (Idraindrift + Irdsshunt - D1current);
2406 
2407  if (Igate != 0.0)
2408  {
2409  fVec[li_Gate] += Igate;
2410  fVec[li_GatePrime] += -Igate;
2411  }
2412  fVec[li_Source] += (Isource - Irdsshunt + Ird1rs);
2413  fVec[li_Bulk] += (ceqbs + ceqbd);
2414  fVec[li_DrainPrime] += (-Idrain-(ceqbd - cdreq));
2415  fVec[li_SourcePrime] += (-Isource-(ceqbs + cdreq));
2416  fVec[li_DrainDrift] += (Idrain - Idraindrift);
2417  fVec[li_D1Prime] += (D1current - Ird1rs);
2418 
2419  // limiter terms:
2420  if (!origFlag)
2421  {
2422  // bulk
2423  coef_Jdxp = Dtype*( + ((gbd-gmin1))*(vbdd-vbdd_orig)
2424  + ((gbs-gmin1))*(vbs-vbs_orig));
2425  dFdxdVp[li_Bulk] += coef_Jdxp;
2426 
2427  // drain-prime
2428  coef_Jdxp = Dtype*(-((gbd-gmin1))*
2430  +Gm*((mode>0)?(vgps-vgps_orig):(vgpdd-vgpdd_orig))
2431  +Gmbs*((mode>0)?(vbs-vbs_orig):(vbdd-vbdd_orig)));
2432  dFdxdVp[li_DrainPrime] += coef_Jdxp;
2433 
2434  // source prime
2435  coef_Jdxp = Dtype*(-((gbs-gmin1))*(vbs-vbs_orig)
2436  -gdds*(vdds-vdds_orig)
2437  -Gm*((mode>0)?(vgps-vgps_orig):(vgpdd-vgpdd_orig))
2438  -Gmbs*((mode>0)?(vbs-vbs_orig):(vbdd-vbdd_orig)));
2439  dFdxdVp[li_SourcePrime] += coef_Jdxp;
2440 
2441  gd_Jdxp = -D1gd * (D1vd-D1vd_orig);
2442  dFdxdVp[li_Drain] += gd_Jdxp;
2443  dFdxdVp[li_D1Prime] -= gd_Jdxp;
2444  }
2445 
2446  if( loadLeadCurrent )
2447  {
2448  double * storeLeadF = extData.nextStoVectorRawPtr;
2449 
2450  storeLeadF[li_store_dev_id] = (Idraindrift + Irdsshunt - D1current);
2451  storeLeadF[li_store_dev_is] = (Isource - Irdsshunt + Ird1rs);
2452  storeLeadF[li_store_dev_ig] = 0;
2453  storeLeadF[li_store_dev_ib] = (ceqbs + ceqbd);
2454  // case where optional nodes become external nodes:
2455  if (Igate != 0.0)
2456  {
2457  storeLeadF[li_store_dev_ig] += Igate;
2458  }
2459  if( !gateCond )
2460  {
2461  // G' is G
2462  storeLeadF[li_store_dev_ig] += -Igate;
2463  }
2464 
2465  if( !sourceCond )
2466  {
2467  // S' is S
2468  storeLeadF[li_store_dev_is] += (-Isource-(ceqbs + cdreq));
2469  }
2470 
2471  if( !drainCond )
2472  {
2473  // Ddrift is D'
2474  }
2475 
2476  if( !model_.D1DIOconductance )
2477  {
2478  // D1' is S
2479  storeLeadF[li_store_dev_is] += (D1current - Ird1rs);
2480  }
2481  }
2482 
2483  return true;
2484 }
2485 
2486 //-----------------------------------------------------------------------------
2487 // Function : Instance::loadDAEdQdx
2488 //
2489 // Purpose : Loads the Q-vector contributions for a single
2490 // VDMOS instance.
2491 //
2492 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2493 // which the system of equations is represented as:
2494 //
2495 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2496 //
2497 // Scope : public
2498 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2499 // Creation Date : 06/02/05
2500 //-----------------------------------------------------------------------------
2502 {
2503  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2504 
2505  if (getSolverState().dcopFlag) return true;
2506 
2511 
2515 
2520 
2524 
2527 
2530 
2531  return true;
2532 }
2533 
2534 //-----------------------------------------------------------------------------
2535 // Function : Instance::loadDAEdFdx ()
2536 //
2537 // Purpose : Loads the F-vector contributions for a single
2538 // instance.
2539 //
2540 // Special Notes : The F-vector is an algebraic constaint.
2541 //
2542 // Scope : public
2543 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2544 // Creation Date : 06/02/05
2545 //-----------------------------------------------------------------------------
2547 {
2548  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2549 
2554 
2555  if (gateCond != 0)
2556  {
2559  }
2560 
2564 
2565  if (sourceCond != 0.0)
2566  {
2568  }
2569 
2572 
2574 
2579  if (drainCond != 0.0)
2580  {
2582  }
2583 
2584  if (gateCond != 0)
2585  {
2588  }
2589 
2590  if (sourceCond != 0.0)
2591  {
2593  }
2598 
2600 
2601  if (drainCond != 0.0)
2602  {
2604  }
2606 
2610 
2611  return true;
2612 }
2613 
2614 //-----------------------------------------------------------------------------
2615 // Function : Instance::updateIntermediateVars
2616 // Purpose :
2617 // Special Notes :
2618 // Scope : public
2619 // Creator : pmc
2620 // Creation Date : 2/17/2004
2621 //-----------------------------------------------------------------------------
2623 {
2624  bool bsuccess = true;
2625 
2626  double * solVec = extData.nextSolVectorRawPtr;
2627 
2628  // 3f5 likes to use the same variable names in local variables and in
2629  // structures. Messes with us! Define some local versions with capitals
2630  // instead
2631 #define ISUBMOD model_.isubmod
2632 
2633  double Von(0.0);
2634  double Vddsat(0.0);
2635  //
2636  double evbs(0.0);
2637  double evbdd(0.0);
2638  double sarg(0.0);
2639  double sargsw(0.0);
2640  double arg(0.0);
2641  int Check(1);
2642 
2643  double capgs_old(0.0);
2644  double capgdd_old(0.0);
2645  double capgb_old(0.0);
2646 
2647  // diode #1
2648  double D1temp(0.0);
2649  double D1power(0.0);
2650  double D1arg(0.0);
2651  double D1cd(0.0);
2652  double D1cdr(0.0);
2653  double D1csat(0.0);
2654  double D1csatr(0.0);
2655  double D1czero(0.0);
2656  double D1czof2(0.0);
2657  double D1evd(0.0);
2658  double D1evr(0.0);
2659  double D1isr(0.0);
2660  double D1evrev(0.0);
2661  double D1gdr(0.0);
2662  double D1sarg(0.0);
2663  double D1vdtemp(0.0);
2664  double D1vtr(0.0);
2665  int D1Check(0);
2666 
2667 #ifdef Xyce_DEBUG_DEVICE
2668 
2669  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2670  {
2671  Xyce::dout() << subsection_divider << std::endl;
2672  Xyce::dout() <<" Instance::updateIntermediateVars.\n"<<std::endl;
2673  Xyce::dout() <<" name = " << getName() << std::endl;
2674  Xyce::dout() <<" Model name = " << model_.getName() << std::endl;
2675  Xyce::dout() <<" dtype is " << model_.dtype << std::endl;
2676  Xyce::dout() << std::endl;
2677  Xyce::dout().width(25); Xyce::dout().precision(17); Xyce::dout().setf(std::ios::scientific);
2678  }
2679 #endif
2680 
2681  if( (tSatCurDens == 0) || (drainArea == 0) || (sourceArea == 0))
2682  {
2683  DrainSatCur = tSatCur;
2685  }
2686  else
2687  {
2690  }
2691 
2692  // we need our solution variables for any of this stuff
2693 
2694  Vd = 0.0;
2695  Vs = 0.0;
2696  Vg = 0.0;
2697  Vb = 0.0;
2698  Vdp = 0.0;
2699  Vgp = 0.0;
2700  Vsp = 0.0;
2701  Vdd = 0.0;
2702 
2703  Vd = solVec[li_Drain];
2704  Vg = solVec[li_Gate];
2705  Vs = solVec[li_Source];
2706  Vb = solVec[li_Bulk];
2707  Vsp = solVec[li_SourcePrime];
2708  Vgp = solVec[li_GatePrime];
2709  Vdp = solVec[li_DrainPrime];
2710  Vdd = solVec[li_DrainDrift];
2711 
2712  // node for diode #1
2713  Vd1p = solVec[li_D1Prime];
2714 
2717  D1vtr = model_.D1DIOnr * D1vt;
2718 
2719 #ifdef Xyce_DEBUG_DEVICE
2720  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2721  {
2722  Xyce::dout() << " " << std::endl;
2723  Xyce::dout() << " Solution vector: " << std::endl;
2724  Xyce::dout() << " Vg = " << Vg << std::endl;
2725  Xyce::dout() << " Vd = " << Vd << std::endl;
2726  Xyce::dout() << " Vs = " << Vs << std::endl;
2727  Xyce::dout() << " Vb = " << Vb << std::endl;
2728  Xyce::dout() << " Vdp = " << Vdp << std::endl;
2729  Xyce::dout() << " Vgp = " << Vgp << std::endl;
2730  Xyce::dout() << " Vsp = " << Vsp << std::endl;
2731  Xyce::dout() << " Vdd = " << Vdd << std::endl;
2732  Xyce::dout() << " Vd1p= " << Vd1p << std::endl;
2733  }
2734 #endif
2735 
2736  // voltage drops
2737  Vddp = Vd - Vdp;
2738  Vddd = Vd - Vdd;
2739  Vdddp = Vdd - Vdp;
2740  Vssp = Vs - Vsp;
2741  Vbsp = Vb - Vsp;
2742  Vbdp = Vb - Vdp;
2743 
2744  Vggp = Vg - Vgp;
2745  Vgpsp = Vgp - Vsp;
2746  Vgpdp = Vgp - Vdp;
2747  Vgpb = Vgp - Vb;
2748  Vdpsp = Vdp - Vsp;
2749 
2750  // setup corrections for dtype.
2751  vbs = model_.dtype * Vbsp;
2752  vgps = model_.dtype * Vgpsp;
2753  vdds = model_.dtype * Vdpsp;
2754  D1vd = model_.dtype * (Vd1p - Vd);
2755 
2756  vbdd = vbs-vdds;
2757  vgpdd = vgps-vdds;
2758 
2759  // set up the orig voltages.
2760  origFlag = 1;
2761  limitedFlag = false;
2762  vgps_orig = vgps;
2763  vdds_orig = vdds;
2764  vbs_orig = vbs;
2765  vbdd_orig = vbdd;
2766  vgpdd_orig = vgpdd;
2767  D1vd_orig = D1vd;
2768 
2769  if (getSolverState().newtonIter == 0)
2770  {
2771  newtonIterOld=0;
2772 
2774  {
2776  {
2777  N_LAS_Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
2778  if ((*flagSolVectorPtr)[li_Drain] == 0 || (*flagSolVectorPtr)[li_Gate] == 0 ||
2779  (*flagSolVectorPtr)[li_Source] == 0 || (*flagSolVectorPtr)[li_SourcePrime] ||
2780  (*flagSolVectorPtr)[li_DrainDrift] == 0 || (*flagSolVectorPtr)[li_GatePrime] ||
2781  (*flagSolVectorPtr)[li_DrainPrime] || (*flagSolVectorPtr)[li_Bulk] )
2782  {
2783  vbs = -1;
2784  vgps = model_.dtype*tVto;
2785  vdds = 0;
2786  vbdd = vbs-vdds;
2787  vgpdd = vgps-vdds;
2788  }
2789  }
2790  else
2791  {
2792  vbs = -1;
2793  vgps = model_.dtype*tVto;
2794  vdds = 0;
2795  vbdd = vbs-vdds;
2796  vgpdd = vgps-vdds;
2797  }
2798  }
2799 
2800  ////////////////////////////////////////////////////////////////////////
2801  // Note: the "old" variables should be the values for the previous
2802  // Newton iteration. That previous newton iteration could
2803  // have happened in a previous time step...
2805  {
2811  Von = model_.dtype *
2813  }
2814  else
2815  { // there's no history
2816  vbs_old = vbs;
2817  vbdd_old = vbdd;
2818  vgps_old = vgps;
2819  vdds_old = vdds;
2820  D1vd_old = D1vd;
2821  }
2822  }
2823  else
2824  {
2830  Von = model_.dtype *
2833  }
2834 
2835 #ifdef Xyce_DEBUG_DEVICE
2837  {
2838  Xyce::dout() << "After Von first set, ";
2839  Xyce::dout() << " von = " << von << " Von = " << Von << std::endl;
2840  }
2841 #endif
2842 
2843  ////////////////////////////////////////////
2844  // SPICE-type Voltage Limiting (PINNING)
2845  ////////////////////////////////////////////
2846  if (getDeviceOptions().voltageLimiterFlag)
2847  {
2848 #ifdef Xyce_DEBUG_DEVICE
2849  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2850  {
2851  Xyce::dout() << " checking whether to limit voltages "<< std::endl;
2852  Xyce::dout() << " Von = " << Von << std::endl;
2853  Xyce::dout() << " before limiting: " << std::endl;
2854  Xyce::dout() << " vgpdd = " << vgpdd << " vgpdd_old = " << vgpdd_old << std::endl;
2855  Xyce::dout() << " vgps = " << vgps << " vgps_old = " << vgps_old << std::endl;
2856  Xyce::dout() << " vdds = " << vdds << " vdds_old = " << vdds_old << std::endl;
2857  Xyce::dout() << " vbs = " << vbs << " vbs_old = " << vbs_old << std::endl;
2858  Xyce::dout() << " vbdd = " << vbdd << " vbdd_old = " << vbdd_old << std::endl;
2859  }
2860 #endif
2861 
2862  if (vdds_old >= 0)
2863  {
2864  vgps = devSupport.fetlim( vgps, vgps_old, Von);
2865  vdds = vgps - vgpdd;
2866  vdds = devSupport.limvds( vdds, vdds_old);
2867  vgpdd = vgps - vdds;
2868  }
2869  else
2870  {
2872  vdds = vgps - vgpdd;
2873  vdds = -devSupport.limvds( -vdds, -vdds_old );
2874  vgps = vgpdd + vdds;
2875  }
2876 
2877  if (vdds >= 0.0)
2878  {
2879  vbs = devSupport.pnjlim( vbs, vbs_old, vt, sourceVcrit, &Check);
2880  vbdd = vbs - vdds;
2881  }
2882  else
2883  {
2884  vbdd = devSupport.pnjlim( vbdd, vbdd_old, vt, drainVcrit, &Check);
2885  vbs = vbdd + vdds;
2886  }
2887 
2888  if (Check == 1) limitedFlag=true;
2889 #ifdef Xyce_DEBUG_DEVICE
2890  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2891  {
2892  Xyce::dout() << " After limiting: " << std::endl;
2893  Xyce::dout() << " vgpdd = " << vgpdd << std::endl;
2894  Xyce::dout() << " vgps = " << vgps << std::endl;
2895  Xyce::dout() << " vdds = " << vdds << std::endl;
2896  Xyce::dout() << " vbs = " << vbs << std::endl;
2897  Xyce::dout() << " vbdd = " << vbdd << std::endl;
2898  }
2899 #endif
2900 
2901  // limit diode junction voltage
2902  bool tmpGiven = false;
2903  tmpGiven = (model_.D1DIObreakdownVoltageGiven);
2904  if (tmpGiven && (D1vd < Xycemin(0.0, 10.0*D1vte-D1DIOtBrkdwnV) ))
2905  {
2906  D1vdtemp = -(D1vd + D1DIOtBrkdwnV);
2907  D1vdtemp = devSupport.pnjlim(D1vdtemp,
2909  D1DIOtVcrit, &D1Check);
2910  D1vd = -(D1vdtemp + D1DIOtBrkdwnV);
2911  }
2912  else
2913  {
2915  D1DIOtVcrit, &D1Check);
2916  }
2917 
2918  if (D1Check == 1) limitedFlag=true;
2919  } // voltage limiter flag
2920 
2921  ////
2922  // now all the preliminaries are over - we can start doing the
2923  // real work
2924  ////
2925  vbdd = vbs - vdds;
2926  vgpdd = vgps - vdds;
2927  Vgpb = vgps - vbs;
2928 
2929 #ifdef Xyce_DEBUG_DEVICE
2930  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2931  {
2932  Xyce::dout() << " vbs = " << vbs << std::endl;
2933  Xyce::dout() << " vgps = " << vgps << std::endl;
2934  Xyce::dout() << " vdds = " << vdds << std::endl;
2935  Xyce::dout() << " vbdd = " << vbdd << std::endl;
2936  Xyce::dout() << " vgpdd= " << vgpdd << std::endl;
2937 
2938  Xyce::dout() << " Vddp = " << Vddp << std::endl;
2939  Xyce::dout() << " Vddd = " << Vddd << std::endl;
2940  Xyce::dout() << " Vdddp= " << Vdddp << std::endl;
2941  Xyce::dout() << " Vssp = " << Vssp << std::endl;
2942  Xyce::dout() << " Vbsp = " << Vbsp << std::endl;
2943  Xyce::dout() << " Vbdp = " << Vbdp << std::endl;
2944  Xyce::dout() << " Vggp = " << Vggp << std::endl;
2945  Xyce::dout() << " Vgpsp = " << Vgpsp << std::endl;
2946  Xyce::dout() << " Vgpdp = " << Vgpdp << std::endl;
2947  Xyce::dout() << " Vgpb = " << Vgpb << std::endl;
2948  Xyce::dout() << " Vdpsp= " << Vdpsp << std::endl;
2949 
2950  }
2951 #endif
2952 
2953  // Now set the origFlag
2954  if (vgps_orig != vgps || vdds_orig != vdds ||
2955  vbs_orig != vbs || vbdd_orig != vbdd || vgpdd_orig != vgpdd) origFlag = 0;
2956 
2957 #ifdef Xyce_DEBUG_DEVICE
2958  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2959  {
2960  if (origFlag == 0)
2961  {
2962  Xyce::dout() << " Something modified the voltages. " << std::endl;
2963  Xyce::dout() << " Voltage before after diff " << std::endl;
2964  Xyce::dout() << " vgps " << vgps_orig << " " << vgps << " " << vgps-vgps_orig << std::endl;
2965  Xyce::dout() << " vdds " << vdds_orig << " " << vdds << " " << vdds-vdds_orig << std::endl;
2966  Xyce::dout() << " vbs " << vbs_orig << " " << vbs << " " << vbs-vbs_orig << std::endl;
2967  Xyce::dout() << " vbdd " << vbdd_orig << " " << vbdd << " " << vbdd-vbdd_orig << std::endl;
2968  Xyce::dout() << " vgpdd " << vgpdd_orig << " " << vgpdd << " " << vgpdd-vgpdd_orig << std::endl;
2969  }
2970  }
2971 #endif
2972 
2974 
2975  ////
2976  // bulk-source and bulk-drain diodes
2977  // here we just evaluate the ideal diode current and the
2978  // corresponding derivative (conductance).
2979  ////
2980 
2981  double pi(0.0);
2982  double end10(0.0);
2983  double end1(0.0);
2984  double end20(0.0);
2985  double end2(0.0);
2986  double end3(0.0);
2987  double j1(0.0);
2988  double fr1(0.0);
2989  double fr2(0.0);
2990  double d1j1(0.0);
2991  double fr3(0.0);
2992  double d2j1(0.0);
2993  double dj1(0.0);
2994 
2995  if(model_.artd != 0.0 && sourceArea != 0.0)
2996  {
2998  end1=1+exp(Xycemin(CONSTMAX_EXP_ARG,end10/vt));
3000  end2=1+exp(Xycemin(CONSTMAX_EXP_ARG,end20/vt));
3001  end3=(model_.crtd-model_.nrtd*vbs)/model_.drtd;
3002  pi = 3.1415927;
3003  j1=model_.artd*log(end1/end2)*(pi/2+atan(end3));
3004  j1=j1*sourceArea;
3005 
3006  fr1=(end1-1)*model_.nrtd/(end1*vt);
3007  fr2=(end2-1)*model_.nrtd/(end2*vt);
3008  d1j1=(fr1-fr2)*(pi/2+atan(end3));
3009  fr3=(-model_.nrtd/model_.drtd)/(1+end3*end3);
3010  d2j1=log(end1/end2)*fr3;
3011  dj1=model_.artd*(d1j1+d2j1);
3012  dj1=dj1*sourceArea;
3013  }
3014  else
3015  {
3016  j1 = 0.0;
3017  dj1 = 0.0;
3018  }
3019 
3020  if(vbs <= 0)
3021  {
3024  cbs = gbs*vbs+j1;
3025 // PMC for D1 diode testing
3026 // gbs = 0.0;
3027 // cbs = 0.0;
3028 
3029 #ifdef Xyce_DEBUG_DEVICE
3030  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3031  {
3032  Xyce::dout() << "*******Setting cbs for vbs<=0 ******" << std::endl;
3033  Xyce::dout() << " vbs = " << vbs << std::endl;
3034  Xyce::dout() << " vt = " << vt << std::endl;
3035  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3036  Xyce::dout() << " SSC = " << SourceSatCur << std::endl;
3037  Xyce::dout() << " gbs = " << gbs << std::endl;
3038  Xyce::dout() << " cbs = " << cbs << std::endl;
3039  Xyce::dout() << " j1 = " << j1 << std::endl;
3040  }
3041 #endif
3042  }
3043  else
3044  {
3045  evbs = exp(Xycemin(CONSTMAX_EXP_ARG,model_.n2*vbs/vt));
3047  + getDeviceOptions().gmin + dj1);
3048  cbs = numberParallel*(SourceSatCur*(evbs-1) + j1);
3049 // PMC for D1 diode testing
3050 // gbs = 0.0;
3051 // cbs = 0.0;
3052 
3053 #ifdef Xyce_DEBUG_DEVICE
3054  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3055  {
3056  Xyce::dout() << "*******Setting cbs for vbs>0 ******" << std::endl;
3057  Xyce::dout() << " vbs = " << vbs << std::endl;
3058  Xyce::dout() << " vt = " << vt << std::endl;
3059  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3060  Xyce::dout() << " vbs/vt = " << vbs/vt << std::endl;
3061  Xyce::dout() << " Maxarg = " << CONSTMAX_EXP_ARG << std::endl;
3062  Xyce::dout() << " arg = " << Xycemin(CONSTMAX_EXP_ARG,
3063  model_.n2*vbs/vt) << std::endl;
3064  Xyce::dout() << " evbs = " << evbs << std::endl;
3065  Xyce::dout() << " gbs = " << gbs << std::endl;
3066  Xyce::dout() << " cbs = " << cbs << std::endl;
3067  }
3068 #endif
3069  }
3070  if(vbdd <= 0)
3071  {
3074  cbd = gbd *vbdd;
3075 // PMC for D1 diode testing
3076 // gbd = 0.0;
3077 // cbd = 0.0;
3078 
3079 #ifdef Xyce_DEBUG_DEVICE
3080  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3081  {
3082  Xyce::dout() << "*******Setting cbd for vbdd<=0 ******" << std::endl;
3083  Xyce::dout() << " vbdd = " << vbdd << std::endl;
3084  Xyce::dout() << " SSC = " << SourceSatCur << std::endl;
3085  Xyce::dout() << " vt = " << vt << std::endl;
3086  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3087  Xyce::dout() << " gbd = " << gbd << std::endl;
3088  Xyce::dout() << " cbd = " << cbd << std::endl;
3089  }
3090 #endif
3091 
3092  }
3093  else
3094  {
3095  evbdd = exp(Xycemin(CONSTMAX_EXP_ARG,model_.n2*vbdd/vt));
3097  + getDeviceOptions().gmin);
3098  cbd = numberParallel*DrainSatCur*(evbdd-1);
3099 // PMC for D1 diode testing
3100 // gbd = 0.0;
3101 // cbd = 0.0;
3102 
3103 #ifdef Xyce_DEBUG_DEVICE
3105  {
3106  Xyce::dout() << "*******Setting cbd for vbdd>0 ******" << std::endl;
3107  Xyce::dout() << " vbdd = " << vbdd << std::endl;
3108  Xyce::dout() << " vt = " << vt << std::endl;
3109  Xyce::dout() << " vbdd/vt = " << vbdd/vt << std::endl;
3110  Xyce::dout() << " Maxarg = " << CONSTMAX_EXP_ARG << std::endl;
3111  Xyce::dout() << " arg = " << Xycemin(CONSTMAX_EXP_ARG,
3112  model_.n2*vbdd/vt) << std::endl;
3113  Xyce::dout() << " evbdd = " << evbdd << std::endl;
3114  Xyce::dout() << " gbd = " << gbd << std::endl;
3115  Xyce::dout() << " cbd = " << cbd << std::endl;
3116  }
3117 #endif
3118  }
3119 
3120  if (vdds >= 0)
3121  mode = 1;
3122  else
3123  mode = -1;
3124 
3125  double dvonvbs(0.0);
3126  double lvbs = mode == 1 ? vbs : vbdd;
3127  UCCMcvon(lvbs, von, dvonvbs);
3128  Von = model_.dtype * von; // von contains dtype, Von does not
3129 
3130  if(!ISUBMOD)
3131  {
3132  // Old version of model with corrected Jacobian terms
3133  UCCMmosa1(vdds>0?vgps:vgpdd,mode*vdds,dvonvbs, cdraindrift, vddsat);
3134  }
3135  else
3136  {
3137  // Version of model with substrate currents
3138  UCCMmosa2(vdds>0?vgps:vgpdd,mode*vdds,dvonvbs, cdraindrift, vddsat);
3139  }
3140  Vddsat = model_.dtype * vddsat;
3141 
3142  ////
3143  // COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
3144  ////
3145 
3146  // Substrate current calculations
3147  ISUB = cdraindrift*mm1;
3148  GMSUB = gm*mm1 + cdraindrift*dmm1vgs;
3149  GDDSSUB = gdds*mm1 + cdraindrift*dmm1vds;
3150  GBSSUB = gmbs*mm1 + cdraindrift*dmm1vbs;
3151 
3152 // PMC ISUBMOD not fully implemented
3153 // - probably we don't have the right model parameters
3154 // cdrain = cdraindrift + ISUB;
3155 
3156  cdrain = cdraindrift;
3157  cd = mode*cdrain - cbd;
3158 
3159  // diode #1 values
3160  D1csat = D1DIOtSatCur * D1DIOarea;
3161  D1csatr = D1DIOtSatRCur * D1DIOarea;
3163  D1vtr = model_.D1DIOnr * D1vt;
3164  D1evd = D1arg = D1evrev = 0.0;
3165 
3166  // compute diode dc current and derivatives
3167  if(D1csatr != 0)
3168  {
3169  D1evr = exp(D1vd/D1vtr);
3170  D1temp = 1 - D1vd/D1DIOtJctPot;
3171  D1arg = D1temp*D1temp;
3172  D1power = pow(D1arg + 0.001,model_.D1DIOgradingCoeff/2);
3173  D1isr = D1csatr*D1power;
3174  D1cdr = D1isr*(D1evr - 1);
3175  D1gdr = -D1cdr*model_.D1DIOgradingCoeff*D1temp/
3176  (D1DIOtJctPot*(D1arg + 0.001)) + D1isr*D1evr/D1vtr;
3177  } else
3178  {
3179  D1cdr = 0;
3180  D1gdr = 0;
3181  }
3182 
3183  // add in diode bulk resistance
3184  if(D1vd >= -3*D1vte)
3185  {
3186  D1evd = exp(D1vd/D1vte);
3187  D1cd = D1csat*(D1evd-1)+D1cdr + getDeviceOptions().gmin*D1vd;
3188  D1gd = D1csat*D1evd/D1vte+D1gdr + getDeviceOptions().gmin;
3189  if(model_.D1DIOikf > 0) {
3190  D1arg = sqrt(model_.D1DIOikf/(model_.D1DIOikf + D1cd));
3191  D1gd = D1arg*D1gd*(1 - 0.5*D1cd/(model_.D1DIOikf + D1cd));
3192  D1cd = D1arg*D1cd;
3193  }
3194  }
3195  else if( (!(D1DIOtBrkdwnV)) || (D1vd >= -D1DIOtBrkdwnV) )
3196  {
3197  D1arg = 3*D1vte/(D1vd*CONSTe);
3198  D1arg = D1arg * D1arg * D1arg;
3199  D1cd = -D1csat*(1 + D1arg) + getDeviceOptions().gmin*D1vd + D1cdr;
3200  D1gd = D1csat*3*D1arg/D1vd + getDeviceOptions().gmin + D1gdr;
3201  }
3202  else
3203  {
3204  D1evrev= exp(-(D1DIOtBrkdwnV + D1vd)/D1vte);
3205  D1cd = -D1csat*D1evrev + getDeviceOptions().gmin*D1vd + D1cdr;
3206  D1gd = D1csat*D1evrev/D1vte + getDeviceOptions().gmin + D1gdr;
3207  }
3208  D1cdeq = D1cd;
3209 
3210 #ifdef Xyce_DEBUG_DEVICE
3211  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3212  {
3213  Xyce::dout() << " " << std::endl;
3214  Xyce::dout() << " dtype = " << model_.dtype << std::endl;
3215  Xyce::dout() << " D1vd = " << D1vd << std::endl;
3216  Xyce::dout() << " D1vtr = " << D1vtr << std::endl;
3217  Xyce::dout() << " D1csat = " << D1csat << std::endl;
3218  Xyce::dout() << " D1csatr = " << D1csatr << std::endl;
3219  Xyce::dout() << " D1gspr = " << D1gspr << std::endl;
3220  Xyce::dout() << " D1cdr = " << D1cdr << std::endl;
3221  Xyce::dout() << " D1gdr = " << D1gdr << std::endl;
3222  Xyce::dout() << " D1vte = " << D1vte << std::endl;
3223  Xyce::dout() << " D1evd = " << D1evd << std::endl;
3224  Xyce::dout() << " D1arg = " << D1arg << std::endl;
3225  Xyce::dout() << " D1evrev = " << D1evrev << std::endl;
3226  Xyce::dout() << " D1DIOtBrkdwnV = " << D1DIOtBrkdwnV << std::endl << std::endl;
3227  Xyce::dout() << " D1cd = " << D1cd << std::endl;
3228  Xyce::dout() << " D1gd = " << D1gd << std::endl;
3229  Xyce::dout() << " D1cdeq = " << D1cdeq << std::endl;
3230  }
3231 #endif
3232 
3233  // in 3f5 this is all in a block conditioned on CKTmode, but since
3234  // it's valid for MODETRAN and MODETRANOP we'll just always do it
3235 
3236  ////
3237  // * now we do the hard part of the bulk-drain and bulk-source
3238  // * diode - we evaluate the non-linear capacitance and
3239  // * charge
3240  // *
3241  // * the basic equations are not hard, but the implementation
3242  // * is somewhat long in an attempt to avoid log/exponential
3243  // * evaluations
3244  ////
3245  ////
3246  // * charge storage elements
3247  // *
3248  // *.. bulk-drain and bulk-source depletion capacitances
3249  ////
3250  // I took out all the CAPBYPASS stuff, and the
3251  // unnecessary curly braces that wind up there if you do
3252 
3253  // can't bypass the diode capacitance calculations
3254  if(Cbs != 0 || Cbssw != 0 )
3255  {
3256  if (vbs < tDepCap)
3257  {
3258  arg=1-vbs/tBulkPot;
3259  ////
3260  // * the following block looks somewhat long and messy,
3261  // * but since most users use the default grading
3262  // * coefficients of .5, and sqrt is MUCH faster than an
3263  // * exp(log()) we use this special case code to buy time.
3264  // * (as much as 10% of total job time!)
3265  ////
3267  {
3268  if(model_.bulkJctBotGradingCoeff == .5)
3269  {
3270  sarg = sargsw = 1/sqrt(arg);
3271  }
3272  else
3273  {
3274  sarg = sargsw = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3275  }
3276  }
3277  else
3278  {
3279  if(model_.bulkJctBotGradingCoeff == .5)
3280  {
3281  sarg = 1/sqrt(arg);
3282  }
3283  else
3284  {
3285  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3286  }
3288  {
3289  sargsw = 1/sqrt(arg);
3290  }
3291  else
3292  {
3293  sargsw =exp(-model_.bulkJctSideGradingCoeff* log(arg));
3294  }
3295  }
3296  qbs = tBulkPot*(Cbs*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff)
3297  +Cbssw*(1-arg*sargsw)/(1-model_.bulkJctSideGradingCoeff));
3298  capbs=Cbs*sarg + Cbssw*sargsw;
3299  }
3300  else
3301  {
3302  qbs = f4s + vbs*(f2s+vbs*(f3s/2));
3303  capbs=f2s+f3s*vbs;
3304  }
3305  }
3306  else
3307  {
3308  qbs = 0;
3309  capbs=0;
3310  }
3311 
3312  //// can't bypass the diode capacitance calculations
3313  if(Cbd != 0 || Cbdsw != 0 )
3314  {
3315 
3316  if (vbdd < tDepCap)
3317  {
3318  arg=1-vbdd/tBulkPot;
3319  ////
3320  // * the following block looks somewhat long and messy,
3321  // * but since most users use the default grading
3322  // * coefficients of .5, and sqrt is MUCH faster than an
3323  // * exp(log()) we use this special case code to buy time.
3324  // * (as much as 10% of total job time!)
3325  ////
3326  if(model_.bulkJctBotGradingCoeff == .5 &&
3328  {
3329  sarg = sargsw = 1/sqrt(arg);
3330  }
3331  else
3332  {
3333  if(model_.bulkJctBotGradingCoeff == .5)
3334  {
3335  sarg = 1/sqrt(arg);
3336  }
3337  else
3338  {
3339  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3340  }
3342  {
3343  sargsw = 1/sqrt(arg);
3344  }
3345  else
3346  {
3347  sargsw =exp(-model_.bulkJctSideGradingCoeff*log(arg));
3348  }
3349  }
3350  qbd =
3351  tBulkPot*(Cbd*(1-arg*sarg)
3353  +Cbdsw*(1-arg*sargsw)
3355  capbd=Cbd*sarg + Cbdsw*sargsw;
3356  }
3357  else
3358  {
3359  qbd = f4d + vbdd * (f2d + vbdd * f3d/2);
3360  capbd= f2d + vbdd * f3d;
3361  }
3362  }
3363  else
3364  {
3365  qbd = 0;
3366  capbd = 0;
3367  }
3368 
3369  // charge storage elements
3370  D1czero = D1DIOtJctCap*D1DIOarea;
3371  if (D1vd < D1DIOtDepCap)
3372  {
3373  D1arg = 1-D1vd/model_.D1DIOjunctionPot;
3374  D1sarg = exp(-model_.D1DIOgradingCoeff*log(D1arg));
3376  model_.D1DIOjunctionPot*D1czero*
3377  (1-D1arg*D1sarg)/(1-model_.D1DIOgradingCoeff);
3378  D1capd = model_.D1DIOtransitTime*D1gd + D1czero*D1sarg;
3379  }
3380  else
3381  {
3382  D1czof2 = D1czero/model_.D1DIOf2;
3383  D1DIOcapCharge = model_.D1DIOtransitTime*D1cd+D1czero*
3384  D1DIOtF1+D1czof2*(model_.D1DIOf3*
3389  D1capd = model_.D1DIOtransitTime*D1gd+D1czof2*
3392  }
3393 
3394 #ifdef Xyce_DEBUG_DEVICE
3396  {
3397  Xyce::dout() << " " << std::endl;
3398  Xyce::dout() << " Going into qmeyer..." << std::endl;
3399  Xyce::dout() << " Mode is " << mode << std::endl;
3400  Xyce::dout() << " Args are vgps = " << vgps << " vgpdd = " << vgpdd << std::endl;
3401  Xyce::dout() << " Vgpb = " << Vgpb << " Von = " << Von << " Vddsat = " << Vddsat << std::endl;
3402  Xyce::dout() << " tPhi = " << tPhi << " OxideCap = " << OxideCap << std::endl;
3403  }
3404 #endif
3405  if (mode > 0)
3406  {
3407  if(model_.cve == 1)
3408  {
3409  UCCMqmeyer (vgps,vgpdd,Vgpb,Von,Vddsat,
3411  }
3412  else
3413  {
3414  // Ward-like model
3416  }
3417  }
3418  else
3419  {
3420  if(model_.cve == 1)
3421  {
3422  UCCMqmeyer (vgpdd,vgps,Vgpb,Von,Vddsat,
3424  }
3425  else
3426  {
3427  // Ward-like model
3429  }
3430  }
3431 
3432  if((getSolverState().dcopFlag))
3433  {
3434  Capgs = 2 * capgs + GateSourceOverlapCap ;
3436  Capgb = 2 * capgb + GateBulkOverlapCap ;
3437  }
3438  else
3439  {
3440  capgs_old = (*extData.currStaVectorPtr)[li_state_capgs];
3441  capgdd_old = (*extData.currStaVectorPtr)[li_state_capgdd];
3442  capgb_old = (*extData.currStaVectorPtr)[li_state_capgb];
3443 
3444 #ifdef Xyce_DEBUG_DEVICE
3446  {
3447  Xyce::dout() << "Doing meyer back averaging..."<< std::endl;
3448  Xyce::dout() << " capgs = " << capgs << " capgs_old = " << capgs_old << std::endl;
3449  Xyce::dout() << " capgdd = " << capgdd << " capgdd_old = " << capgdd_old << std::endl;
3450  Xyce::dout() << " capgb = " << capgb << " capgb_old = " << capgb_old << std::endl;
3451  }
3452 #endif
3453  Capgs = ( capgs+capgs_old + GateSourceOverlapCap );
3454  Capgdd = ( capgdd+capgdd_old + GateDrainOverlapCap );
3455  Capgb = ( capgb+capgb_old + GateBulkOverlapCap );
3456  }
3457 #ifdef Xyce_DEBUG_DEVICE
3459  {
3460  Xyce::dout() << "Capgs = " << Capgs << std::endl;
3461  Xyce::dout() << "Capgdd = " << Capgdd << std::endl;
3462  Xyce::dout() << "Capgb = " << Capgb << std::endl;
3463  Xyce::dout() << "capgs = " << capgs << std::endl;
3464  Xyce::dout() << "capgdd = " << capgdd << std::endl;
3465  Xyce::dout() << "capgb = " << capgb << std::endl;
3466  }
3467 #endif
3468  Capgs *= (Capgs < 0.0)?-1.0:1.0;
3469  Capgdd *= (Capgdd < 0.0)?-1.0:1.0;
3470  Capgb *= (Capgb < 0.0)?-1.0:1.0;
3471 
3472  // Voltage-dependent drain-drift conductance
3473  double absV = fabs(Vddd);
3475  if(gddd != 0) gddd = 1.0/gddd;
3476  draindriftCond = gddd;
3477 
3478  // need a more precise derivative than gddd for the jacobian.
3479  // w.r.t. Vd and Vdd.
3480  double dVddd_dVd (1.0);
3481  double d_absVddd_dVd (0.0);
3482  if (Vddd > 0.0)
3483  {
3484  d_absVddd_dVd = 1.0;
3485  }
3486  else if (Vddd < 0.0)
3487  {
3488  d_absVddd_dVd = -1.0;
3489  }
3490 
3491  dIdd_dVd = dVddd_dVd * gddd -
3492  Vddd * (gddd*gddd)*(model_.driftParamB)*d_absVddd_dVd;
3493 
3494  // now do the shundt resistor
3495  if(model_.rdsshunt == 0.0)
3496  {
3497  gdsshunt = 0.0;
3498  }
3499  else
3500  {
3502  }
3503 
3504  Idrain = drainCond * Vdddp;
3505  Igate = gateCond * Vggp;
3506  Isource = sourceCond * Vssp;
3508  Irdsshunt = gdsshunt * (Vd - Vs);
3509  // Rd1rs current:
3510  Ird1rs = D1gspr*(Vs - Vd1p);
3511 
3512  if (mode >= 0) // Normal mode
3513  {
3514  Gm = gm; // (xnrm-xrev)*gm in 3f5
3515  Gmbs = gmbs; // (xnrm-xrev)*gmbs in 3f5
3516  nrmsum = Gm+Gmbs; // xnrm*(gm+gmbs)
3517  revsum = 0; // xrev*(gm+gmbs)
3519  }
3520  else
3521  {
3522  Gm = -gm;
3523  Gmbs = -gmbs;
3524  nrmsum = 0;
3525  revsum = -(Gm+Gmbs); // because Gm and Gmbs already have - in them!
3526  cdreq = -(model_.dtype)*cdrain;
3527  }
3528 
3529 #ifdef Xyce_DEBUG_DEVICE
3531  {
3532  Xyce::dout() << " Done with Instance::updateIntermediateVars " << std::endl;
3533  Xyce::dout() << " mode = " << mode << std::endl;
3534  Xyce::dout() << " Idrain = " << Idrain << std::endl;
3535  Xyce::dout() << " Igate = " << Igate << std::endl;
3536  Xyce::dout() << " Isource = " << Isource << std::endl;
3537  Xyce::dout() << " Idraindrift = " << Idraindrift << std::endl;
3538  Xyce::dout() << " Ird1rs = " << Ird1rs << std::endl;
3539  Xyce::dout() << " dIdd_dVd = " << dIdd_dVd << std::endl;
3540  Xyce::dout() << " gddd = " << gddd << std::endl;
3541  Xyce::dout() << " Irdsshunt = " << Irdsshunt << std::endl;
3542  Xyce::dout() << " D1DIOcapCurrent = " << D1DIOcapCurrent << std::endl;
3543  Xyce::dout() << " cbd = " << cbd << std::endl;
3544  Xyce::dout() << " cbs = " << cbs << std::endl;
3545  Xyce::dout() << " qbd = " << qbd << std::endl;
3546  Xyce::dout() << " qbs = " << qbs << std::endl;
3547  Xyce::dout() << " cdrain = " << cdrain << std::endl;
3548  Xyce::dout() << " cdraindrift = " << cdraindrift << std::endl;
3549  Xyce::dout() << " cdreq = " << cdreq << std::endl;
3550  Xyce::dout() << " gdds = " << gdds << std::endl;
3551  Xyce::dout() << " gdsshunt = " << gdsshunt << std::endl;
3552  Xyce::dout() << " gm = " << gm << std::endl;
3553  Xyce::dout() << " gmbs = " << gmbs << std::endl;
3554  Xyce::dout() << " Gm = " << Gm << std::endl;
3555  Xyce::dout() << " Gmbs = " << Gmbs << std::endl;
3556  }
3557 #endif
3558 
3559  /// CURRENTS to load into RHS:
3560 
3561  // current out of drain is
3562  // Idraindrift + Irdsshunt - Dtype*(D1cdeq + D1DIOcapCurrent)
3563 
3564  // current out of gate:
3565  // dtype*( (deriv of qgs) + (deriv of qgdd) + (deriv of qgb))
3566 
3567  // the current *out of* the source is
3568  // Isource - Irdsshunt + Ird1rs
3569 
3570  // current out of bulk is
3571  // dtype*(deriv of qbd) + dtype*cbd + dtype*cbs + dtype*(deriv of qbs)
3572  // - dtype*(deriv of qgb)
3573 
3574  // current out of drain' is
3575  // -Idrain - dtype*(deriv of qgd) - (deriv of qbd) - dtype*cbd +
3576  // mode*dtype*cdrain
3577 
3578  // the current out of the source' is
3579  // -Isource - dtype*(deriv of qgs) - dtype*cbs - (deriv of qbs) -
3580  // mode*dtype*cdrain -Irdsshunt
3581 
3582  // the current out of the draindrift node is
3583  // Idrain - IdraindriftDtype*(D1cdeq + D1DIOcapCurrent)
3584 
3585  // the current out of the d1' pos node is
3586  // Dtype*(D1cdeq + D1DIOcapCurrent) - Ird1rs
3587 
3588  return bsuccess;
3589 }
3590 
3591 //-----------------------------------------------------------------------------
3592 // Function : Instance::updateTemperature
3593 // Purpose :
3594 // Special Notes :
3595 // Scope : public
3596 // Creator : pmc
3597 // Creation Date : 2/17/2004
3598 //-----------------------------------------------------------------------------
3599 bool Instance::updateTemperature ( const double & temp_tmp)
3600 {
3601  bool bsuccess = true;
3602  // mos3temp vars
3603  double czbd(0.0); // zero voltage bulk-drain capacitance
3604  double czbdsw(0.0); // zero voltage bulk-drain sidewall capacitance
3605  double czbs(0.0); // zero voltage bulk-source capacitance
3606  double czbssw(0.0); // zero voltage bulk-source sidewall capacitance
3607  double arg(0.0); // 1 - fc
3608  double sarg(0.0); // (1-fc) ^^ (-mj)
3609  double sargsw(0.0); // (1-fc) ^^ (-mjsw)
3610  double ratio,ratio4(0.0);
3611  double fact2(0.0);
3612  double kt(0.0);
3613  double egfet(0.0);
3614  double pbfact(0.0);
3615  double capfact(0.0);
3616  double phio(0.0);
3617  double pbo(0.0);
3618  double gmanew,gmaold(0.0);
3619  // end of mos3temp stuff
3620 
3621 //variables related to the diode 1
3622  double D1xfc(0.0);
3623  double D1vte_loc(0.0);
3624  double D1cbv(0.0);
3625  double D1xbv(0.0);
3626  double D1xcbv(0.0);
3627  double D1tol(0.0);
3628  double D1vt_loc(0.0);
3629  register int D1iter(0.0);
3630  double D1egfet1(0.0),D1arg1(0.0),D1fact1(0.0),D1pbfact1(0.0),D1pbo(0.0),D1gmaold(0.0);
3631  double D1fact2(0.0),D1pbfact(0.0),D1arg(0.0),D1egfet(0.0),D1gmanew(0.0);
3632  double reltol(0.0);
3633 
3634  double tnom(0.0);
3635  double VMAX(0.0);
3636 
3637 // oxide dielectric permitivity
3638 //#define EPSSIO2 3.453130e-11 == CONSTEPSOX (Xyce value)
3639 
3640 #ifdef Xyce_DEBUG_DEVICE
3641 
3642  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3643  {
3644  Xyce::dout() << subsection_divider << std::endl;
3645  Xyce::dout() << " Instance::Begin of updateTemperature. \n";
3646  Xyce::dout() <<" name = " << getName() << std::endl;
3647  Xyce::dout() << std::endl;
3648  }
3649 #endif
3650 
3651  // first set the instance temperature to the new temperature:
3652  if (temp_tmp != -999.0) temp = temp_tmp;
3654  {
3655  // make sure interpolation doesn't take any resistance negative
3660  if(model_.D1DIOresist < 0) model_.D1DIOresist = 0;
3661 
3662  // some params may have changed during interpolation
3664  }
3665 
3666  VMAX = model_.maxDriftVel;
3667  tnom = model_.tnom;
3668  ratio = temp/tnom;
3669 #ifdef Xyce_DEBUG_DEVICE
3670  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3671  {
3672  Xyce::dout() << " Temperature = "<< temp << std::endl;
3673  Xyce::dout() << " tnom = " << tnom << std::endl;
3674  Xyce::dout() << " ratio = " << ratio << std::endl;
3675  }
3676 #endif
3677 
3678  vt = temp * CONSTKoverQ;
3679  ratio = temp/tnom;
3680  fact2 = temp/CONSTREFTEMP;
3681  kt = temp * CONSTboltz;
3682  egfet = 1.16-(7.02e-4*temp*temp)/(temp+1108);
3683  arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3684  pbfact = -2*vt *(1.5*log(fact2)+CONSTQ*arg);
3685 
3686 #ifdef Xyce_DEBUG_DEVICE
3688  {
3689  Xyce::dout() << " fact1 = " << model_.fact1 << std::endl;
3690  Xyce::dout() << " vtnom = " << model_.vtnom << std::endl;
3691  Xyce::dout() << " egfet1 = " << model_.egfet1 << std::endl;
3692  Xyce::dout() << " pbfact1= " << model_.pbfact1 << std::endl;
3693  Xyce::dout() << " vt = " << vt << std::endl;
3694  Xyce::dout() << " ratio = " << ratio << std::endl;
3695  Xyce::dout() << " fact2 = " << fact2 << std::endl;
3696  Xyce::dout() << " kt = " << kt << std::endl;
3697  Xyce::dout() << " egfet = " << egfet << std::endl;
3698  Xyce::dout() << " arg = " << arg << std::endl;
3699  Xyce::dout() << " pbfact = " << pbfact << std::endl;
3700  }
3701 #endif
3702 
3703  ratio4 = ratio * sqrt(ratio);
3704  tSurfMob = 1.e-4*model_.surfaceMobility/ratio4;
3705  phio= (model_.phi-model_.pbfact1)/model_.fact1;
3706  tPhi = fact2 * phio + pbfact;
3707  tVbi = model_.vt0 - model_.dtype *
3708  (model_.gamma* sqrt(model_.phi))+.5*(model_.egfet1-egfet)
3709  + model_.dtype*.5* (tPhi-model_.phi);
3710  tVto = tVbi + model_.dtype * model_.gamma * sqrt(tPhi);
3711  if(model_.mdtemp != 0) tVto = model_.vt0 -
3712  model_.kvt*(temp-tnom);
3714  exp(-egfet/vt+model_.egfet1/model_.vtnom);
3716  exp(-egfet/vt+model_.egfet1/model_.vtnom);
3718  gmaold = (model_.bulkJctPotential-pbo)/pbo;
3719  capfact = 1/(1+model_.bulkJctBotGradingCoeff*
3720  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3721  tCbd = model_.capBD * capfact;
3722  tCbs = model_.capBS * capfact;
3723  tCj = model_.bulkCapFactor * capfact;
3724  capfact = 1/(1+model_.bulkJctSideGradingCoeff*
3725  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3726  tCjsw = model_.sideWallCapFactor * capfact;
3727  tBulkPot = fact2 * pbo+pbfact;
3728  gmanew = (tBulkPot-pbo)/pbo;
3729  capfact = (1+model_.bulkJctBotGradingCoeff *
3730  (4e-4*(temp-CONSTREFTEMP)-gmanew));
3731  tCbd *= capfact;
3732  tCbs *= capfact;
3733  tCj *= capfact;
3734  capfact = (1+model_.bulkJctSideGradingCoeff *
3735  (4e-4*(temp-CONSTREFTEMP)-gmanew));
3736  tCjsw *= capfact;
3738 
3739 #ifdef Xyce_DEBUG_DEVICE
3741  {
3742  Xyce::dout() << " ratio4 = " << ratio4 << std::endl;
3743  Xyce::dout() << " tSurfMob = " << tSurfMob << std::endl;
3744  Xyce::dout() << " phio = " << phio << std::endl;
3745  Xyce::dout() << " tPhi = " << tPhi << std::endl;
3746  Xyce::dout() << " tVbi = " << tVbi << std::endl;
3747  Xyce::dout() << " tVto = " << tVto << std::endl;
3748  Xyce::dout() << " tSatCur = " << tSatCur << std::endl;
3749  Xyce::dout() << " tSatCurDens = " << tSatCurDens << std::endl;
3750  Xyce::dout() << " pbo = " << pbo << std::endl;
3751  Xyce::dout() << " gmaold = " << gmaold << std::endl;
3752  Xyce::dout() << " tBulkPot = " << tBulkPot << std::endl;
3753  Xyce::dout() << " gmanew = " << gmanew << std::endl;
3754  Xyce::dout() << " capfact = " << capfact << std::endl;
3755  Xyce::dout() << " tCbd = " << tCbd << std::endl;
3756  Xyce::dout() << " tCbs = " << tCbs << std::endl;
3757  Xyce::dout() << " tCj = " << tCj << std::endl;
3758  Xyce::dout() << " capfact = " << capfact << std::endl;
3759  Xyce::dout() << " tCjsw = " << tCjsw << std::endl;
3760  Xyce::dout() << " tDepCap = " << tDepCap << std::endl;
3761  }
3762 #endif
3763 
3764  if( (model_.jctSatCurDensity == 0) || (drainArea == 0) ||
3765  (sourceArea == 0) )
3766  {
3768  vt*log(vt/(CONSTroot2*model_.jctSatCur));
3769  }
3770  else
3771  {
3772  drainVcrit = vt * log( vt / (CONSTroot2 *
3774  sourceVcrit = vt * log( vt / (CONSTroot2 *
3776  }
3777  if(model_.capBDGiven)
3778  {
3779  czbd = tCbd;
3780  }
3781  else
3782  {
3784  {
3785  czbd=tCj*drainArea;
3786  }
3787  else
3788  {
3789  czbd=0;
3790  }
3791  }
3793  {
3794  czbdsw= tCjsw * drainPerimeter;
3795  }
3796  else
3797  {
3798  czbdsw=0;
3799  }
3800  arg = 1-model_.fwdCapDepCoeff;
3801  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3802  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3803  Cbd = czbd;
3804  Cbdsw = czbdsw;
3805  f2d = czbd*(1-model_.fwdCapDepCoeff*
3806  (1+model_.bulkJctBotGradingCoeff))* sarg/arg
3807  + czbdsw*(1-model_.fwdCapDepCoeff*
3808  (1+model_.bulkJctSideGradingCoeff))*sargsw/arg;
3809  f3d = czbd * model_.bulkJctBotGradingCoeff * sarg/arg/tBulkPot
3810  + czbdsw * model_.bulkJctSideGradingCoeff *
3811  sargsw/arg/tBulkPot;
3812  f4d = czbd*tBulkPot*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff) +
3813  czbdsw*tBulkPot*(1-arg*sargsw)/
3815  f3d/2*(tDepCap*tDepCap) - tDepCap * f2d;
3816  if(model_.capBSGiven)
3817  {
3818  czbs=tCbs;
3819  }
3820  else
3821  {
3823  {
3824  czbs=tCj*sourceArea;
3825  }
3826  else
3827  {
3828  czbs=0;
3829  }
3830  }
3832  {
3833  czbssw = tCjsw * sourcePerimeter;
3834  }
3835  else
3836  {
3837  czbssw=0;
3838  }
3839  arg = 1-model_.fwdCapDepCoeff;
3840  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3841  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3842  Cbs = czbs;
3843  Cbssw = czbssw;
3844  f2s = czbs*(1-model_.fwdCapDepCoeff*
3845  (1+model_.bulkJctBotGradingCoeff))*sarg/arg +
3846  czbssw*(1-model_.fwdCapDepCoeff*
3847  (1+model_.bulkJctSideGradingCoeff))*sargsw/arg;
3848  f3s = czbs * model_.bulkJctBotGradingCoeff * sarg/arg/tBulkPot
3849  + czbssw * model_.bulkJctSideGradingCoeff *
3850  sargsw/arg /tBulkPot;
3851  f4s = czbs*tBulkPot*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff)
3852  + czbssw*tBulkPot*(1-arg*sargsw)/
3854  (tDepCap*tDepCap) - tDepCap * f2s;
3855 
3857 
3858  if(!model_.vpGiven)
3859  {
3860  vp = VMAX*(l-2*model_.latDiff)/tSurfMob;
3861  if(model_.dtype == CONSTNMOS) vp *= 2.0;
3862  } else
3863  vp = model_.vp;
3864 
3865  gchi0 = CONSTQ*w/(l-2*model_.latDiff);
3866  gammas =
3868  model_.wgammas*(1-model_.w0/w);
3869  gammal =
3871  model_.wgammal*(1-model_.w0/w);
3872  if(gammal != 0.0) {
3873  vthLimit = gammas/(2*gammal);
3875  } else
3876  vthLimit = N_UTL_MachineDependentParams::DoubleMax();
3877  vtoo = tVto*model_.dtype+ gammal*tPhi- gammas*sqrt(tPhi);
3878 
3879  // quantities related to diode #1
3880 
3881  D1DIOtemp = temp;
3882  model_.D1DIOnomTemp = tnom;
3883  D1vt_loc = CONSTKoverQ * D1DIOtemp;
3884  D1xfc = log(1-model_.D1DIOdepletionCapCoeff);
3885 
3886 // this part gets really ugly - I don't know how to explain these equations
3887 
3888  D1fact2 = D1DIOtemp/CONSTREFTEMP;
3889  D1egfet = 1.16-(7.02e-4*D1DIOtemp*D1DIOtemp)/(D1DIOtemp+1108);
3890  D1arg = -D1egfet/(2*CONSTboltz*D1DIOtemp) + 1.1150877/
3891  (CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3892  D1pbfact = -2*D1vt_loc*(1.5*log(D1fact2)+CONSTQ*D1arg);
3893  D1egfet1 = 1.16 - (7.02e-4*model_.D1DIOnomTemp*
3895  D1arg1 = -D1egfet1/(CONSTboltz*2*model_.D1DIOnomTemp) +
3896  1.1150877/(2*CONSTboltz*CONSTREFTEMP);
3897  D1fact1 = model_.D1DIOnomTemp/CONSTREFTEMP;
3898  D1pbfact1 = -2*CONSTKoverQ*model_.D1DIOnomTemp*
3899  (1.5*log(D1fact1)+CONSTQ*D1arg1);
3900  D1pbo = (model_.D1DIOjunctionPot-D1pbfact1)/D1fact1;
3901  D1gmaold = (model_.D1DIOjunctionPot -D1pbo)/D1pbo;
3904  (400e-6*(model_.D1DIOnomTemp-CONSTREFTEMP)-D1gmaold) );
3905  D1DIOtJctPot = D1pbfact+D1fact2*D1pbo;
3906  D1gmanew = (D1DIOtJctPot-D1pbo)/D1pbo;
3908  (400e-6*(D1DIOtemp-CONSTREFTEMP)-D1gmanew);
3909  D1DIOtSatCur = model_.D1DIOsatCur*exp( ((D1DIOtemp/
3910  model_.D1DIOnomTemp)-1)*
3912  (model_.D1DIOemissionCoeff*D1vt_loc)+
3915  log(D1DIOtemp/model_.D1DIOnomTemp) );
3917 
3918  // the defintion of f1, just recompute after temperature adjusting
3919  // all the variables used in it
3920  D1DIOtF1=D1DIOtJctPot*(1-exp((1-model_.D1DIOgradingCoeff)*D1xfc))/
3922 
3923  // same for Depletion Capacitance
3925 
3926  // and Vcrit
3927  D1vte_loc=model_.D1DIOemissionCoeff*D1vt_loc;
3928  D1DIOtVcrit=D1vte_loc*log(D1vte_loc/(CONSTroot2*D1DIOtSatCur));
3929 
3930  // and now to copute the breakdown voltage, again using
3931  // temperature adjusted basic parameters
3933  {
3935  if (D1cbv < D1DIOtSatCur*model_.D1DIObreakdownVoltage/D1vt_loc)
3936  {
3937  D1cbv=D1DIOtSatCur*model_.D1DIObreakdownVoltage/D1vt_loc;
3938  Xyce::dout() << " breakdown current increased to " << D1cbv <<
3939  "to resolve incompatability " <<
3940  "with specified saturation current" << std::endl;
3942  } else
3943  {
3944  reltol = 1e-3;
3945  D1tol=reltol*D1cbv;
3947  D1vt_loc*log(1+D1cbv/D1DIOtSatCur);
3948  for(D1iter=0; D1iter<25; ++D1iter)
3949  {
3950  D1xbv=model_.D1DIObreakdownVoltage-D1vt_loc*log(D1cbv/
3951  D1DIOtSatCur+1-D1xbv/D1vt_loc);
3952  D1xcbv=D1DIOtSatCur*(exp((model_.D1DIObreakdownVoltage
3953  -D1xbv)/D1vt_loc)-1+D1xbv/D1vt_loc);
3954  if (fabs(D1xcbv-D1cbv) <= D1tol) goto matched;
3955  }
3956  Xyce::dout() << " unable to match forward and reverse diode regions: D1bv = "
3957  << D1xbv << " D1ibv = " << D1xcbv << std::endl;
3958  }
3959  matched:
3960  D1DIOtBrkdwnV = D1xbv;
3961  }
3962 
3963  return bsuccess;
3964 }
3965 
3966 //-----------------------------------------------------------------------------
3967 // Function : Instance::updatePrimaryState
3968 // Purpose :
3969 // Special Notes :
3970 // Scope : public
3971 // Creator : Tom Russo, Component Information and Models
3972 // Creation Date : 02/28/01
3973 //-----------------------------------------------------------------------------
3975 {
3976  bool bsuccess = true;
3977  double vgs1(0.0), vgdd1(0.0), vbs1(0.0),vgb1(0.0), vdds1(0.0);
3978  double * staVector = extData.nextStaVectorRawPtr;
3979  double * currStaVector = extData.currStaVectorRawPtr;
3980 
3981  bool tmpBool = updateIntermediateVars ();
3982  bsuccess = bsuccess && tmpBool;
3983 
3984  // voltage drops:
3985  staVector[li_state_vbdd] = vbdd;
3986  staVector[li_state_vbs] = vbs;
3987  staVector[li_state_vgps] = vgps;
3988  staVector[li_state_vdds] = vdds;
3989  staVector[li_state_D1vd] = D1vd;
3990 
3991  // now the meyer capacitances
3992  // we didn't calculate these charges in update IntermediateVars
3993  // but we did calculate the voltage drops and capacitances.
3994  // first store the capacitances themselves:
3995  staVector[li_state_capgs] = capgs;
3996  staVector[li_state_capgdd] = capgdd;
3997  staVector[li_state_capgb] = capgb;
3998 
3999  // now the charges
4000  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
4001  // supposed to be *INTEGRATED*:
4002  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
4003  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
4004  // Now with Meyer back averaging, Capxx is the average between the last
4005  // time step and this one. So we gotta do the right thing for non-DCOP
4006  // when backaverage is on.
4007 
4008  if((getSolverState().dcopFlag))
4009  {
4010  qgs = Capgs *vgps;
4011  qgdd = Capgdd*vgpdd;
4012  qgb = Capgb *Vgpb;
4013  }
4014  else
4015  {
4016  // get the ones from last time step
4017  qgs = currStaVector[li_state_qgs];
4018  qgdd = currStaVector[li_state_qgdd];
4019  qgb = currStaVector[li_state_qgb];
4020  // get the voltage drops, too
4021  vgs1 = currStaVector[li_state_vgps];
4022  vbs1 = currStaVector[li_state_vbs];
4023  vdds1 = currStaVector[li_state_vdds];
4024 
4025  vgb1 = vgs1-vbs1;
4026  vgdd1 = vgs1-vdds1;
4027 
4028  // NOW we can calculate the charge update
4029  qgs += Capgs*(vgps-vgs1);
4030  qgdd += Capgdd*(vgpdd-vgdd1);
4031  qgb += Capgb*((vgps-vbs)-vgb1);
4032  }
4033 
4034  staVector[li_state_qgs] = qgs;
4035  staVector[li_state_qgdd] = qgdd;
4036  staVector[li_state_qgb] = qgb;
4037 
4038  // and the diode parasitic capacitors
4039  // these charges were set in updateIntermediateVars
4040  staVector[li_state_qbd] = qbd;
4041  staVector[li_state_qbs] = qbs;
4042 
4043 // diode #1 quatntities
4044 
4046 
4047  // In the case of a charge, need to handle this:
4048  // Ensure dQ/dt = 0 for initial step after dcOP by setting the history equal
4049  // to the current value
4050  if( !getSolverState().dcopFlag && getSolverState().initTranFlag && !getSolverState().newtonIter )
4051  {
4052  currStaVector[li_state_D1DIOcapCharge] = D1DIOcapCharge;
4053  }
4054 
4055  staVector[ li_state_von ] = von;
4056 
4057  return bsuccess;
4058 }
4059 
4060 //-----------------------------------------------------------------------------
4061 // Function : Instance::updateSecondaryState
4062 // Purpose :
4063 // Special Notes :
4064 // Scope : public
4065 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
4066 // Creation Date : 01/09/01
4067 //-----------------------------------------------------------------------------
4069 {
4070  double * staDerivVector = (extData.nextStaDerivVectorRawPtr);
4071 
4072  cqgs = staDerivVector[li_state_qgs];
4073  cqgdd = staDerivVector[li_state_qgdd];
4074  cqgb = staDerivVector[li_state_qgb];
4075  cqbd = staDerivVector[li_state_qbd];
4076  cqbs = staDerivVector[li_state_qbs];
4077 
4078  D1DIOcapCurrent = staDerivVector[li_state_D1DIOcapCharge];
4079 
4080  double Dtype =model_.dtype;
4081  double D1current = Dtype*(D1cdeq + D1DIOcapCurrent);
4082 
4083  // Even though these do not look exactly like the RHS loads, they do account
4084  // for the currents into the leads even with the lead resistors in place
4085  // --- since the lead resistances are the only thing between the primed node
4086  // and the lead, the currents are still correct AT CONVERGED SOLUTIONS
4087 
4088  /*
4089  lead current load has been moved to F & Q loads
4090  LeadCurrentD = -model_.dtype*(-mode*cdrain+cbd+cqgdd+cqbd) - D1current-Irdsshunt;
4091  LeadCurrentG = model_.dtype*(cqgs+cqgb+cqgdd);
4092  LeadCurrentS = model_.dtype*(-mode*cdrain+cbs-cqgs-cqbs) + D1current+Irdsshunt;
4093  LeadCurrentB = model_.dtype*(cbd-cbs-cqgb+cqbd+cqbs);
4094  */
4095 
4096  return true;
4097 }
4098 
4099 
4100 //-----------------------------------------------------------------------------
4101 // Function : Instance::processParams
4102 // Purpose :
4103 // Special Notes :
4104 // Scope : public
4105 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
4106 // Creation Date : 6/03/02
4107 //-----------------------------------------------------------------------------
4109 {
4110 
4111 #ifdef Xyce_DEBUG_DEVICE
4112  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
4113  {
4114  Xyce::dout() << " L = " << l << std::endl;
4115  Xyce::dout() << " W = " << w<< std::endl;
4116  Xyce::dout() << " drainArea = " << drainArea<< std::endl;
4117  Xyce::dout() << " sourceArea = " << sourceArea<< std::endl;
4118  Xyce::dout() << " drainSquares = " << drainSquares<< std::endl;
4119  Xyce::dout() << " sourceSquares = " << sourceSquares<< std::endl;
4120  Xyce::dout() << " drainPerimeter = " << drainPerimeter<< std::endl;
4121  Xyce::dout() << " sourcePerimeter = " << sourcePerimeter<< std::endl;
4122  Xyce::dout() << " drainCond = " << drainCond<< std::endl;
4123  Xyce::dout() << " sourceCond = " << sourceCond << std::endl;
4124  Xyce::dout() << " draindriftCond = " << draindriftCond<< std::endl;
4125  Xyce::dout() << " temp = " << temp<< std::endl;
4126  }
4127 #endif
4128 
4129  // now set the temperature related stuff
4131 
4132  return true;
4133 }
4134 
4135 // Additional Declarations
4136 
4137 
4138 //-----------------------------------------------------------------------------
4139 // Function : Instance::UCCMqmeyer
4140 // Purpose : Compute the MOS overlap capacitances as functions of the
4141 // device terminal voltages
4142 //
4143 // Special Notes :
4144 //
4145 // Scope : public
4146 // Creator : pmc
4147 // Creation Date : 02/17/2004
4148 //-----------------------------------------------------------------------------
4150  double xvgs, // initial voltage gate-source (mode > 0)
4151  double xvgdd, // initial voltage gate-drain (mode > 0)
4152  double vgb, // initial voltage gate-bulk
4153  double von_local, // threshold voltage
4154  double vddsat_local, // saturation drain voltage
4155  double & capgs_local, // non-constant portion of g-s overlap capacitance
4156  double & capgdd_local,// non-constant portion of g-d overlap capacitance
4157  double & capgb_local, // non-constant portion of g-b overlap capacitance
4158  double phi,
4159  double cox // oxide capactiance
4160  )
4161 {
4162  double vdds_local(0.0);
4163  double vddif(0.0);
4164  double vddif1(0.0);
4165  double vddif2(0.0);
4166  double vgst(0.0);
4167  double etavt(0.0);
4168  double cgc(0.0);
4169  double x(0.0);
4170 
4171 #define W w
4172 #define L EffectiveLength
4173 #define ETA model_.eta
4174 #define TOX model_.oxideThickness
4175 
4176  vgst = xvgs-von_local;
4177  if (vgst <= -phi)
4178  {
4179  capgb_local = cox/2;
4180  capgs_local = 0;
4181  capgdd_local = 0;
4182  }
4183  else if (vgst <= -phi/2)
4184  {
4185  capgb_local = -vgst*cox/(2*phi);
4186  capgs_local = 0;
4187  capgdd_local = 0;
4188  }
4189  else if (vgst <= 0)
4190  {
4191  capgb_local = -vgst*cox/(2*phi);
4192  capgs_local = vgst*cox/(1.5*phi)+cox/3;
4193  capgdd_local = 0;
4194  }
4195  else
4196  {
4197  vdds_local = xvgs-xvgdd;
4198  capgb_local = 0;
4199  if (vddsat_local <= vdds_local)
4200  {
4201  capgs_local = cox/3;
4202  capgdd_local = 0;
4203  }
4204  else
4205  {
4206  vddif = 2.0*vddsat_local-vdds_local;
4207  vddif1 = vddsat_local-vdds_local/*-1.0e-12*/;
4208  vddif2 = vddif*vddif;
4209  capgdd_local = cox*(1.0-vddsat_local*vddsat_local/vddif2)/3;
4210  capgs_local = cox*(1.0-vddif1*vddif1/vddif2)/3;
4211  }
4212  }
4213 
4214  // at this point we have unmodified Xyce values
4215  // the following is the UCCM adjustment
4216 
4217  if(model_.cv == 2 && vddsat_local != 0)
4218  {
4219  vdds_local = fabs(xvgs-xvgdd);
4220  vdds_local = vdds_local/pow(1+pow(vdds_local/vddsat_local,model_.mc),
4221  1.0/model_.mc);
4222  vddif = 2.0*vddsat_local-vdds_local;
4223  vddif1 = vddsat_local-vdds_local;
4224  vddif2 = vddif*vddif;
4225  etavt = ETA*vt;
4226  x = vgst/etavt;
4227  cgc = L*W/(TOX/CONSTEPSSI+etavt/(CONSTQ*n0)*exp(-x));
4228  capgdd_local = cgc*(1.0-vddsat_local*vddsat_local/vddif2)/3;
4229  capgs_local = cgc*(1.0-vddif1*vddif1/vddif2)/3;
4230  }
4231 
4232  return true;
4233 }
4234 
4235 //-----------------------------------------------------------------------------
4236 // Function : Instance::UCCMMeyercap
4237 // Purpose :
4238 //
4239 //
4240 // Special Notes :
4241 //
4242 // Scope : public
4243 // Creator : pmc
4244 // Creation Date : 02/17/2004
4245 //-----------------------------------------------------------------------------
4247  double xvgs, // initial voltage gate-source (mode > 0)
4248  double xvgdd, // initial voltage gate-drain (mode > 0)
4249  double vgb, // initial voltage gate-bulk
4250  double & cgs,
4251  double & cgd,
4252  double & cgb
4253  )
4254 {
4255  double vbs_local(0.0);
4256  double vdds_local(0.0);
4257  double zetanb(0.0);
4258  double xi(0.0);
4259  double xisqrt(0.0);
4260  double nsd(0.0);
4261  double nss(0.0);
4262  double tnss(0.0);
4263  double tnsd(0.0);
4264  double DeltaVT(0.0);
4265  double DnsdVgs(0.0);
4266  double DnsdVgd(0.0);
4267  double DnsdVgb(0.0);
4268  double DnssVgs(0.0);
4269  double DnssVgd(0.0);
4270  double DnssVgb(0.0);
4271  double DndepVgs(0.0);
4272  double DndepVgd(0.0);
4273  double DndepVgb(0.0);
4274  double UI(0.0);
4275  double VI(0.0);
4276  double DxiVgs(0.0);
4277  double DxiVgd(0.0);
4278  double DxiVgb(0.0);
4279  double DUIVgs(0.0);
4280  double DUIVgd(0.0);
4281  double DUIVgb(0.0);
4282  double DVIVgs(0.0);
4283  double DVIVgd(0.0);
4284  double DVIVgb(0.0); // With use of the chain rule, this routine may
4285  double DqiVgs(0.0); // be used to calculate the Ward capacitors.
4286  double DqiVgd(0.0); //
4287  double DqiVgb(0.0); // Cs, gs=dqs/dVgs= DqiVgs*fp+qiVgs*dfp
4288  double DqbVgs(0.0); // fp: partitioning factor
4289  double DqbVgd(0.0);
4290  double DqbVgb(0.0);
4291  double DqgVgs(0.0);
4292  double DqgVgd(0.0);
4293  double DqgVgb(0.0);
4294  double SigmaVgs(0.0); // This Sigma-parameter acounts for the DIBL
4295  double SigmaVgd(0.0); // effect on the capasitors. The physical
4296  double etavt(0.0);
4297  double VFB(0.0);
4298  double mqWL(0.0);
4299  double gamma(0.0);
4300  double A(0.0);
4301  double ALPHA(0.0);
4302 
4303  vbs_local = xvgs-vgb;
4304  vdds_local = xvgs-xvgdd;
4306  VFB =model_.vfb;
4307  ALPHA =model_.alpha;
4308 
4309  if(xvgs > VFB+vbs_local)
4310  {
4311  gamma= model_.gammas0;
4312  mqWL=(-CONSTQ)*EffectiveLength*(w);
4313  etavt=model_.eta*vt;
4314  nss=2.0*n0*log(1+0.5*exp((xvgs-von)/etavt));
4315  nsd=2.0*n0*log(1+0.5*exp((xvgs-von-ALPHA*vdds_local)/etavt));
4316 
4317  if (nss<1e-36) {nss=1.0e-36;}
4318  if (nsd<1e-36) {nsd=1.0e-36;}
4319  zetanb = (1-ALPHA)/ALPHA;
4320  xi = gamma*gamma/(A*A)+4/(A*A)*(vgb-VFB)-4.0/A*nss;
4321  xisqrt=sqrt(xi);
4322  tnsd = etavt/nsd+A;
4323  tnss = etavt/nss+A;
4324  if (vbs_local <= 0) { DeltaVT= 0.5*gamma/sqrt(tPhi-vbs_local); }
4325  if ((vbs_local > 0)&&(vbs_local <= 2*tPhi)) { DeltaVT=0.5*gamma/sqrt(tPhi); }
4326  if ((vbs_local > 0)&&(vbs_local > 2*tPhi)) { DeltaVT=0; }
4327 
4328  DnsdVgs=(1+DeltaVT-ALPHA+SigmaVgs)/tnsd;
4329  DnsdVgd=(-SigmaVgd+ALPHA)/tnsd;
4330  DnsdVgb=-DeltaVT/tnsd;
4331 
4332  DnssVgs= (1+DeltaVT+SigmaVgs)/tnss;
4333  DnssVgd=-SigmaVgd/tnss;
4334  DnssVgb=-DeltaVT/tnss;
4335 
4336  UI= etavt/2.0*(nsd*nsd-nss*nss) + A/3.0*(nsd*nsd*nsd-nss*nss*nss);
4337  VI= etavt*(nsd-nss) + A/2.0*(nsd*nsd-nss*nss);
4338  DUIVgs = etavt*(nsd*DnsdVgs-nss*DnssVgs) +
4339  A*(nsd*nsd*DnsdVgs-nss*nss*DnssVgs);
4340  DUIVgd= etavt*(nsd*DnsdVgd-nss*DnssVgd) +
4341  A*(nsd*nsd*DnsdVgd-nss*nss*DnssVgd);
4342  DUIVgb= etavt*(nsd*DnsdVgb-nss*DnssVgb) +
4343  A*(nsd*nsd*DnsdVgb-nss*nss*DnssVgb);
4344 
4345  DVIVgs= etavt*(DnsdVgs-DnssVgs) + A*(nsd*DnsdVgs-nss*DnssVgs);
4346  DVIVgd= etavt*(DnsdVgd-DnssVgd) + A*(nsd*DnsdVgd-nss*DnssVgd);
4347  DVIVgb= etavt*(DnsdVgb-DnssVgb) + A*(nsd*DnsdVgb-nss*DnssVgb);
4348  if (VI != 0)
4349  {
4350  DqiVgs= mqWL*(DUIVgs*VI-DVIVgs*UI)/(VI*VI);
4351  DqiVgd= mqWL*(DUIVgd*VI-DVIVgd*UI)/(VI*VI);
4352  DqiVgb= mqWL*(DUIVgb*VI-DVIVgb*UI)/(VI*VI);
4353  }
4354  else
4355  {
4356  DqiVgs=mqWL*DnssVgs;
4357  DqiVgd=mqWL*DnssVgd;
4358  DqiVgb=mqWL*DnssVgb;
4359  }
4360 
4361  DxiVgs= -4.0/A*DnssVgs;
4362  DxiVgd= -4.0/A*DnssVgd;
4363  DxiVgb= 4.0/(A*A)-4/A*DnssVgb;
4364 
4365  if (xisqrt !=0)
4366  {DndepVgs= gamma/4.0*1.0/xisqrt*DxiVgs;
4367  DndepVgd= gamma/4.0*1.0/xisqrt*DxiVgd;
4368  DndepVgb= gamma/4.0*1.0/xisqrt*DxiVgb;
4369  }
4370  else
4371  {
4372  DndepVgs=0;
4373  DndepVgd=0;
4374  DndepVgb=0;
4375  }
4376 
4377  DqbVgs = mqWL*(DndepVgs-zetanb*DnssVgs)+zetanb*DqiVgs;
4378  DqbVgd = mqWL*(DndepVgd-zetanb*DnssVgd)+zetanb*DqiVgd;
4379  DqbVgb = mqWL*(DndepVgb-zetanb*DnssVgb)+zetanb*DqiVgb;
4380 
4381  DqgVgs= -DqiVgs-DqbVgs;
4382  DqgVgd= -DqiVgd-DqbVgd;
4383  DqgVgb= -DqiVgb-DqbVgb;
4384  }
4385  else
4386  {
4387  // Below flat band
4388  DqgVgs=0.0;
4389  DqgVgd=0.0;
4391  }
4392 
4393  if (DqgVgs<0) {DqgVgs=0;} // Because of truncation error cgb may turn
4394  if (DqgVgd<0) {DqgVgd=0;} // negative in extreme inversion, while cgd
4395  if (DqgVgb<0) {DqgVgb=0;} // and cgs may turn negative in accumulation
4396  cgs= 0.5*DqgVgs;
4397  cgd= 0.5*DqgVgd;
4398  cgb= 0.5*DqgVgb;
4399 
4400  return true;
4401 }
4402 
4403 //----------------------------------------------------------------------------
4404 // Function : Instance::UCCMCharges
4405 // Purpose :
4406 //
4407 //
4408 // Special Notes :
4409 //
4410 // Scope : public
4411 // Creator : pmc
4412 // Creation Date : 02/17/2004
4413 //----------------------------------------------------------------------------
4414 bool Instance::UCCMCharges( double vgs, double vgdd,
4415  double vgb, double & qD, double & qS, double & qB)
4416 {
4417  double VT(0.0); // Threshold voltage
4418  double nss(0.0); // Inversion charge density at source
4419  double nsd(0.0); // Inversion charge density at drain
4420  double etavth(0.0);
4421  double mqWL(0.0);
4422  double nsdsqr(0.0);
4423  double nsssqr(0.0);
4424  double arg1(0.0);
4425  double arg2(0.0);
4426  double qn(0.0); // Inversion charge
4427  double VFB(0.0); // Flat-band voltage
4428  double xisqrt(0.0);
4429  double ndeps(0.0); // Depletion charge density
4430  double zetanb(0.0);
4431  double fp1(0.0); // Partitioning factor
4432  double gamma(0.0);
4433  double ALPHA(0.0);
4434  double A(0.0);
4435  double cox(0.0); // oxide capasity per unit area
4436  double vdds_local(0.0);
4437 
4438  cox = model_.oxideCapFactor;
4439  gamma = model_.gammas0;
4440  A = CONSTQ/cox;
4441  ETA = model_.eta;
4442  ALPHA = model_.alpha;
4443  VFB = model_.vfb;
4444 
4445  vdds_local=vgs-vgdd;
4446 
4447  if (vgb > VFB)
4448  {
4449  VT = von;
4450  etavth = ETA*temp*CONSTKoverQ;
4451 
4452  nsd=2*n0*log(1+0.5*exp((vgs-VT-ALPHA*vdds_local)/etavth));
4453  nss=2*n0*log(1+0.5*exp((vgs-VT)/etavth));
4454 
4455  nsdsqr=nsd*nsd;
4456  nsssqr=nss*nss;
4457  mqWL=-CONSTQ*EffectiveLength*(w);
4458 
4459  arg1= 0.5*etavth*(nsdsqr-nsssqr)+1/3.0*A*(nsdsqr*nsd-nsssqr*nss);
4460  arg2= etavth*(nsd-nss) +0.5*A*(nsdsqr-nsssqr);
4461 
4462  if (arg2==0) //||(fabs(nss-nsd)<1e-12))
4463  { qn=mqWL*nss;}
4464  else {qn = mqWL*arg1/arg2;}
4465  xisqrt= sqrt(gamma*gamma/(A*A)+4.0/(A*A)*(vgb-VFB)-4.0/A*nss);
4466  ndeps = -gamma*gamma/(2.0*A)+ gamma/2.0*xisqrt;
4467  zetanb =(1-ALPHA)/ALPHA;
4468  mqWL=-CONSTQ*EffectiveLength*(w);
4469  qB =mqWL*(ndeps-zetanb*nss)+zetanb*qn;
4470 
4471  switch(model_.fpe)
4472  {
4473  case 1:
4474  fp1=model_.xqc;
4475  break;
4476 
4477  case 2:
4478  {
4479  double vsat(0.0);
4480  double beta(0.0);
4481  double a0(0.0);
4482  double vdsabs(0.0);
4483  double m(0.0);
4484  double fp1denum(0.0);
4485 
4486  vdsabs=fabs(vdds_local);
4487  vsat=vddsat;
4488  if (vgs-VT > 1e-36)
4489  {
4490  if((vsat > 1e-36)&&(vdds_local>1e-36))
4491  { beta=vdsabs/vsat;}else{beta=1e-36;}
4492  m = model_.mcv;
4493  a0 = (model_.xqc - 0.5)/vsat;
4494  fp1denum = exp(1/m*log(1+exp(m*log(beta))));
4495  if (fp1denum > 1e-36)
4496  {fp1= 0.5+ a0*vdsabs/fp1denum;}
4497  else {fp1=0.5;}
4498 
4499  } else {fp1=0.5;}
4500  }
4501  break;
4502  case 3:
4503  {
4504  double nd0(0.0);
4505  double ns0(0.0);
4506  double arg1_loc(0.0);
4507  double arg2_loc(0.0);
4508  double arg3_loc(0.0);
4509 
4510  nd0=nss/(A*etavth);
4511  ns0=nss/(A*etavth);
4512  arg1_loc= nd0*nd0*nd0*(1/3.0+nd0*(3.0/8.0+1/10.0*nd0))
4513  - (1.0/2.0+1.0/3.0*nd0)*(1.0+1/2.0*ns0)*nd0*nd0*ns0
4514  + ns0*ns0*ns0*(1.0/6.0+ns0*(5.0/24.0+1.0/15.0*ns0));
4515  arg2_loc = 1.0/2.0*(nd0*nd0-ns0*ns0)+1.0/3.0*(nd0*nd0*nd0-ns0*ns0*ns0);
4516  arg3_loc = nd0-ns0+1.0/2.0*(nd0*nd0-ns0*ns0);
4517  if ((arg2_loc==0)||(arg3_loc==0)) {fp1=0.5;}
4518  else { fp1 = 1-arg1_loc/(arg2_loc*arg3_loc);}
4519  }
4520  break;
4521  default:
4522  {
4523  UserWarning(*this) << "Partitioning model does not exist";
4524  return true;
4525  }
4526  }
4527  }
4528  else
4529  { // Below flatband
4530  qB = -EffectiveLength*(w)*cox*(vgb-VFB);
4531  qn = 0;
4532  }
4533 
4534  qS = -fp1*qn;
4535  qD = -(1-fp1)*qn;
4536  qB = -qB;
4537 
4538  return true;
4539 }
4540 
4541 //----------------------------------------------------------------------------
4542 // Function : Instance::UCCMcvon
4543 // Purpose : Compute the threshold voltage
4544 //
4545 // Special Notes : ERK. The "local" named variables (von_local, dvonvbs_local)
4546 // are named that way to avoid conflicts with the instance
4547 // variables of the same name.
4548 //
4549 // Scope : public
4550 // Creator : pmc
4551 // Creation Date : 02/17/2004
4552 //----------------------------------------------------------------------------
4553 bool Instance::UCCMcvon(double vbs_local,
4554  double & von_local, double & dvonvbs_local)
4555 {
4556  double PhiMinVbs = tPhi - vbs_local;
4557  double sarg(0.0);
4558  double dsrgdb(0.0);
4559 
4560 // vtoo, vthLimit calculated in updateTemp
4561 
4562  if(vtoo-vbs_local > vthLimit) {
4563  von_local = vtoo + gammal*vthLimit;
4564  dvonvbs_local = 0.0;
4565  return true;
4566  }
4567  if(PhiMinVbs > 0.0)
4568  {
4569  sarg = sqrt(PhiMinVbs);
4570  dsrgdb = -0.5/sarg;
4571  } else
4572  {
4573  sarg = 0;
4574  dsrgdb = 0;
4575  }
4576  von_local = vtoo + gammas*sarg - gammal*PhiMinVbs;
4577  dvonvbs_local = gammas*dsrgdb + gammal;
4578 
4579  return true;
4580 }
4581 
4582 //-----------------------------------------------------------------------------
4583 // Function : Instance::UCCMmosa1
4584 // Purpose : Compute currents and conductances in drain region
4585 //
4586 //
4587 // Special Notes :
4588 //
4589 // Scope : public
4590 // Creator : pmc
4591 // Creation Date : 02/17/2004
4592 //-----------------------------------------------------------------------------
4593 
4594 bool Instance::UCCMmosa1(double xvgs, double xvdds,
4595  double dvonvbs, double & cdraindrift_loc, double & vsate)
4596 {
4597  double etavt(0.0);
4598  double vgt(0.0);
4599  double vgt0(0.0);
4600  double sigma(0.0);
4601  double vgte(0.0);
4602  double isat(0.0);
4603  double mu(0.0);
4604  double ns(0.0);
4605  double a(0.0);
4606  double b(0.0);
4607  double d(0.0);
4608  double g(0.0);
4609  double h(0.0);
4610  double q(0.0);
4611  double r(0.0);
4612  double t(0.0);
4613  double u(0.0);
4614  double x(0.0),y(0.0),z(0.0);
4615 
4616  double gch(0.0);
4617  double gchi(0.0);
4618  double rt(0.0);
4619  double vl(0.0);
4620  double vl2(0.0);
4621  double ichoo(0.0);
4622 
4623  double dichoodvds(0.0);
4624  double dichoodvgs(0.0);
4625  double dichoodvbs(0.0);
4626  double dichooisat(0.0);
4627  double dichoodgch(0.0);
4628  double delgchgchi(0.0);
4629  double disatdvds(0.0);
4630  double disatdvgs(0.0);
4631  double disatdvbs(0.0);
4632  double dgchidvds(0.0);
4633  double dgchidvgs(0.0);
4634  double dgchidvbs(0.0);
4635  double disatvgte(0.0);
4636  double disatgchi(0.0);
4637  double dvgtedvgt(0.0);
4638  double dvgtdvds(0.0);
4639  double dvgtdvgs(0.0);
4640  double dvgtdvbs(0.0);
4641  double dnsdvgt(0.0);
4642  double dnsdvds(0.0);
4643  double dnsdvgs(0.0);
4644  double dnsdvbs(0.0);
4645  double dmudvgte(0.0);
4646  double dmudvds(0.0);
4647  double dmudvgs(0.0);
4648  double dmudvbs(0.0);
4649 
4650  static int output=0;
4651 
4652 #define ETA model_.eta
4653 #define RS model_.sourceResistance
4654 #define RD model_.drainResistance
4655 #define VSIGMAT model_.vsigmat
4656 #define VSIGMA model_.vsigma
4657 #define SIGMA0 model_.sigma0
4658 #define THETA model_.theta
4659 #define LAMBDA model_.lambda
4660 #define DELTA model_.delta
4661 #define VMAX model_.maxDriftVel
4662 #define TOX model_.oxideThickness
4663 
4664 #define EXP_MAX 150.0
4665 
4666  if(output == 1) {
4667  Xyce::dout() << " " << std::endl;
4668  Xyce::dout() << "ETA = " << ETA << std::endl;
4669  Xyce::dout() << "RS = " << RS << std::endl;
4670  Xyce::dout() << "RD = " << RD << std::endl;
4671  Xyce::dout() << "VSIGMAT = " << VSIGMAT << std::endl;
4672  Xyce::dout() << "VSIGMA = " << VSIGMA << std::endl;
4673  Xyce::dout() << "SIGMA0 = " << SIGMA0 << std::endl;
4674  Xyce::dout() << "THETA = " << THETA << std::endl;
4675  Xyce::dout() << "LAMBDA = " << LAMBDA << std::endl;
4676  Xyce::dout() << "DELTA = " << DELTA << std::endl;
4677  Xyce::dout() << "VMAX = " << VMAX << std::endl;
4678  Xyce::dout() << "TOX = " << TOX << std::endl;
4679  output=0;
4680  }
4681 
4682  etavt = ETA*vt;
4683  rt = RS+RD;
4684  vgt0 = xvgs - von;
4685  a = exp((vgt0-VSIGMAT)/VSIGMA);
4686  sigma = SIGMA0/(1+a);
4687  vgt = vgt0+sigma*xvdds;
4688  b = 0.5*vgt/vt-1;
4689  q = sqrt(model_.deltaSqr+b*b);
4690  vgte = vt*(1+b+1+q);
4691  u = 1+THETA*(vgte+2*von)/TOX;
4692  mu = tSurfMob/u;
4693 
4694  x = vgt/etavt;
4695  if (x > 50.0)
4696  {
4697  ns = n0*2.0*x;
4698  }
4699  else if (x < -30)
4700  {
4701  ns = n0*exp(x);
4702  }
4703  else
4704  {
4705  ns = 2.0*n0*log(1+0.5*exp(x));
4706  }
4707 
4708  if(ns < 1.0e-38) {
4709  cdraindrift_loc = 0.0;
4710  vsate = 0.0;
4711  gm = 0.0;
4712  gdds = 0.0;
4713  gmbs = 0.0;
4714  mm1 = 0.0;
4715  dmm1vgs = 0.0;
4716  dmm1vds = 0.0;
4717  dmm1vbs = 0.0;
4718  return true;
4719  }
4720 
4721  gchi = gchi0*mu*ns;
4722  gch = gchi/(1+gchi*rt);
4723  t = VMAX*L;
4724 // vl = t/mu;
4725  vl = t/tSurfMob;
4726  vl2 = vl*vl;
4727  d = sqrt(1+2*gchi*RS + vgte*vgte/vl2);
4728  r = gchi*vgte;
4729  h = 1+gchi*RS+d;
4730  isat = r/h;
4731  vsate = isat/gch;
4732  y = xvdds/(vsate);
4733 
4734  if(fabs(y) > EXP_MAX) z = 0;
4735  else z = 1/(cosh(y)*cosh(y));
4736 
4737  // drain current
4738  ichoo = isat*(1+LAMBDA*xvdds)*tanh(y);
4739 
4740  dvgtedvgt = 0.5*(1+b/q);
4741  dnsdvgt = n0/(etavt*(exp(-x)+0.5));
4742  dmudvgte = -tSurfMob*THETA/(TOX*u*u);
4743 
4744  dvgtdvds = sigma;
4745  dvgtdvgs = 1 - SIGMA0*a*xvdds/(VSIGMA*(1+a)*(1+a));
4746  dvgtdvbs = -dvonvbs*dvgtdvgs;
4747 
4748  dnsdvds = dnsdvgt*dvgtdvds;
4749  dnsdvgs = dnsdvgt*dvgtdvgs;
4750  dnsdvbs = dnsdvgt*dvgtdvbs;
4751  dmudvds = (dmudvgte*dvgtedvgt)*dvgtdvds;;
4752  dmudvgs = (dmudvgte*dvgtedvgt)*dvgtdvgs;;
4753  dmudvbs = (dmudvgte*dvgtedvgt)*dvgtdvbs + 2*dmudvgte*dvonvbs;
4754 
4755  dgchidvds = gchi0*(mu*dnsdvds + ns*dmudvds);
4756  dgchidvgs = gchi0*(mu*dnsdvgs + ns*dmudvgs);
4757  dgchidvbs = gchi0*(mu*dnsdvbs + ns*dmudvbs);
4758 
4759  disatvgte = gchi/h - gchi*vgte*vgte/vl2/(d*h*h);
4760  disatgchi = vgte/h - gchi*vgte*RS*(1+1/d)/(h*h);
4761 
4762  disatdvds = (disatvgte*dvgtedvgt)*dvgtdvds + disatgchi*dgchidvds;
4763  disatdvgs = (disatvgte*dvgtedvgt)*dvgtdvgs + disatgchi*dgchidvgs;
4764  disatdvbs = (disatvgte*dvgtedvgt)*dvgtdvbs + disatgchi*dgchidvbs;
4765 
4766  dichoodgch = (1+LAMBDA*xvdds)*xvdds*z;
4767  dichooisat = (1+LAMBDA*xvdds)*(tanh(y) - gch*xvdds*z/isat);
4768  g = 1+gchi*rt;
4769  delgchgchi = 1/(g*g);
4770 
4771  dichoodvds = dichooisat*disatdvds + (dichoodgch*delgchgchi)*dgchidvds
4772  + isat*LAMBDA*tanh(y) + (1+LAMBDA*xvdds)*gch*z;
4773  dichoodvgs = dichooisat*disatdvgs + (dichoodgch*delgchgchi)*dgchidvgs;
4774  dichoodvbs = dichooisat*disatdvbs + (dichoodgch*delgchgchi)*dgchidvbs;
4775 
4776 
4777  cdraindrift_loc = ichoo;
4778  gm = dichoodvgs;
4779  gdds = dichoodvds;
4780  gmbs = dichoodvbs;
4781 
4782 // the mm1 factors are for the ISUB calc which we don't use
4783  mm1 = 0.0;
4784  dmm1vgs = 0.0;
4785  dmm1vds = 0.0;
4786  dmm1vbs = 0.0;
4787 
4788  return true;
4789 }
4790 
4791 
4792 //-----------------------------------------------------------------------------
4793 // Function : Instance::UCCMmosa2
4794 // Purpose : Compute currents and conductances in
4795 // : drain and substrate regions
4796 //
4797 //
4798 // Special Notes :
4799 //
4800 // Scope : public
4801 // Creator : pmc
4802 // Creation Date : 02/17/2004
4803 //-----------------------------------------------------------------------------
4804 
4805 bool Instance::UCCMmosa2(double xvgs, double xvdds,
4806  double dvonvbs, double & cdraindrift_loc, double & vsate)
4807 {
4808  double etavt(0.0);
4809  double vgt(0.0);
4810  double vgt0(0.0);
4811  double sigma(0.0);
4812  double vgte(0.0);
4813  double isat(0.0);
4814  double mu(0.0);
4815  double ns(0.0);
4816  double a(0.0);
4817  double b(0.0);
4818  double c(0.0);
4819  double d(0.0);
4820  double e(0.0);
4821  double f(0.0);
4822  double g(0.0);
4823  double h(0.0);
4824  double p(0.0);
4825  double q(0.0);
4826  double r(0.0);
4827  double s(0.0);
4828  double t(0.0);
4829  double u(0.0);
4830  double x,y,z(0.0);
4831  double gch(0.0);
4832  double gchi(0.0);
4833  double rt(0.0);
4834  double vl(0.0);
4835  double vl2(0.0);
4836  double ichoo(0.0);
4837  double gmoo(0.0);
4838  double gdsoo(0.0);
4839  double gbsoo(0.0);
4840  double icho(0.0);
4841  double gmo(0.0);
4842  double gdso(0.0);
4843  double gbso(0.0);
4844  double vsat(0.0);
4845  double vdso(0.0);
4846  double vdse(0.0);
4847  double cox(0.0);
4848  double temp1(0.0);
4849  double qs(0.0);
4850  double dqsvgt(0.0);
4851  double dqsvbs(0.0);
4852  double delidgch(0.0);
4853  double delgchgchi(0.0);
4854  double delgchins(0.0);
4855  double dvgtevgt(0.0);
4856  double delidvsate(0.0);
4857  double delvsateisat(0.0);
4858  double delisatvgte(0.0);
4859  double delisatgchi(0.0);
4860  double delisatvl(0.0);
4861  double dgchivgt(0.0);
4862  double delvsategch(0.0);
4863  double delidvds(0.0);
4864  double dsigmavgs(0.0);
4865  double delnsvgt(0.0);
4866  double dvsatevgt(0.0);
4867  double dvgtvgs(0.0);
4868  double dmuvon(0.0);
4869  double dmuvgt(0.0);
4870  double dvgtvon(0.0);
4871  double delvsatqs(0.0);
4872  double delvsatmu(0.0);
4873  double dvsatvgt(0.0);
4874  double dvsatvbs(0.0);
4875  double delvdsevdso(0.0);
4876  double delvdsevsat(0.0);
4877  double dvdsevgs(0.0);
4878  double dvdsevds(0.0);
4879  double dvdsevbs(0.0);
4880 
4881  double del(0.0);
4882  double delmm1vdso(0.0);
4883  double ddelvgs(0.0);
4884  double ddelvds(0.0);
4885  double ddelvbs(0.0);
4886 
4887  // These "loc" variables are named such to avoid name conflicts with
4888  // instance variables.
4889  double mm1_loc(0.0);
4890  double dmm1vgs_loc(0.0);
4891  double dmm1vds_loc(0.0);
4892  double dmm1vbs_loc(0.0);
4893 
4894  static int output(0);
4895 
4896 #define ETA model_.eta
4897 #define RS model_.sourceResistance
4898 #define RD model_.drainResistance
4899 #define VSIGMAT model_.vsigmat
4900 #define VSIGMA model_.vsigma
4901 #define SIGMA0 model_.sigma0
4902 #define THETA model_.theta
4903 #define LAMBDA model_.lambda
4904 #define DELTA model_.delta
4905 #define ALPHA model_.alpha
4906 #define VMAX model_.maxDriftVel
4907 #define TOX model_.oxideThickness
4908 #define W w
4909 #define L EffectiveLength
4910 #define LS model_.ls
4911 #define M model_.m
4912 #define INVM 1.0/model_.m
4913 #define MC model_.mc
4914 #define INVMC 1.0/model_.mc
4915 #define RSUB model_.rsub
4916 #define AI model_.ai
4917 #define BI model_.bi
4918 #define MD model_.md
4919 #define INVMD 1.0/model_.md
4920 #define DELMAX model_.delmax
4921 
4922  if(output == 1) {
4923  Xyce::dout() << " " << std::endl;
4924  Xyce::dout() << "ETA = " << ETA << std::endl;
4925  Xyce::dout() << "RS = " << RS << std::endl;
4926  Xyce::dout() << "RD = " << RD << std::endl;
4927  Xyce::dout() << "VSIGMAT = " << VSIGMAT << std::endl;
4928  Xyce::dout() << "VSIGMA = " << VSIGMA << std::endl;
4929  Xyce::dout() << "SIGMA0 = " << SIGMA0 << std::endl;
4930  Xyce::dout() << "THETA = " << THETA << std::endl;
4931  Xyce::dout() << "LAMBDA = " << LAMBDA << std::endl;
4932  Xyce::dout() << "DELTA = " << DELTA << std::endl;
4933  Xyce::dout() << "ALPHA = " << ALPHA << std::endl;
4934  Xyce::dout() << "VMAX = " << VMAX << std::endl;
4935  Xyce::dout() << "TOX = " << TOX << std::endl;
4936  Xyce::dout() << "W = " << W << std::endl;
4937  Xyce::dout() << "L = " << L << std::endl;
4938  Xyce::dout() << "LS = " << LS << std::endl;
4939  Xyce::dout() << "M = " << M << std::endl;
4940  Xyce::dout() << "INVM = " << INVM << std::endl;
4941  Xyce::dout() << "MC = " << MC << std::endl;
4942  Xyce::dout() << "INVMC = " << INVMC << std::endl;
4943  Xyce::dout() << "RSUB = " << RSUB << std::endl;
4944  Xyce::dout() << "AI = " << AI << std::endl;
4945  Xyce::dout() << "BI = " << BI << std::endl;
4946  Xyce::dout() << "MD = " << MD << std::endl;
4947  Xyce::dout() << "INVMD = " << INVMD << std::endl;
4948  Xyce::dout() << "DELMAX = " << DELMAX << std::endl;
4949  Xyce::dout() << "VP = " << vp << std::endl;
4950  output=0;
4951  }
4952 
4953 
4954  etavt = ETA*vt;
4955  rt = RS+RD;
4956  vgt0 = xvgs - von;
4957  a = exp((vgt0-VSIGMAT)/VSIGMA);
4958  sigma = SIGMA0/(1+a);
4959  vgt = vgt0+sigma*xvdds;
4960  b = 0.5*vgt/vt-1;
4961  q = sqrt(model_.deltaSqr+b*b);
4962  vgte = vt*(1+b+1+q);
4963  u = 1+THETA*(vgte+2*von)/TOX;
4964  mu = tSurfMob/u;
4965 
4966  x = vgt/etavt;
4967  if (x > 50.0)
4968  {
4969  ns = n0*2.0*x;
4970  }
4971  else if (x < -30)
4972  {
4973  ns = n0*exp(x);
4974  }
4975  else
4976  {
4977  ns = 2.0*n0*log(1+0.5*exp(x));
4978  }
4979  //ns = 2.0*n0*log(1+0.5*c);
4980 
4981  if(ns < 1.0e-38)
4982  {
4983  cdraindrift_loc = 0.0;
4984  vsate = 0.0;
4985  gm = 0.0;
4986  gdds = 0.0;
4987  gmbs = 0.0;
4988 
4989  mm1 = mm1_loc = 0.0;
4990  dmm1vgs = dmm1vgs_loc = 0.0;
4991  dmm1vds = dmm1vds_loc = 0.0;
4992  dmm1vbs = dmm1vbs_loc = 0.0;
4993  return true;
4994  }
4995 
4996  gchi = gchi0*mu*ns;
4997  gch = gchi/(1+gchi*rt);
4998  t = VMAX*L;
4999  vl = t/mu;
5000  vl2 = vl*vl;
5001  d = sqrt(1+2*gchi*RS + vgte*vgte/vl2);
5002  r = gchi*vgte;
5003  isat = r/(1+gchi*RS+d);
5004  vsate = isat/gch;
5005  y = xvdds/(vsate);
5006  z = 0.5*(cosh(2*y)+1);
5007 
5008 // Old model
5009 // e = pow(xvdds/(*vsate),M);
5010 // f = pow(1+e,INVM);
5011 // delidgch = xvdds*(1+LAMBDA*xvdds)/f;
5012 
5013  ichoo = isat*(1+LAMBDA*xvdds)*tanh(y);
5014  delidgch = ichoo/gch;
5015  g = 1+gchi*rt;
5016  delgchgchi = 1/(g*g);
5017  delgchins = gchi0*mu;
5018  x = vgt/etavt;
5019  delnsvgt = n0/(etavt*(exp(-x) + 0.5));
5020  dvgtevgt = 0.5*(1+b/q);
5021 
5022 // delidvds = gch*(1+2*LAMBDA*xvdds)/f-
5023 // ichoo*pow(vdds/(*vsate),M-1)/((*vsate)*(1+e));
5024 // delidvsate = ichoo*e/((*vsate)*(1+e));
5025  delidvds = ichoo*LAMBDA/(1+LAMBDA*xvdds) + gch*(1+LAMBDA*xvdds)/z;
5026  delidvsate = gch*(1+LAMBDA*xvdds)*xvdds/(vsate)/z;
5027 
5028  delvsateisat = 1/gch;
5029  delvsategch = -(vsate)/gch;
5030  h = 1+gchi*RS+d;
5031  delisatgchi = (vgte*h - gchi*vgte*RS*(1+1/d))/(h*h);
5032  delisatvgte = (gchi*h - gchi*vgte*vgte/(vl2*d))/(h*h);
5033  delisatvl = isat*isat*vgte/(gchi*d*vl2*vl);
5034  s = THETA/(tSurfMob*TOX);
5035  dgchivgt = delgchins*delnsvgt-gchi*mu*s*dvgtevgt;
5036  dsigmavgs = -SIGMA0*a/(VSIGMA*((1+a)*(1+a)));
5037  p = delgchgchi*dgchivgt;
5038  dvsatevgt = delvsateisat*(delisatgchi*dgchivgt+
5039  (delisatvgte+delisatvl*t*s)*dvgtevgt)+ delvsategch*p;
5040  g = delidgch*p+delidvsate*dvsatevgt;
5041  dvgtvgs = (1+xvdds*dsigmavgs);
5042  gmoo = g*dvgtvgs;
5043  gdsoo = delidvds+g*sigma;
5044 
5045  dmuvon = -(2-dvgtevgt*dvgtvgs)*mu*mu*s;
5046  dmuvgt = -mu*mu*THETA*dvgtevgt/(tSurfMob*TOX);
5047  dvgtvon = -dvgtvgs;
5048 
5049  if(THETA == 0.0)
5050  {
5051  gbsoo = -(gmoo)*dvonvbs;
5052  }
5053  else
5054  {
5055  double dgchivon = -delgchins*delnsvgt*dvgtvgs+gchi*dmuvon/mu;
5056  p = delgchgchi*dgchivon;
5057  double dvsatevon = delvsateisat*(delisatgchi*dgchivon+
5058  delisatvgte*dvgtevgt*dvgtvon+delisatvl*(-vl2/t)*dmuvon)+delvsategch*p;
5059  gbsoo = (delidgch*p+delidvsate*dvsatevon)*dvonvbs;
5060  }
5061 
5062 // mosa2: New Version
5063 
5064  cox = CONSTEPSOX/TOX;
5065  temp1 = cox*RS/CONSTQ;
5066  qs = CONSTQ*(ns-ichoo*temp1);
5067  dqsvgt = CONSTQ*(delnsvgt-g*temp1);
5068  dqsvbs = CONSTQ*(delnsvgt*dvgtvon*dvonvbs-gbsoo*temp1);
5069 
5070  // A more precise vsat model for deltal and isub calculations
5071  if(model_.dtype == CONSTNMOS)
5072  {
5073  a = 2*qs*VMAX*L;
5074  b = qs*mu+2*cox*ALPHA*VMAX*L;
5075  temp1 = b*b;
5076  vsat = a/b;
5077  delvsatqs = 2*VMAX*L*(b-qs*mu)/temp1;
5078  delvsatmu = -a*qs/temp1;
5079  dvsatvgt = delvsatqs*dqsvgt+delvsatmu*dmuvgt;
5080  dvsatvbs = delvsatqs*dqsvbs+delvsatmu*dmuvon*dvonvbs;
5081  }
5082  else
5083  {
5084  a = VMAX*L/mu;
5085  b = 2/(cox*ALPHA*VMAX*L);
5086  c = sqrt(1+qs*mu*b);
5087  vsat = a*(c-1);
5088  delvsatqs = a*(0.5*b*mu/c);
5089  delvsatmu = -vsat/mu+a*(0.5*b*qs/c);
5090  dvsatvgt = delvsatqs*dqsvgt+delvsatmu*dmuvgt;
5091  dvsatvbs = delvsatqs*dqsvbs+delvsatmu*dmuvon*dvonvbs;
5092  }
5093 
5094  // Effective intrinsic drain-source voltage calculation
5095  vdso = xvdds-ichoo*rt;
5096  a = pow(vdso/vsat,MC);
5097  b = pow(1+a,INVMC);
5098  vdse = vdso/b;
5099  delvdsevdso = (1-a/(1+a))/b;
5100  delvdsevsat = vdse*a/(vsat*(1+a));
5101 
5102  // DeltaL calculation
5103  double deltal(0.0);
5104  double deldeltalvdse(0.0);
5105  double deldeltalvdso(0.0);
5106  double deldeltalmu(0.0);
5107  double ddeltalvgs(0.0);
5108  double ddeltalvds(0.0);
5109  double ddeltalvbs(0.0);
5110 
5111  a = 1+(vdso-vdse)/vp;
5112  b = W*mu*cox*vdse*RS/L;
5113  c = 1+vdse/vp+b;
5114  d = LS*log10(a);
5115  deltal = d/c;
5116  e = 1/(1-deltal/L);
5117  icho = ichoo*e;
5118  f = log(10.0);
5119  deldeltalvdse = (-LS/(f*a*vp)*c-d*(1/vp+W*mu*cox*RS/L))/(c*c);
5120  deldeltalvdso = LS/(c*a*f*vp);
5121  deldeltalmu = -d*W*cox*vdse*RS/(L*c*c);
5122  temp1 = -gmoo*rt;
5123  dvdsevgs = delvdsevsat*dvsatvgt*dvgtvgs+delvdsevdso*temp1;
5124  ddeltalvgs = deldeltalvdse*dvdsevgs + deldeltalmu*dmuvgt*dvgtvgs
5125  + deldeltalvdso*temp1;
5126  gmo = e*(gmoo+ichoo*ddeltalvgs*e/L);
5127  temp1 = 1-gdsoo*rt;
5128  dvdsevds = delvdsevsat*dvsatvgt*sigma+delvdsevdso*temp1;
5129  ddeltalvds = deldeltalvdse*dvdsevds + deldeltalmu*dmuvgt*sigma
5130  + deldeltalvdso*temp1;
5131  gdso = e*(gdsoo+ichoo*ddeltalvds*e/L);
5132  temp = -gbsoo*rt;
5133  dvdsevbs = delvdsevsat*dvsatvbs+delvdsevdso*temp1;
5134  ddeltalvbs = deldeltalvdse*dvdsevbs + deldeltalmu*dmuvon*dvonvbs
5135  + deldeltalvdso*temp1;;
5136  gbso = e*(gbsoo+ichoo*ddeltalvbs*e/L);
5137 
5138  a = AI/BI;
5139  b = vdso-vdse+vt;
5140  c = exp(-LS*BI/b);
5141  mm1_loc = a*b*c;
5142  if(RSUB != 0.0)
5143  {
5144  d = 0.5*W*(ALPHA-1)*cox*RSUB/L;
5145  del = d*mm1_loc*mu*vdse;
5146  f = pow(del/DELMAX,MD);
5147  g = pow(1+f,INVMD);
5148  h = (1-f/(1+f))/g;
5149  del = del/g;
5150  e = 1/(1-del);//1+del;
5151  }
5152  else
5153  {
5154  d = 0;
5155  h = 1;
5156  e = 1;
5157  }
5158 
5159  cdraindrift_loc = icho*e;
5160  delmm1vdso = a*c+mm1_loc*LS*BI/(b*b);
5161  dmm1vgs_loc = delmm1vdso*(-gmoo*rt-dvdsevgs);
5162  ddelvgs = h*d*(mu*vdse*dmm1vgs_loc + mm1_loc*vdse*dmuvgt*dvgtvgs
5163  + mu*mm1_loc*dvdsevgs);
5164  gm = e*(gmo+icho*ddelvgs*e); //gmo*e+icho*ddelvgs;
5165  dmm1vds_loc = delmm1vdso*(1-gdsoo*rt-dvdsevds);
5166  ddelvds = h*d*(mu*vdse*dmm1vds_loc + mm1_loc*vdse*dmuvgt*sigma
5167  + mu*mm1_loc*dvdsevds);
5168  gdds = e*(gdso+icho*ddelvds*e); //gdso*e+icho*ddelvds;
5169  dmm1vbs_loc = delmm1vdso*(-gbsoo*rt-dvdsevbs);
5170  ddelvbs = h*d*(mu*vdse*dmm1vbs_loc + mm1_loc*vdse*dmuvon*dvonvbs
5171  + mu*mm1_loc*dvdsevbs);
5172  gmbs = e*(gbso+icho*ddelvbs*e); //gbso*e+icho*ddelvbs;
5173 
5174 
5175  // saving some quantities for substrate current calculations
5176  mm1 = mm1_loc;
5177  dmm1vgs = dmm1vgs_loc;
5178  dmm1vds = dmm1vds_loc;
5179  dmm1vbs = dmm1vbs_loc;
5180 
5181  return true;
5182 }
5183 
5184 
5185 //-----------------------------------------------------------------------------
5186 // VDMOS Master functions:
5187 //-----------------------------------------------------------------------------
5188 
5189 //-----------------------------------------------------------------------------
5190 // Function : Master::updateState
5191 // Purpose :
5192 // Special Notes :
5193 // Scope : public
5194 // Creator : Eric Keiter, SNL
5195 // Creation Date : 11/26/08
5196 //-----------------------------------------------------------------------------
5197 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
5198 {
5199  bool bsuccess = true;
5200 
5201  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5202  {
5203  Instance & mi = *(*it);
5204 
5205  double * currStaVector = mi.extData.currStaVectorRawPtr;
5206 
5207  bool btmp = mi.updateIntermediateVars ();
5208  bsuccess = bsuccess && btmp;
5209 
5210  double vgs1(0.0), vgdd1(0.0), vbs1(0.0),vgb1(0.0), vdds1(0.0);
5211 
5212  // voltage drops:
5213  staVec[mi.li_state_vbdd] = mi.vbdd;
5214  staVec[mi.li_state_vbs] = mi.vbs;
5215  staVec[mi.li_state_vgps] = mi.vgps;
5216  staVec[mi.li_state_vdds] = mi.vdds;
5217  staVec[mi.li_state_D1vd] = mi.D1vd;
5218 
5219  // now the meyer capacitances
5220  // we didn't calculate these charges in update IntermediateVars
5221  // but we did calculate the voltage drops and capacitances.
5222  // first store the capacitances themselves:
5223  staVec[mi.li_state_capgs] = mi.capgs;
5224  staVec[mi.li_state_capgdd] = mi.capgdd;
5225  staVec[mi.li_state_capgb] = mi.capgb;
5226 
5227  // now the charges
5228  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
5229  // supposed to be *INTEGRATED*:
5230  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
5231  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
5232  // Now with Meyer back averaging, Capxx is the average between the last
5233  // time step and this one. So we gotta do the right thing for non-DCOP
5234  // when backaverage is on.
5235 
5236  if((getSolverState().dcopFlag))
5237  {
5238  mi.qgs = mi.Capgs *mi.vgps;
5239  mi.qgdd = mi.Capgdd*mi.vgpdd;
5240  mi.qgb = mi.Capgb *mi.Vgpb;
5241  }
5242  else
5243  {
5244  // get the ones from last time step
5245  mi.qgs = currStaVector[mi.li_state_qgs];
5246  mi.qgdd = currStaVector[mi.li_state_qgdd];
5247  mi.qgb = currStaVector[mi.li_state_qgb];
5248  // get the voltage drops, too
5249  vgs1 = currStaVector[mi.li_state_vgps];
5250  vbs1 = currStaVector[mi.li_state_vbs];
5251  vdds1 = currStaVector[mi.li_state_vdds];
5252 
5253  vgb1 = vgs1-vbs1;
5254  vgdd1 = vgs1-vdds1;
5255 
5256  // NOW we can calculate the charge update
5257  mi.qgs += mi.Capgs*(mi.vgps-vgs1);
5258  mi.qgdd += mi.Capgdd*(mi.vgpdd-vgdd1);
5259  mi.qgb += mi.Capgb*((mi.vgps-mi.vbs)-vgb1);
5260  }
5261 
5262  staVec[mi.li_state_qgs] = mi.qgs;
5263  staVec[mi.li_state_qgdd] = mi.qgdd;
5264  staVec[mi.li_state_qgb] = mi.qgb;
5265 
5266  // and the diode parasitic capacitors
5267  // these charges were set in updateIntermediateVars
5268  staVec[mi.li_state_qbd] = mi.qbd;
5269  staVec[mi.li_state_qbs] = mi.qbs;
5270 
5271  // diode #1 quatntities
5272 
5273  staVec[mi.li_state_D1DIOcapCharge] = mi.D1DIOcapCharge;
5274 
5275  // In the case of a charge, need to handle this:
5276  // Ensure dQ/dt = 0 for initial step after dcOP by setting the history equal
5277  // to the current value
5279  {
5280  currStaVector[mi.li_state_D1DIOcapCharge] = mi.D1DIOcapCharge;
5281  }
5282 
5283  staVec[ mi.li_state_von ] = mi.von;
5284 
5285  }
5286 // }
5287 
5288  return bsuccess;
5289 }
5290 
5291 //-----------------------------------------------------------------------------
5292 // Function : Master::updateSecondaryState
5293 // Purpose :
5294 // Special Notes :
5295 // Scope : public
5296 // Creator : Eric Keiter, SNL
5297 // Creation Date : 11/26/08
5298 //-----------------------------------------------------------------------------
5299 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
5300 {
5301  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5302  {
5303  Instance & mi = *(*it);
5304 
5305  mi.cqgs = staDerivVec[mi.li_state_qgs];
5306  mi.cqgdd = staDerivVec[mi.li_state_qgdd];
5307  mi.cqgb = staDerivVec[mi.li_state_qgb];
5308  mi.cqbd = staDerivVec[mi.li_state_qbd];
5309  mi.cqbs = staDerivVec[mi.li_state_qbs];
5310 
5311  mi.D1DIOcapCurrent = staDerivVec[mi.li_state_D1DIOcapCharge];
5312 
5313  double Dtype =mi.getModel().dtype;
5314  double D1current = Dtype*(mi.D1cdeq + mi.D1DIOcapCurrent);
5315 
5316  // Even though these do not look exactly like the RHS loads, they do account
5317  // for the currents into the leads even with the lead resistors in place
5318  // --- since the lead resistances are the only thing between the primed node
5319  // and the lead, the currents are still correct AT CONVERGED SOLUTIONS
5320  /*
5321  Lead current load has been moved to F & Q loads
5322  mi.LeadCurrentD = -mi.getModel().dtype*(-mi.mode*mi.cdrain+mi.cbd+mi.cqgdd+mi.cqbd)-D1current-mi.Irdsshunt;
5323  mi.LeadCurrentG = mi.getModel().dtype*(mi.cqgs+mi.cqgb+mi.cqgdd);
5324  mi.LeadCurrentS = mi.getModel().dtype*(-mi.mode*mi.cdrain+mi.cbs-mi.cqgs-mi.cqbs) + D1current+mi.Irdsshunt;
5325  mi.LeadCurrentB = mi.getModel().dtype*(mi.cbd-mi.cbs-mi.cqgb+mi.cqbd+mi.cqbs);
5326  */
5327  }
5328 // }
5329 
5330  return true;
5331 }
5332 
5333 //-----------------------------------------------------------------------------
5334 // Function : Master::loadDAEVectors
5335 // Purpose :
5336 // Special Notes :
5337 // Scope : public
5338 // Creator : Eric Keiter, SNL
5339 // Creation Date : 11/26/08
5340 //-----------------------------------------------------------------------------
5341 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ)
5342 {
5343  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5344  {
5345  Instance & mi = *(*it);
5346 
5347  // F-vector:
5348  double * dFdxdVp = mi.extData.dFdxdVpVectorRawPtr;
5349 
5350  double coef_Jdxp(0.0), gd_Jdxp(0.0);
5351  double gmin1 = getDeviceOptions().gmin;
5352  double Dtype =mi.getModel().dtype;
5353 
5354  double ceqbs = Dtype*(mi.cbs+mi.cqbs);
5355  double ceqbd = Dtype*(mi.cbd+mi.cqbd);
5356 
5357  double D1current = Dtype*mi.D1cdeq; // don't add in the capacitor stuff
5358 
5359 
5360  fVec[mi.li_Drain] += (mi.Idraindrift + mi.Irdsshunt - D1current);
5361 
5362  if (mi.Igate != 0.0)
5363  {
5364  fVec[mi.li_Gate] += mi.Igate;
5365  fVec[mi.li_GatePrime] += -mi.Igate;
5366  }
5367 
5368 
5369  fVec[mi.li_Source] += (mi.Isource - mi.Irdsshunt + mi.Ird1rs);
5370  fVec[mi.li_Bulk] += (ceqbs + ceqbd);
5371  fVec[mi.li_DrainPrime] += (-mi.Idrain-(ceqbd - mi.cdreq));
5372  fVec[mi.li_SourcePrime] += (-mi.Isource-(ceqbs + mi.cdreq));
5373  fVec[mi.li_DrainDrift] += (mi.Idrain - mi.Idraindrift);
5374  fVec[mi.li_D1Prime] += (D1current - mi.Ird1rs);
5375 
5376  // limiter terms:
5377  if (!mi.origFlag)
5378  {
5379  // bulk
5380  coef_Jdxp = Dtype*( + ((mi.gbd-gmin1))*(mi.vbdd-mi.vbdd_orig)
5381  + ((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig));
5382  dFdxdVp[mi.li_Bulk] += coef_Jdxp;
5383 
5384  // drain-prime
5385  coef_Jdxp = Dtype*(-((mi.gbd-gmin1))*
5386  (mi.vbdd-mi.vbdd_orig)+mi.gdds*(mi.vdds-mi.vdds_orig)
5387  +mi.Gm*((mi.mode>0)?(mi.vgps-mi.vgps_orig):(mi.vgpdd-mi.vgpdd_orig))
5388  +mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbdd-mi.vbdd_orig)));
5389  dFdxdVp[mi.li_DrainPrime] += coef_Jdxp;
5390 
5391  // source prime
5392  coef_Jdxp = Dtype*(-((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig)
5393  -mi.gdds*(mi.vdds-mi.vdds_orig)
5394  -mi.Gm*((mi.mode>0)?(mi.vgps-mi.vgps_orig):(mi.vgpdd-mi.vgpdd_orig))
5395  -mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbdd-mi.vbdd_orig)));
5396 
5397 
5398  dFdxdVp[mi.li_SourcePrime] += coef_Jdxp;
5399  gd_Jdxp = -mi.D1gd * (mi.D1vd-mi.D1vd_orig);
5400  dFdxdVp[mi.li_Drain] += gd_Jdxp;
5401  dFdxdVp[mi.li_D1Prime] -= gd_Jdxp;
5402  }
5403 
5404  // Q-vector:
5405  double * dQdxdVp = mi.extData.dQdxdVpVectorRawPtr;
5406 
5407  double qcoef_Jdxp(0.0);
5408 
5409  double Qeqbs = Dtype*mi.qbs;
5410  double Qeqbd = Dtype*mi.qbd;
5411  double Qeqgb = Dtype*mi.qgb;
5412  double Qeqgs = Dtype*mi.qgs;
5413  double Qeqgdd = Dtype*mi.qgdd;
5414 
5415 
5416  qVec[mi.li_Bulk] += (Qeqbs + Qeqbd - Qeqgb);
5417  qVec[mi.li_DrainPrime] += -(Qeqbd + Qeqgdd);
5418  qVec[mi.li_GatePrime] += (Qeqgs+Qeqgdd+Qeqgb);
5419  qVec[mi.li_SourcePrime] += (-(Qeqbs + Qeqgs));
5420  qVec[mi.li_D1Prime] += mi.D1DIOcapCharge;
5421  qVec[mi.li_Drain] += -mi.D1DIOcapCharge;
5422 
5423  // voltlim section:
5424  if (!mi.origFlag)
5425  {
5426  // bulk
5427  qcoef_Jdxp = Dtype*(-mi.Capgb*(mi.vgps-mi.vgps_orig-mi.vbs+mi.vbs_orig)
5428  + (+mi.Capgb)*(mi.vbdd-mi.vbdd_orig)
5429  + (+mi.capbs)*(mi.vbs-mi.vbs_orig));
5430  dQdxdVp[mi.li_Bulk] += qcoef_Jdxp;
5431 
5432  // drain-prime
5433  qcoef_Jdxp = Dtype*(-mi.Capgdd*(mi.vgpdd-mi.vgpdd_orig)-mi.capbd*(mi.vbdd-mi.vbdd_orig));
5434  dQdxdVp[mi.li_DrainPrime] += qcoef_Jdxp;
5435 
5436  // gate-prime
5437  qcoef_Jdxp = Dtype*(mi.Capgdd*(mi.vgpdd-mi.vgpdd_orig)+mi.Capgs*(mi.vgps-mi.vgps_orig)+
5438  mi.Capgb*(mi.vgps-mi.vgps_orig-mi.vbs+mi.vbs_orig));
5439  dQdxdVp[mi.li_GatePrime] += qcoef_Jdxp;
5440 
5441  // source-prime
5442  qcoef_Jdxp = Dtype*(-mi.Capgs*(mi.vgps-mi.vgps_orig)-mi.capbs*(mi.vbs-mi.vbs_orig));
5443  dQdxdVp[mi.li_SourcePrime] += qcoef_Jdxp;
5444  qcoef_Jdxp = -mi.D1capd*(mi.D1vd-mi.D1vd_orig);
5445  dQdxdVp[mi.li_D1Prime] -= qcoef_Jdxp;
5446  dQdxdVp[mi.li_Drain] += qcoef_Jdxp;
5447  }
5448 
5449  if( mi.loadLeadCurrent )
5450  {
5451  storeLeadF[mi.li_store_dev_id] = (mi.Idraindrift + mi.Irdsshunt - D1current);
5452  storeLeadF[mi.li_store_dev_is] = (mi.Isource - mi.Irdsshunt + mi.Ird1rs);
5453  storeLeadF[mi.li_store_dev_ig] = 0;
5454  storeLeadF[mi.li_store_dev_ib] = (ceqbs + ceqbd);
5455  // case where optional nodes become external nodes:
5456  if (mi.Igate != 0.0)
5457  {
5458  storeLeadF[mi.li_store_dev_ig] += mi.Igate;
5459  }
5460  if( !mi.gateCond )
5461  {
5462  // G' is G
5463  storeLeadF[mi.li_store_dev_ig] += -mi.Igate;
5464  }
5465 
5466  if( !mi.sourceCond )
5467  {
5468  // S' is S
5469  storeLeadF[mi.li_store_dev_is] += (-mi.Isource-(ceqbs + mi.cdreq));
5470  }
5471 
5472  if( !mi.drainCond )
5473  {
5474  // Ddrift is D'
5475  }
5476 
5477  if( !mi.model_.D1DIOconductance )
5478  {
5479  // D1' is S
5480  storeLeadF[mi.li_store_dev_is] += (D1current - mi.Ird1rs);
5481  }
5482 
5483  storeLeadQ[mi.li_store_dev_id] = -mi.D1DIOcapCharge;
5484  storeLeadQ[mi.li_store_dev_is] = 0;
5485  storeLeadQ[mi.li_store_dev_ig] = 0;
5486  storeLeadQ[mi.li_store_dev_ib] = (Qeqbs + Qeqbd - Qeqgb);
5487  // case where optional nodes become external nodes:
5488  if( !mi.gateCond )
5489  {
5490  // G' is G
5491  storeLeadQ[mi.li_store_dev_ig] += (Qeqgs+Qeqgdd+Qeqgb);
5492  }
5493 
5494  if( !mi.sourceCond )
5495  {
5496  // S' is S
5497  storeLeadQ[mi.li_store_dev_is] += (-(Qeqbs + Qeqgs));
5498  }
5499 
5500  if( !mi.drainCond )
5501  {
5502  // Ddrift is D'
5503  }
5504 
5505  if( !mi.model_.D1DIOconductance )
5506  {
5507  // D1' is S
5508  storeLeadQ[mi.li_store_dev_is] += mi.D1DIOcapCharge;
5509  }
5510  }
5511 
5512  }
5513 
5514  return true;
5515 }
5516 
5517 
5518 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
5519 //-----------------------------------------------------------------------------
5520 // Function : Master::loadDAEMatrices
5521 // Purpose :
5522 // Special Notes :
5523 // Scope : public
5524 // Creator : Eric Keiter, SNL
5525 // Creation Date : 11/26/08
5526 //-----------------------------------------------------------------------------
5527 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
5528 {
5529 #ifdef _OMP
5530 #pragma omp parallel for
5531 #endif
5532  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5533  {
5534  Instance & mi = *(*it);
5535 
5536  // F-matrix:
5537 
5538  *mi.f_DrainEquDrainNodePtr += mi.dIdd_dVd + mi.gdsshunt + mi.D1gd;
5539 
5541 
5543 
5544  *mi.f_DrainEquD1PrimeNodePtr -= mi.D1gd;
5545 
5546  if (mi.gateCond != 0)
5547  {
5548 
5549  *mi.f_GateEquGateNodePtr += mi.gateCond;
5550 
5552  }
5553 
5554 
5556 
5557  *mi.f_SourceEquSourceNodePtr += mi.sourceCond + mi.gdsshunt + mi.D1gspr;
5558 
5559  *mi.f_SourceEquD1PrimeNodePtr += -mi.D1gspr;
5560 
5561  if (mi.sourceCond != 0.0)
5562  {
5563 
5565  }
5566 
5567 
5568  *mi.f_BulkEquBulkNodePtr += mi.gbs+mi.gbd;
5569 
5570  *mi.f_BulkEquDrainPrimeNodePtr -= mi.gbd;
5571 
5572 
5573  *mi.f_BulkEquSourcePrimeNodePtr -= mi.gbs;
5574 
5575 
5576  *mi.f_DrainPrimeEquBulkNodePtr += -mi.gbd+mi.Gmbs;
5577 
5579 
5581 
5583  if (mi.drainCond != 0.0)
5584  {
5585 
5587  }
5588 
5589  if (mi.gateCond != 0)
5590  {
5591 
5593 
5595  }
5596 
5597  if (mi.sourceCond != 0.0)
5598  {
5599 
5601  }
5602 
5603  *mi.f_SourcePrimeEquBulkNodePtr -= mi.gbs+mi.Gmbs;
5604 
5606 
5608 
5610 
5611 
5613 
5614  if (mi.drainCond != 0.0)
5615  {
5616 
5618  }
5619 
5621 
5622 
5623  *mi.f_D1PrimeEquDrainNodePtr -= mi.D1gd;
5624 
5625  *mi.f_D1PrimeEquSourceNodePtr += -mi.D1gspr;
5626 
5627  *mi.f_D1PrimeEquD1PrimeNodePtr += mi.D1gd + mi.D1gspr;
5628 
5629  // Q-matrix:
5630  if (!getSolverState().dcopFlag)
5631  {
5632 
5633  *mi.q_BulkEquBulkNodePtr += +mi.capbs+mi.capbd+mi.Capgb;
5634 
5635  *mi.q_BulkEquDrainPrimeNodePtr -= +mi.capbd;
5636 
5637  *mi.q_BulkEquGatePrimeNodePtr -= mi.Capgb;
5638 
5640 
5641 
5642  *mi.q_DrainPrimeEquBulkNodePtr += -mi.capbd;
5643 
5645 
5647 
5648 
5649  *mi.q_GatePrimeEquBulkNodePtr -= mi.Capgb;
5650 
5652 
5654 
5656 
5657 
5659 
5661 
5663 
5664 
5665  *mi.q_DrainEquDrainNodePtr += mi.D1capd;
5666 
5667  *mi.q_DrainEquD1PrimeNodePtr -= mi.D1capd;
5668 
5669 
5670  *mi.q_D1PrimeEquDrainNodePtr -= mi.D1capd;
5671 
5673  }
5674  }
5675  return true;
5676 }
5677 #else
5678 //-----------------------------------------------------------------------------
5679 // Function : Master::loadDAEMatrices
5680 // Purpose :
5681 // Special Notes :
5682 // Scope : public
5683 // Creator : Eric Keiter, SNL
5684 // Creation Date : 11/26/08
5685 //-----------------------------------------------------------------------------
5686 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
5687 {
5688  int sizeInstances = instanceContainer_.size();
5689 
5690 #ifdef _OMP
5691 #pragma omp parallel for
5692 #endif
5693  for (int i=0; i<sizeInstances; ++i)
5694  {
5695  Instance & mi = *(instanceContainer_.at(i));
5696 
5697  // F-matrix:
5698 
5699  dFdx[mi.li_Drain][mi.ADrainEquDrainNodeOffset] += mi.dIdd_dVd + mi.gdsshunt + mi.D1gd;
5700 
5701  dFdx[mi.li_Drain][mi.ADrainEquSourceNodeOffset] -= mi.gdsshunt;
5702 
5703  dFdx[mi.li_Drain][mi.ADrainEquDrainDriftNodeOffset] -= mi.dIdd_dVd;
5704 
5705  dFdx[mi.li_Drain][mi.ADrainEquD1PrimeNodeOffset] -= mi.D1gd;
5706 
5707  if (mi.gateCond != 0)
5708  {
5709 
5710  dFdx[mi.li_Gate][mi.AGateEquGateNodeOffset] += mi.gateCond;
5711 
5712  dFdx[mi.li_Gate][mi.AGateEquGatePrimeNodeOffset] -= mi.gateCond;
5713  }
5714 
5715 
5716  dFdx[mi.li_Source][mi.ASourceEquDrainNodeOffset] -= mi.gdsshunt;
5717 
5718  dFdx[mi.li_Source][mi.ASourceEquSourceNodeOffset] += mi.sourceCond + mi.gdsshunt + mi.D1gspr;
5719 
5720  dFdx[mi.li_Source][mi.ASourceEquD1PrimeNodeOffset] += -mi.D1gspr;
5721 
5722  if (mi.sourceCond != 0.0)
5723  {
5724 
5726  }
5727 
5728 
5729  dFdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] += mi.gbs+mi.gbd;
5730 
5731  dFdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -= mi.gbd;
5732 
5733  dFdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -= mi.gbs;
5734 
5735 
5736  dFdx[mi.li_DrainPrime][mi.ADrainPrimeEquBulkNodeOffset] += -mi.gbd+mi.Gmbs;
5737 
5739 
5741 
5743  if (mi.drainCond != 0.0)
5744  {
5745 
5747  }
5748 
5749  if (mi.gateCond != 0)
5750  {
5751 
5753 
5755  }
5756 
5757  if (mi.sourceCond != 0.0)
5758  {
5759 
5761  }
5762 
5763  dFdx[mi.li_SourcePrime][mi.ASourcePrimeEquBulkNodeOffset] -= mi.gbs+mi.Gmbs;
5764 
5766 
5768 
5770 
5771 
5773 
5774  if (mi.drainCond != 0.0)
5775  {
5776 
5778  }
5779 
5781 
5782 
5783  dFdx[mi.li_D1Prime][mi.AD1PrimeEquDrainNodeOffset] -= mi.D1gd;
5784 
5785  dFdx[mi.li_D1Prime][mi.AD1PrimeEquSourceNodeOffset] += -mi.D1gspr;
5786 
5787  dFdx[mi.li_D1Prime][mi.AD1PrimeEquD1PrimeNodeOffset] += mi.D1gd + mi.D1gspr;
5788 
5789  // Q-matrix:
5790  if (!getSolverState().dcopFlag)
5791  {
5792 
5793  dQdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] += +mi.capbs+mi.capbd+mi.Capgb;
5794 
5795  dQdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -= +mi.capbd;
5796 
5797  dQdx[mi.li_Bulk][mi.ABulkEquGatePrimeNodeOffset] -= mi.Capgb;
5798 
5799  dQdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -= +mi.capbs;
5800 
5801 
5802  dQdx[mi.li_DrainPrime][mi.ADrainPrimeEquBulkNodeOffset] += -mi.capbd;
5803 
5805 
5807 
5808 
5809  dQdx[mi.li_GatePrime][mi.AGatePrimeEquBulkNodeOffset] -= mi.Capgb;
5810 
5812 
5814 
5816 
5817 
5819 
5821 
5823 
5824 
5825  dQdx[mi.li_Drain][mi.ADrainEquDrainNodeOffset] += mi.D1capd;
5826 
5827  dQdx[mi.li_Drain][mi.ADrainEquD1PrimeNodeOffset] -= mi.D1capd;
5828 
5829 
5830  dQdx[mi.li_D1Prime][mi.AD1PrimeEquDrainNodeOffset] -= mi.D1capd;
5831 
5832  dQdx[mi.li_D1Prime][mi.AD1PrimeEquD1PrimeNodeOffset] += mi.D1capd;
5833  }
5834 
5835  }
5836  return true;
5837 }
5838 #endif
5839 
5840 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
5841 {
5842 
5843  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
5844 }
5845 
5847 {
5849  .registerDevice("m", 18)
5850  .registerModelType("pmos", 18)
5851  .registerModelType("nmos", 18);
5852 }
5853 
5854 } // namespace VDMOS
5855 } // namespace Device
5856 } // namespace Xyce