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