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.156.2.3 $
40 //
41 // Revision Date : $Date: 2014/03/06 23:33:43 $
42 //
43 // Current Owner : $Author: tvrusso $
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) << "You have specified both uo and u0, which is not allowed.";
772 
773  UserWarning0(*this) << "You have specified the surface mobility as u0 instead of uo. This is supported, but ill-advised.";
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  // set up the internal name map:
1795  std::string tmpstr;
1796  tmpstr = getName()+"_drainprime";
1797  spiceInternalName (tmpstr);
1798  intNameMap[ li_DrainPrime ] = tmpstr;
1799 
1800  if ( li_GatePrime != li_Gate )
1801  {
1802  tmpstr = getName()+"_gateprime";
1803  spiceInternalName (tmpstr);
1804  intNameMap[ li_GatePrime ] = tmpstr;
1805  }
1806 
1807  if ( li_SourcePrime != li_Source )
1808  {
1809  tmpstr = getName()+"_sourceprime";
1810  spiceInternalName (tmpstr);
1811  intNameMap[ li_SourcePrime ] = tmpstr;
1812  }
1813 
1814  if ( li_DrainDrift != li_DrainPrime )
1815  {
1816  tmpstr = getName()+"_draindrift";
1817  spiceInternalName (tmpstr);
1818  intNameMap[ li_DrainDrift ] = tmpstr;
1819  }
1820 
1821  if ( li_D1Prime != li_Source )
1822  {
1823  tmpstr = getName()+"_d1pos";
1824  spiceInternalName (tmpstr);
1825  intNameMap[ li_D1Prime ] = tmpstr;
1826  }
1827  }
1828 
1829  return intNameMap;
1830 }
1831 
1832 //-----------------------------------------------------------------------------
1833 // Function : Instance::registerStateLIDs
1834 // Purpose :
1835 // Special Notes :
1836 // Scope : public
1837 // Creator : Robert Hoekstra, Computational Sciences
1838 // Creation Date : 6/21/02
1839 //-----------------------------------------------------------------------------
1840 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
1841 {
1842  AssertLIDs(staLIDVecRef.size() == numStateVars);
1843 
1844 #ifdef Xyce_DEBUG_DEVICE
1845  if (getDeviceOptions().debugLevel > 0)
1846  {
1847  Xyce::dout() << std::endl;
1848  Xyce::dout() << section_divider << std::endl;
1849  Xyce::dout() << " In Instance::registerStateLIDs\n\n";
1850  Xyce::dout() << " name = " << getName() << std::endl;
1851  Xyce::dout() << " Number of State LIDs: " << numStateVars << std::endl;
1852  }
1853 #endif
1854 
1855  // Copy over the global ID lists:
1856  staLIDVec = staLIDVecRef;
1857 
1858  int lid=0;
1859  li_state_vbdd = staLIDVec[lid++];
1860  li_state_vbs = staLIDVec[lid++];
1861  li_state_vgps = staLIDVec[lid++];
1862  li_state_vdds = staLIDVec[lid++];
1863  li_state_D1vd = staLIDVec[lid++];
1864 
1865  li_state_qgs = staLIDVec[lid++];
1866  //li_state_cqgs = staLIDVec[lid++];
1867  li_state_qgdd = staLIDVec[lid++];
1868  //li_state_cqgdd = staLIDVec[lid++];
1869  li_state_qgb = staLIDVec[lid++];
1870  //li_state_cqgb = staLIDVec[lid++];
1871 
1872  li_state_capgs = staLIDVec[lid++];
1873  li_state_capgdd = staLIDVec[lid++];
1874  li_state_capgb = staLIDVec[lid++];
1875 
1876  li_state_qbd = staLIDVec[lid++];
1877  //li_state_cqbd = staLIDVec[lid++];
1878  li_state_qbs = staLIDVec[lid++];
1879  //li_state_cqbs = staLIDVec[lid++];
1880 
1882  //li_state_D1DIOcapCurrent = staLIDVec[lid++];
1883 
1884  li_state_von = staLIDVec[lid++];
1885 
1886 #ifdef Xyce_DEBUG_DEVICE
1887  if (getDeviceOptions().debugLevel > 0)
1888  {
1889  Xyce::dout() << " State local indices:" << std::endl;
1890  Xyce::dout() << std::endl;
1891 
1892  Xyce::dout() << " li_state_vbdd = " << li_state_vbdd << "\n";
1893  Xyce::dout() << " li_state_vbs = " << li_state_vbs << "\n";
1894  Xyce::dout() << " li_state_vgps = " << li_state_vgps << "\n";
1895  Xyce::dout() << " li_state_vdds = " << li_state_vdds << "\n";
1896  Xyce::dout() << " li_state_qgs = " << li_state_qgs << "\n";
1897  //Xyce::dout() << " li_state_cqgs = " << li_state_cqgs << "\n";
1898  Xyce::dout() << " li_state_capgs = " << li_state_capgs << "\n";
1899  Xyce::dout() << " li_state_capgdd = " << li_state_capgdd << "\n";
1900  Xyce::dout() << " li_state_capgb = " << li_state_capgb << "\n";
1901  Xyce::dout() << " li_state_qgdd = " << li_state_qgdd << "\n";
1902  //Xyce::dout() << " li_state_cqgdd = " << li_state_cqgdd << "\n";
1903  Xyce::dout() << " li_state_qgb = " << li_state_qgb << "\n";
1904  //Xyce::dout() << " li_state_cqgb = " << li_state_cqgb << "\n";
1905  Xyce::dout() << " li_state_qbs = " << li_state_qbs << "\n";
1906  //Xyce::dout() << " li_state_cqbs = " << li_state_cqbs << "\n";
1907  Xyce::dout() << " li_state_qbd = " << li_state_qbd << "\n";
1908  //Xyce::dout() << " li_state_cqbd = " << li_state_cqbd << "\n";
1909  Xyce::dout() << " li_state_D1DIOcapCharge = " << li_state_D1DIOcapCharge << "\n";
1910  //Xyce::dout() << " li_state_D1DIOcapCurrent = " << li_state_D1DIOcapCurrent << "\n";
1911  Xyce::dout() << " li_state_von = " << li_state_von << "\n";
1912 
1913  Xyce::dout() << std::endl;
1914  Xyce::dout() << section_divider << std::endl;
1915  }
1916 #endif
1917 
1918 }
1919 
1920 
1921 //-----------------------------------------------------------------------------
1922 // Function : Instance::registerStoreLIDs
1923 // Purpose :
1924 // Special Notes :
1925 // Scope : public
1926 // Creator : Richard Schiek, Electrical Systems Modeling
1927 // Creation Date : 4/23/2013
1928 //-----------------------------------------------------------------------------
1929 void Instance::registerStoreLIDs( const std::vector<int> & stoLIDVecRef )
1930 {
1931  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
1932 
1933  // Copy over the global ID lists:
1934  stoLIDVec = stoLIDVecRef;
1935  if( loadLeadCurrent )
1936  {
1937  li_store_dev_id = stoLIDVec[0];
1938  li_store_dev_ig = stoLIDVec[1];
1939  li_store_dev_is = stoLIDVec[2];
1940  li_store_dev_ib = stoLIDVec[3];
1941  }
1942 }
1943 
1944 //-----------------------------------------------------------------------------
1945 // Function : Instance::getStoreNameMap
1946 // Purpose :
1947 // Special Notes :
1948 // Scope : public
1949 // Creator : Richard Schiek, Electrical Systems Modeling
1950 // Creation Date : 4/23/2013
1951 //-----------------------------------------------------------------------------
1952 std::map<int,std::string> & Instance::getStoreNameMap ()
1953 {
1954  // set up the internal name map, if it hasn't been already.
1955  if( loadLeadCurrent && storeNameMap.empty ())
1956  {
1957  // change subcircuitname:devicetype_deviceName to
1958  // devicetype:subcircuitName:deviceName
1959  std::string modName(getName());
1960  spiceInternalName(modName);
1961  std::string tmpstr;
1962  tmpstr = modName+":DEV_ID";
1963  storeNameMap[ li_store_dev_id ] = tmpstr;
1964  tmpstr = modName+":DEV_IG";
1965  storeNameMap[ li_store_dev_ig ] = tmpstr;
1966  tmpstr = modName+":DEV_IS";
1967  storeNameMap[ li_store_dev_is ] = tmpstr;
1968  tmpstr = modName+":DEV_IB";
1969  storeNameMap[ li_store_dev_ib ] = tmpstr;
1970  }
1971 
1972  return storeNameMap;
1973 }
1974 
1975 //-----------------------------------------------------------------------------
1976 // Function : Instance::jacobianStamp
1977 // Purpose :
1978 // Special Notes :
1979 // Scope : public
1980 // Creator : Robert Hoekstra, Computational Sciences
1981 // Creation Date : 9/3/02
1982 //-----------------------------------------------------------------------------
1983 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
1984 {
1985  if( drainCond != 0.0 && gateCond != 0.0 && sourceCond != 0.0)
1987  else if( drainCond != 0.0 && gateCond != 0.0 && sourceCond == 0.0 )
1989  else if( drainCond == 0.0 && gateCond != 0.0 && sourceCond != 0.0 )
1991  else if( drainCond != 0.0 && gateCond == 0.0 && sourceCond != 0.0 )
1993  else if( drainCond == 0.0 && gateCond != 0.0 && sourceCond == 0.0 )
1995  else if( drainCond != 0.0 && gateCond == 0.0 && sourceCond == 0.0 )
1997  else if( drainCond == 0.0 && gateCond == 0.0 && sourceCond != 0.0 )
1999  else if( drainCond == 0.0 && gateCond == 0.0 && sourceCond == 0.0 )
2001  else
2003 }
2004 
2005 //-----------------------------------------------------------------------------
2006 // Function : Instance::registerJacLIDs
2007 // Purpose :
2008 // Special Notes :
2009 // Scope : public
2010 // Creator : Robert Hoekstra, Computational Sciences
2011 // Creation Date : 9/3/02
2012 //-----------------------------------------------------------------------------
2013 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
2014 {
2015  DeviceInstance::registerJacLIDs( jacLIDVec );
2016  std::vector<int> map;
2017  std::vector< std::vector<int> > map2;
2018  double d1dcond=(model_.D1DIOconductance);
2019  if (gateCond != 0.0)
2020  {
2021  if (drainCond != 0.0)
2022  {
2023  if (sourceCond != 0.0)
2024  {
2025  if (d1dcond != 0)
2026  {
2027  map = jacMap_D1C_DC_SC_GC;
2028  map2 = jacMap2_D1C_DC_SC_GC;
2029  }
2030  else
2031  {
2032  map = jacMap_DC_SC_GC;
2033  map2 = jacMap2_DC_SC_GC;
2034  }
2035  }
2036  else
2037  {
2038  if (d1dcond != 0)
2039  {
2040  map = jacMap_D1C_DC_GC;
2041  map2 = jacMap2_D1C_DC_GC;
2042  }
2043  else
2044  {
2045  map = jacMap_DC_GC;
2046  map2 = jacMap2_DC_GC;
2047  }
2048  }
2049  }
2050  else
2051  {
2052  if (sourceCond != 0.0)
2053  {
2054  if (d1dcond != 0)
2055  {
2056  map = jacMap_D1C_SC_GC;
2057  map2 = jacMap2_D1C_SC_GC;
2058  }
2059  else
2060  {
2061  map = jacMap_SC_GC;
2062  map2 = jacMap2_SC_GC;
2063  }
2064  }
2065  else
2066  {
2067  if (d1dcond != 0)
2068  {
2069  map = jacMap_D1C_GC;
2070  map2 = jacMap2_D1C_GC;
2071  }
2072  else
2073  {
2074  map = jacMap_GC;
2075  map2 = jacMap2_GC;
2076  }
2077  }
2078  }
2079  }
2080  else
2081  {
2082  if (drainCond != 0.0)
2083  {
2084  if (sourceCond != 0.0)
2085  {
2086  if (d1dcond != 0)
2087  {
2088  map = jacMap_D1C_DC_SC;
2089  map2 = jacMap2_D1C_DC_SC;
2090  }
2091  else
2092  {
2093  map = jacMap_DC_SC;
2094  map2 = jacMap2_DC_SC;
2095  }
2096  }
2097  else
2098  {
2099  if (d1dcond != 0)
2100  {
2101  map = jacMap_D1C_DC;
2102  map2 = jacMap2_D1C_DC;
2103  }
2104  else
2105  {
2106  map = jacMap_DC;
2107  map2 = jacMap2_DC;
2108  }
2109  }
2110  }
2111  else
2112  {
2113  if (sourceCond != 0.0)
2114  {
2115  if (d1dcond != 0)
2116  {
2117  map = jacMap_D1C_SC;
2118  map2 = jacMap2_D1C_SC;
2119  }
2120  else
2121  {
2122  map = jacMap_SC;
2123  map2 = jacMap2_SC;
2124  }
2125  }
2126  else
2127  {
2128  if (d1dcond != 0)
2129  {
2130  map = jacMap_D1C;
2131  map2 = jacMap2_D1C;
2132  }
2133  else
2134  {
2135  map = jacMap;
2136  map2 = jacMap2;
2137  }
2138  }
2139  }
2140  }
2141 
2142  ADrainEquDrainNodeOffset = jacLIDVec[map[0]][map2[0][0]];
2143  ADrainEquSourceNodeOffset = jacLIDVec[map[0]][map2[0][1]];
2144  ADrainEquDrainDriftNodeOffset = jacLIDVec[map[0]][map2[0][2]];
2145  ADrainEquD1PrimeNodeOffset = jacLIDVec[map[0]][map2[0][3]];
2146 
2147  AGateEquGateNodeOffset = jacLIDVec[map[1]][map2[1][0]];
2148  AGateEquGatePrimeNodeOffset = jacLIDVec[map[1]][map2[1][1]];
2149 
2150  ASourceEquDrainNodeOffset = jacLIDVec[map[2]][map2[2][0]];
2151  ASourceEquSourceNodeOffset = jacLIDVec[map[2]][map2[2][1]];
2152  ASourceEquSourcePrimeNodeOffset = jacLIDVec[map[2]][map2[2][2]];
2153  ASourceEquD1PrimeNodeOffset = jacLIDVec[map[2]][map2[2][3]];
2154 
2155  ABulkEquBulkNodeOffset = jacLIDVec[map[3]][map2[3][0]];
2156  ABulkEquDrainPrimeNodeOffset = jacLIDVec[map[3]][map2[3][1]];
2157  ABulkEquGatePrimeNodeOffset = jacLIDVec[map[3]][map2[3][2]];
2158  ABulkEquSourcePrimeNodeOffset = jacLIDVec[map[3]][map2[3][3]];
2159 
2160  ADrainPrimeEquBulkNodeOffset = jacLIDVec[map[4]][map2[4][0]];
2161  ADrainPrimeEquDrainPrimeNodeOffset = jacLIDVec[map[4]][map2[4][1]];
2162  ADrainPrimeEquGatePrimeNodeOffset = jacLIDVec[map[4]][map2[4][2]];
2163  ADrainPrimeEquSourcePrimeNodeOffset = jacLIDVec[map[4]][map2[4][3]];
2164  ADrainPrimeEquDrainDriftNodeOffset = jacLIDVec[map[4]][map2[4][4]];
2165 
2166  AGatePrimeEquGateNodeOffset = jacLIDVec[map[5]][map2[5][0]];
2167  AGatePrimeEquBulkNodeOffset = jacLIDVec[map[5]][map2[5][1]];
2168  AGatePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[5]][map2[5][2]];
2169  AGatePrimeEquGatePrimeNodeOffset = jacLIDVec[map[5]][map2[5][3]];
2170  AGatePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[5]][map2[5][4]];
2171 
2172  ASourcePrimeEquSourceNodeOffset = jacLIDVec[map[6]][map2[6][0]];
2173  ASourcePrimeEquBulkNodeOffset = jacLIDVec[map[6]][map2[6][1]];
2174  ASourcePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[6]][map2[6][2]];
2175  ASourcePrimeEquGatePrimeNodeOffset = jacLIDVec[map[6]][map2[6][3]];
2176  ASourcePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[6]][map2[6][4]];
2177 
2178  ADrainDriftEquDrainNodeOffset = jacLIDVec[map[7]][map2[7][0]];
2179  ADrainDriftEquDrainPrimeNodeOffset = jacLIDVec[map[7]][map2[7][1]];
2180  ADrainDriftEquDrainDriftNodeOffset = jacLIDVec[map[7]][map2[7][2]];
2181 
2182  AD1PrimeEquDrainNodeOffset = jacLIDVec[map[8]][map2[8][0]];
2183  AD1PrimeEquSourceNodeOffset = jacLIDVec[map[8]][map2[8][1]];
2184  AD1PrimeEquD1PrimeNodeOffset = jacLIDVec[map[8]][map2[8][2]];
2185 }
2186 
2187 //-----------------------------------------------------------------------------
2188 // Function : Instance::setupPointers
2189 // Purpose :
2190 // Special Notes :
2191 // Scope : public
2192 // Creator : Eric Keiter, SNL
2193 // Creation Date : 12/06/08
2194 //-----------------------------------------------------------------------------
2196 {
2197 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2198  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2199  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2200 
2205 
2208 
2213 
2218 
2224 
2230 
2236 
2240 
2244 
2245 
2246 
2251 
2254 
2259 
2264 
2270 
2276 
2282 
2286 
2290 
2291 
2292 
2293 
2294 #endif
2295 }
2296 
2297 //-----------------------------------------------------------------------------
2298 // Function : Instance::loadDAEQVector
2299 //
2300 // Purpose : Loads the Q-vector contributions for a single
2301 // voltage source instance.
2302 //
2303 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2304 // which the system of equations is represented as:
2305 //
2306 // f(x) = dQ(x)/dt + F(x) + B(t) = 0
2307 //
2308 // The "Q" vector contains charges and fluxes, mostly.
2309 // The voltage source will not make any contributions to Q,
2310 // so this function does nothing.
2311 //
2312 // Scope : public
2313 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2314 // Creation Date : 06/02/05
2315 //-----------------------------------------------------------------------------
2317 {
2318  double * qVec = extData.daeQVectorRawPtr;
2319  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
2320 
2321  double coef_Jdxp(0.0);
2322 
2323  double ceqbs(0.0), ceqbd(0.0), ceqgb(0.0), ceqgs(0.0), ceqgdd(0.0); // 3f5 vars
2324  double Dtype =model_.dtype;
2325 
2326  ceqbs = Dtype*qbs;
2327  ceqbd = Dtype*qbd;
2328  ceqgb = Dtype*qgb;
2329  ceqgs = Dtype*qgs;
2330  ceqgdd = Dtype*qgdd;
2331 
2332  qVec[li_Bulk] += (ceqbs + ceqbd - ceqgb);
2333  qVec[li_DrainPrime] += -(ceqbd + ceqgdd);
2334  qVec[li_GatePrime] += (ceqgs+ceqgdd+ceqgb);
2335  qVec[li_SourcePrime] += (-(ceqbs + ceqgs));
2336  qVec[li_D1Prime] += D1DIOcapCharge;
2337  qVec[li_Drain] += -D1DIOcapCharge;
2338  // voltlim section:
2339  if (!origFlag)
2340  {
2341  // bulk
2342  coef_Jdxp = Dtype*(-Capgb*(vgps-vgps_orig-vbs+vbs_orig)
2343  + (+Capgb)*(vbdd-vbdd_orig)
2344  + (+capbs)*(vbs-vbs_orig));
2345  dQdxdVp[li_Bulk] += coef_Jdxp;
2346 
2347  // drain-prime
2348  coef_Jdxp = Dtype*(-Capgdd*(vgpdd-vgpdd_orig)-capbd*(vbdd-vbdd_orig));
2349  dQdxdVp[li_DrainPrime] += coef_Jdxp;
2350 
2351  // gate-prime
2352  coef_Jdxp = Dtype*(Capgdd*(vgpdd-vgpdd_orig)+Capgs*(vgps-vgps_orig)+
2354  dQdxdVp[li_GatePrime] += coef_Jdxp;
2355 
2356  // source-prime
2357  coef_Jdxp = Dtype*(-Capgs*(vgps-vgps_orig)-capbs*(vbs-vbs_orig));
2358  dQdxdVp[li_SourcePrime] += coef_Jdxp;
2359 
2360  coef_Jdxp = -D1capd*(D1vd-D1vd_orig);
2361  dQdxdVp[li_D1Prime] -= coef_Jdxp;
2362  dQdxdVp[li_Drain] += coef_Jdxp;
2363  }
2364 
2365  if( loadLeadCurrent )
2366  {
2367  double * storeLeadQ = extData.storeLeadCurrQCompRawPtr;
2368 
2369  storeLeadQ[li_store_dev_id] = -D1DIOcapCharge;
2370  storeLeadQ[li_store_dev_is] = 0;
2371  storeLeadQ[li_store_dev_ig] = 0;
2372  storeLeadQ[li_store_dev_ib] = (ceqbs + ceqbd - ceqgb);
2373  // case where optional nodes become external nodes:
2374  if( !gateCond )
2375  {
2376  // G' is G
2377  storeLeadQ[li_store_dev_ig] += (ceqgs+ceqgdd+ceqgb);
2378  }
2379 
2380  if( !sourceCond )
2381  {
2382  // S' is S
2383  storeLeadQ[li_store_dev_is] += (-(ceqbs + ceqgs));
2384  }
2385 
2386  if( !drainCond )
2387  {
2388  // Ddrift is D'
2389  }
2390 
2391  if( !model_.D1DIOconductance )
2392  {
2393  // D1' is S
2394  storeLeadQ[li_store_dev_is] += D1DIOcapCharge;
2395  }
2396  }
2397 
2398  return true;
2399 }
2400 
2401 //-----------------------------------------------------------------------------
2402 // Function : Instance::loadDAEFVector
2403 //
2404 // Purpose : Loads the F-vector contributions for a single
2405 // VDMOS instance.
2406 //
2407 // Special Notes :
2408 //
2409 // Scope : public
2410 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2411 // Creation Date : 06/02/05
2412 //-----------------------------------------------------------------------------
2414 {
2415  double * fVec = extData.daeFVectorRawPtr;
2416  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
2417 
2418  double coef_Jdxp(0.0), gd_Jdxp(0.0);
2419  double gmin1 = getDeviceOptions().gmin;
2420  double Dtype =model_.dtype;
2421 
2422  double ceqbs = Dtype*(cbs+cqbs);
2423  double ceqbd = Dtype*(cbd+cqbd);
2424 
2425  double D1current = Dtype*D1cdeq; // don't add in the capacitor stuff
2426  fVec[li_Drain] += (Idraindrift + Irdsshunt - D1current);
2427 
2428  if (Igate != 0.0)
2429  {
2430  fVec[li_Gate] += Igate;
2431  fVec[li_GatePrime] += -Igate;
2432  }
2433  fVec[li_Source] += (Isource - Irdsshunt + Ird1rs);
2434  fVec[li_Bulk] += (ceqbs + ceqbd);
2435  fVec[li_DrainPrime] += (-Idrain-(ceqbd - cdreq));
2436  fVec[li_SourcePrime] += (-Isource-(ceqbs + cdreq));
2437  fVec[li_DrainDrift] += (Idrain - Idraindrift);
2438  fVec[li_D1Prime] += (D1current - Ird1rs);
2439 
2440  // limiter terms:
2441  if (!origFlag)
2442  {
2443  // bulk
2444  coef_Jdxp = Dtype*( + ((gbd-gmin1))*(vbdd-vbdd_orig)
2445  + ((gbs-gmin1))*(vbs-vbs_orig));
2446  dFdxdVp[li_Bulk] += coef_Jdxp;
2447 
2448  // drain-prime
2449  coef_Jdxp = Dtype*(-((gbd-gmin1))*
2451  +Gm*((mode>0)?(vgps-vgps_orig):(vgpdd-vgpdd_orig))
2452  +Gmbs*((mode>0)?(vbs-vbs_orig):(vbdd-vbdd_orig)));
2453  dFdxdVp[li_DrainPrime] += coef_Jdxp;
2454 
2455  // source prime
2456  coef_Jdxp = Dtype*(-((gbs-gmin1))*(vbs-vbs_orig)
2457  -gdds*(vdds-vdds_orig)
2458  -Gm*((mode>0)?(vgps-vgps_orig):(vgpdd-vgpdd_orig))
2459  -Gmbs*((mode>0)?(vbs-vbs_orig):(vbdd-vbdd_orig)));
2460  dFdxdVp[li_SourcePrime] += coef_Jdxp;
2461 
2462  gd_Jdxp = -D1gd * (D1vd-D1vd_orig);
2463  dFdxdVp[li_Drain] += gd_Jdxp;
2464  dFdxdVp[li_D1Prime] -= gd_Jdxp;
2465  }
2466 
2467  if( loadLeadCurrent )
2468  {
2469  double * storeLeadF = extData.nextStoVectorRawPtr;
2470 
2471  storeLeadF[li_store_dev_id] = (Idraindrift + Irdsshunt - D1current);
2472  storeLeadF[li_store_dev_is] = (Isource - Irdsshunt + Ird1rs);
2473  storeLeadF[li_store_dev_ig] = 0;
2474  storeLeadF[li_store_dev_ib] = (ceqbs + ceqbd);
2475  // case where optional nodes become external nodes:
2476  if (Igate != 0.0)
2477  {
2478  storeLeadF[li_store_dev_ig] += Igate;
2479  }
2480  if( !gateCond )
2481  {
2482  // G' is G
2483  storeLeadF[li_store_dev_ig] += -Igate;
2484  }
2485 
2486  if( !sourceCond )
2487  {
2488  // S' is S
2489  storeLeadF[li_store_dev_is] += (-Isource-(ceqbs + cdreq));
2490  }
2491 
2492  if( !drainCond )
2493  {
2494  // Ddrift is D'
2495  }
2496 
2497  if( !model_.D1DIOconductance )
2498  {
2499  // D1' is S
2500  storeLeadF[li_store_dev_is] += (D1current - Ird1rs);
2501  }
2502  }
2503 
2504  return true;
2505 }
2506 
2507 //-----------------------------------------------------------------------------
2508 // Function : Instance::loadDAEdQdx
2509 //
2510 // Purpose : Loads the Q-vector contributions for a single
2511 // VDMOS instance.
2512 //
2513 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2514 // which the system of equations is represented as:
2515 //
2516 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2517 //
2518 // Scope : public
2519 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2520 // Creation Date : 06/02/05
2521 //-----------------------------------------------------------------------------
2523 {
2524  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2525 
2526  if (getSolverState().dcopFlag) return true;
2527 
2532 
2536 
2541 
2545 
2548 
2551 
2552  return true;
2553 }
2554 
2555 //-----------------------------------------------------------------------------
2556 // Function : Instance::loadDAEdFdx ()
2557 //
2558 // Purpose : Loads the F-vector contributions for a single
2559 // instance.
2560 //
2561 // Special Notes : The F-vector is an algebraic constaint.
2562 //
2563 // Scope : public
2564 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
2565 // Creation Date : 06/02/05
2566 //-----------------------------------------------------------------------------
2568 {
2569  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2570 
2575 
2576  if (gateCond != 0)
2577  {
2580  }
2581 
2585 
2586  if (sourceCond != 0.0)
2587  {
2589  }
2590 
2593 
2595 
2600  if (drainCond != 0.0)
2601  {
2603  }
2604 
2605  if (gateCond != 0)
2606  {
2609  }
2610 
2611  if (sourceCond != 0.0)
2612  {
2614  }
2619 
2621 
2622  if (drainCond != 0.0)
2623  {
2625  }
2627 
2631 
2632  return true;
2633 }
2634 
2635 //-----------------------------------------------------------------------------
2636 // Function : Instance::updateIntermediateVars
2637 // Purpose :
2638 // Special Notes :
2639 // Scope : public
2640 // Creator : pmc
2641 // Creation Date : 2/17/2004
2642 //-----------------------------------------------------------------------------
2644 {
2645  bool bsuccess = true;
2646 
2647  double * solVec = extData.nextSolVectorRawPtr;
2648 
2649  // 3f5 likes to use the same variable names in local variables and in
2650  // structures. Messes with us! Define some local versions with capitals
2651  // instead
2652 #define ISUBMOD model_.isubmod
2653 
2654  double Von(0.0);
2655  double Vddsat(0.0);
2656  //
2657  double evbs(0.0);
2658  double evbdd(0.0);
2659  double sarg(0.0);
2660  double sargsw(0.0);
2661  double arg(0.0);
2662  int Check(1);
2663 
2664  double capgs_old(0.0);
2665  double capgdd_old(0.0);
2666  double capgb_old(0.0);
2667 
2668  // diode #1
2669  double D1temp(0.0);
2670  double D1power(0.0);
2671  double D1arg(0.0);
2672  double D1cd(0.0);
2673  double D1cdr(0.0);
2674  double D1csat(0.0);
2675  double D1csatr(0.0);
2676  double D1czero(0.0);
2677  double D1czof2(0.0);
2678  double D1evd(0.0);
2679  double D1evr(0.0);
2680  double D1isr(0.0);
2681  double D1evrev(0.0);
2682  double D1gdr(0.0);
2683  double D1sarg(0.0);
2684  double D1vdtemp(0.0);
2685  double D1vtr(0.0);
2686  int D1Check(0);
2687 
2688 #ifdef Xyce_DEBUG_DEVICE
2689 
2690  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2691  {
2692  Xyce::dout() << subsection_divider << std::endl;
2693  Xyce::dout() <<" Instance::updateIntermediateVars.\n"<<std::endl;
2694  Xyce::dout() <<" name = " << getName() << std::endl;
2695  Xyce::dout() <<" Model name = " << model_.getName() << std::endl;
2696  Xyce::dout() <<" dtype is " << model_.dtype << std::endl;
2697  Xyce::dout() << std::endl;
2698  Xyce::dout().width(25); Xyce::dout().precision(17); Xyce::dout().setf(std::ios::scientific);
2699  }
2700 #endif
2701 
2702  if( (tSatCurDens == 0) || (drainArea == 0) || (sourceArea == 0))
2703  {
2704  DrainSatCur = tSatCur;
2706  }
2707  else
2708  {
2711  }
2712 
2713  // we need our solution variables for any of this stuff
2714 
2715  Vd = 0.0;
2716  Vs = 0.0;
2717  Vg = 0.0;
2718  Vb = 0.0;
2719  Vdp = 0.0;
2720  Vgp = 0.0;
2721  Vsp = 0.0;
2722  Vdd = 0.0;
2723 
2724  Vd = solVec[li_Drain];
2725  Vg = solVec[li_Gate];
2726  Vs = solVec[li_Source];
2727  Vb = solVec[li_Bulk];
2728  Vsp = solVec[li_SourcePrime];
2729  Vgp = solVec[li_GatePrime];
2730  Vdp = solVec[li_DrainPrime];
2731  Vdd = solVec[li_DrainDrift];
2732 
2733  // node for diode #1
2734  Vd1p = solVec[li_D1Prime];
2735 
2738  D1vtr = model_.D1DIOnr * D1vt;
2739 
2740 #ifdef Xyce_DEBUG_DEVICE
2741  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2742  {
2743  Xyce::dout() << " " << std::endl;
2744  Xyce::dout() << " Solution vector: " << std::endl;
2745  Xyce::dout() << " Vg = " << Vg << std::endl;
2746  Xyce::dout() << " Vd = " << Vd << std::endl;
2747  Xyce::dout() << " Vs = " << Vs << std::endl;
2748  Xyce::dout() << " Vb = " << Vb << std::endl;
2749  Xyce::dout() << " Vdp = " << Vdp << std::endl;
2750  Xyce::dout() << " Vgp = " << Vgp << std::endl;
2751  Xyce::dout() << " Vsp = " << Vsp << std::endl;
2752  Xyce::dout() << " Vdd = " << Vdd << std::endl;
2753  Xyce::dout() << " Vd1p= " << Vd1p << std::endl;
2754  }
2755 #endif
2756 
2757  // voltage drops
2758  Vddp = Vd - Vdp;
2759  Vddd = Vd - Vdd;
2760  Vdddp = Vdd - Vdp;
2761  Vssp = Vs - Vsp;
2762  Vbsp = Vb - Vsp;
2763  Vbdp = Vb - Vdp;
2764 
2765  Vggp = Vg - Vgp;
2766  Vgpsp = Vgp - Vsp;
2767  Vgpdp = Vgp - Vdp;
2768  Vgpb = Vgp - Vb;
2769  Vdpsp = Vdp - Vsp;
2770 
2771  // setup corrections for dtype.
2772  vbs = model_.dtype * Vbsp;
2773  vgps = model_.dtype * Vgpsp;
2774  vdds = model_.dtype * Vdpsp;
2775  D1vd = model_.dtype * (Vd1p - Vd);
2776 
2777  vbdd = vbs-vdds;
2778  vgpdd = vgps-vdds;
2779 
2780  // set up the orig voltages.
2781  origFlag = 1;
2782  limitedFlag = false;
2783  vgps_orig = vgps;
2784  vdds_orig = vdds;
2785  vbs_orig = vbs;
2786  vbdd_orig = vbdd;
2787  vgpdd_orig = vgpdd;
2788  D1vd_orig = D1vd;
2789 
2790  if (getSolverState().newtonIter == 0)
2791  {
2792  newtonIterOld=0;
2793 
2795  {
2797  {
2798  N_LAS_Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
2799  if ((*flagSolVectorPtr)[li_Drain] == 0 || (*flagSolVectorPtr)[li_Gate] == 0 ||
2800  (*flagSolVectorPtr)[li_Source] == 0 || (*flagSolVectorPtr)[li_SourcePrime] ||
2801  (*flagSolVectorPtr)[li_DrainDrift] == 0 || (*flagSolVectorPtr)[li_GatePrime] ||
2802  (*flagSolVectorPtr)[li_DrainPrime] || (*flagSolVectorPtr)[li_Bulk] )
2803  {
2804  vbs = -1;
2805  vgps = model_.dtype*tVto;
2806  vdds = 0;
2807  vbdd = vbs-vdds;
2808  vgpdd = vgps-vdds;
2809  }
2810  }
2811  else
2812  {
2813  vbs = -1;
2814  vgps = model_.dtype*tVto;
2815  vdds = 0;
2816  vbdd = vbs-vdds;
2817  vgpdd = vgps-vdds;
2818  }
2819  }
2820 
2821  ////////////////////////////////////////////////////////////////////////
2822  // Note: the "old" variables should be the values for the previous
2823  // Newton iteration. That previous newton iteration could
2824  // have happened in a previous time step...
2826  {
2832  Von = model_.dtype *
2834  }
2835  else
2836  { // there's no history
2837  vbs_old = vbs;
2838  vbdd_old = vbdd;
2839  vgps_old = vgps;
2840  vdds_old = vdds;
2841  D1vd_old = D1vd;
2842  }
2843  }
2844  else
2845  {
2851  Von = model_.dtype *
2854  }
2855 
2856 #ifdef Xyce_DEBUG_DEVICE
2858  {
2859  Xyce::dout() << "After Von first set, ";
2860  Xyce::dout() << " von = " << von << " Von = " << Von << std::endl;
2861  }
2862 #endif
2863 
2864  ////////////////////////////////////////////
2865  // SPICE-type Voltage Limiting (PINNING)
2866  ////////////////////////////////////////////
2867  if (getDeviceOptions().voltageLimiterFlag)
2868  {
2869 #ifdef Xyce_DEBUG_DEVICE
2870  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2871  {
2872  Xyce::dout() << " checking whether to limit voltages "<< std::endl;
2873  Xyce::dout() << " Von = " << Von << std::endl;
2874  Xyce::dout() << " before limiting: " << std::endl;
2875  Xyce::dout() << " vgpdd = " << vgpdd << " vgpdd_old = " << vgpdd_old << std::endl;
2876  Xyce::dout() << " vgps = " << vgps << " vgps_old = " << vgps_old << std::endl;
2877  Xyce::dout() << " vdds = " << vdds << " vdds_old = " << vdds_old << std::endl;
2878  Xyce::dout() << " vbs = " << vbs << " vbs_old = " << vbs_old << std::endl;
2879  Xyce::dout() << " vbdd = " << vbdd << " vbdd_old = " << vbdd_old << std::endl;
2880  }
2881 #endif
2882 
2883  if (vdds_old >= 0)
2884  {
2885  vgps = devSupport.fetlim( vgps, vgps_old, Von);
2886  vdds = vgps - vgpdd;
2887  vdds = devSupport.limvds( vdds, vdds_old);
2888  vgpdd = vgps - vdds;
2889  }
2890  else
2891  {
2893  vdds = vgps - vgpdd;
2894  vdds = -devSupport.limvds( -vdds, -vdds_old );
2895  vgps = vgpdd + vdds;
2896  }
2897 
2898  if (vdds >= 0.0)
2899  {
2900  vbs = devSupport.pnjlim( vbs, vbs_old, vt, sourceVcrit, &Check);
2901  vbdd = vbs - vdds;
2902  }
2903  else
2904  {
2905  vbdd = devSupport.pnjlim( vbdd, vbdd_old, vt, drainVcrit, &Check);
2906  vbs = vbdd + vdds;
2907  }
2908 
2909  if (Check == 1) limitedFlag=true;
2910 #ifdef Xyce_DEBUG_DEVICE
2911  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2912  {
2913  Xyce::dout() << " After limiting: " << std::endl;
2914  Xyce::dout() << " vgpdd = " << vgpdd << std::endl;
2915  Xyce::dout() << " vgps = " << vgps << std::endl;
2916  Xyce::dout() << " vdds = " << vdds << std::endl;
2917  Xyce::dout() << " vbs = " << vbs << std::endl;
2918  Xyce::dout() << " vbdd = " << vbdd << std::endl;
2919  }
2920 #endif
2921 
2922  // limit diode junction voltage
2923  bool tmpGiven = false;
2924  tmpGiven = (model_.D1DIObreakdownVoltageGiven);
2925  if (tmpGiven && (D1vd < Xycemin(0.0, 10.0*D1vte-D1DIOtBrkdwnV) ))
2926  {
2927  D1vdtemp = -(D1vd + D1DIOtBrkdwnV);
2928  D1vdtemp = devSupport.pnjlim(D1vdtemp,
2930  D1DIOtVcrit, &D1Check);
2931  D1vd = -(D1vdtemp + D1DIOtBrkdwnV);
2932  }
2933  else
2934  {
2936  D1DIOtVcrit, &D1Check);
2937  }
2938 
2939  if (D1Check == 1) limitedFlag=true;
2940  } // voltage limiter flag
2941 
2942  ////
2943  // now all the preliminaries are over - we can start doing the
2944  // real work
2945  ////
2946  vbdd = vbs - vdds;
2947  vgpdd = vgps - vdds;
2948  Vgpb = vgps - vbs;
2949 
2950 #ifdef Xyce_DEBUG_DEVICE
2951  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2952  {
2953  Xyce::dout() << " vbs = " << vbs << std::endl;
2954  Xyce::dout() << " vgps = " << vgps << std::endl;
2955  Xyce::dout() << " vdds = " << vdds << std::endl;
2956  Xyce::dout() << " vbdd = " << vbdd << std::endl;
2957  Xyce::dout() << " vgpdd= " << vgpdd << std::endl;
2958 
2959  Xyce::dout() << " Vddp = " << Vddp << std::endl;
2960  Xyce::dout() << " Vddd = " << Vddd << std::endl;
2961  Xyce::dout() << " Vdddp= " << Vdddp << std::endl;
2962  Xyce::dout() << " Vssp = " << Vssp << std::endl;
2963  Xyce::dout() << " Vbsp = " << Vbsp << std::endl;
2964  Xyce::dout() << " Vbdp = " << Vbdp << std::endl;
2965  Xyce::dout() << " Vggp = " << Vggp << std::endl;
2966  Xyce::dout() << " Vgpsp = " << Vgpsp << std::endl;
2967  Xyce::dout() << " Vgpdp = " << Vgpdp << std::endl;
2968  Xyce::dout() << " Vgpb = " << Vgpb << std::endl;
2969  Xyce::dout() << " Vdpsp= " << Vdpsp << std::endl;
2970 
2971  }
2972 #endif
2973 
2974  // Now set the origFlag
2975  if (vgps_orig != vgps || vdds_orig != vdds ||
2976  vbs_orig != vbs || vbdd_orig != vbdd || vgpdd_orig != vgpdd) origFlag = 0;
2977 
2978 #ifdef Xyce_DEBUG_DEVICE
2979  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2980  {
2981  if (origFlag == 0)
2982  {
2983  Xyce::dout() << " Something modified the voltages. " << std::endl;
2984  Xyce::dout() << " Voltage before after diff " << std::endl;
2985  Xyce::dout() << " vgps " << vgps_orig << " " << vgps << " " << vgps-vgps_orig << std::endl;
2986  Xyce::dout() << " vdds " << vdds_orig << " " << vdds << " " << vdds-vdds_orig << std::endl;
2987  Xyce::dout() << " vbs " << vbs_orig << " " << vbs << " " << vbs-vbs_orig << std::endl;
2988  Xyce::dout() << " vbdd " << vbdd_orig << " " << vbdd << " " << vbdd-vbdd_orig << std::endl;
2989  Xyce::dout() << " vgpdd " << vgpdd_orig << " " << vgpdd << " " << vgpdd-vgpdd_orig << std::endl;
2990  }
2991  }
2992 #endif
2993 
2995 
2996  ////
2997  // bulk-source and bulk-drain diodes
2998  // here we just evaluate the ideal diode current and the
2999  // corresponding derivative (conductance).
3000  ////
3001 
3002  double pi(0.0);
3003  double end10(0.0);
3004  double end1(0.0);
3005  double end20(0.0);
3006  double end2(0.0);
3007  double end3(0.0);
3008  double j1(0.0);
3009  double fr1(0.0);
3010  double fr2(0.0);
3011  double d1j1(0.0);
3012  double fr3(0.0);
3013  double d2j1(0.0);
3014  double dj1(0.0);
3015 
3016  if(model_.artd != 0.0 && sourceArea != 0.0)
3017  {
3019  end1=1+exp(Xycemin(CONSTMAX_EXP_ARG,end10/vt));
3021  end2=1+exp(Xycemin(CONSTMAX_EXP_ARG,end20/vt));
3022  end3=(model_.crtd-model_.nrtd*vbs)/model_.drtd;
3023  pi = 3.1415927;
3024  j1=model_.artd*log(end1/end2)*(pi/2+atan(end3));
3025  j1=j1*sourceArea;
3026 
3027  fr1=(end1-1)*model_.nrtd/(end1*vt);
3028  fr2=(end2-1)*model_.nrtd/(end2*vt);
3029  d1j1=(fr1-fr2)*(pi/2+atan(end3));
3030  fr3=(-model_.nrtd/model_.drtd)/(1+end3*end3);
3031  d2j1=log(end1/end2)*fr3;
3032  dj1=model_.artd*(d1j1+d2j1);
3033  dj1=dj1*sourceArea;
3034  }
3035  else
3036  {
3037  j1 = 0.0;
3038  dj1 = 0.0;
3039  }
3040 
3041  if(vbs <= 0)
3042  {
3045  cbs = gbs*vbs+j1;
3046 // PMC for D1 diode testing
3047 // gbs = 0.0;
3048 // cbs = 0.0;
3049 
3050 #ifdef Xyce_DEBUG_DEVICE
3051  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3052  {
3053  Xyce::dout() << "*******Setting cbs for vbs<=0 ******" << std::endl;
3054  Xyce::dout() << " vbs = " << vbs << std::endl;
3055  Xyce::dout() << " vt = " << vt << std::endl;
3056  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3057  Xyce::dout() << " SSC = " << SourceSatCur << std::endl;
3058  Xyce::dout() << " gbs = " << gbs << std::endl;
3059  Xyce::dout() << " cbs = " << cbs << std::endl;
3060  Xyce::dout() << " j1 = " << j1 << std::endl;
3061  }
3062 #endif
3063  }
3064  else
3065  {
3066  evbs = exp(Xycemin(CONSTMAX_EXP_ARG,model_.n2*vbs/vt));
3068  + getDeviceOptions().gmin + dj1);
3069  cbs = numberParallel*(SourceSatCur*(evbs-1) + j1);
3070 // PMC for D1 diode testing
3071 // gbs = 0.0;
3072 // cbs = 0.0;
3073 
3074 #ifdef Xyce_DEBUG_DEVICE
3075  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3076  {
3077  Xyce::dout() << "*******Setting cbs for vbs>0 ******" << std::endl;
3078  Xyce::dout() << " vbs = " << vbs << std::endl;
3079  Xyce::dout() << " vt = " << vt << std::endl;
3080  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3081  Xyce::dout() << " vbs/vt = " << vbs/vt << std::endl;
3082  Xyce::dout() << " Maxarg = " << CONSTMAX_EXP_ARG << std::endl;
3083  Xyce::dout() << " arg = " << Xycemin(CONSTMAX_EXP_ARG,
3084  model_.n2*vbs/vt) << std::endl;
3085  Xyce::dout() << " evbs = " << evbs << std::endl;
3086  Xyce::dout() << " gbs = " << gbs << std::endl;
3087  Xyce::dout() << " cbs = " << cbs << std::endl;
3088  }
3089 #endif
3090  }
3091  if(vbdd <= 0)
3092  {
3095  cbd = gbd *vbdd;
3096 // PMC for D1 diode testing
3097 // gbd = 0.0;
3098 // cbd = 0.0;
3099 
3100 #ifdef Xyce_DEBUG_DEVICE
3101  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3102  {
3103  Xyce::dout() << "*******Setting cbd for vbdd<=0 ******" << std::endl;
3104  Xyce::dout() << " vbdd = " << vbdd << std::endl;
3105  Xyce::dout() << " SSC = " << SourceSatCur << std::endl;
3106  Xyce::dout() << " vt = " << vt << std::endl;
3107  Xyce::dout() << " n2 = " << model_.n2 << std::endl;
3108  Xyce::dout() << " gbd = " << gbd << std::endl;
3109  Xyce::dout() << " cbd = " << cbd << std::endl;
3110  }
3111 #endif
3112 
3113  }
3114  else
3115  {
3116  evbdd = exp(Xycemin(CONSTMAX_EXP_ARG,model_.n2*vbdd/vt));
3118  + getDeviceOptions().gmin);
3119  cbd = numberParallel*DrainSatCur*(evbdd-1);
3120 // PMC for D1 diode testing
3121 // gbd = 0.0;
3122 // cbd = 0.0;
3123 
3124 #ifdef Xyce_DEBUG_DEVICE
3126  {
3127  Xyce::dout() << "*******Setting cbd for vbdd>0 ******" << std::endl;
3128  Xyce::dout() << " vbdd = " << vbdd << std::endl;
3129  Xyce::dout() << " vt = " << vt << std::endl;
3130  Xyce::dout() << " vbdd/vt = " << vbdd/vt << std::endl;
3131  Xyce::dout() << " Maxarg = " << CONSTMAX_EXP_ARG << std::endl;
3132  Xyce::dout() << " arg = " << Xycemin(CONSTMAX_EXP_ARG,
3133  model_.n2*vbdd/vt) << std::endl;
3134  Xyce::dout() << " evbdd = " << evbdd << std::endl;
3135  Xyce::dout() << " gbd = " << gbd << std::endl;
3136  Xyce::dout() << " cbd = " << cbd << std::endl;
3137  }
3138 #endif
3139  }
3140 
3141  if (vdds >= 0)
3142  mode = 1;
3143  else
3144  mode = -1;
3145 
3146  double dvonvbs(0.0);
3147  double lvbs = mode == 1 ? vbs : vbdd;
3148  UCCMcvon(lvbs, von, dvonvbs);
3149  Von = model_.dtype * von; // von contains dtype, Von does not
3150 
3151  if(!ISUBMOD)
3152  {
3153  // Old version of model with corrected Jacobian terms
3154  UCCMmosa1(vdds>0?vgps:vgpdd,mode*vdds,dvonvbs, cdraindrift, vddsat);
3155  }
3156  else
3157  {
3158  // Version of model with substrate currents
3159  UCCMmosa2(vdds>0?vgps:vgpdd,mode*vdds,dvonvbs, cdraindrift, vddsat);
3160  }
3161  Vddsat = model_.dtype * vddsat;
3162 
3163  ////
3164  // COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
3165  ////
3166 
3167  // Substrate current calculations
3168  ISUB = cdraindrift*mm1;
3169  GMSUB = gm*mm1 + cdraindrift*dmm1vgs;
3170  GDDSSUB = gdds*mm1 + cdraindrift*dmm1vds;
3171  GBSSUB = gmbs*mm1 + cdraindrift*dmm1vbs;
3172 
3173 // PMC ISUBMOD not fully implemented
3174 // - probably we don't have the right model parameters
3175 // cdrain = cdraindrift + ISUB;
3176 
3177  cdrain = cdraindrift;
3178  cd = mode*cdrain - cbd;
3179 
3180  // diode #1 values
3181  D1csat = D1DIOtSatCur * D1DIOarea;
3182  D1csatr = D1DIOtSatRCur * D1DIOarea;
3184  D1vtr = model_.D1DIOnr * D1vt;
3185  D1evd = D1arg = D1evrev = 0.0;
3186 
3187  // compute diode dc current and derivatives
3188  if(D1csatr != 0)
3189  {
3190  D1evr = exp(D1vd/D1vtr);
3191  D1temp = 1 - D1vd/D1DIOtJctPot;
3192  D1arg = D1temp*D1temp;
3193  D1power = pow(D1arg + 0.001,model_.D1DIOgradingCoeff/2);
3194  D1isr = D1csatr*D1power;
3195  D1cdr = D1isr*(D1evr - 1);
3196  D1gdr = -D1cdr*model_.D1DIOgradingCoeff*D1temp/
3197  (D1DIOtJctPot*(D1arg + 0.001)) + D1isr*D1evr/D1vtr;
3198  } else
3199  {
3200  D1cdr = 0;
3201  D1gdr = 0;
3202  }
3203 
3204  // add in diode bulk resistance
3205  if(D1vd >= -3*D1vte)
3206  {
3207  D1evd = exp(D1vd/D1vte);
3208  D1cd = D1csat*(D1evd-1)+D1cdr + getDeviceOptions().gmin*D1vd;
3209  D1gd = D1csat*D1evd/D1vte+D1gdr + getDeviceOptions().gmin;
3210  if(model_.D1DIOikf > 0) {
3211  D1arg = sqrt(model_.D1DIOikf/(model_.D1DIOikf + D1cd));
3212  D1gd = D1arg*D1gd*(1 - 0.5*D1cd/(model_.D1DIOikf + D1cd));
3213  D1cd = D1arg*D1cd;
3214  }
3215  }
3216  else if( (!(D1DIOtBrkdwnV)) || (D1vd >= -D1DIOtBrkdwnV) )
3217  {
3218  D1arg = 3*D1vte/(D1vd*CONSTe);
3219  D1arg = D1arg * D1arg * D1arg;
3220  D1cd = -D1csat*(1 + D1arg) + getDeviceOptions().gmin*D1vd + D1cdr;
3221  D1gd = D1csat*3*D1arg/D1vd + getDeviceOptions().gmin + D1gdr;
3222  }
3223  else
3224  {
3225  D1evrev= exp(-(D1DIOtBrkdwnV + D1vd)/D1vte);
3226  D1cd = -D1csat*D1evrev + getDeviceOptions().gmin*D1vd + D1cdr;
3227  D1gd = D1csat*D1evrev/D1vte + getDeviceOptions().gmin + D1gdr;
3228  }
3229  D1cdeq = D1cd;
3230 
3231 #ifdef Xyce_DEBUG_DEVICE
3232  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3233  {
3234  Xyce::dout() << " " << std::endl;
3235  Xyce::dout() << " dtype = " << model_.dtype << std::endl;
3236  Xyce::dout() << " D1vd = " << D1vd << std::endl;
3237  Xyce::dout() << " D1vtr = " << D1vtr << std::endl;
3238  Xyce::dout() << " D1csat = " << D1csat << std::endl;
3239  Xyce::dout() << " D1csatr = " << D1csatr << std::endl;
3240  Xyce::dout() << " D1gspr = " << D1gspr << std::endl;
3241  Xyce::dout() << " D1cdr = " << D1cdr << std::endl;
3242  Xyce::dout() << " D1gdr = " << D1gdr << std::endl;
3243  Xyce::dout() << " D1vte = " << D1vte << std::endl;
3244  Xyce::dout() << " D1evd = " << D1evd << std::endl;
3245  Xyce::dout() << " D1arg = " << D1arg << std::endl;
3246  Xyce::dout() << " D1evrev = " << D1evrev << std::endl;
3247  Xyce::dout() << " D1DIOtBrkdwnV = " << D1DIOtBrkdwnV << std::endl << std::endl;
3248  Xyce::dout() << " D1cd = " << D1cd << std::endl;
3249  Xyce::dout() << " D1gd = " << D1gd << std::endl;
3250  Xyce::dout() << " D1cdeq = " << D1cdeq << std::endl;
3251  }
3252 #endif
3253 
3254  // in 3f5 this is all in a block conditioned on CKTmode, but since
3255  // it's valid for MODETRAN and MODETRANOP we'll just always do it
3256 
3257  ////
3258  // * now we do the hard part of the bulk-drain and bulk-source
3259  // * diode - we evaluate the non-linear capacitance and
3260  // * charge
3261  // *
3262  // * the basic equations are not hard, but the implementation
3263  // * is somewhat long in an attempt to avoid log/exponential
3264  // * evaluations
3265  ////
3266  ////
3267  // * charge storage elements
3268  // *
3269  // *.. bulk-drain and bulk-source depletion capacitances
3270  ////
3271  // I took out all the CAPBYPASS stuff, and the
3272  // unnecessary curly braces that wind up there if you do
3273 
3274  // can't bypass the diode capacitance calculations
3275  if(Cbs != 0 || Cbssw != 0 )
3276  {
3277  if (vbs < tDepCap)
3278  {
3279  arg=1-vbs/tBulkPot;
3280  ////
3281  // * the following block looks somewhat long and messy,
3282  // * but since most users use the default grading
3283  // * coefficients of .5, and sqrt is MUCH faster than an
3284  // * exp(log()) we use this special case code to buy time.
3285  // * (as much as 10% of total job time!)
3286  ////
3288  {
3289  if(model_.bulkJctBotGradingCoeff == .5)
3290  {
3291  sarg = sargsw = 1/sqrt(arg);
3292  }
3293  else
3294  {
3295  sarg = sargsw = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3296  }
3297  }
3298  else
3299  {
3300  if(model_.bulkJctBotGradingCoeff == .5)
3301  {
3302  sarg = 1/sqrt(arg);
3303  }
3304  else
3305  {
3306  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3307  }
3309  {
3310  sargsw = 1/sqrt(arg);
3311  }
3312  else
3313  {
3314  sargsw =exp(-model_.bulkJctSideGradingCoeff* log(arg));
3315  }
3316  }
3317  qbs = tBulkPot*(Cbs*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff)
3318  +Cbssw*(1-arg*sargsw)/(1-model_.bulkJctSideGradingCoeff));
3319  capbs=Cbs*sarg + Cbssw*sargsw;
3320  }
3321  else
3322  {
3323  qbs = f4s + vbs*(f2s+vbs*(f3s/2));
3324  capbs=f2s+f3s*vbs;
3325  }
3326  }
3327  else
3328  {
3329  qbs = 0;
3330  capbs=0;
3331  }
3332 
3333  //// can't bypass the diode capacitance calculations
3334  if(Cbd != 0 || Cbdsw != 0 )
3335  {
3336 
3337  if (vbdd < tDepCap)
3338  {
3339  arg=1-vbdd/tBulkPot;
3340  ////
3341  // * the following block looks somewhat long and messy,
3342  // * but since most users use the default grading
3343  // * coefficients of .5, and sqrt is MUCH faster than an
3344  // * exp(log()) we use this special case code to buy time.
3345  // * (as much as 10% of total job time!)
3346  ////
3347  if(model_.bulkJctBotGradingCoeff == .5 &&
3349  {
3350  sarg = sargsw = 1/sqrt(arg);
3351  }
3352  else
3353  {
3354  if(model_.bulkJctBotGradingCoeff == .5)
3355  {
3356  sarg = 1/sqrt(arg);
3357  }
3358  else
3359  {
3360  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3361  }
3363  {
3364  sargsw = 1/sqrt(arg);
3365  }
3366  else
3367  {
3368  sargsw =exp(-model_.bulkJctSideGradingCoeff*log(arg));
3369  }
3370  }
3371  qbd =
3372  tBulkPot*(Cbd*(1-arg*sarg)
3374  +Cbdsw*(1-arg*sargsw)
3376  capbd=Cbd*sarg + Cbdsw*sargsw;
3377  }
3378  else
3379  {
3380  qbd = f4d + vbdd * (f2d + vbdd * f3d/2);
3381  capbd= f2d + vbdd * f3d;
3382  }
3383  }
3384  else
3385  {
3386  qbd = 0;
3387  capbd = 0;
3388  }
3389 
3390  // charge storage elements
3391  D1czero = D1DIOtJctCap*D1DIOarea;
3392  if (D1vd < D1DIOtDepCap)
3393  {
3394  D1arg = 1-D1vd/model_.D1DIOjunctionPot;
3395  D1sarg = exp(-model_.D1DIOgradingCoeff*log(D1arg));
3397  model_.D1DIOjunctionPot*D1czero*
3398  (1-D1arg*D1sarg)/(1-model_.D1DIOgradingCoeff);
3399  D1capd = model_.D1DIOtransitTime*D1gd + D1czero*D1sarg;
3400  }
3401  else
3402  {
3403  D1czof2 = D1czero/model_.D1DIOf2;
3404  D1DIOcapCharge = model_.D1DIOtransitTime*D1cd+D1czero*
3405  D1DIOtF1+D1czof2*(model_.D1DIOf3*
3410  D1capd = model_.D1DIOtransitTime*D1gd+D1czof2*
3413  }
3414 
3415 #ifdef Xyce_DEBUG_DEVICE
3417  {
3418  Xyce::dout() << " " << std::endl;
3419  Xyce::dout() << " Going into qmeyer..." << std::endl;
3420  Xyce::dout() << " Mode is " << mode << std::endl;
3421  Xyce::dout() << " Args are vgps = " << vgps << " vgpdd = " << vgpdd << std::endl;
3422  Xyce::dout() << " Vgpb = " << Vgpb << " Von = " << Von << " Vddsat = " << Vddsat << std::endl;
3423  Xyce::dout() << " tPhi = " << tPhi << " OxideCap = " << OxideCap << std::endl;
3424  }
3425 #endif
3426  if (mode > 0)
3427  {
3428  if(model_.cve == 1)
3429  {
3430  UCCMqmeyer (vgps,vgpdd,Vgpb,Von,Vddsat,
3432  }
3433  else
3434  {
3435  // Ward-like model
3437  }
3438  }
3439  else
3440  {
3441  if(model_.cve == 1)
3442  {
3443  UCCMqmeyer (vgpdd,vgps,Vgpb,Von,Vddsat,
3445  }
3446  else
3447  {
3448  // Ward-like model
3450  }
3451  }
3452 
3453  if((getSolverState().dcopFlag))
3454  {
3455  Capgs = 2 * capgs + GateSourceOverlapCap ;
3457  Capgb = 2 * capgb + GateBulkOverlapCap ;
3458  }
3459  else
3460  {
3461  capgs_old = (*extData.currStaVectorPtr)[li_state_capgs];
3462  capgdd_old = (*extData.currStaVectorPtr)[li_state_capgdd];
3463  capgb_old = (*extData.currStaVectorPtr)[li_state_capgb];
3464 
3465 #ifdef Xyce_DEBUG_DEVICE
3467  {
3468  Xyce::dout() << "Doing meyer back averaging..."<< std::endl;
3469  Xyce::dout() << " capgs = " << capgs << " capgs_old = " << capgs_old << std::endl;
3470  Xyce::dout() << " capgdd = " << capgdd << " capgdd_old = " << capgdd_old << std::endl;
3471  Xyce::dout() << " capgb = " << capgb << " capgb_old = " << capgb_old << std::endl;
3472  }
3473 #endif
3474  Capgs = ( capgs+capgs_old + GateSourceOverlapCap );
3475  Capgdd = ( capgdd+capgdd_old + GateDrainOverlapCap );
3476  Capgb = ( capgb+capgb_old + GateBulkOverlapCap );
3477  }
3478 #ifdef Xyce_DEBUG_DEVICE
3480  {
3481  Xyce::dout() << "Capgs = " << Capgs << std::endl;
3482  Xyce::dout() << "Capgdd = " << Capgdd << std::endl;
3483  Xyce::dout() << "Capgb = " << Capgb << std::endl;
3484  Xyce::dout() << "capgs = " << capgs << std::endl;
3485  Xyce::dout() << "capgdd = " << capgdd << std::endl;
3486  Xyce::dout() << "capgb = " << capgb << std::endl;
3487  }
3488 #endif
3489  Capgs *= (Capgs < 0.0)?-1.0:1.0;
3490  Capgdd *= (Capgdd < 0.0)?-1.0:1.0;
3491  Capgb *= (Capgb < 0.0)?-1.0:1.0;
3492 
3493  // Voltage-dependent drain-drift conductance
3494  double absV = fabs(Vddd);
3496  if(gddd != 0) gddd = 1.0/gddd;
3497  draindriftCond = gddd;
3498 
3499  // need a more precise derivative than gddd for the jacobian.
3500  // w.r.t. Vd and Vdd.
3501  double dVddd_dVd (1.0);
3502  double d_absVddd_dVd (0.0);
3503  if (Vddd > 0.0)
3504  {
3505  d_absVddd_dVd = 1.0;
3506  }
3507  else if (Vddd < 0.0)
3508  {
3509  d_absVddd_dVd = -1.0;
3510  }
3511 
3512  dIdd_dVd = dVddd_dVd * gddd -
3513  Vddd * (gddd*gddd)*(model_.driftParamB)*d_absVddd_dVd;
3514 
3515  // now do the shundt resistor
3516  if(model_.rdsshunt == 0.0)
3517  {
3518  gdsshunt = 0.0;
3519  }
3520  else
3521  {
3523  }
3524 
3525  Idrain = drainCond * Vdddp;
3526  Igate = gateCond * Vggp;
3527  Isource = sourceCond * Vssp;
3529  Irdsshunt = gdsshunt * (Vd - Vs);
3530  // Rd1rs current:
3531  Ird1rs = D1gspr*(Vs - Vd1p);
3532 
3533  if (mode >= 0) // Normal mode
3534  {
3535  Gm = gm; // (xnrm-xrev)*gm in 3f5
3536  Gmbs = gmbs; // (xnrm-xrev)*gmbs in 3f5
3537  nrmsum = Gm+Gmbs; // xnrm*(gm+gmbs)
3538  revsum = 0; // xrev*(gm+gmbs)
3540  }
3541  else
3542  {
3543  Gm = -gm;
3544  Gmbs = -gmbs;
3545  nrmsum = 0;
3546  revsum = -(Gm+Gmbs); // because Gm and Gmbs already have - in them!
3547  cdreq = -(model_.dtype)*cdrain;
3548  }
3549 
3550 #ifdef Xyce_DEBUG_DEVICE
3552  {
3553  Xyce::dout() << " Done with Instance::updateIntermediateVars " << std::endl;
3554  Xyce::dout() << " mode = " << mode << std::endl;
3555  Xyce::dout() << " Idrain = " << Idrain << std::endl;
3556  Xyce::dout() << " Igate = " << Igate << std::endl;
3557  Xyce::dout() << " Isource = " << Isource << std::endl;
3558  Xyce::dout() << " Idraindrift = " << Idraindrift << std::endl;
3559  Xyce::dout() << " Ird1rs = " << Ird1rs << std::endl;
3560  Xyce::dout() << " dIdd_dVd = " << dIdd_dVd << std::endl;
3561  Xyce::dout() << " gddd = " << gddd << std::endl;
3562  Xyce::dout() << " Irdsshunt = " << Irdsshunt << std::endl;
3563  Xyce::dout() << " D1DIOcapCurrent = " << D1DIOcapCurrent << std::endl;
3564  Xyce::dout() << " cbd = " << cbd << std::endl;
3565  Xyce::dout() << " cbs = " << cbs << std::endl;
3566  Xyce::dout() << " qbd = " << qbd << std::endl;
3567  Xyce::dout() << " qbs = " << qbs << std::endl;
3568  Xyce::dout() << " cdrain = " << cdrain << std::endl;
3569  Xyce::dout() << " cdraindrift = " << cdraindrift << std::endl;
3570  Xyce::dout() << " cdreq = " << cdreq << std::endl;
3571  Xyce::dout() << " gdds = " << gdds << std::endl;
3572  Xyce::dout() << " gdsshunt = " << gdsshunt << std::endl;
3573  Xyce::dout() << " gm = " << gm << std::endl;
3574  Xyce::dout() << " gmbs = " << gmbs << std::endl;
3575  Xyce::dout() << " Gm = " << Gm << std::endl;
3576  Xyce::dout() << " Gmbs = " << Gmbs << std::endl;
3577  }
3578 #endif
3579 
3580  /// CURRENTS to load into RHS:
3581 
3582  // current out of drain is
3583  // Idraindrift + Irdsshunt - Dtype*(D1cdeq + D1DIOcapCurrent)
3584 
3585  // current out of gate:
3586  // dtype*( (deriv of qgs) + (deriv of qgdd) + (deriv of qgb))
3587 
3588  // the current *out of* the source is
3589  // Isource - Irdsshunt + Ird1rs
3590 
3591  // current out of bulk is
3592  // dtype*(deriv of qbd) + dtype*cbd + dtype*cbs + dtype*(deriv of qbs)
3593  // - dtype*(deriv of qgb)
3594 
3595  // current out of drain' is
3596  // -Idrain - dtype*(deriv of qgd) - (deriv of qbd) - dtype*cbd +
3597  // mode*dtype*cdrain
3598 
3599  // the current out of the source' is
3600  // -Isource - dtype*(deriv of qgs) - dtype*cbs - (deriv of qbs) -
3601  // mode*dtype*cdrain -Irdsshunt
3602 
3603  // the current out of the draindrift node is
3604  // Idrain - IdraindriftDtype*(D1cdeq + D1DIOcapCurrent)
3605 
3606  // the current out of the d1' pos node is
3607  // Dtype*(D1cdeq + D1DIOcapCurrent) - Ird1rs
3608 
3609  return bsuccess;
3610 }
3611 
3612 //-----------------------------------------------------------------------------
3613 // Function : Instance::updateTemperature
3614 // Purpose :
3615 // Special Notes :
3616 // Scope : public
3617 // Creator : pmc
3618 // Creation Date : 2/17/2004
3619 //-----------------------------------------------------------------------------
3620 bool Instance::updateTemperature ( const double & temp_tmp)
3621 {
3622  bool bsuccess = true;
3623  // mos3temp vars
3624  double czbd(0.0); // zero voltage bulk-drain capacitance
3625  double czbdsw(0.0); // zero voltage bulk-drain sidewall capacitance
3626  double czbs(0.0); // zero voltage bulk-source capacitance
3627  double czbssw(0.0); // zero voltage bulk-source sidewall capacitance
3628  double arg(0.0); // 1 - fc
3629  double sarg(0.0); // (1-fc) ^^ (-mj)
3630  double sargsw(0.0); // (1-fc) ^^ (-mjsw)
3631  double ratio,ratio4(0.0);
3632  double fact2(0.0);
3633  double kt(0.0);
3634  double egfet(0.0);
3635  double pbfact(0.0);
3636  double capfact(0.0);
3637  double phio(0.0);
3638  double pbo(0.0);
3639  double gmanew,gmaold(0.0);
3640  // end of mos3temp stuff
3641 
3642 //variables related to the diode 1
3643  double D1xfc(0.0);
3644  double D1vte_loc(0.0);
3645  double D1cbv(0.0);
3646  double D1xbv(0.0);
3647  double D1xcbv(0.0);
3648  double D1tol(0.0);
3649  double D1vt_loc(0.0);
3650  register int D1iter(0.0);
3651  double D1egfet1(0.0),D1arg1(0.0),D1fact1(0.0),D1pbfact1(0.0),D1pbo(0.0),D1gmaold(0.0);
3652  double D1fact2(0.0),D1pbfact(0.0),D1arg(0.0),D1egfet(0.0),D1gmanew(0.0);
3653  double reltol(0.0);
3654 
3655  double tnom(0.0);
3656  double VMAX(0.0);
3657 
3658 // oxide dielectric permitivity
3659 //#define EPSSIO2 3.453130e-11 == CONSTEPSOX (Xyce value)
3660 
3661 #ifdef Xyce_DEBUG_DEVICE
3662 
3663  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3664  {
3665  Xyce::dout() << subsection_divider << std::endl;
3666  Xyce::dout() << " Instance::Begin of updateTemperature. \n";
3667  Xyce::dout() <<" name = " << getName() << std::endl;
3668  Xyce::dout() << std::endl;
3669  }
3670 #endif
3671 
3672  // first set the instance temperature to the new temperature:
3673  if (temp_tmp != -999.0) temp = temp_tmp;
3675  {
3676  // make sure interpolation doesn't take any resistance negative
3681  if(model_.D1DIOresist < 0) model_.D1DIOresist = 0;
3682 
3683  // some params may have changed during interpolation
3685  }
3686 
3687  VMAX = model_.maxDriftVel;
3688  tnom = model_.tnom;
3689  ratio = temp/tnom;
3690 #ifdef Xyce_DEBUG_DEVICE
3691  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3692  {
3693  Xyce::dout() << " Temperature = "<< temp << std::endl;
3694  Xyce::dout() << " tnom = " << tnom << std::endl;
3695  Xyce::dout() << " ratio = " << ratio << std::endl;
3696  }
3697 #endif
3698 
3699  vt = temp * CONSTKoverQ;
3700  ratio = temp/tnom;
3701  fact2 = temp/CONSTREFTEMP;
3702  kt = temp * CONSTboltz;
3703  egfet = 1.16-(7.02e-4*temp*temp)/(temp+1108);
3704  arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3705  pbfact = -2*vt *(1.5*log(fact2)+CONSTQ*arg);
3706 
3707 #ifdef Xyce_DEBUG_DEVICE
3709  {
3710  Xyce::dout() << " fact1 = " << model_.fact1 << std::endl;
3711  Xyce::dout() << " vtnom = " << model_.vtnom << std::endl;
3712  Xyce::dout() << " egfet1 = " << model_.egfet1 << std::endl;
3713  Xyce::dout() << " pbfact1= " << model_.pbfact1 << std::endl;
3714  Xyce::dout() << " vt = " << vt << std::endl;
3715  Xyce::dout() << " ratio = " << ratio << std::endl;
3716  Xyce::dout() << " fact2 = " << fact2 << std::endl;
3717  Xyce::dout() << " kt = " << kt << std::endl;
3718  Xyce::dout() << " egfet = " << egfet << std::endl;
3719  Xyce::dout() << " arg = " << arg << std::endl;
3720  Xyce::dout() << " pbfact = " << pbfact << std::endl;
3721  }
3722 #endif
3723 
3724  ratio4 = ratio * sqrt(ratio);
3725  tSurfMob = 1.e-4*model_.surfaceMobility/ratio4;
3726  phio= (model_.phi-model_.pbfact1)/model_.fact1;
3727  tPhi = fact2 * phio + pbfact;
3728  tVbi = model_.vt0 - model_.dtype *
3729  (model_.gamma* sqrt(model_.phi))+.5*(model_.egfet1-egfet)
3730  + model_.dtype*.5* (tPhi-model_.phi);
3731  tVto = tVbi + model_.dtype * model_.gamma * sqrt(tPhi);
3732  if(model_.mdtemp != 0) tVto = model_.vt0 -
3733  model_.kvt*(temp-tnom);
3735  exp(-egfet/vt+model_.egfet1/model_.vtnom);
3737  exp(-egfet/vt+model_.egfet1/model_.vtnom);
3739  gmaold = (model_.bulkJctPotential-pbo)/pbo;
3740  capfact = 1/(1+model_.bulkJctBotGradingCoeff*
3741  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3742  tCbd = model_.capBD * capfact;
3743  tCbs = model_.capBS * capfact;
3744  tCj = model_.bulkCapFactor * capfact;
3745  capfact = 1/(1+model_.bulkJctSideGradingCoeff*
3746  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3747  tCjsw = model_.sideWallCapFactor * capfact;
3748  tBulkPot = fact2 * pbo+pbfact;
3749  gmanew = (tBulkPot-pbo)/pbo;
3750  capfact = (1+model_.bulkJctBotGradingCoeff *
3751  (4e-4*(temp-CONSTREFTEMP)-gmanew));
3752  tCbd *= capfact;
3753  tCbs *= capfact;
3754  tCj *= capfact;
3755  capfact = (1+model_.bulkJctSideGradingCoeff *
3756  (4e-4*(temp-CONSTREFTEMP)-gmanew));
3757  tCjsw *= capfact;
3759 
3760 #ifdef Xyce_DEBUG_DEVICE
3762  {
3763  Xyce::dout() << " ratio4 = " << ratio4 << std::endl;
3764  Xyce::dout() << " tSurfMob = " << tSurfMob << std::endl;
3765  Xyce::dout() << " phio = " << phio << std::endl;
3766  Xyce::dout() << " tPhi = " << tPhi << std::endl;
3767  Xyce::dout() << " tVbi = " << tVbi << std::endl;
3768  Xyce::dout() << " tVto = " << tVto << std::endl;
3769  Xyce::dout() << " tSatCur = " << tSatCur << std::endl;
3770  Xyce::dout() << " tSatCurDens = " << tSatCurDens << std::endl;
3771  Xyce::dout() << " pbo = " << pbo << std::endl;
3772  Xyce::dout() << " gmaold = " << gmaold << std::endl;
3773  Xyce::dout() << " tBulkPot = " << tBulkPot << std::endl;
3774  Xyce::dout() << " gmanew = " << gmanew << std::endl;
3775  Xyce::dout() << " capfact = " << capfact << std::endl;
3776  Xyce::dout() << " tCbd = " << tCbd << std::endl;
3777  Xyce::dout() << " tCbs = " << tCbs << std::endl;
3778  Xyce::dout() << " tCj = " << tCj << std::endl;
3779  Xyce::dout() << " capfact = " << capfact << std::endl;
3780  Xyce::dout() << " tCjsw = " << tCjsw << std::endl;
3781  Xyce::dout() << " tDepCap = " << tDepCap << std::endl;
3782  }
3783 #endif
3784 
3785  if( (model_.jctSatCurDensity == 0) || (drainArea == 0) ||
3786  (sourceArea == 0) )
3787  {
3789  vt*log(vt/(CONSTroot2*model_.jctSatCur));
3790  }
3791  else
3792  {
3793  drainVcrit = vt * log( vt / (CONSTroot2 *
3795  sourceVcrit = vt * log( vt / (CONSTroot2 *
3797  }
3798  if(model_.capBDGiven)
3799  {
3800  czbd = tCbd;
3801  }
3802  else
3803  {
3805  {
3806  czbd=tCj*drainArea;
3807  }
3808  else
3809  {
3810  czbd=0;
3811  }
3812  }
3814  {
3815  czbdsw= tCjsw * drainPerimeter;
3816  }
3817  else
3818  {
3819  czbdsw=0;
3820  }
3821  arg = 1-model_.fwdCapDepCoeff;
3822  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3823  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3824  Cbd = czbd;
3825  Cbdsw = czbdsw;
3826  f2d = czbd*(1-model_.fwdCapDepCoeff*
3827  (1+model_.bulkJctBotGradingCoeff))* sarg/arg
3828  + czbdsw*(1-model_.fwdCapDepCoeff*
3829  (1+model_.bulkJctSideGradingCoeff))*sargsw/arg;
3830  f3d = czbd * model_.bulkJctBotGradingCoeff * sarg/arg/tBulkPot
3831  + czbdsw * model_.bulkJctSideGradingCoeff *
3832  sargsw/arg/tBulkPot;
3833  f4d = czbd*tBulkPot*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff) +
3834  czbdsw*tBulkPot*(1-arg*sargsw)/
3836  f3d/2*(tDepCap*tDepCap) - tDepCap * f2d;
3837  if(model_.capBSGiven)
3838  {
3839  czbs=tCbs;
3840  }
3841  else
3842  {
3844  {
3845  czbs=tCj*sourceArea;
3846  }
3847  else
3848  {
3849  czbs=0;
3850  }
3851  }
3853  {
3854  czbssw = tCjsw * sourcePerimeter;
3855  }
3856  else
3857  {
3858  czbssw=0;
3859  }
3860  arg = 1-model_.fwdCapDepCoeff;
3861  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3862  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3863  Cbs = czbs;
3864  Cbssw = czbssw;
3865  f2s = czbs*(1-model_.fwdCapDepCoeff*
3866  (1+model_.bulkJctBotGradingCoeff))*sarg/arg +
3867  czbssw*(1-model_.fwdCapDepCoeff*
3868  (1+model_.bulkJctSideGradingCoeff))*sargsw/arg;
3869  f3s = czbs * model_.bulkJctBotGradingCoeff * sarg/arg/tBulkPot
3870  + czbssw * model_.bulkJctSideGradingCoeff *
3871  sargsw/arg /tBulkPot;
3872  f4s = czbs*tBulkPot*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff)
3873  + czbssw*tBulkPot*(1-arg*sargsw)/
3875  (tDepCap*tDepCap) - tDepCap * f2s;
3876 
3878 
3879  if(!model_.vpGiven)
3880  {
3881  vp = VMAX*(l-2*model_.latDiff)/tSurfMob;
3882  if(model_.dtype == CONSTNMOS) vp *= 2.0;
3883  } else
3884  vp = model_.vp;
3885 
3886  gchi0 = CONSTQ*w/(l-2*model_.latDiff);
3887  gammas =
3889  model_.wgammas*(1-model_.w0/w);
3890  gammal =
3892  model_.wgammal*(1-model_.w0/w);
3893  if(gammal != 0.0) {
3894  vthLimit = gammas/(2*gammal);
3896  } else
3897  vthLimit = N_UTL_MachineDependentParams::DoubleMax();
3898  vtoo = tVto*model_.dtype+ gammal*tPhi- gammas*sqrt(tPhi);
3899 
3900  // quantities related to diode #1
3901 
3902  D1DIOtemp = temp;
3903  model_.D1DIOnomTemp = tnom;
3904  D1vt_loc = CONSTKoverQ * D1DIOtemp;
3905  D1xfc = log(1-model_.D1DIOdepletionCapCoeff);
3906 
3907 // this part gets really ugly - I don't know how to explain these equations
3908 
3909  D1fact2 = D1DIOtemp/CONSTREFTEMP;
3910  D1egfet = 1.16-(7.02e-4*D1DIOtemp*D1DIOtemp)/(D1DIOtemp+1108);
3911  D1arg = -D1egfet/(2*CONSTboltz*D1DIOtemp) + 1.1150877/
3912  (CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3913  D1pbfact = -2*D1vt_loc*(1.5*log(D1fact2)+CONSTQ*D1arg);
3914  D1egfet1 = 1.16 - (7.02e-4*model_.D1DIOnomTemp*
3916  D1arg1 = -D1egfet1/(CONSTboltz*2*model_.D1DIOnomTemp) +
3917  1.1150877/(2*CONSTboltz*CONSTREFTEMP);
3918  D1fact1 = model_.D1DIOnomTemp/CONSTREFTEMP;
3919  D1pbfact1 = -2*CONSTKoverQ*model_.D1DIOnomTemp*
3920  (1.5*log(D1fact1)+CONSTQ*D1arg1);
3921  D1pbo = (model_.D1DIOjunctionPot-D1pbfact1)/D1fact1;
3922  D1gmaold = (model_.D1DIOjunctionPot -D1pbo)/D1pbo;
3925  (400e-6*(model_.D1DIOnomTemp-CONSTREFTEMP)-D1gmaold) );
3926  D1DIOtJctPot = D1pbfact+D1fact2*D1pbo;
3927  D1gmanew = (D1DIOtJctPot-D1pbo)/D1pbo;
3929  (400e-6*(D1DIOtemp-CONSTREFTEMP)-D1gmanew);
3930  D1DIOtSatCur = model_.D1DIOsatCur*exp( ((D1DIOtemp/
3931  model_.D1DIOnomTemp)-1)*
3933  (model_.D1DIOemissionCoeff*D1vt_loc)+
3936  log(D1DIOtemp/model_.D1DIOnomTemp) );
3938 
3939  // the defintion of f1, just recompute after temperature adjusting
3940  // all the variables used in it
3941  D1DIOtF1=D1DIOtJctPot*(1-exp((1-model_.D1DIOgradingCoeff)*D1xfc))/
3943 
3944  // same for Depletion Capacitance
3946 
3947  // and Vcrit
3948  D1vte_loc=model_.D1DIOemissionCoeff*D1vt_loc;
3949  D1DIOtVcrit=D1vte_loc*log(D1vte_loc/(CONSTroot2*D1DIOtSatCur));
3950 
3951  // and now to copute the breakdown voltage, again using
3952  // temperature adjusted basic parameters
3954  {
3956  if (D1cbv < D1DIOtSatCur*model_.D1DIObreakdownVoltage/D1vt_loc)
3957  {
3958  D1cbv=D1DIOtSatCur*model_.D1DIObreakdownVoltage/D1vt_loc;
3959  Xyce::dout() << " breakdown current increased to " << D1cbv <<
3960  "to resolve incompatability " <<
3961  "with specified saturation current" << std::endl;
3963  } else
3964  {
3965  reltol = 1e-3;
3966  D1tol=reltol*D1cbv;
3968  D1vt_loc*log(1+D1cbv/D1DIOtSatCur);
3969  for(D1iter=0; D1iter<25; ++D1iter)
3970  {
3971  D1xbv=model_.D1DIObreakdownVoltage-D1vt_loc*log(D1cbv/
3972  D1DIOtSatCur+1-D1xbv/D1vt_loc);
3973  D1xcbv=D1DIOtSatCur*(exp((model_.D1DIObreakdownVoltage
3974  -D1xbv)/D1vt_loc)-1+D1xbv/D1vt_loc);
3975  if (fabs(D1xcbv-D1cbv) <= D1tol) goto matched;
3976  }
3977  Xyce::dout() << " unable to match forward and reverse diode regions: D1bv = "
3978  << D1xbv << " D1ibv = " << D1xcbv << std::endl;
3979  }
3980  matched:
3981  D1DIOtBrkdwnV = D1xbv;
3982  }
3983 
3984  return bsuccess;
3985 }
3986 
3987 //-----------------------------------------------------------------------------
3988 // Function : Instance::updatePrimaryState
3989 // Purpose :
3990 // Special Notes :
3991 // Scope : public
3992 // Creator : Tom Russo, Component Information and Models
3993 // Creation Date : 02/28/01
3994 //-----------------------------------------------------------------------------
3996 {
3997  bool bsuccess = true;
3998  double vgs1(0.0), vgdd1(0.0), vbs1(0.0),vgb1(0.0), vdds1(0.0);
3999  double * staVector = extData.nextStaVectorRawPtr;
4000  double * currStaVector = extData.currStaVectorRawPtr;
4001 
4002  bool tmpBool = updateIntermediateVars ();
4003  bsuccess = bsuccess && tmpBool;
4004 
4005  // voltage drops:
4006  staVector[li_state_vbdd] = vbdd;
4007  staVector[li_state_vbs] = vbs;
4008  staVector[li_state_vgps] = vgps;
4009  staVector[li_state_vdds] = vdds;
4010  staVector[li_state_D1vd] = D1vd;
4011 
4012  // now the meyer capacitances
4013  // we didn't calculate these charges in update IntermediateVars
4014  // but we did calculate the voltage drops and capacitances.
4015  // first store the capacitances themselves:
4016  staVector[li_state_capgs] = capgs;
4017  staVector[li_state_capgdd] = capgdd;
4018  staVector[li_state_capgb] = capgb;
4019 
4020  // now the charges
4021  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
4022  // supposed to be *INTEGRATED*:
4023  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
4024  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
4025  // Now with Meyer back averaging, Capxx is the average between the last
4026  // time step and this one. So we gotta do the right thing for non-DCOP
4027  // when backaverage is on.
4028 
4029  if((getSolverState().dcopFlag))
4030  {
4031  qgs = Capgs *vgps;
4032  qgdd = Capgdd*vgpdd;
4033  qgb = Capgb *Vgpb;
4034  }
4035  else
4036  {
4037  // get the ones from last time step
4038  qgs = currStaVector[li_state_qgs];
4039  qgdd = currStaVector[li_state_qgdd];
4040  qgb = currStaVector[li_state_qgb];
4041  // get the voltage drops, too
4042  vgs1 = currStaVector[li_state_vgps];
4043  vbs1 = currStaVector[li_state_vbs];
4044  vdds1 = currStaVector[li_state_vdds];
4045 
4046  vgb1 = vgs1-vbs1;
4047  vgdd1 = vgs1-vdds1;
4048 
4049  // NOW we can calculate the charge update
4050  qgs += Capgs*(vgps-vgs1);
4051  qgdd += Capgdd*(vgpdd-vgdd1);
4052  qgb += Capgb*((vgps-vbs)-vgb1);
4053  }
4054 
4055  staVector[li_state_qgs] = qgs;
4056  staVector[li_state_qgdd] = qgdd;
4057  staVector[li_state_qgb] = qgb;
4058 
4059  // and the diode parasitic capacitors
4060  // these charges were set in updateIntermediateVars
4061  staVector[li_state_qbd] = qbd;
4062  staVector[li_state_qbs] = qbs;
4063 
4064 // diode #1 quatntities
4065 
4067 
4068  // In the case of a charge, need to handle this:
4069  // Ensure dQ/dt = 0 for initial step after dcOP by setting the history equal
4070  // to the current value
4071  if( !getSolverState().dcopFlag && getSolverState().initTranFlag && !getSolverState().newtonIter )
4072  {
4073  currStaVector[li_state_D1DIOcapCharge] = D1DIOcapCharge;
4074  }
4075 
4076  staVector[ li_state_von ] = von;
4077 
4078  return bsuccess;
4079 }
4080 
4081 //-----------------------------------------------------------------------------
4082 // Function : Instance::updateSecondaryState
4083 // Purpose :
4084 // Special Notes :
4085 // Scope : public
4086 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
4087 // Creation Date : 01/09/01
4088 //-----------------------------------------------------------------------------
4090 {
4091  double * staDerivVector = (extData.nextStaDerivVectorRawPtr);
4092 
4093  cqgs = staDerivVector[li_state_qgs];
4094  cqgdd = staDerivVector[li_state_qgdd];
4095  cqgb = staDerivVector[li_state_qgb];
4096  cqbd = staDerivVector[li_state_qbd];
4097  cqbs = staDerivVector[li_state_qbs];
4098 
4099  D1DIOcapCurrent = staDerivVector[li_state_D1DIOcapCharge];
4100 
4101  double Dtype =model_.dtype;
4102  double D1current = Dtype*(D1cdeq + D1DIOcapCurrent);
4103 
4104  // Even though these do not look exactly like the RHS loads, they do account
4105  // for the currents into the leads even with the lead resistors in place
4106  // --- since the lead resistances are the only thing between the primed node
4107  // and the lead, the currents are still correct AT CONVERGED SOLUTIONS
4108 
4109  /*
4110  lead current load has been moved to F & Q loads
4111  LeadCurrentD = -model_.dtype*(-mode*cdrain+cbd+cqgdd+cqbd) - D1current-Irdsshunt;
4112  LeadCurrentG = model_.dtype*(cqgs+cqgb+cqgdd);
4113  LeadCurrentS = model_.dtype*(-mode*cdrain+cbs-cqgs-cqbs) + D1current+Irdsshunt;
4114  LeadCurrentB = model_.dtype*(cbd-cbs-cqgb+cqbd+cqbs);
4115  */
4116 
4117  return true;
4118 }
4119 
4120 
4121 //-----------------------------------------------------------------------------
4122 // Function : Instance::processParams
4123 // Purpose :
4124 // Special Notes :
4125 // Scope : public
4126 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
4127 // Creation Date : 6/03/02
4128 //-----------------------------------------------------------------------------
4130 {
4131 
4132 #ifdef Xyce_DEBUG_DEVICE
4133  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
4134  {
4135  Xyce::dout() << " L = " << l << std::endl;
4136  Xyce::dout() << " W = " << w<< std::endl;
4137  Xyce::dout() << " drainArea = " << drainArea<< std::endl;
4138  Xyce::dout() << " sourceArea = " << sourceArea<< std::endl;
4139  Xyce::dout() << " drainSquares = " << drainSquares<< std::endl;
4140  Xyce::dout() << " sourceSquares = " << sourceSquares<< std::endl;
4141  Xyce::dout() << " drainPerimeter = " << drainPerimeter<< std::endl;
4142  Xyce::dout() << " sourcePerimeter = " << sourcePerimeter<< std::endl;
4143  Xyce::dout() << " drainCond = " << drainCond<< std::endl;
4144  Xyce::dout() << " sourceCond = " << sourceCond << std::endl;
4145  Xyce::dout() << " draindriftCond = " << draindriftCond<< std::endl;
4146  Xyce::dout() << " temp = " << temp<< std::endl;
4147  }
4148 #endif
4149 
4150  // now set the temperature related stuff
4152 
4153  return true;
4154 }
4155 
4156 // Additional Declarations
4157 
4158 
4159 //-----------------------------------------------------------------------------
4160 // Function : Instance::UCCMqmeyer
4161 // Purpose : Compute the MOS overlap capacitances as functions of the
4162 // device terminal voltages
4163 //
4164 // Special Notes :
4165 //
4166 // Scope : public
4167 // Creator : pmc
4168 // Creation Date : 02/17/2004
4169 //-----------------------------------------------------------------------------
4171  double xvgs, // initial voltage gate-source (mode > 0)
4172  double xvgdd, // initial voltage gate-drain (mode > 0)
4173  double vgb, // initial voltage gate-bulk
4174  double von_local, // threshold voltage
4175  double vddsat_local, // saturation drain voltage
4176  double & capgs_local, // non-constant portion of g-s overlap capacitance
4177  double & capgdd_local,// non-constant portion of g-d overlap capacitance
4178  double & capgb_local, // non-constant portion of g-b overlap capacitance
4179  double phi,
4180  double cox // oxide capactiance
4181  )
4182 {
4183  double vdds_local(0.0);
4184  double vddif(0.0);
4185  double vddif1(0.0);
4186  double vddif2(0.0);
4187  double vgst(0.0);
4188  double etavt(0.0);
4189  double cgc(0.0);
4190  double x(0.0);
4191 
4192 #define W w
4193 #define L EffectiveLength
4194 #define ETA model_.eta
4195 #define TOX model_.oxideThickness
4196 
4197  vgst = xvgs-von_local;
4198  if (vgst <= -phi)
4199  {
4200  capgb_local = cox/2;
4201  capgs_local = 0;
4202  capgdd_local = 0;
4203  }
4204  else if (vgst <= -phi/2)
4205  {
4206  capgb_local = -vgst*cox/(2*phi);
4207  capgs_local = 0;
4208  capgdd_local = 0;
4209  }
4210  else if (vgst <= 0)
4211  {
4212  capgb_local = -vgst*cox/(2*phi);
4213  capgs_local = vgst*cox/(1.5*phi)+cox/3;
4214  capgdd_local = 0;
4215  }
4216  else
4217  {
4218  vdds_local = xvgs-xvgdd;
4219  capgb_local = 0;
4220  if (vddsat_local <= vdds_local)
4221  {
4222  capgs_local = cox/3;
4223  capgdd_local = 0;
4224  }
4225  else
4226  {
4227  vddif = 2.0*vddsat_local-vdds_local;
4228  vddif1 = vddsat_local-vdds_local/*-1.0e-12*/;
4229  vddif2 = vddif*vddif;
4230  capgdd_local = cox*(1.0-vddsat_local*vddsat_local/vddif2)/3;
4231  capgs_local = cox*(1.0-vddif1*vddif1/vddif2)/3;
4232  }
4233  }
4234 
4235  // at this point we have unmodified Xyce values
4236  // the following is the UCCM adjustment
4237 
4238  if(model_.cv == 2 && vddsat_local != 0)
4239  {
4240  vdds_local = fabs(xvgs-xvgdd);
4241  vdds_local = vdds_local/pow(1+pow(vdds_local/vddsat_local,model_.mc),
4242  1.0/model_.mc);
4243  vddif = 2.0*vddsat_local-vdds_local;
4244  vddif1 = vddsat_local-vdds_local;
4245  vddif2 = vddif*vddif;
4246  etavt = ETA*vt;
4247  x = vgst/etavt;
4248  cgc = L*W/(TOX/CONSTEPSSI+etavt/(CONSTQ*n0)*exp(-x));
4249  capgdd_local = cgc*(1.0-vddsat_local*vddsat_local/vddif2)/3;
4250  capgs_local = cgc*(1.0-vddif1*vddif1/vddif2)/3;
4251  }
4252 
4253  return true;
4254 }
4255 
4256 //-----------------------------------------------------------------------------
4257 // Function : Instance::UCCMMeyercap
4258 // Purpose :
4259 //
4260 //
4261 // Special Notes :
4262 //
4263 // Scope : public
4264 // Creator : pmc
4265 // Creation Date : 02/17/2004
4266 //-----------------------------------------------------------------------------
4268  double xvgs, // initial voltage gate-source (mode > 0)
4269  double xvgdd, // initial voltage gate-drain (mode > 0)
4270  double vgb, // initial voltage gate-bulk
4271  double & cgs,
4272  double & cgd,
4273  double & cgb
4274  )
4275 {
4276  double vbs_local(0.0);
4277  double vdds_local(0.0);
4278  double zetanb(0.0);
4279  double xi(0.0);
4280  double xisqrt(0.0);
4281  double nsd(0.0);
4282  double nss(0.0);
4283  double tnss(0.0);
4284  double tnsd(0.0);
4285  double DeltaVT(0.0);
4286  double DnsdVgs(0.0);
4287  double DnsdVgd(0.0);
4288  double DnsdVgb(0.0);
4289  double DnssVgs(0.0);
4290  double DnssVgd(0.0);
4291  double DnssVgb(0.0);
4292  double DndepVgs(0.0);
4293  double DndepVgd(0.0);
4294  double DndepVgb(0.0);
4295  double UI(0.0);
4296  double VI(0.0);
4297  double DxiVgs(0.0);
4298  double DxiVgd(0.0);
4299  double DxiVgb(0.0);
4300  double DUIVgs(0.0);
4301  double DUIVgd(0.0);
4302  double DUIVgb(0.0);
4303  double DVIVgs(0.0);
4304  double DVIVgd(0.0);
4305  double DVIVgb(0.0); // With use of the chain rule, this routine may
4306  double DqiVgs(0.0); // be used to calculate the Ward capacitors.
4307  double DqiVgd(0.0); //
4308  double DqiVgb(0.0); // Cs, gs=dqs/dVgs= DqiVgs*fp+qiVgs*dfp
4309  double DqbVgs(0.0); // fp: partitioning factor
4310  double DqbVgd(0.0);
4311  double DqbVgb(0.0);
4312  double DqgVgs(0.0);
4313  double DqgVgd(0.0);
4314  double DqgVgb(0.0);
4315  double SigmaVgs(0.0); // This Sigma-parameter acounts for the DIBL
4316  double SigmaVgd(0.0); // effect on the capasitors. The physical
4317  double etavt(0.0);
4318  double VFB(0.0);
4319  double mqWL(0.0);
4320  double gamma(0.0);
4321  double A(0.0);
4322  double ALPHA(0.0);
4323 
4324  vbs_local = xvgs-vgb;
4325  vdds_local = xvgs-xvgdd;
4327  VFB =model_.vfb;
4328  ALPHA =model_.alpha;
4329 
4330  if(xvgs > VFB+vbs_local)
4331  {
4332  gamma= model_.gammas0;
4333  mqWL=(-CONSTQ)*EffectiveLength*(w);
4334  etavt=model_.eta*vt;
4335  nss=2.0*n0*log(1+0.5*exp((xvgs-von)/etavt));
4336  nsd=2.0*n0*log(1+0.5*exp((xvgs-von-ALPHA*vdds_local)/etavt));
4337 
4338  if (nss<1e-36) {nss=1.0e-36;}
4339  if (nsd<1e-36) {nsd=1.0e-36;}
4340  zetanb = (1-ALPHA)/ALPHA;
4341  xi = gamma*gamma/(A*A)+4/(A*A)*(vgb-VFB)-4.0/A*nss;
4342  xisqrt=sqrt(xi);
4343  tnsd = etavt/nsd+A;
4344  tnss = etavt/nss+A;
4345  if (vbs_local <= 0) { DeltaVT= 0.5*gamma/sqrt(tPhi-vbs_local); }
4346  if ((vbs_local > 0)&&(vbs_local <= 2*tPhi)) { DeltaVT=0.5*gamma/sqrt(tPhi); }
4347  if ((vbs_local > 0)&&(vbs_local > 2*tPhi)) { DeltaVT=0; }
4348 
4349  DnsdVgs=(1+DeltaVT-ALPHA+SigmaVgs)/tnsd;
4350  DnsdVgd=(-SigmaVgd+ALPHA)/tnsd;
4351  DnsdVgb=-DeltaVT/tnsd;
4352 
4353  DnssVgs= (1+DeltaVT+SigmaVgs)/tnss;
4354  DnssVgd=-SigmaVgd/tnss;
4355  DnssVgb=-DeltaVT/tnss;
4356 
4357  UI= etavt/2.0*(nsd*nsd-nss*nss) + A/3.0*(nsd*nsd*nsd-nss*nss*nss);
4358  VI= etavt*(nsd-nss) + A/2.0*(nsd*nsd-nss*nss);
4359  DUIVgs = etavt*(nsd*DnsdVgs-nss*DnssVgs) +
4360  A*(nsd*nsd*DnsdVgs-nss*nss*DnssVgs);
4361  DUIVgd= etavt*(nsd*DnsdVgd-nss*DnssVgd) +
4362  A*(nsd*nsd*DnsdVgd-nss*nss*DnssVgd);
4363  DUIVgb= etavt*(nsd*DnsdVgb-nss*DnssVgb) +
4364  A*(nsd*nsd*DnsdVgb-nss*nss*DnssVgb);
4365 
4366  DVIVgs= etavt*(DnsdVgs-DnssVgs) + A*(nsd*DnsdVgs-nss*DnssVgs);
4367  DVIVgd= etavt*(DnsdVgd-DnssVgd) + A*(nsd*DnsdVgd-nss*DnssVgd);
4368  DVIVgb= etavt*(DnsdVgb-DnssVgb) + A*(nsd*DnsdVgb-nss*DnssVgb);
4369  if (VI != 0)
4370  {
4371  DqiVgs= mqWL*(DUIVgs*VI-DVIVgs*UI)/(VI*VI);
4372  DqiVgd= mqWL*(DUIVgd*VI-DVIVgd*UI)/(VI*VI);
4373  DqiVgb= mqWL*(DUIVgb*VI-DVIVgb*UI)/(VI*VI);
4374  }
4375  else
4376  {
4377  DqiVgs=mqWL*DnssVgs;
4378  DqiVgd=mqWL*DnssVgd;
4379  DqiVgb=mqWL*DnssVgb;
4380  }
4381 
4382  DxiVgs= -4.0/A*DnssVgs;
4383  DxiVgd= -4.0/A*DnssVgd;
4384  DxiVgb= 4.0/(A*A)-4/A*DnssVgb;
4385 
4386  if (xisqrt !=0)
4387  {DndepVgs= gamma/4.0*1.0/xisqrt*DxiVgs;
4388  DndepVgd= gamma/4.0*1.0/xisqrt*DxiVgd;
4389  DndepVgb= gamma/4.0*1.0/xisqrt*DxiVgb;
4390  }
4391  else
4392  {
4393  DndepVgs=0;
4394  DndepVgd=0;
4395  DndepVgb=0;
4396  }
4397 
4398  DqbVgs = mqWL*(DndepVgs-zetanb*DnssVgs)+zetanb*DqiVgs;
4399  DqbVgd = mqWL*(DndepVgd-zetanb*DnssVgd)+zetanb*DqiVgd;
4400  DqbVgb = mqWL*(DndepVgb-zetanb*DnssVgb)+zetanb*DqiVgb;
4401 
4402  DqgVgs= -DqiVgs-DqbVgs;
4403  DqgVgd= -DqiVgd-DqbVgd;
4404  DqgVgb= -DqiVgb-DqbVgb;
4405  }
4406  else
4407  {
4408  // Below flat band
4409  DqgVgs=0.0;
4410  DqgVgd=0.0;
4412  }
4413 
4414  if (DqgVgs<0) {DqgVgs=0;} // Because of truncation error cgb may turn
4415  if (DqgVgd<0) {DqgVgd=0;} // negative in extreme inversion, while cgd
4416  if (DqgVgb<0) {DqgVgb=0;} // and cgs may turn negative in accumulation
4417  cgs= 0.5*DqgVgs;
4418  cgd= 0.5*DqgVgd;
4419  cgb= 0.5*DqgVgb;
4420 
4421  return true;
4422 }
4423 
4424 //----------------------------------------------------------------------------
4425 // Function : Instance::UCCMCharges
4426 // Purpose :
4427 //
4428 //
4429 // Special Notes :
4430 //
4431 // Scope : public
4432 // Creator : pmc
4433 // Creation Date : 02/17/2004
4434 //----------------------------------------------------------------------------
4435 bool Instance::UCCMCharges( double vgs, double vgdd,
4436  double vgb, double & qD, double & qS, double & qB)
4437 {
4438  double VT(0.0); // Threshold voltage
4439  double nss(0.0); // Inversion charge density at source
4440  double nsd(0.0); // Inversion charge density at drain
4441  double etavth(0.0);
4442  double mqWL(0.0);
4443  double nsdsqr(0.0);
4444  double nsssqr(0.0);
4445  double arg1(0.0);
4446  double arg2(0.0);
4447  double qn(0.0); // Inversion charge
4448  double VFB(0.0); // Flat-band voltage
4449  double xisqrt(0.0);
4450  double ndeps(0.0); // Depletion charge density
4451  double zetanb(0.0);
4452  double fp1(0.0); // Partitioning factor
4453  double gamma(0.0);
4454  double ALPHA(0.0);
4455  double A(0.0);
4456  double cox(0.0); // oxide capasity per unit area
4457  double vdds_local(0.0);
4458 
4459  cox = model_.oxideCapFactor;
4460  gamma = model_.gammas0;
4461  A = CONSTQ/cox;
4462  ETA = model_.eta;
4463  ALPHA = model_.alpha;
4464  VFB = model_.vfb;
4465 
4466  vdds_local=vgs-vgdd;
4467 
4468  if (vgb > VFB)
4469  {
4470  VT = von;
4471  etavth = ETA*temp*CONSTKoverQ;
4472 
4473  nsd=2*n0*log(1+0.5*exp((vgs-VT-ALPHA*vdds_local)/etavth));
4474  nss=2*n0*log(1+0.5*exp((vgs-VT)/etavth));
4475 
4476  nsdsqr=nsd*nsd;
4477  nsssqr=nss*nss;
4478  mqWL=-CONSTQ*EffectiveLength*(w);
4479 
4480  arg1= 0.5*etavth*(nsdsqr-nsssqr)+1/3.0*A*(nsdsqr*nsd-nsssqr*nss);
4481  arg2= etavth*(nsd-nss) +0.5*A*(nsdsqr-nsssqr);
4482 
4483  if (arg2==0) //||(fabs(nss-nsd)<1e-12))
4484  { qn=mqWL*nss;}
4485  else {qn = mqWL*arg1/arg2;}
4486  xisqrt= sqrt(gamma*gamma/(A*A)+4.0/(A*A)*(vgb-VFB)-4.0/A*nss);
4487  ndeps = -gamma*gamma/(2.0*A)+ gamma/2.0*xisqrt;
4488  zetanb =(1-ALPHA)/ALPHA;
4489  mqWL=-CONSTQ*EffectiveLength*(w);
4490  qB =mqWL*(ndeps-zetanb*nss)+zetanb*qn;
4491 
4492  switch(model_.fpe)
4493  {
4494  case 1:
4495  fp1=model_.xqc;
4496  break;
4497 
4498  case 2:
4499  {
4500  double vsat(0.0);
4501  double beta(0.0);
4502  double a0(0.0);
4503  double vdsabs(0.0);
4504  double m(0.0);
4505  double fp1denum(0.0);
4506 
4507  vdsabs=fabs(vdds_local);
4508  vsat=vddsat;
4509  if (vgs-VT > 1e-36)
4510  {
4511  if((vsat > 1e-36)&&(vdds_local>1e-36))
4512  { beta=vdsabs/vsat;}else{beta=1e-36;}
4513  m = model_.mcv;
4514  a0 = (model_.xqc - 0.5)/vsat;
4515  fp1denum = exp(1/m*log(1+exp(m*log(beta))));
4516  if (fp1denum > 1e-36)
4517  {fp1= 0.5+ a0*vdsabs/fp1denum;}
4518  else {fp1=0.5;}
4519 
4520  } else {fp1=0.5;}
4521  }
4522  break;
4523  case 3:
4524  {
4525  double nd0(0.0);
4526  double ns0(0.0);
4527  double arg1_loc(0.0);
4528  double arg2_loc(0.0);
4529  double arg3_loc(0.0);
4530 
4531  nd0=nss/(A*etavth);
4532  ns0=nss/(A*etavth);
4533  arg1_loc= nd0*nd0*nd0*(1/3.0+nd0*(3.0/8.0+1/10.0*nd0))
4534  - (1.0/2.0+1.0/3.0*nd0)*(1.0+1/2.0*ns0)*nd0*nd0*ns0
4535  + ns0*ns0*ns0*(1.0/6.0+ns0*(5.0/24.0+1.0/15.0*ns0));
4536  arg2_loc = 1.0/2.0*(nd0*nd0-ns0*ns0)+1.0/3.0*(nd0*nd0*nd0-ns0*ns0*ns0);
4537  arg3_loc = nd0-ns0+1.0/2.0*(nd0*nd0-ns0*ns0);
4538  if ((arg2_loc==0)||(arg3_loc==0)) {fp1=0.5;}
4539  else { fp1 = 1-arg1_loc/(arg2_loc*arg3_loc);}
4540  }
4541  break;
4542  default:
4543  {
4544  UserWarning(*this) << "Partitioning model does not exist";
4545  return true;
4546  }
4547  }
4548  }
4549  else
4550  { // Below flatband
4551  qB = -EffectiveLength*(w)*cox*(vgb-VFB);
4552  qn = 0;
4553  }
4554 
4555  qS = -fp1*qn;
4556  qD = -(1-fp1)*qn;
4557  qB = -qB;
4558 
4559  return true;
4560 }
4561 
4562 //----------------------------------------------------------------------------
4563 // Function : Instance::UCCMcvon
4564 // Purpose : Compute the threshold voltage
4565 //
4566 // Special Notes : ERK. The "local" named variables (von_local, dvonvbs_local)
4567 // are named that way to avoid conflicts with the instance
4568 // variables of the same name.
4569 //
4570 // Scope : public
4571 // Creator : pmc
4572 // Creation Date : 02/17/2004
4573 //----------------------------------------------------------------------------
4574 bool Instance::UCCMcvon(double vbs_local,
4575  double & von_local, double & dvonvbs_local)
4576 {
4577  double PhiMinVbs = tPhi - vbs_local;
4578  double sarg(0.0);
4579  double dsrgdb(0.0);
4580 
4581 // vtoo, vthLimit calculated in updateTemp
4582 
4583  if(vtoo-vbs_local > vthLimit) {
4584  von_local = vtoo + gammal*vthLimit;
4585  dvonvbs_local = 0.0;
4586  return true;
4587  }
4588  if(PhiMinVbs > 0.0)
4589  {
4590  sarg = sqrt(PhiMinVbs);
4591  dsrgdb = -0.5/sarg;
4592  } else
4593  {
4594  sarg = 0;
4595  dsrgdb = 0;
4596  }
4597  von_local = vtoo + gammas*sarg - gammal*PhiMinVbs;
4598  dvonvbs_local = gammas*dsrgdb + gammal;
4599 
4600  return true;
4601 }
4602 
4603 //-----------------------------------------------------------------------------
4604 // Function : Instance::UCCMmosa1
4605 // Purpose : Compute currents and conductances in drain region
4606 //
4607 //
4608 // Special Notes :
4609 //
4610 // Scope : public
4611 // Creator : pmc
4612 // Creation Date : 02/17/2004
4613 //-----------------------------------------------------------------------------
4614 
4615 bool Instance::UCCMmosa1(double xvgs, double xvdds,
4616  double dvonvbs, double & cdraindrift_loc, double & vsate)
4617 {
4618  double etavt(0.0);
4619  double vgt(0.0);
4620  double vgt0(0.0);
4621  double sigma(0.0);
4622  double vgte(0.0);
4623  double isat(0.0);
4624  double mu(0.0);
4625  double ns(0.0);
4626  double a(0.0);
4627  double b(0.0);
4628  double d(0.0);
4629  double g(0.0);
4630  double h(0.0);
4631  double q(0.0);
4632  double r(0.0);
4633  double t(0.0);
4634  double u(0.0);
4635  double x(0.0),y(0.0),z(0.0);
4636 
4637  double gch(0.0);
4638  double gchi(0.0);
4639  double rt(0.0);
4640  double vl(0.0);
4641  double vl2(0.0);
4642  double ichoo(0.0);
4643 
4644  double dichoodvds(0.0);
4645  double dichoodvgs(0.0);
4646  double dichoodvbs(0.0);
4647  double dichooisat(0.0);
4648  double dichoodgch(0.0);
4649  double delgchgchi(0.0);
4650  double disatdvds(0.0);
4651  double disatdvgs(0.0);
4652  double disatdvbs(0.0);
4653  double dgchidvds(0.0);
4654  double dgchidvgs(0.0);
4655  double dgchidvbs(0.0);
4656  double disatvgte(0.0);
4657  double disatgchi(0.0);
4658  double dvgtedvgt(0.0);
4659  double dvgtdvds(0.0);
4660  double dvgtdvgs(0.0);
4661  double dvgtdvbs(0.0);
4662  double dnsdvgt(0.0);
4663  double dnsdvds(0.0);
4664  double dnsdvgs(0.0);
4665  double dnsdvbs(0.0);
4666  double dmudvgte(0.0);
4667  double dmudvds(0.0);
4668  double dmudvgs(0.0);
4669  double dmudvbs(0.0);
4670 
4671  static int output=0;
4672 
4673 #define ETA model_.eta
4674 #define RS model_.sourceResistance
4675 #define RD model_.drainResistance
4676 #define VSIGMAT model_.vsigmat
4677 #define VSIGMA model_.vsigma
4678 #define SIGMA0 model_.sigma0
4679 #define THETA model_.theta
4680 #define LAMBDA model_.lambda
4681 #define DELTA model_.delta
4682 #define VMAX model_.maxDriftVel
4683 #define TOX model_.oxideThickness
4684 
4685 #define EXP_MAX 150.0
4686 
4687  if(output == 1) {
4688  Xyce::dout() << " " << std::endl;
4689  Xyce::dout() << "ETA = " << ETA << std::endl;
4690  Xyce::dout() << "RS = " << RS << std::endl;
4691  Xyce::dout() << "RD = " << RD << std::endl;
4692  Xyce::dout() << "VSIGMAT = " << VSIGMAT << std::endl;
4693  Xyce::dout() << "VSIGMA = " << VSIGMA << std::endl;
4694  Xyce::dout() << "SIGMA0 = " << SIGMA0 << std::endl;
4695  Xyce::dout() << "THETA = " << THETA << std::endl;
4696  Xyce::dout() << "LAMBDA = " << LAMBDA << std::endl;
4697  Xyce::dout() << "DELTA = " << DELTA << std::endl;
4698  Xyce::dout() << "VMAX = " << VMAX << std::endl;
4699  Xyce::dout() << "TOX = " << TOX << std::endl;
4700  output=0;
4701  }
4702 
4703  etavt = ETA*vt;
4704  rt = RS+RD;
4705  vgt0 = xvgs - von;
4706  a = exp((vgt0-VSIGMAT)/VSIGMA);
4707  sigma = SIGMA0/(1+a);
4708  vgt = vgt0+sigma*xvdds;
4709  b = 0.5*vgt/vt-1;
4710  q = sqrt(model_.deltaSqr+b*b);
4711  vgte = vt*(1+b+1+q);
4712  u = 1+THETA*(vgte+2*von)/TOX;
4713  mu = tSurfMob/u;
4714 
4715  x = vgt/etavt;
4716  if (x > 50.0)
4717  {
4718  ns = n0*2.0*x;
4719  }
4720  else if (x < -30)
4721  {
4722  ns = n0*exp(x);
4723  }
4724  else
4725  {
4726  ns = 2.0*n0*log(1+0.5*exp(x));
4727  }
4728 
4729  if(ns < 1.0e-38) {
4730  cdraindrift_loc = 0.0;
4731  vsate = 0.0;
4732  gm = 0.0;
4733  gdds = 0.0;
4734  gmbs = 0.0;
4735  mm1 = 0.0;
4736  dmm1vgs = 0.0;
4737  dmm1vds = 0.0;
4738  dmm1vbs = 0.0;
4739  return true;
4740  }
4741 
4742  gchi = gchi0*mu*ns;
4743  gch = gchi/(1+gchi*rt);
4744  t = VMAX*L;
4745 // vl = t/mu;
4746  vl = t/tSurfMob;
4747  vl2 = vl*vl;
4748  d = sqrt(1+2*gchi*RS + vgte*vgte/vl2);
4749  r = gchi*vgte;
4750  h = 1+gchi*RS+d;
4751  isat = r/h;
4752  vsate = isat/gch;
4753  y = xvdds/(vsate);
4754 
4755  if(fabs(y) > EXP_MAX) z = 0;
4756  else z = 1/(cosh(y)*cosh(y));
4757 
4758  // drain current
4759  ichoo = isat*(1+LAMBDA*xvdds)*tanh(y);
4760 
4761  dvgtedvgt = 0.5*(1+b/q);
4762  dnsdvgt = n0/(etavt*(exp(-x)+0.5));
4763  dmudvgte = -tSurfMob*THETA/(TOX*u*u);
4764 
4765  dvgtdvds = sigma;
4766  dvgtdvgs = 1 - SIGMA0*a*xvdds/(VSIGMA*(1+a)*(1+a));
4767  dvgtdvbs = -dvonvbs*dvgtdvgs;
4768 
4769  dnsdvds = dnsdvgt*dvgtdvds;
4770  dnsdvgs = dnsdvgt*dvgtdvgs;
4771  dnsdvbs = dnsdvgt*dvgtdvbs;
4772  dmudvds = (dmudvgte*dvgtedvgt)*dvgtdvds;;
4773  dmudvgs = (dmudvgte*dvgtedvgt)*dvgtdvgs;;
4774  dmudvbs = (dmudvgte*dvgtedvgt)*dvgtdvbs + 2*dmudvgte*dvonvbs;
4775 
4776  dgchidvds = gchi0*(mu*dnsdvds + ns*dmudvds);
4777  dgchidvgs = gchi0*(mu*dnsdvgs + ns*dmudvgs);
4778  dgchidvbs = gchi0*(mu*dnsdvbs + ns*dmudvbs);
4779 
4780  disatvgte = gchi/h - gchi*vgte*vgte/vl2/(d*h*h);
4781  disatgchi = vgte/h - gchi*vgte*RS*(1+1/d)/(h*h);
4782 
4783  disatdvds = (disatvgte*dvgtedvgt)*dvgtdvds + disatgchi*dgchidvds;
4784  disatdvgs = (disatvgte*dvgtedvgt)*dvgtdvgs + disatgchi*dgchidvgs;
4785  disatdvbs = (disatvgte*dvgtedvgt)*dvgtdvbs + disatgchi*dgchidvbs;
4786 
4787  dichoodgch = (1+LAMBDA*xvdds)*xvdds*z;
4788  dichooisat = (1+LAMBDA*xvdds)*(tanh(y) - gch*xvdds*z/isat);
4789  g = 1+gchi*rt;
4790  delgchgchi = 1/(g*g);
4791 
4792  dichoodvds = dichooisat*disatdvds + (dichoodgch*delgchgchi)*dgchidvds
4793  + isat*LAMBDA*tanh(y) + (1+LAMBDA*xvdds)*gch*z;
4794  dichoodvgs = dichooisat*disatdvgs + (dichoodgch*delgchgchi)*dgchidvgs;
4795  dichoodvbs = dichooisat*disatdvbs + (dichoodgch*delgchgchi)*dgchidvbs;
4796 
4797 
4798  cdraindrift_loc = ichoo;
4799  gm = dichoodvgs;
4800  gdds = dichoodvds;
4801  gmbs = dichoodvbs;
4802 
4803 // the mm1 factors are for the ISUB calc which we don't use
4804  mm1 = 0.0;
4805  dmm1vgs = 0.0;
4806  dmm1vds = 0.0;
4807  dmm1vbs = 0.0;
4808 
4809  return true;
4810 }
4811 
4812 
4813 //-----------------------------------------------------------------------------
4814 // Function : Instance::UCCMmosa2
4815 // Purpose : Compute currents and conductances in
4816 // : drain and substrate regions
4817 //
4818 //
4819 // Special Notes :
4820 //
4821 // Scope : public
4822 // Creator : pmc
4823 // Creation Date : 02/17/2004
4824 //-----------------------------------------------------------------------------
4825 
4826 bool Instance::UCCMmosa2(double xvgs, double xvdds,
4827  double dvonvbs, double & cdraindrift_loc, double & vsate)
4828 {
4829  double etavt(0.0);
4830  double vgt(0.0);
4831  double vgt0(0.0);
4832  double sigma(0.0);
4833  double vgte(0.0);
4834  double isat(0.0);
4835  double mu(0.0);
4836  double ns(0.0);
4837  double a(0.0);
4838  double b(0.0);
4839  double c(0.0);
4840  double d(0.0);
4841  double e(0.0);
4842  double f(0.0);
4843  double g(0.0);
4844  double h(0.0);
4845  double p(0.0);
4846  double q(0.0);
4847  double r(0.0);
4848  double s(0.0);
4849  double t(0.0);
4850  double u(0.0);
4851  double x,y,z(0.0);
4852  double gch(0.0);
4853  double gchi(0.0);
4854  double rt(0.0);
4855  double vl(0.0);
4856  double vl2(0.0);
4857  double ichoo(0.0);
4858  double gmoo(0.0);
4859  double gdsoo(0.0);
4860  double gbsoo(0.0);
4861  double icho(0.0);
4862  double gmo(0.0);
4863  double gdso(0.0);
4864  double gbso(0.0);
4865  double vsat(0.0);
4866  double vdso(0.0);
4867  double vdse(0.0);
4868  double cox(0.0);
4869  double temp1(0.0);
4870  double qs(0.0);
4871  double dqsvgt(0.0);
4872  double dqsvbs(0.0);
4873  double delidgch(0.0);
4874  double delgchgchi(0.0);
4875  double delgchins(0.0);
4876  double dvgtevgt(0.0);
4877  double delidvsate(0.0);
4878  double delvsateisat(0.0);
4879  double delisatvgte(0.0);
4880  double delisatgchi(0.0);
4881  double delisatvl(0.0);
4882  double dgchivgt(0.0);
4883  double delvsategch(0.0);
4884  double delidvds(0.0);
4885  double dsigmavgs(0.0);
4886  double delnsvgt(0.0);
4887  double dvsatevgt(0.0);
4888  double dvgtvgs(0.0);
4889  double dmuvon(0.0);
4890  double dmuvgt(0.0);
4891  double dvgtvon(0.0);
4892  double delvsatqs(0.0);
4893  double delvsatmu(0.0);
4894  double dvsatvgt(0.0);
4895  double dvsatvbs(0.0);
4896  double delvdsevdso(0.0);
4897  double delvdsevsat(0.0);
4898  double dvdsevgs(0.0);
4899  double dvdsevds(0.0);
4900  double dvdsevbs(0.0);
4901 
4902  double del(0.0);
4903  double delmm1vdso(0.0);
4904  double ddelvgs(0.0);
4905  double ddelvds(0.0);
4906  double ddelvbs(0.0);
4907 
4908  // These "loc" variables are named such to avoid name conflicts with
4909  // instance variables.
4910  double mm1_loc(0.0);
4911  double dmm1vgs_loc(0.0);
4912  double dmm1vds_loc(0.0);
4913  double dmm1vbs_loc(0.0);
4914 
4915  static int output(0);
4916 
4917 #define ETA model_.eta
4918 #define RS model_.sourceResistance
4919 #define RD model_.drainResistance
4920 #define VSIGMAT model_.vsigmat
4921 #define VSIGMA model_.vsigma
4922 #define SIGMA0 model_.sigma0
4923 #define THETA model_.theta
4924 #define LAMBDA model_.lambda
4925 #define DELTA model_.delta
4926 #define ALPHA model_.alpha
4927 #define VMAX model_.maxDriftVel
4928 #define TOX model_.oxideThickness
4929 #define W w
4930 #define L EffectiveLength
4931 #define LS model_.ls
4932 #define M model_.m
4933 #define INVM 1.0/model_.m
4934 #define MC model_.mc
4935 #define INVMC 1.0/model_.mc
4936 #define RSUB model_.rsub
4937 #define AI model_.ai
4938 #define BI model_.bi
4939 #define MD model_.md
4940 #define INVMD 1.0/model_.md
4941 #define DELMAX model_.delmax
4942 
4943  if(output == 1) {
4944  Xyce::dout() << " " << std::endl;
4945  Xyce::dout() << "ETA = " << ETA << std::endl;
4946  Xyce::dout() << "RS = " << RS << std::endl;
4947  Xyce::dout() << "RD = " << RD << std::endl;
4948  Xyce::dout() << "VSIGMAT = " << VSIGMAT << std::endl;
4949  Xyce::dout() << "VSIGMA = " << VSIGMA << std::endl;
4950  Xyce::dout() << "SIGMA0 = " << SIGMA0 << std::endl;
4951  Xyce::dout() << "THETA = " << THETA << std::endl;
4952  Xyce::dout() << "LAMBDA = " << LAMBDA << std::endl;
4953  Xyce::dout() << "DELTA = " << DELTA << std::endl;
4954  Xyce::dout() << "ALPHA = " << ALPHA << std::endl;
4955  Xyce::dout() << "VMAX = " << VMAX << std::endl;
4956  Xyce::dout() << "TOX = " << TOX << std::endl;
4957  Xyce::dout() << "W = " << W << std::endl;
4958  Xyce::dout() << "L = " << L << std::endl;
4959  Xyce::dout() << "LS = " << LS << std::endl;
4960  Xyce::dout() << "M = " << M << std::endl;
4961  Xyce::dout() << "INVM = " << INVM << std::endl;
4962  Xyce::dout() << "MC = " << MC << std::endl;
4963  Xyce::dout() << "INVMC = " << INVMC << std::endl;
4964  Xyce::dout() << "RSUB = " << RSUB << std::endl;
4965  Xyce::dout() << "AI = " << AI << std::endl;
4966  Xyce::dout() << "BI = " << BI << std::endl;
4967  Xyce::dout() << "MD = " << MD << std::endl;
4968  Xyce::dout() << "INVMD = " << INVMD << std::endl;
4969  Xyce::dout() << "DELMAX = " << DELMAX << std::endl;
4970  Xyce::dout() << "VP = " << vp << std::endl;
4971  output=0;
4972  }
4973 
4974 
4975  etavt = ETA*vt;
4976  rt = RS+RD;
4977  vgt0 = xvgs - von;
4978  a = exp((vgt0-VSIGMAT)/VSIGMA);
4979  sigma = SIGMA0/(1+a);
4980  vgt = vgt0+sigma*xvdds;
4981  b = 0.5*vgt/vt-1;
4982  q = sqrt(model_.deltaSqr+b*b);
4983  vgte = vt*(1+b+1+q);
4984  u = 1+THETA*(vgte+2*von)/TOX;
4985  mu = tSurfMob/u;
4986 
4987  x = vgt/etavt;
4988  if (x > 50.0)
4989  {
4990  ns = n0*2.0*x;
4991  }
4992  else if (x < -30)
4993  {
4994  ns = n0*exp(x);
4995  }
4996  else
4997  {
4998  ns = 2.0*n0*log(1+0.5*exp(x));
4999  }
5000  //ns = 2.0*n0*log(1+0.5*c);
5001 
5002  if(ns < 1.0e-38)
5003  {
5004  cdraindrift_loc = 0.0;
5005  vsate = 0.0;
5006  gm = 0.0;
5007  gdds = 0.0;
5008  gmbs = 0.0;
5009 
5010  mm1 = mm1_loc = 0.0;
5011  dmm1vgs = dmm1vgs_loc = 0.0;
5012  dmm1vds = dmm1vds_loc = 0.0;
5013  dmm1vbs = dmm1vbs_loc = 0.0;
5014  return true;
5015  }
5016 
5017  gchi = gchi0*mu*ns;
5018  gch = gchi/(1+gchi*rt);
5019  t = VMAX*L;
5020  vl = t/mu;
5021  vl2 = vl*vl;
5022  d = sqrt(1+2*gchi*RS + vgte*vgte/vl2);
5023  r = gchi*vgte;
5024  isat = r/(1+gchi*RS+d);
5025  vsate = isat/gch;
5026  y = xvdds/(vsate);
5027  z = 0.5*(cosh(2*y)+1);
5028 
5029 // Old model
5030 // e = pow(xvdds/(*vsate),M);
5031 // f = pow(1+e,INVM);
5032 // delidgch = xvdds*(1+LAMBDA*xvdds)/f;
5033 
5034  ichoo = isat*(1+LAMBDA*xvdds)*tanh(y);
5035  delidgch = ichoo/gch;
5036  g = 1+gchi*rt;
5037  delgchgchi = 1/(g*g);
5038  delgchins = gchi0*mu;
5039  x = vgt/etavt;
5040  delnsvgt = n0/(etavt*(exp(-x) + 0.5));
5041  dvgtevgt = 0.5*(1+b/q);
5042 
5043 // delidvds = gch*(1+2*LAMBDA*xvdds)/f-
5044 // ichoo*pow(vdds/(*vsate),M-1)/((*vsate)*(1+e));
5045 // delidvsate = ichoo*e/((*vsate)*(1+e));
5046  delidvds = ichoo*LAMBDA/(1+LAMBDA*xvdds) + gch*(1+LAMBDA*xvdds)/z;
5047  delidvsate = gch*(1+LAMBDA*xvdds)*xvdds/(vsate)/z;
5048 
5049  delvsateisat = 1/gch;
5050  delvsategch = -(vsate)/gch;
5051  h = 1+gchi*RS+d;
5052  delisatgchi = (vgte*h - gchi*vgte*RS*(1+1/d))/(h*h);
5053  delisatvgte = (gchi*h - gchi*vgte*vgte/(vl2*d))/(h*h);
5054  delisatvl = isat*isat*vgte/(gchi*d*vl2*vl);
5055  s = THETA/(tSurfMob*TOX);
5056  dgchivgt = delgchins*delnsvgt-gchi*mu*s*dvgtevgt;
5057  dsigmavgs = -SIGMA0*a/(VSIGMA*((1+a)*(1+a)));
5058  p = delgchgchi*dgchivgt;
5059  dvsatevgt = delvsateisat*(delisatgchi*dgchivgt+
5060  (delisatvgte+delisatvl*t*s)*dvgtevgt)+ delvsategch*p;
5061  g = delidgch*p+delidvsate*dvsatevgt;
5062  dvgtvgs = (1+xvdds*dsigmavgs);
5063  gmoo = g*dvgtvgs;
5064  gdsoo = delidvds+g*sigma;
5065 
5066  dmuvon = -(2-dvgtevgt*dvgtvgs)*mu*mu*s;
5067  dmuvgt = -mu*mu*THETA*dvgtevgt/(tSurfMob*TOX);
5068  dvgtvon = -dvgtvgs;
5069 
5070  if(THETA == 0.0)
5071  {
5072  gbsoo = -(gmoo)*dvonvbs;
5073  }
5074  else
5075  {
5076  double dgchivon = -delgchins*delnsvgt*dvgtvgs+gchi*dmuvon/mu;
5077  p = delgchgchi*dgchivon;
5078  double dvsatevon = delvsateisat*(delisatgchi*dgchivon+
5079  delisatvgte*dvgtevgt*dvgtvon+delisatvl*(-vl2/t)*dmuvon)+delvsategch*p;
5080  gbsoo = (delidgch*p+delidvsate*dvsatevon)*dvonvbs;
5081  }
5082 
5083 // mosa2: New Version
5084 
5085  cox = CONSTEPSOX/TOX;
5086  temp1 = cox*RS/CONSTQ;
5087  qs = CONSTQ*(ns-ichoo*temp1);
5088  dqsvgt = CONSTQ*(delnsvgt-g*temp1);
5089  dqsvbs = CONSTQ*(delnsvgt*dvgtvon*dvonvbs-gbsoo*temp1);
5090 
5091  // A more precise vsat model for deltal and isub calculations
5092  if(model_.dtype == CONSTNMOS)
5093  {
5094  a = 2*qs*VMAX*L;
5095  b = qs*mu+2*cox*ALPHA*VMAX*L;
5096  temp1 = b*b;
5097  vsat = a/b;
5098  delvsatqs = 2*VMAX*L*(b-qs*mu)/temp1;
5099  delvsatmu = -a*qs/temp1;
5100  dvsatvgt = delvsatqs*dqsvgt+delvsatmu*dmuvgt;
5101  dvsatvbs = delvsatqs*dqsvbs+delvsatmu*dmuvon*dvonvbs;
5102  }
5103  else
5104  {
5105  a = VMAX*L/mu;
5106  b = 2/(cox*ALPHA*VMAX*L);
5107  c = sqrt(1+qs*mu*b);
5108  vsat = a*(c-1);
5109  delvsatqs = a*(0.5*b*mu/c);
5110  delvsatmu = -vsat/mu+a*(0.5*b*qs/c);
5111  dvsatvgt = delvsatqs*dqsvgt+delvsatmu*dmuvgt;
5112  dvsatvbs = delvsatqs*dqsvbs+delvsatmu*dmuvon*dvonvbs;
5113  }
5114 
5115  // Effective intrinsic drain-source voltage calculation
5116  vdso = xvdds-ichoo*rt;
5117  a = pow(vdso/vsat,MC);
5118  b = pow(1+a,INVMC);
5119  vdse = vdso/b;
5120  delvdsevdso = (1-a/(1+a))/b;
5121  delvdsevsat = vdse*a/(vsat*(1+a));
5122 
5123  // DeltaL calculation
5124  double deltal(0.0);
5125  double deldeltalvdse(0.0);
5126  double deldeltalvdso(0.0);
5127  double deldeltalmu(0.0);
5128  double ddeltalvgs(0.0);
5129  double ddeltalvds(0.0);
5130  double ddeltalvbs(0.0);
5131 
5132  a = 1+(vdso-vdse)/vp;
5133  b = W*mu*cox*vdse*RS/L;
5134  c = 1+vdse/vp+b;
5135  d = LS*log10(a);
5136  deltal = d/c;
5137  e = 1/(1-deltal/L);
5138  icho = ichoo*e;
5139  f = log(10.0);
5140  deldeltalvdse = (-LS/(f*a*vp)*c-d*(1/vp+W*mu*cox*RS/L))/(c*c);
5141  deldeltalvdso = LS/(c*a*f*vp);
5142  deldeltalmu = -d*W*cox*vdse*RS/(L*c*c);
5143  temp1 = -gmoo*rt;
5144  dvdsevgs = delvdsevsat*dvsatvgt*dvgtvgs+delvdsevdso*temp1;
5145  ddeltalvgs = deldeltalvdse*dvdsevgs + deldeltalmu*dmuvgt*dvgtvgs
5146  + deldeltalvdso*temp1;
5147  gmo = e*(gmoo+ichoo*ddeltalvgs*e/L);
5148  temp1 = 1-gdsoo*rt;
5149  dvdsevds = delvdsevsat*dvsatvgt*sigma+delvdsevdso*temp1;
5150  ddeltalvds = deldeltalvdse*dvdsevds + deldeltalmu*dmuvgt*sigma
5151  + deldeltalvdso*temp1;
5152  gdso = e*(gdsoo+ichoo*ddeltalvds*e/L);
5153  temp = -gbsoo*rt;
5154  dvdsevbs = delvdsevsat*dvsatvbs+delvdsevdso*temp1;
5155  ddeltalvbs = deldeltalvdse*dvdsevbs + deldeltalmu*dmuvon*dvonvbs
5156  + deldeltalvdso*temp1;;
5157  gbso = e*(gbsoo+ichoo*ddeltalvbs*e/L);
5158 
5159  a = AI/BI;
5160  b = vdso-vdse+vt;
5161  c = exp(-LS*BI/b);
5162  mm1_loc = a*b*c;
5163  if(RSUB != 0.0)
5164  {
5165  d = 0.5*W*(ALPHA-1)*cox*RSUB/L;
5166  del = d*mm1_loc*mu*vdse;
5167  f = pow(del/DELMAX,MD);
5168  g = pow(1+f,INVMD);
5169  h = (1-f/(1+f))/g;
5170  del = del/g;
5171  e = 1/(1-del);//1+del;
5172  }
5173  else
5174  {
5175  d = 0;
5176  h = 1;
5177  e = 1;
5178  }
5179 
5180  cdraindrift_loc = icho*e;
5181  delmm1vdso = a*c+mm1_loc*LS*BI/(b*b);
5182  dmm1vgs_loc = delmm1vdso*(-gmoo*rt-dvdsevgs);
5183  ddelvgs = h*d*(mu*vdse*dmm1vgs_loc + mm1_loc*vdse*dmuvgt*dvgtvgs
5184  + mu*mm1_loc*dvdsevgs);
5185  gm = e*(gmo+icho*ddelvgs*e); //gmo*e+icho*ddelvgs;
5186  dmm1vds_loc = delmm1vdso*(1-gdsoo*rt-dvdsevds);
5187  ddelvds = h*d*(mu*vdse*dmm1vds_loc + mm1_loc*vdse*dmuvgt*sigma
5188  + mu*mm1_loc*dvdsevds);
5189  gdds = e*(gdso+icho*ddelvds*e); //gdso*e+icho*ddelvds;
5190  dmm1vbs_loc = delmm1vdso*(-gbsoo*rt-dvdsevbs);
5191  ddelvbs = h*d*(mu*vdse*dmm1vbs_loc + mm1_loc*vdse*dmuvon*dvonvbs
5192  + mu*mm1_loc*dvdsevbs);
5193  gmbs = e*(gbso+icho*ddelvbs*e); //gbso*e+icho*ddelvbs;
5194 
5195 
5196  // saving some quantities for substrate current calculations
5197  mm1 = mm1_loc;
5198  dmm1vgs = dmm1vgs_loc;
5199  dmm1vds = dmm1vds_loc;
5200  dmm1vbs = dmm1vbs_loc;
5201 
5202  return true;
5203 }
5204 
5205 
5206 //-----------------------------------------------------------------------------
5207 // VDMOS Master functions:
5208 //-----------------------------------------------------------------------------
5209 
5210 //-----------------------------------------------------------------------------
5211 // Function : Master::updateState
5212 // Purpose :
5213 // Special Notes :
5214 // Scope : public
5215 // Creator : Eric Keiter, SNL
5216 // Creation Date : 11/26/08
5217 //-----------------------------------------------------------------------------
5218 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
5219 {
5220  bool bsuccess = true;
5221 
5222  // first loop over the models:
5223  // for (ModelMap::const_iterator model_it = getModelMap().begin(); model_it != getModelMap().end(); ++model_it)
5224  // {
5225  // // loop over the instances for this model.
5226  // InstanceVector::const_iterator first = (*model_it).second->instanceContainer.begin();
5227  // InstanceVector::const_iterator last = (*model_it).second->instanceContainer.end();
5228 
5229  // for (InstanceVector::const_iterator it = first; it != last; ++it)
5230  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5231  {
5232  Instance & mi = *(*it);
5233 
5234  double * currStaVector = mi.extData.currStaVectorRawPtr;
5235 
5236  bool btmp = mi.updateIntermediateVars ();
5237  bsuccess = bsuccess && btmp;
5238 
5239  double vgs1(0.0), vgdd1(0.0), vbs1(0.0),vgb1(0.0), vdds1(0.0);
5240 
5241  // voltage drops:
5242  staVec[mi.li_state_vbdd] = mi.vbdd;
5243  staVec[mi.li_state_vbs] = mi.vbs;
5244  staVec[mi.li_state_vgps] = mi.vgps;
5245  staVec[mi.li_state_vdds] = mi.vdds;
5246  staVec[mi.li_state_D1vd] = mi.D1vd;
5247 
5248  // now the meyer capacitances
5249  // we didn't calculate these charges in update IntermediateVars
5250  // but we did calculate the voltage drops and capacitances.
5251  // first store the capacitances themselves:
5252  staVec[mi.li_state_capgs] = mi.capgs;
5253  staVec[mi.li_state_capgdd] = mi.capgdd;
5254  staVec[mi.li_state_capgb] = mi.capgb;
5255 
5256  // now the charges
5257  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
5258  // supposed to be *INTEGRATED*:
5259  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
5260  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
5261  // Now with Meyer back averaging, Capxx is the average between the last
5262  // time step and this one. So we gotta do the right thing for non-DCOP
5263  // when backaverage is on.
5264 
5265  if((getSolverState().dcopFlag))
5266  {
5267  mi.qgs = mi.Capgs *mi.vgps;
5268  mi.qgdd = mi.Capgdd*mi.vgpdd;
5269  mi.qgb = mi.Capgb *mi.Vgpb;
5270  }
5271  else
5272  {
5273  // get the ones from last time step
5274  mi.qgs = currStaVector[mi.li_state_qgs];
5275  mi.qgdd = currStaVector[mi.li_state_qgdd];
5276  mi.qgb = currStaVector[mi.li_state_qgb];
5277  // get the voltage drops, too
5278  vgs1 = currStaVector[mi.li_state_vgps];
5279  vbs1 = currStaVector[mi.li_state_vbs];
5280  vdds1 = currStaVector[mi.li_state_vdds];
5281 
5282  vgb1 = vgs1-vbs1;
5283  vgdd1 = vgs1-vdds1;
5284 
5285  // NOW we can calculate the charge update
5286  mi.qgs += mi.Capgs*(mi.vgps-vgs1);
5287  mi.qgdd += mi.Capgdd*(mi.vgpdd-vgdd1);
5288  mi.qgb += mi.Capgb*((mi.vgps-mi.vbs)-vgb1);
5289  }
5290 
5291  staVec[mi.li_state_qgs] = mi.qgs;
5292  staVec[mi.li_state_qgdd] = mi.qgdd;
5293  staVec[mi.li_state_qgb] = mi.qgb;
5294 
5295  // and the diode parasitic capacitors
5296  // these charges were set in updateIntermediateVars
5297  staVec[mi.li_state_qbd] = mi.qbd;
5298  staVec[mi.li_state_qbs] = mi.qbs;
5299 
5300  // diode #1 quatntities
5301 
5302  staVec[mi.li_state_D1DIOcapCharge] = mi.D1DIOcapCharge;
5303 
5304  // In the case of a charge, need to handle this:
5305  // Ensure dQ/dt = 0 for initial step after dcOP by setting the history equal
5306  // to the current value
5308  {
5309  currStaVector[mi.li_state_D1DIOcapCharge] = mi.D1DIOcapCharge;
5310  }
5311 
5312  staVec[ mi.li_state_von ] = mi.von;
5313 
5314  }
5315 // }
5316 
5317  return bsuccess;
5318 }
5319 
5320 //-----------------------------------------------------------------------------
5321 // Function : Master::updateSecondaryState
5322 // Purpose :
5323 // Special Notes :
5324 // Scope : public
5325 // Creator : Eric Keiter, SNL
5326 // Creation Date : 11/26/08
5327 //-----------------------------------------------------------------------------
5328 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
5329 {
5330  // first loop over the models:
5331  // for (ModelMap::const_iterator model_it = getModelMap().begin(); model_it != getModelMap().end(); ++model_it)
5332  // {
5333  // // loop over the instances for this model.
5334  // InstanceVector::const_iterator first = (*model_it).second->instanceContainer.begin();
5335  // InstanceVector::const_iterator last = (*model_it).second->instanceContainer.end();
5336 
5337  // for (InstanceVector::const_iterator it = first; it != last; ++it)
5338  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5339  {
5340  Instance & mi = *(*it);
5341 
5342  mi.cqgs = staDerivVec[mi.li_state_qgs];
5343  mi.cqgdd = staDerivVec[mi.li_state_qgdd];
5344  mi.cqgb = staDerivVec[mi.li_state_qgb];
5345  mi.cqbd = staDerivVec[mi.li_state_qbd];
5346  mi.cqbs = staDerivVec[mi.li_state_qbs];
5347 
5348  mi.D1DIOcapCurrent = staDerivVec[mi.li_state_D1DIOcapCharge];
5349 
5350  double Dtype =mi.getModel().dtype;
5351  double D1current = Dtype*(mi.D1cdeq + mi.D1DIOcapCurrent);
5352 
5353  // Even though these do not look exactly like the RHS loads, they do account
5354  // for the currents into the leads even with the lead resistors in place
5355  // --- since the lead resistances are the only thing between the primed node
5356  // and the lead, the currents are still correct AT CONVERGED SOLUTIONS
5357  /*
5358  Lead current load has been moved to F & Q loads
5359  mi.LeadCurrentD = -mi.getModel().dtype*(-mi.mode*mi.cdrain+mi.cbd+mi.cqgdd+mi.cqbd)-D1current-mi.Irdsshunt;
5360  mi.LeadCurrentG = mi.getModel().dtype*(mi.cqgs+mi.cqgb+mi.cqgdd);
5361  mi.LeadCurrentS = mi.getModel().dtype*(-mi.mode*mi.cdrain+mi.cbs-mi.cqgs-mi.cqbs) + D1current+mi.Irdsshunt;
5362  mi.LeadCurrentB = mi.getModel().dtype*(mi.cbd-mi.cbs-mi.cqgb+mi.cqbd+mi.cqbs);
5363  */
5364  }
5365 // }
5366 
5367  return true;
5368 }
5369 
5370 //-----------------------------------------------------------------------------
5371 // Function : Master::loadDAEVectors
5372 // Purpose :
5373 // Special Notes :
5374 // Scope : public
5375 // Creator : Eric Keiter, SNL
5376 // Creation Date : 11/26/08
5377 //-----------------------------------------------------------------------------
5378 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * storeLeadF, double * storeLeadQ)
5379 {
5380  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5381  {
5382  Instance & mi = *(*it);
5383 
5384  // F-vector:
5385  double * dFdxdVp = mi.extData.dFdxdVpVectorRawPtr;
5386 
5387  double coef_Jdxp(0.0), gd_Jdxp(0.0);
5388  double gmin1 = getDeviceOptions().gmin;
5389  double Dtype =mi.getModel().dtype;
5390 
5391  double ceqbs = Dtype*(mi.cbs+mi.cqbs);
5392  double ceqbd = Dtype*(mi.cbd+mi.cqbd);
5393 
5394  double D1current = Dtype*mi.D1cdeq; // don't add in the capacitor stuff
5395 
5396 
5397  fVec[mi.li_Drain] += (mi.Idraindrift + mi.Irdsshunt - D1current);
5398 
5399  if (mi.Igate != 0.0)
5400  {
5401  fVec[mi.li_Gate] += mi.Igate;
5402  fVec[mi.li_GatePrime] += -mi.Igate;
5403  }
5404 
5405 
5406  fVec[mi.li_Source] += (mi.Isource - mi.Irdsshunt + mi.Ird1rs);
5407  fVec[mi.li_Bulk] += (ceqbs + ceqbd);
5408  fVec[mi.li_DrainPrime] += (-mi.Idrain-(ceqbd - mi.cdreq));
5409  fVec[mi.li_SourcePrime] += (-mi.Isource-(ceqbs + mi.cdreq));
5410  fVec[mi.li_DrainDrift] += (mi.Idrain - mi.Idraindrift);
5411  fVec[mi.li_D1Prime] += (D1current - mi.Ird1rs);
5412 
5413  // limiter terms:
5414  if (!mi.origFlag)
5415  {
5416  // bulk
5417  coef_Jdxp = Dtype*( + ((mi.gbd-gmin1))*(mi.vbdd-mi.vbdd_orig)
5418  + ((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig));
5419  dFdxdVp[mi.li_Bulk] += coef_Jdxp;
5420 
5421  // drain-prime
5422  coef_Jdxp = Dtype*(-((mi.gbd-gmin1))*
5423  (mi.vbdd-mi.vbdd_orig)+mi.gdds*(mi.vdds-mi.vdds_orig)
5424  +mi.Gm*((mi.mode>0)?(mi.vgps-mi.vgps_orig):(mi.vgpdd-mi.vgpdd_orig))
5425  +mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbdd-mi.vbdd_orig)));
5426  dFdxdVp[mi.li_DrainPrime] += coef_Jdxp;
5427 
5428  // source prime
5429  coef_Jdxp = Dtype*(-((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig)
5430  -mi.gdds*(mi.vdds-mi.vdds_orig)
5431  -mi.Gm*((mi.mode>0)?(mi.vgps-mi.vgps_orig):(mi.vgpdd-mi.vgpdd_orig))
5432  -mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbdd-mi.vbdd_orig)));
5433 
5434 
5435  dFdxdVp[mi.li_SourcePrime] += coef_Jdxp;
5436  gd_Jdxp = -mi.D1gd * (mi.D1vd-mi.D1vd_orig);
5437  dFdxdVp[mi.li_Drain] += gd_Jdxp;
5438  dFdxdVp[mi.li_D1Prime] -= gd_Jdxp;
5439  }
5440 
5441  // Q-vector:
5442  double * dQdxdVp = mi.extData.dQdxdVpVectorRawPtr;
5443 
5444  double qcoef_Jdxp(0.0);
5445 
5446  double Qeqbs = Dtype*mi.qbs;
5447  double Qeqbd = Dtype*mi.qbd;
5448  double Qeqgb = Dtype*mi.qgb;
5449  double Qeqgs = Dtype*mi.qgs;
5450  double Qeqgdd = Dtype*mi.qgdd;
5451 
5452 
5453  qVec[mi.li_Bulk] += (Qeqbs + Qeqbd - Qeqgb);
5454  qVec[mi.li_DrainPrime] += -(Qeqbd + Qeqgdd);
5455  qVec[mi.li_GatePrime] += (Qeqgs+Qeqgdd+Qeqgb);
5456  qVec[mi.li_SourcePrime] += (-(Qeqbs + Qeqgs));
5457  qVec[mi.li_D1Prime] += mi.D1DIOcapCharge;
5458  qVec[mi.li_Drain] += -mi.D1DIOcapCharge;
5459 
5460  // voltlim section:
5461  if (!mi.origFlag)
5462  {
5463  // bulk
5464  qcoef_Jdxp = Dtype*(-mi.Capgb*(mi.vgps-mi.vgps_orig-mi.vbs+mi.vbs_orig)
5465  + (+mi.Capgb)*(mi.vbdd-mi.vbdd_orig)
5466  + (+mi.capbs)*(mi.vbs-mi.vbs_orig));
5467  dQdxdVp[mi.li_Bulk] += qcoef_Jdxp;
5468 
5469  // drain-prime
5470  qcoef_Jdxp = Dtype*(-mi.Capgdd*(mi.vgpdd-mi.vgpdd_orig)-mi.capbd*(mi.vbdd-mi.vbdd_orig));
5471  dQdxdVp[mi.li_DrainPrime] += qcoef_Jdxp;
5472 
5473  // gate-prime
5474  qcoef_Jdxp = Dtype*(mi.Capgdd*(mi.vgpdd-mi.vgpdd_orig)+mi.Capgs*(mi.vgps-mi.vgps_orig)+
5475  mi.Capgb*(mi.vgps-mi.vgps_orig-mi.vbs+mi.vbs_orig));
5476  dQdxdVp[mi.li_GatePrime] += qcoef_Jdxp;
5477 
5478  // source-prime
5479  qcoef_Jdxp = Dtype*(-mi.Capgs*(mi.vgps-mi.vgps_orig)-mi.capbs*(mi.vbs-mi.vbs_orig));
5480  dQdxdVp[mi.li_SourcePrime] += qcoef_Jdxp;
5481  qcoef_Jdxp = -mi.D1capd*(mi.D1vd-mi.D1vd_orig);
5482  dQdxdVp[mi.li_D1Prime] -= qcoef_Jdxp;
5483  dQdxdVp[mi.li_Drain] += qcoef_Jdxp;
5484  }
5485 
5486  if( mi.loadLeadCurrent )
5487  {
5488  storeLeadF[mi.li_store_dev_id] = (mi.Idraindrift + mi.Irdsshunt - D1current);
5489  storeLeadF[mi.li_store_dev_is] = (mi.Isource - mi.Irdsshunt + mi.Ird1rs);
5490  storeLeadF[mi.li_store_dev_ig] = 0;
5491  storeLeadF[mi.li_store_dev_ib] = (ceqbs + ceqbd);
5492  // case where optional nodes become external nodes:
5493  if (mi.Igate != 0.0)
5494  {
5495  storeLeadF[mi.li_store_dev_ig] += mi.Igate;
5496  }
5497  if( !mi.gateCond )
5498  {
5499  // G' is G
5500  storeLeadF[mi.li_store_dev_ig] += -mi.Igate;
5501  }
5502 
5503  if( !mi.sourceCond )
5504  {
5505  // S' is S
5506  storeLeadF[mi.li_store_dev_is] += (-mi.Isource-(ceqbs + mi.cdreq));
5507  }
5508 
5509  if( !mi.drainCond )
5510  {
5511  // Ddrift is D'
5512  }
5513 
5514  if( !mi.model_.D1DIOconductance )
5515  {
5516  // D1' is S
5517  storeLeadF[mi.li_store_dev_is] += (D1current - mi.Ird1rs);
5518  }
5519 
5520  storeLeadQ[mi.li_store_dev_id] = -mi.D1DIOcapCharge;
5521  storeLeadQ[mi.li_store_dev_is] = 0;
5522  storeLeadQ[mi.li_store_dev_ig] = 0;
5523  storeLeadQ[mi.li_store_dev_ib] = (Qeqbs + Qeqbd - Qeqgb);
5524  // case where optional nodes become external nodes:
5525  if( !mi.gateCond )
5526  {
5527  // G' is G
5528  storeLeadQ[mi.li_store_dev_ig] += (Qeqgs+Qeqgdd+Qeqgb);
5529  }
5530 
5531  if( !mi.sourceCond )
5532  {
5533  // S' is S
5534  storeLeadQ[mi.li_store_dev_is] += (-(Qeqbs + Qeqgs));
5535  }
5536 
5537  if( !mi.drainCond )
5538  {
5539  // Ddrift is D'
5540  }
5541 
5542  if( !mi.model_.D1DIOconductance )
5543  {
5544  // D1' is S
5545  storeLeadQ[mi.li_store_dev_is] += mi.D1DIOcapCharge;
5546  }
5547  }
5548 
5549  }
5550 
5551  return true;
5552 }
5553 
5554 
5555 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
5556 //-----------------------------------------------------------------------------
5557 // Function : Master::loadDAEMatrices
5558 // Purpose :
5559 // Special Notes :
5560 // Scope : public
5561 // Creator : Eric Keiter, SNL
5562 // Creation Date : 11/26/08
5563 //-----------------------------------------------------------------------------
5564 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
5565 {
5566 #ifdef _OMP
5567 #pragma omp parallel for
5568 #endif
5569  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
5570  {
5571  Instance & mi = *(*it);
5572 
5573  // F-matrix:
5574 
5575  *mi.f_DrainEquDrainNodePtr += mi.dIdd_dVd + mi.gdsshunt + mi.D1gd;
5576 
5578 
5580 
5581  *mi.f_DrainEquD1PrimeNodePtr -= mi.D1gd;
5582 
5583  if (mi.gateCond != 0)
5584  {
5585 
5586  *mi.f_GateEquGateNodePtr += mi.gateCond;
5587 
5589  }
5590 
5591 
5593 
5594  *mi.f_SourceEquSourceNodePtr += mi.sourceCond + mi.gdsshunt + mi.D1gspr;
5595 
5596  *mi.f_SourceEquD1PrimeNodePtr += -mi.D1gspr;
5597 
5598  if (mi.sourceCond != 0.0)
5599  {
5600 
5602  }
5603 
5604 
5605  *mi.f_BulkEquBulkNodePtr += mi.gbs+mi.gbd;
5606 
5607  *mi.f_BulkEquDrainPrimeNodePtr -= mi.gbd;
5608 
5609 
5610  *mi.f_BulkEquSourcePrimeNodePtr -= mi.gbs;
5611 
5612 
5613  *mi.f_DrainPrimeEquBulkNodePtr += -mi.gbd+mi.Gmbs;
5614 
5616 
5618 
5620  if (mi.drainCond != 0.0)
5621  {
5622 
5624  }
5625 
5626  if (mi.gateCond != 0)
5627  {
5628 
5630 
5632  }
5633 
5634  if (mi.sourceCond != 0.0)
5635  {
5636 
5638  }
5639 
5640  *mi.f_SourcePrimeEquBulkNodePtr -= mi.gbs+mi.Gmbs;
5641 
5643 
5645 
5647 
5648 
5650 
5651  if (mi.drainCond != 0.0)
5652  {
5653 
5655  }
5656 
5658 
5659 
5660  *mi.f_D1PrimeEquDrainNodePtr -= mi.D1gd;
5661 
5662  *mi.f_D1PrimeEquSourceNodePtr += -mi.D1gspr;
5663 
5664  *mi.f_D1PrimeEquD1PrimeNodePtr += mi.D1gd + mi.D1gspr;
5665 
5666  // Q-matrix:
5667  if (!getSolverState().dcopFlag)
5668  {
5669 
5670  *mi.q_BulkEquBulkNodePtr += +mi.capbs+mi.capbd+mi.Capgb;
5671 
5672  *mi.q_BulkEquDrainPrimeNodePtr -= +mi.capbd;
5673 
5674  *mi.q_BulkEquGatePrimeNodePtr -= mi.Capgb;
5675 
5677 
5678 
5679  *mi.q_DrainPrimeEquBulkNodePtr += -mi.capbd;
5680 
5682 
5684 
5685 
5686  *mi.q_GatePrimeEquBulkNodePtr -= mi.Capgb;
5687 
5689 
5691 
5693 
5694 
5696 
5698 
5700 
5701 
5702  *mi.q_DrainEquDrainNodePtr += mi.D1capd;
5703 
5704  *mi.q_DrainEquD1PrimeNodePtr -= mi.D1capd;
5705 
5706 
5707  *mi.q_D1PrimeEquDrainNodePtr -= mi.D1capd;
5708 
5710  }
5711  }
5712  return true;
5713 }
5714 #else
5715 //-----------------------------------------------------------------------------
5716 // Function : Master::loadDAEMatrices
5717 // Purpose :
5718 // Special Notes :
5719 // Scope : public
5720 // Creator : Eric Keiter, SNL
5721 // Creation Date : 11/26/08
5722 //-----------------------------------------------------------------------------
5723 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
5724 {
5725  int sizeInstances = instanceContainer_.size();
5726 
5727 #ifdef _OMP
5728 #pragma omp parallel for
5729 #endif
5730  for (int i=0; i<sizeInstances; ++i)
5731  {
5732  Instance & mi = *(instanceContainer_.at(i));
5733 
5734  // F-matrix:
5735 
5736  dFdx[mi.li_Drain][mi.ADrainEquDrainNodeOffset] += mi.dIdd_dVd + mi.gdsshunt + mi.D1gd;
5737 
5738  dFdx[mi.li_Drain][mi.ADrainEquSourceNodeOffset] -= mi.gdsshunt;
5739 
5740  dFdx[mi.li_Drain][mi.ADrainEquDrainDriftNodeOffset] -= mi.dIdd_dVd;
5741 
5742  dFdx[mi.li_Drain][mi.ADrainEquD1PrimeNodeOffset] -= mi.D1gd;
5743 
5744  if (mi.gateCond != 0)
5745  {
5746 
5747  dFdx[mi.li_Gate][mi.AGateEquGateNodeOffset] += mi.gateCond;
5748 
5749  dFdx[mi.li_Gate][mi.AGateEquGatePrimeNodeOffset] -= mi.gateCond;
5750  }
5751 
5752 
5753  dFdx[mi.li_Source][mi.ASourceEquDrainNodeOffset] -= mi.gdsshunt;
5754 
5755  dFdx[mi.li_Source][mi.ASourceEquSourceNodeOffset] += mi.sourceCond + mi.gdsshunt + mi.D1gspr;
5756 
5757  dFdx[mi.li_Source][mi.ASourceEquD1PrimeNodeOffset] += -mi.D1gspr;
5758 
5759  if (mi.sourceCond != 0.0)
5760  {
5761 
5763  }
5764 
5765 
5766  dFdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] += mi.gbs+mi.gbd;
5767 
5768  dFdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -= mi.gbd;
5769 
5770  dFdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -= mi.gbs;
5771 
5772 
5773  dFdx[mi.li_DrainPrime][mi.ADrainPrimeEquBulkNodeOffset] += -mi.gbd+mi.Gmbs;
5774 
5776 
5778 
5780  if (mi.drainCond != 0.0)
5781  {
5782 
5784  }
5785 
5786  if (mi.gateCond != 0)
5787  {
5788 
5790 
5792  }
5793 
5794  if (mi.sourceCond != 0.0)
5795  {
5796 
5798  }
5799 
5800  dFdx[mi.li_SourcePrime][mi.ASourcePrimeEquBulkNodeOffset] -= mi.gbs+mi.Gmbs;
5801 
5803 
5805 
5807 
5808 
5810 
5811  if (mi.drainCond != 0.0)
5812  {
5813 
5815  }
5816 
5818 
5819 
5820  dFdx[mi.li_D1Prime][mi.AD1PrimeEquDrainNodeOffset] -= mi.D1gd;
5821 
5822  dFdx[mi.li_D1Prime][mi.AD1PrimeEquSourceNodeOffset] += -mi.D1gspr;
5823 
5824  dFdx[mi.li_D1Prime][mi.AD1PrimeEquD1PrimeNodeOffset] += mi.D1gd + mi.D1gspr;
5825 
5826  // Q-matrix:
5827  if (!getSolverState().dcopFlag)
5828  {
5829 
5830  dQdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] += +mi.capbs+mi.capbd+mi.Capgb;
5831 
5832  dQdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -= +mi.capbd;
5833 
5834  dQdx[mi.li_Bulk][mi.ABulkEquGatePrimeNodeOffset] -= mi.Capgb;
5835 
5836  dQdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -= +mi.capbs;
5837 
5838 
5839  dQdx[mi.li_DrainPrime][mi.ADrainPrimeEquBulkNodeOffset] += -mi.capbd;
5840 
5842 
5844 
5845 
5846  dQdx[mi.li_GatePrime][mi.AGatePrimeEquBulkNodeOffset] -= mi.Capgb;
5847 
5849 
5851 
5853 
5854 
5856 
5858 
5860 
5861 
5862  dQdx[mi.li_Drain][mi.ADrainEquDrainNodeOffset] += mi.D1capd;
5863 
5864  dQdx[mi.li_Drain][mi.ADrainEquD1PrimeNodeOffset] -= mi.D1capd;
5865 
5866 
5867  dQdx[mi.li_D1Prime][mi.AD1PrimeEquDrainNodeOffset] -= mi.D1capd;
5868 
5869  dQdx[mi.li_D1Prime][mi.AD1PrimeEquD1PrimeNodeOffset] += mi.D1capd;
5870  }
5871 
5872  }
5873  return true;
5874 }
5875 #endif
5876 
5877 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
5878 {
5879 
5880  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
5881 }
5882 
5884 {
5886  .registerDevice("m", 18)
5887  .registerModelType("pmos", 18)
5888  .registerModelType("nmos", 18);
5889 }
5890 
5891 } // namespace VDMOS
5892 } // namespace Device
5893 } // namespace Xyce