Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_MOSFET1.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_MOSFET1.C,v $
27 //
28 // Purpose : Implement the MOSFET Level 1 static model
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.320.2.3 $
40 //
41 // Revision Date : $Date: 2014/03/06 23:33:43 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #ifdef HAVE_CMATH
49 #include <cmath>
50 #else
51 #include <math.h>
52 #endif
53 
54 // ---------- Xyce Includes ----------
55 #include <N_DEV_Const.h>
56 #include <N_DEV_DeviceOptions.h>
57 #include <N_DEV_ExternData.h>
58 #include <N_DEV_MOSFET1.h>
59 #include <N_DEV_MatrixLoadData.h>
60 #include <N_DEV_SolverState.h>
61 #include <N_DEV_Message.h>
62 #include <N_ERH_ErrorMgr.h>
63 
64 #include <N_LAS_Matrix.h>
65 #include <N_LAS_Vector.h>
66 
67 namespace Xyce {
68 namespace Device {
69 
70 
71 namespace MOSFET1 {
72 
73 
75 {
76 // Set up double precision variables:
77  p.addPar ("TEMP", 0.0, false, ParameterType::TIME_DEP, &MOSFET1::Instance::temp, NULL,
78  STANDARD, CAT_NONE, "Device temperature");
79  p.addPar ("L", 0.0, true, ParameterType::NO_DEP, &MOSFET1::Instance::l, NULL,
80  U_METER, CAT_GEOMETRY, "Channel length");
81  p.addPar ("W", 0.0, true, ParameterType::NO_DEP, &MOSFET1::Instance::w, NULL,
82  U_METER, CAT_GEOMETRY, "Channel width");
83  p.addPar ("AD", 0.0, false, ParameterType::NO_DEP, &MOSFET1::Instance::drainArea, NULL,
84  U_METER2, CAT_GEOMETRY, "Drain diffusion area");
85  p.addPar ("AS", 0.0, false, ParameterType::NO_DEP, &MOSFET1::Instance::sourceArea, NULL,
86  U_METER2, CAT_GEOMETRY, "Source diffusion area");
87  p.addPar ("NRD", 1.0, false, ParameterType::NO_DEP, &MOSFET1::Instance::drainSquares, NULL,
88  U_SQUARES, CAT_GEOMETRY, "Multiplier for RSH to yield parasitic resistance of drain");
90  U_SQUARES, CAT_GEOMETRY, "Multiplier for RSH to yield parasitic resistance of source");
92  U_METER, CAT_GEOMETRY, "Drain diffusion perimeter");
94  U_METER, CAT_GEOMETRY, "Source diffusion perimeter");
96  U_NONE, CAT_CONTROL, "Multiplier for M devices connected in parallel");
97 
98  // Initial conditions
99  p.addPar ("IC1", 0.0, false, NO_DEP,
102  U_VOLT, CAT_INITIAL, "Initial condition on Drain-Source voltage");
103 
104  p.addPar ("IC2", 0.0, false, NO_DEP,
107  U_VOLT, CAT_INITIAL, "Initial condition on Gate-Source voltage");
108 
109  p.addPar ("IC3", 0.0, false, NO_DEP,
112  U_VOLT, CAT_INITIAL, "Initial condition on Bulk-Source voltage");
113 
114  p.makeVector ("IC",3);
115 
116  // Set up non-double precision variables:
117  p.addPar ("OFF",false,false, ParameterType::NO_DEP,
119  NULL, U_LOGIC, CAT_VOLT,
120  "Initial condition of no voltage drops across device");
121 }
122 
124 {
125  // Set up double precision variables:
126  p.addPar ("L", 1e-4, false, ParameterType::NO_DEP,
128  U_METER, CAT_GEOMETRY, "Default channel length");
129 
130  p.addPar ("W", 1e-4, false, ParameterType::NO_DEP,
132  U_METER, CAT_GEOMETRY, "Default channel width");
133 
134  p.addPar ("VTO", 0.0, false, ParameterType::NO_DEP,
135  &MOSFET1::Model::vt0, NULL,
136  U_VOLT, CAT_VOLT, "Zero-bias threshold voltage");
137 
138  p.addPar ("KP", 2e-5, false, ParameterType::NO_DEP,
140  U_AMPVM2, CAT_PROCESS, "Transconductance coefficient");
141 
142  p.addPar ("GAMMA", 0.0, false, ParameterType::NO_DEP,
143  &MOSFET1::Model::gamma, NULL,
144  U_VOLTH, CAT_PROCESS, "Bulk threshold parameter");
145 
146  p.addPar ("PHI", 0.6, false, ParameterType::NO_DEP,
147  &MOSFET1::Model::phi, NULL,
148  U_VOLT, CAT_PROCESS, "Surface potential");
149 
150  p.addPar ("LAMBDA", 0.0, false, ParameterType::NO_DEP,
151  &MOSFET1::Model::lambda, NULL,
152  U_VOLTM1, CAT_PROCESS, "Channel-length modulation");
153 
154  p.addPar ("RD", 0.0, false, ParameterType::MIN_RES,
156  U_OHM, CAT_RES, "Drain ohmic resistance");
157 
158  p.addPar ("RS", 0.0, false, ParameterType::MIN_RES,
160  U_OHM, CAT_RES, "Source ohmic resistance");
161 
162  p.addPar ("CBD", 0.0, false, ParameterType::MIN_CAP,
165  U_FARAD, CAT_CAP, "Zero-bias bulk-drain p-n capacitance");
166 
167  p.addPar ("CBS", 0.0, false, ParameterType::MIN_CAP,
170  U_FARAD, CAT_CAP, "Zero-bias bulk-source p-n capacitance");
171 
172  p.addPar ("IS", 1e-14, false, ParameterType::NO_DEP,
174  U_AMP, CAT_CURRENT, "Bulk p-n saturation current");
175 
176  p.addPar ("PB", 0.8, false, ParameterType::NO_DEP,
178  U_VOLT, CAT_VOLT, "Bulk p-n bottom potential");
179 
180  p.addPar ("CGSO", 0.0, false, ParameterType::NO_DEP,
182  U_FARADMM1, CAT_CAP, "Gate-source overlap capacitance/channel width");
183 
184  p.addPar ("CGDO", 0.0, false, ParameterType::NO_DEP,
186  U_FARADMM1, CAT_CAP, "Gate-drain overlap capacitance/channel width");
187 
188  p.addPar ("CGBO", 0.0, false, ParameterType::NO_DEP,
190  U_FARADMM1, CAT_CAP, "Gate-bulk overlap capacitance/channel length");
191 
192  p.addPar ("RSH", 0.0, false, ParameterType::NO_DEP,
194  U_OHM, CAT_RES, "Drain, source diffusion sheet resistance");
195 
196  p.addPar ("CJ", 0.0, false, ParameterType::NO_DEP,
199  U_FARADMM2, CAT_CAP, "Bulk p-n zero-bias bottom capacitance/area");
200 
201  p.addPar ("MJ", 0.5, false, ParameterType::NO_DEP,
203  U_NONE, CAT_DOPING, "Bulk p-n bottom grading coefficient");
204 
205  p.addPar ("CJSW", 0.0, false, ParameterType::NO_DEP,
208  U_FARADMM2, CAT_CAP, "Bulk p-n zero-bias sidewall capacitance/area");
209 
210  p.addPar ("MJSW", 0.5, false, ParameterType::NO_DEP,
212  U_NONE, CAT_DOPING, "Bulk p-n sidewall grading coefficient");
213 
214  p.addPar ("JS", 0.0,false, ParameterType::NO_DEP,
216  U_AMPMM2, CAT_PROCESS, "Bulk p-n saturation current density");
217 
218  p.addPar ("TOX", 1e-7, true, ParameterType::NO_DEP,
220  U_METER, CAT_GEOMETRY, "Gate oxide thickness");
221 
222  p.addPar ("LD", 0.0, false, ParameterType::NO_DEP,
224  U_METER, CAT_DOPING, "Lateral diffusion length");
225 
226  p.addPar ("UO", 600.0, false, ParameterType::NO_DEP,
228  U_CMM2VM1SM1, ParameterCategory(CAT_PROCESS | UNDOCUMENTED), "Surface mobility");
229 
230  p.addPar ("U0", 600.0, false, ParameterType::NO_DEP,
232  U_CMM2VM1SM1, CAT_PROCESS, "Surface mobility");
233 
234  p.addPar ("FC", 0.5, false, ParameterType::NO_DEP,
236  U_NONE, CAT_CAP, "Bulk p-n forward-bias capacitance coefficient");
237 
238  p.addPar ("NSUB", 0.0, false, ParameterType::NO_DEP,
240  U_CMM3, CAT_DOPING, "Substrate doping density");
241 
242  p.addPar ("NSS", 0.0, false, ParameterType::NO_DEP,
244  U_CMM2, CAT_PROCESS, "Surface state density");
245 
246  p.addPar ("TNOM", 27.0, false, ParameterType::NO_DEP,
247  &MOSFET1::Model::tnom, NULL,
248  STANDARD, CAT_NONE, "");
249 
250  p.addPar ("KF", 0.0, false, ParameterType::NO_DEP,
251  &MOSFET1::Model::fNcoef, NULL,
252  U_NONE, CAT_FLICKER, "Flicker noise coefficient");
253 
254  p.addPar ("AF", 1.0, false, ParameterType::NO_DEP,
255  &MOSFET1::Model::fNexp, NULL,
256  U_NONE, CAT_FLICKER, "Flicker noise exponent");
257 
258  // Set up non-double precision variables:
259  p.addPar ("TPG", 0, false, ParameterType::NO_DEP,
261  U_NONE, CAT_MATERIAL, "Gate material type (-1 = same as substrate,"
262  " 0 = aluminum, 1 = opposite of substrate)");
263 
265 }
266 
267 
268 
269 std::vector< std::vector<int> > Instance::jacStamp_DC_SC;
270 std::vector< std::vector<int> > Instance::jacStamp_DC;
271 std::vector< std::vector<int> > Instance::jacStamp_SC;
272 std::vector< std::vector<int> > Instance::jacStamp;
273 
274 
275 std::vector<int> Instance::jacMap_DC_SC;
276 std::vector<int> Instance::jacMap_DC;
277 std::vector<int> Instance::jacMap_SC;
278 std::vector<int> Instance::jacMap;
279 
280 
281 std::vector< std::vector<int> > Instance::jacMap2_DC_SC;
282 std::vector< std::vector<int> > Instance::jacMap2_DC;
283 std::vector< std::vector<int> > Instance::jacMap2_SC;
284 std::vector< std::vector<int> > Instance::jacMap2;
285 
286 
287 // Class Instance
288 //-----------------------------------------------------------------------------
289 // Function : Instance::processParams
290 // Purpose :
291 // Special Notes :
292 // Scope : public
293 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
294 // Creation Date : 6/03/02
295 //-----------------------------------------------------------------------------
297 {
298 
299  // now set the temperature related stuff
301 
302  return true;
303 }
304 
305 //-----------------------------------------------------------------------------
306 // Function : Instance::Instance
307 // Purpose : instance block constructor
308 // Special Notes :
309 // Scope : public
310 // Creator : Tom Russo, Component Information and Models
311 // Creation Date : 3/21/01
312 //-----------------------------------------------------------------------------
314  const Configuration & configuration,
315  const InstanceBlock & IB,
316  Model & Miter,
317  const FactoryBlock & factory_block)
318  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
319  model_(Miter),
320  dNode(0),
321  gNode(0),
322  sNode(0),
323  bNode(0),
324  dNodePrime(0),
325  sNodePrime(0),
326  l(getDeviceOptions().defl),
327  w(getDeviceOptions().defw),
328  OFF(false),
329  drainArea(getDeviceOptions().defad),
330  sourceArea(getDeviceOptions().defas),
331  drainSquares(1.0),
332  sourceSquares(1.0),
333  drainPerimeter(0.0),
334  sourcePerimeter(0.0),
335  sourceConductance(0.0),
336  drainConductance(0.0),
337  temp(getDeviceOptions().temp.getImmutableValue<double>()),
338  numberParallel(1),
339  tTransconductance(0.0),
340  tSurfMob(0.0),
341  tPhi(0.0),
342  tVto(0.0),
343  tSatCur(0.0),
344  tSatCurDens(0.0),
345  tCbd(0.0),
346  tCbs(0.0),
347  tCj(0.0),
348  tCjsw(0.0),
349  tBulkPot(0.0),
350  tDepCap(0.0),
351  tVbi(0.0),
352  icVBS(0.0),
353  icVDS(0.0),
354  icVGS(0.0),
355  von(0.0),
356  vdsat(0.0),
357  sourceVcrit(0.0),
358  drainVcrit(0.0),
359  cd(0.0),
360  cbs(0.0),
361  cbd(0.0),
362  gmbs(0.0),
363  gm(0.0),
364  gds(0.0),
365  gbd(0.0),
366  gbs(0.0),
367  capbd(0.0),
368  capbs(0.0),
369  Cbd(0.0),
370  Cbdsw(0.0),
371  Cbs(0.0),
372  Cbssw(0.0),
373  f2d(0.0),
374  f3d(0.0),
375  f4d(0.0),
376  f2s(0.0),
377  f3s(0.0),
378  f4s(0.0),
379  mode(1),
380  mode_low(0.0),
381  mode_high(0.0),
382  limitedFlag(false),
383  IC_GIVEN(false),
384  Idrain(0.0),
385  Isource(0.0),
386  //calculated quantities
387  EffectiveLength(0),
388  DrainSatCur(0),
389  SourceSatCur(0),
390  GateSourceOverlapCap(0),
391  GateDrainOverlapCap(0),
392  GateBulkOverlapCap(0),
393  OxideCap(0),
394  // solution vector:
395  // local indices
396  li_Drain(-1),
397  li_DrainPrime(-1),
398  li_Source(-1),
399  li_SourcePrime(-1),
400  li_Gate(-1),
401  li_Bulk(-1),
402  //KRS, 2/8/08: adding in local indices to derivatives. Also, adding in
403  // derivatives themselves and initializing to 0
404  li_Draindot(-1),
405  li_DrainPrimedot(-1),
406  li_Sourcedot(-1),
407  li_SourcePrimedot(-1),
408  li_Gatedot(-1),
409  li_Bulkdot(-1),
410 
411  //going to comment out these initializations for now:
412  //Vddot(0.0),
413  //Vsdot(0.0),
414  //Vgdot(0.0),
415  //Vbdot(0.0),
416  //Vdpdot(0.0),
417  //Vspdot(0.0),
418  // matrix and vector pointers:
419  // jacobian:
420  // drain row
421  ADrainEquDrainNodeOffset(-1),
422  ADrainEquDrainPrimeNodeOffset(-1),
423  // gate row
424  AGateEquGateNodeOffset(-1),
425  AGateEquBulkNodeOffset(-1),
426  AGateEquDrainPrimeNodeOffset(-1),
427  AGateEquSourcePrimeNodeOffset(-1),
428  // for new Meyer stuff:
429  AGateEquVGatedotNodeOffset(-1),
430  AGateEquVBulkdotNodeOffset(-1),
431  AGateEquVDrainPrimedotNodeOffset(-1),
432  AGateEquVSourcePrimedotNodeOffset(-1),
433  // source row
434  ASourceEquSourceNodeOffset(-1),
435  ASourceEquSourcePrimeNodeOffset(-1),
436  // bulk row
437  ABulkEquGateNodeOffset(-1),
438  ABulkEquBulkNodeOffset(-1),
439  ABulkEquDrainPrimeNodeOffset(-1),
440  ABulkEquSourcePrimeNodeOffset(-1),
441  // for new Meyer/DAE stuff
442  ABulkEquVGatedotNodeOffset(-1),
443  ABulkEquVBulkdotNodeOffset(-1),
444  ABulkEquVDrainPrimedotNodeOffset(-1),
445  ABulkEquVSourcePrimedotNodeOffset(-1),
446  // drain' row
447  ADrainPrimeEquDrainNodeOffset(-1),
448  ADrainPrimeEquGateNodeOffset(-1),
449  ADrainPrimeEquBulkNodeOffset(-1),
450  ADrainPrimeEquDrainPrimeNodeOffset(-1),
451  ADrainPrimeEquSourcePrimeNodeOffset(-1),
452  // for new Meyer/DAE stuff
453  ADrainPrimeEquVGatedotNodeOffset(-1),
454  ADrainPrimeEquVBulkdotNodeOffset(-1),
455  ADrainPrimeEquVDrainPrimedotNodeOffset(-1),
456  // source' row
457  ASourcePrimeEquGateNodeOffset(-1),
458  ASourcePrimeEquSourceNodeOffset(-1),
459  ASourcePrimeEquBulkNodeOffset(-1),
460  ASourcePrimeEquDrainPrimeNodeOffset(-1),
461  ASourcePrimeEquSourcePrimeNodeOffset(-1),
462  // for new Meyer/DAE stuff
463  ASourcePrimeEquVGatedotNodeOffset(-1),
464  ASourcePrimeEquVBulkdotNodeOffset(-1),
465  ASourcePrimeEquVSourcePrimedotNodeOffset(-1),
466  //the remainder of these are all for new Meyer/DAE:
467  ADraindotEquVDrainNodeOffset(-1),
468  ADraindotEquVDraindotNodeOffset(-1),
469  AGatedotEquVGateNodeOffset(-1),
470  AGatedotEquVGatedotNodeOffset(-1),
471  ASourcedotEquVSourceNodeOffset(-1),
472  ASourcedotEquVSourcedotNodeOffset(-1),
473  ABulkdotEquVBulkNodeOffset(-1),
474  ABulkdotEquVBulkdotNodeOffset(-1),
475  ADrainPrimedotEquVDrainPrimeNodeOffset(-1),
476  ADrainPrimedotEquVDrainPrimedotNodeOffset(-1),
477 
478 
480  // F-Matrix Pointers:
481  // V_d Row:
482  f_DrainEquDrainNodePtr(0), // a
483  f_DrainEquDrainPrimeNodePtr(0), // b
484 
485  // V_g Row:
486  f_GateEquGateNodePtr(0), // c
487  f_GateEquBulkNodePtr(0), // d
488  f_GateEquDrainPrimeNodePtr(0), // e
489  f_GateEquSourcePrimeNodePtr(0), // f
490  // for new Meyer stuff:
491  f_GateEquVGatedotNodePtr(0),
492  f_GateEquVBulkdotNodePtr(0),
493  f_GateEquVDrainPrimedotNodePtr(0),
494  f_GateEquVSourcePrimedotNodePtr(0),
495 
496  // V_s Row:
497  f_SourceEquSourceNodePtr(0), // g
498  f_SourceEquSourcePrimeNodePtr(0), // h
499 
500  // V_b Row:
501  f_BulkEquGateNodePtr(0), // i
502  f_BulkEquBulkNodePtr(0), // j
503  f_BulkEquDrainPrimeNodePtr(0), // k
504  f_BulkEquSourcePrimeNodePtr(0), // l
505  // for new Meyer/DAE stuff
506  f_BulkEquVGatedotNodePtr(0),
507  f_BulkEquVBulkdotNodePtr(0),
508  f_BulkEquVDrainPrimedotNodePtr(0),
509  f_BulkEquVSourcePrimedotNodePtr(0),
510 
511  // V_d' Row:
512  f_DrainPrimeEquDrainNodePtr(0), // m
513  f_DrainPrimeEquGateNodePtr(0), // n
514  f_DrainPrimeEquBulkNodePtr(0), // o
515  f_DrainPrimeEquDrainPrimeNodePtr(0), // p
516  f_DrainPrimeEquSourcePrimeNodePtr(0), // q
517  // for new Meyer/DAE stuff
518  f_DrainPrimeEquVGatedotNodePtr(0),
519  f_DrainPrimeEquVBulkdotNodePtr(0),
520  f_DrainPrimeEquVDrainPrimedotNodePtr(0),
521 
522  // V_s' Row:
523  f_SourcePrimeEquGateNodePtr(0), // r
524  f_SourcePrimeEquSourceNodePtr(0), // s
525  f_SourcePrimeEquBulkNodePtr(0), // t
526  f_SourcePrimeEquDrainPrimeNodePtr(0), // u
527  f_SourcePrimeEquSourcePrimeNodePtr(0), // v
528  // for new Meyer/DAE stuff
529  f_SourcePrimeEquVGatedotNodePtr(0),
530  f_SourcePrimeEquVBulkdotNodePtr(0),
531  f_SourcePrimeEquVSourcePrimedotNodePtr(0),
532 
533  //the remainder of these are all for new Meyer/DAE:
534  f_DraindotEquVDrainNodePtr(0),
535  f_DraindotEquVDraindotNodePtr(0),
536  f_GatedotEquVGateNodePtr(0),
537  f_GatedotEquVGatedotNodePtr(0),
538  f_SourcedotEquVSourceNodePtr(0),
539  f_SourcedotEquVSourcedotNodePtr(0),
540  f_BulkdotEquVBulkNodePtr(0),
541  f_BulkdotEquVBulkdotNodePtr(0),
542  f_DrainPrimedotEquVDrainPrimeNodePtr(0),
543  f_DrainPrimedotEquVDrainPrimedotNodePtr(0),
544  f_SourcePrimedotEquVSourcePrimeNodePtr(0),
545  f_SourcePrimedotEquVSourcePrimedotNodePtr(0),
546 
547  // Q-Matrix Pointers:
548  // V_d Row:
549  q_DrainEquDrainNodePtr(0), // a
550  q_DrainEquDrainPrimeNodePtr(0), // b
551 
552  // V_g Row:
553  q_GateEquGateNodePtr(0), // c
554  q_GateEquBulkNodePtr(0), // d
555  q_GateEquDrainPrimeNodePtr(0), // e
556  q_GateEquSourcePrimeNodePtr(0), // f
557  // for new Meyer stuff:
558  q_GateEquVGatedotNodePtr(0),
559  q_GateEquVBulkdotNodePtr(0),
560  q_GateEquVDrainPrimedotNodePtr(0),
561  q_GateEquVSourcePrimedotNodePtr(0),
562 
563  // V_s Row:
564  q_SourceEquSourceNodePtr(0), // g
565  q_SourceEquSourcePrimeNodePtr(0), // h
566 
567  // V_b Row:
568  q_BulkEquGateNodePtr(0), // i
569  q_BulkEquBulkNodePtr(0), // j
570  q_BulkEquDrainPrimeNodePtr(0), // k
571  q_BulkEquSourcePrimeNodePtr(0), // l
572  // for new Meyer/DAE stuff
573  q_BulkEquVGatedotNodePtr(0),
574  q_BulkEquVBulkdotNodePtr(0),
575  q_BulkEquVDrainPrimedotNodePtr(0),
576  q_BulkEquVSourcePrimedotNodePtr(0),
577 
578  // V_d' Row:
579  q_DrainPrimeEquDrainNodePtr(0), // m
580  q_DrainPrimeEquGateNodePtr(0), // n
581  q_DrainPrimeEquBulkNodePtr(0), // o
582  q_DrainPrimeEquDrainPrimeNodePtr(0), // p
583  q_DrainPrimeEquSourcePrimeNodePtr(0), // q
584  // for new Meyer/DAE stuff
585  q_DrainPrimeEquVGatedotNodePtr(0),
586  q_DrainPrimeEquVBulkdotNodePtr(0),
587  q_DrainPrimeEquVDrainPrimedotNodePtr(0),
588 
589  // V_s' Row:
590  q_SourcePrimeEquGateNodePtr(0), // r
591  q_SourcePrimeEquSourceNodePtr(0), // s
592  q_SourcePrimeEquBulkNodePtr(0), // t
593  q_SourcePrimeEquDrainPrimeNodePtr(0), // u
594  q_SourcePrimeEquSourcePrimeNodePtr(0), // v
595  // for new Meyer/DAE stuff
596  q_SourcePrimeEquVGatedotNodePtr(0),
597  q_SourcePrimeEquVBulkdotNodePtr(0),
598  q_SourcePrimeEquVSourcePrimedotNodePtr(0),
599 
600  //the remainder of these are all for new Meyer/DAE:
601  q_DraindotEquVDrainNodePtr(0),
602  q_DraindotEquVDraindotNodePtr(0),
603  q_GatedotEquVGateNodePtr(0),
604  q_GatedotEquVGatedotNodePtr(0),
605  q_SourcedotEquVSourceNodePtr(0),
606  q_SourcedotEquVSourcedotNodePtr(0),
607  q_BulkdotEquVBulkNodePtr(0),
608  q_BulkdotEquVBulkdotNodePtr(0),
609  q_DrainPrimedotEquVDrainPrimeNodePtr(0),
610  q_DrainPrimedotEquVDrainPrimedotNodePtr(0),
611  q_SourcePrimedotEquVSourcePrimeNodePtr(0),
612  q_SourcePrimedotEquVSourcePrimedotNodePtr(0),
613 #endif
614 
615  vbd(0.0),
616  vbs(0.0),
617  vgs(0.0),
618  vds(0.0),
619  vbd_old(0.0),
620  vbs_old(0.0),
621  vgs_old(0.0),
622  vds_old(0.0),
623  vbd_orig(0.0),
624  vbs_orig(0.0),
625  vgs_orig(0.0),
626  vds_orig(0.0),
627  capgs(0.0),
628  dcapgsdvgs(0.0),
629  dcapgsdvgd(0.0),
630  dcapgsdvgb(0.0),
631  qgs(0.0),
632  capgd(0.0),
633  dcapgddvgs(0.0),
634  dcapgddvgb(0.0),
635  dcapgddvgd(0.0),
636  qgd(0.0),
637  capgb(0.0),
638  dcapgbdvgs(0.0),
639  dcapgbdvgb(0.0),
640  dcapgbdvgd(0.0),
641  qgb(0.0),
642  qbd(0.0),
643  cqbd(0.0),
644  qbs(0.0),
645  // local indices
646  li_store_vbd(-1),
647  li_store_vbs(-1),
648  li_store_vgs(-1),
649  li_store_vds(-1),
650  li_store_von(-1),
651  li_store_dev_id(-1),
652  li_store_dev_ig(-1),
653  li_store_dev_is(-1),
654  li_store_dev_ib(-1),
655  li_state_qgs(-1),
656  li_state_qgd(-1),
657  li_state_qgb(-1),
658  li_state_capgs(-1),
659  li_state_capgd(-1),
660  li_state_capgb(-1),
661  li_state_qbd(-1),
662  li_state_qbs(-1),
663  blockHomotopyID(0),
664  randomPerturb(0.0)
665 {
666  numExtVars = 4;
667 
668  setNumStoreVars(5);
669  numStateVars = 8;
670  numLeadCurrentStoreVars = 4; // drain, gate, source & base lead currents
671 
672  devConMap.resize(4);
673  devConMap[0] = 1;
674  devConMap[1] = 2;
675  devConMap[2] = 1;
676  devConMap[3] = 3;
677 
679  devSupport.getGainScaleBlockID(getDeviceOptions().numGainScaleBlocks);
680  randomPerturb =
682 
683  //KRS, 2/11/08: different Jacobian stamps depending on new/old DAE. First
684  //one here is new Meyer::
685 
686  if (getDeviceOptions().newMeyerFlag)
687  {
688  if( jacStamp.empty() )
689  {
690  //We have to compute all of the separate maps and stamps by hand here
691  //since the old jacStampMap function won't work on the new stamp
692  //structure we're imposing here.
693 
694  // stamp for RS!=0, RD!=0
695  jacStamp_DC_SC.resize(12);
696  jacStamp_DC_SC[0].resize(2); // Drain row
697  jacStamp_DC_SC[0][0]=0; // d-d
698  jacStamp_DC_SC[0][1]=4; // d-d'
699  jacStamp_DC_SC[1].resize(8); // Gate row
700  jacStamp_DC_SC[1][0]=1; // g-g
701  jacStamp_DC_SC[1][1]=3; // g-b
702  jacStamp_DC_SC[1][2]=4; // g-d'
703  jacStamp_DC_SC[1][3]=5; // g-s'
704  jacStamp_DC_SC[1][4]=7; // g-gdot
705  jacStamp_DC_SC[1][5]=9; // g-bdot
706  jacStamp_DC_SC[1][6]=10; // g-dprimedot
707  jacStamp_DC_SC[1][7]=11; // g-sprimedot
708  jacStamp_DC_SC[2].resize(2); // Source row
709  jacStamp_DC_SC[2][0]=2; // s-s
710  jacStamp_DC_SC[2][1]=5; // s-s'
711  jacStamp_DC_SC[3].resize(8); // Bulk row
712  jacStamp_DC_SC[3][0]=1; // b-g
713  jacStamp_DC_SC[3][1]=3; // b-b
714  jacStamp_DC_SC[3][2]=4; // b-d'
715  jacStamp_DC_SC[3][3]=5; // b-s'
716  jacStamp_DC_SC[3][4]=7; // b-gdot
717  jacStamp_DC_SC[3][5]=9; // b-bdot
718  jacStamp_DC_SC[3][6]=10; // b-dprimedot
719  jacStamp_DC_SC[3][7]=11; // b-sprimedot
720  jacStamp_DC_SC[4].resize(8); // Drain' row
721  jacStamp_DC_SC[4][0]=0; // d'-d
722  jacStamp_DC_SC[4][1]=1; // d'-g
723  jacStamp_DC_SC[4][2]=3; // d'-b
724  jacStamp_DC_SC[4][3]=4; // d'-d'
725  jacStamp_DC_SC[4][4]=5; // d'-s'
726  jacStamp_DC_SC[4][5]=7; // d'-gdot
727  jacStamp_DC_SC[4][6]=9; // d'-bdot
728  jacStamp_DC_SC[4][7]=10; // d'-dprimedot
729  jacStamp_DC_SC[5].resize(8); // Source' row
730  jacStamp_DC_SC[5][0]=1; // s'-g
731  jacStamp_DC_SC[5][1]=2; // s'-s
732  jacStamp_DC_SC[5][2]=3; // s'-b
733  jacStamp_DC_SC[5][3]=4; // s'-d'
734  jacStamp_DC_SC[5][4]=5; // s'-s'
735  jacStamp_DC_SC[5][5]=7; // s'-gdot
736  jacStamp_DC_SC[5][6]=9; // s'-bdot
737  jacStamp_DC_SC[5][7]=11; // s'-sprimedot
738  jacStamp_DC_SC[6].resize(2); // Ddot row
739 
740  //Adding in some extra spots in drain, source, drainprime, sourceprime to
741  //try to force the jacStampMap function to work the way its intended.
742  jacStamp_DC_SC[6][0]=0; // ddot-d
743  jacStamp_DC_SC[6][1]=6; // ddot-ddot
744  jacStamp_DC_SC[7].resize(2); // Gdot row
745  jacStamp_DC_SC[7][0]=1; // gdot-g
746  jacStamp_DC_SC[7][1]=7; // gdot-gdot
747  jacStamp_DC_SC[8].resize(2); // Sdot row
748  jacStamp_DC_SC[8][0]=2; // sdot-s
749  jacStamp_DC_SC[8][1]=8; // sdot-sdot
750  jacStamp_DC_SC[9].resize(2); // Bdot row
751  jacStamp_DC_SC[9][0]=3; // bdot-b
752  jacStamp_DC_SC[9][1]=9; // bdot-bdot
753  jacStamp_DC_SC[10].resize(2); // Dprimedot row
754  jacStamp_DC_SC[10][0]=4; // dprimedot-dprime
755  jacStamp_DC_SC[10][1]=10; // dprimedot-dprimedot
756  jacStamp_DC_SC[11].resize(2); // Sprimedot row
757  jacStamp_DC_SC[11][0]=5; // sprimedot-sprime
758  jacStamp_DC_SC[11][1]=11; // sprimedot-sprimedot
759 
760  jacMap_DC_SC.resize(12);
761  jacMap2_DC_SC.resize(12);
762  for (int i=0; i < 12; i++)
763  {
764  jacMap_DC_SC[i]=i;
765  jacMap2_DC_SC[i].resize(jacStamp_DC_SC[i].size());
766  for (int j=0; j < jacStamp_DC_SC[i].size(); j++)
767  jacMap2_DC_SC[i][j]=j;
768  }
769 
770  //Now for _DC stuff
771  jacStamp_DC.resize(10);
772  jacStamp_DC[0].resize(2);
773  jacStamp_DC[0][0]=0;
774  jacStamp_DC[0][1]=4;
775  jacStamp_DC[1].resize(8);
776  jacStamp_DC[1][0]=1;
777  jacStamp_DC[1][1]=2;
778  jacStamp_DC[1][2]=3;
779  jacStamp_DC[1][3]=4;
780  jacStamp_DC[1][4]=6;
781  jacStamp_DC[1][5]=7;
782  jacStamp_DC[1][6]=8;
783  jacStamp_DC[1][7]=9;
784  jacStamp_DC[2].resize(7);
785  jacStamp_DC[2][0]=1;
786  jacStamp_DC[2][1]=2;
787  jacStamp_DC[2][2]=3;
788  jacStamp_DC[2][3]=4;
789  jacStamp_DC[2][4]=6;
790  jacStamp_DC[2][5]=7;
791  jacStamp_DC[2][6]=8;
792  jacStamp_DC[3].resize(8);
793  jacStamp_DC[3][0]=1;
794  jacStamp_DC[3][1]=2;
795  jacStamp_DC[3][2]=3;
796  jacStamp_DC[3][3]=4;
797  jacStamp_DC[3][4]=6;
798  jacStamp_DC[3][5]=7;
799  jacStamp_DC[3][6]=8;
800  jacStamp_DC[3][7]=9;
801  jacStamp_DC[4].resize(8);
802  jacStamp_DC[4][0]=0;
803  jacStamp_DC[4][1]=1;
804  jacStamp_DC[4][2]=2;
805  jacStamp_DC[4][3]=3;
806  jacStamp_DC[4][4]=4;
807  jacStamp_DC[4][5]=6;
808  jacStamp_DC[4][6]=8;
809  jacStamp_DC[4][7]=9;
810  jacStamp_DC[5].resize(2);
811  jacStamp_DC[5][0]=0;
812  jacStamp_DC[5][1]=5;
813  jacStamp_DC[6].resize(2);
814  jacStamp_DC[6][0]=1;
815  jacStamp_DC[6][1]=6;
816  jacStamp_DC[7].resize(2);
817  jacStamp_DC[7][0]=2;
818  jacStamp_DC[7][1]=7;
819  jacStamp_DC[8].resize(2);
820  jacStamp_DC[8][0]=3;
821  jacStamp_DC[8][1]=8;
822  jacStamp_DC[9].resize(2);
823  jacStamp_DC[9][0]=4;
824  jacStamp_DC[9][1]=9;
825 
826  jacMap_DC.resize(12);
827  for (int i=0; i < 5; i++)
828  jacMap_DC[i]=i;
829  jacMap_DC[5]=2;
830  jacMap_DC[6]=5;
831  jacMap_DC[7]=6;
832  jacMap_DC[8]=7;
833  jacMap_DC[9]=8;
834  jacMap_DC[10]=9;
835  jacMap_DC[11]=7;
836 
837  jacMap2_DC.resize(12);
838  jacMap2_DC[0].resize(2);
839  jacMap2_DC[0][0]=0;
840  jacMap2_DC[0][1]=1;
841  jacMap2_DC[1].resize(8);
842  jacMap2_DC[1][0]=0;
843  jacMap2_DC[1][1]=2;
844  jacMap2_DC[1][2]=3;
845  jacMap2_DC[1][3]=1;
846  jacMap2_DC[1][4]=4;
847  jacMap2_DC[1][5]=6;
848  jacMap2_DC[1][6]=7;
849  jacMap2_DC[1][7]=5;
850  jacMap2_DC[2].resize(2);
851  jacMap2_DC[2][0]=0;
852  jacMap2_DC[2][1]=0;
853  jacMap2_DC[3].resize(8);
854  jacMap2_DC[3][0]=0;
855  jacMap2_DC[3][1]=2;
856  jacMap2_DC[3][2]=3;
857  jacMap2_DC[3][3]=1;
858  jacMap2_DC[3][4]=4;
859  jacMap2_DC[3][5]=6;
860  jacMap2_DC[3][6]=7;
861  jacMap2_DC[3][7]=5;
862  jacMap2_DC[4].resize(8);
863  jacMap2_DC[4][0]=0;
864  jacMap2_DC[4][1]=1;
865  jacMap2_DC[4][2]=3;
866  jacMap2_DC[4][3]=4;
867  jacMap2_DC[4][4]=2;
868  jacMap2_DC[4][5]=5;
869  jacMap2_DC[4][6]=6;
870  jacMap2_DC[4][7]=7;
871  jacMap2_DC[5].resize(8);
872  jacMap2_DC[5][0]=0;
873  jacMap2_DC[5][1]=1;
874  jacMap2_DC[5][2]=2;
875  jacMap2_DC[5][3]=3;
876  jacMap2_DC[5][4]=1;
877  jacMap2_DC[5][5]=4;
878  jacMap2_DC[5][6]=6;
879  jacMap2_DC[5][7]=5;
880  for (int i=6; i < 12; i++)
881  {
882  jacMap2_DC[i].resize(2);
883  for (int j=0; j < 2; j++)
884  {
885  jacMap2_DC[i][j]=j;
886  }
887  }
888 
889  //Now for _SC stuff
890  jacStamp_SC.resize(10);
891  jacStamp_SC[0].resize(7);
892  jacStamp_SC[0][0]=0;
893  jacStamp_SC[0][1]=1;
894  jacStamp_SC[0][2]=3;
895  jacStamp_SC[0][3]=4;
896  jacStamp_SC[0][4]=5;
897  jacStamp_SC[0][5]=6;
898  jacStamp_SC[0][6]=8;
899  jacStamp_SC[1].resize(8);
900  jacStamp_SC[1][0]=0;
901  jacStamp_SC[1][1]=1;
902  jacStamp_SC[1][2]=3;
903  jacStamp_SC[1][3]=4;
904  jacStamp_SC[1][4]=5;
905  jacStamp_SC[1][5]=6;
906  jacStamp_SC[1][6]=8;
907  jacStamp_SC[1][7]=9;
908  jacStamp_SC[2].resize(2);
909  jacStamp_SC[2][0]=2;
910  jacStamp_SC[2][1]=4;
911  jacStamp_SC[3].resize(8);
912  jacStamp_SC[3][0]=0;
913  jacStamp_SC[3][1]=1;
914  jacStamp_SC[3][2]=3;
915  jacStamp_SC[3][3]=4;
916  jacStamp_SC[3][4]=5;
917  jacStamp_SC[3][5]=6;
918  jacStamp_SC[3][6]=8;
919  jacStamp_SC[3][7]=9;
920  jacStamp_SC[4].resize(8);
921  jacStamp_SC[4][0]=0;
922  jacStamp_SC[4][1]=1;
923  jacStamp_SC[4][2]=2;
924  jacStamp_SC[4][3]=3;
925  jacStamp_SC[4][4]=4;
926  jacStamp_SC[4][5]=6;
927  jacStamp_SC[4][6]=8;
928  jacStamp_SC[4][7]=9;
929  jacStamp_SC[5].resize(2);
930  jacStamp_SC[5][0]=0;
931  jacStamp_SC[5][1]=5;
932  jacStamp_SC[6].resize(2);
933  jacStamp_SC[6][0]=1;
934  jacStamp_SC[6][1]=6;
935  jacStamp_SC[7].resize(2);
936  jacStamp_SC[7][0]=2;
937  jacStamp_SC[7][1]=7;
938  jacStamp_SC[8].resize(2);
939  jacStamp_SC[8][0]=3;
940  jacStamp_SC[8][1]=8;
941  jacStamp_SC[9].resize(2);
942  jacStamp_SC[9][0]=4;
943  jacStamp_SC[9][1]=9;
944 
945  jacMap_SC.resize(12);
946  for (int i=0; i < 4; i++)
947  jacMap_SC[i]=i;
948  jacMap_SC[4]=0;
949  jacMap_SC[5]=4;
950  jacMap_SC[6]=5;
951  jacMap_SC[7]=6;
952  jacMap_SC[8]=7;
953  jacMap_SC[9]=8;
954  jacMap_SC[10]=5;
955  jacMap_SC[11]=9;
956 
957  jacMap2_SC.resize(12);
958  jacMap2_SC[0].resize(2);
959  jacMap2_SC[0][0]=0;
960  jacMap2_SC[0][1]=0;
961  jacMap2_SC[1].resize(8);
962  jacMap2_SC[1][0]=1;
963  jacMap2_SC[1][1]=2;
964  jacMap2_SC[1][2]=0;
965  jacMap2_SC[1][3]=3;
966  jacMap2_SC[1][4]=5;
967  jacMap2_SC[1][5]=6;
968  jacMap2_SC[1][6]=4;
969  jacMap2_SC[1][7]=7;
970  jacMap2_SC[2].resize(2);
971  jacMap2_SC[2][0]=0;
972  jacMap2_SC[2][1]=1;
973  jacMap2_SC[3].resize(8);
974  jacMap2_SC[3][0]=1;
975  jacMap2_SC[3][1]=2;
976  jacMap2_SC[3][2]=0;
977  jacMap2_SC[3][3]=3;
978  jacMap2_SC[3][4]=5;
979  jacMap2_SC[3][5]=6;
980  jacMap2_SC[3][6]=4;
981  jacMap2_SC[3][7]=7;
982  jacMap2_SC[4].resize(8);
983  jacMap2_SC[4][0]=0;
984  jacMap2_SC[4][1]=1;
985  jacMap2_SC[4][2]=2;
986  jacMap2_SC[4][3]=0;
987  jacMap2_SC[4][4]=3;
988  jacMap2_SC[4][5]=5;
989  jacMap2_SC[4][6]=6;
990  jacMap2_SC[4][7]=4;
991  jacMap2_SC[5].resize(8);
992  jacMap2_SC[5][0]=1;
993  jacMap2_SC[5][1]=2;
994  jacMap2_SC[5][2]=3;
995  jacMap2_SC[5][3]=0;
996  jacMap2_SC[5][4]=4;
997  jacMap2_SC[5][5]=5;
998  jacMap2_SC[5][6]=6;
999  jacMap2_SC[5][7]=7;
1000  for (int i=6; i < 12; i++)
1001  {
1002  jacMap2_SC[i].resize(2);
1003  for (int j=0; j < 2; j++)
1004  {
1005  jacMap2_SC[i][j]=j;
1006  }
1007  }
1008 
1009  //Now for final stuff
1010  jacStamp.resize(8);
1011  jacStamp[0].resize(7);
1012  jacStamp[0][0]=0;
1013  jacStamp[0][1]=1;
1014  jacStamp[0][2]=2;
1015  jacStamp[0][3]=3;
1016  jacStamp[0][4]=4;
1017  jacStamp[0][5]=5;
1018  jacStamp[0][6]=7;
1019  jacStamp[1].resize(8);
1020  jacStamp[1][0]=0;
1021  jacStamp[1][1]=1;
1022  jacStamp[1][2]=2;
1023  jacStamp[1][3]=3;
1024  jacStamp[1][4]=4;
1025  jacStamp[1][5]=5;
1026  jacStamp[1][6]=6;
1027  jacStamp[1][7]=7;
1028  jacStamp[2].resize(7);
1029  jacStamp[2][0]=0;
1030  jacStamp[2][1]=1;
1031  jacStamp[2][2]=2;
1032  jacStamp[2][3]=3;
1033  jacStamp[2][4]=5;
1034  jacStamp[2][5]=6;
1035  jacStamp[2][6]=7;
1036  jacStamp[3].resize(8);
1037  jacStamp[3][0]=0;
1038  jacStamp[3][1]=1;
1039  jacStamp[3][2]=2;
1040  jacStamp[3][3]=3;
1041  jacStamp[3][4]=4;
1042  jacStamp[3][5]=5;
1043  jacStamp[3][6]=6;
1044  jacStamp[3][7]=7;
1045  jacStamp[4].resize(2);
1046  jacStamp[4][0]=0;
1047  jacStamp[4][1]=4;
1048  jacStamp[5].resize(2);
1049  jacStamp[5][0]=1;
1050  jacStamp[5][1]=5;
1051  jacStamp[6].resize(2);
1052  jacStamp[6][0]=2;
1053  jacStamp[6][1]=6;
1054  jacStamp[7].resize(2);
1055  jacStamp[7][0]=3;
1056  jacStamp[7][1]=7;
1057 
1058  jacMap.resize(12);
1059  for (int i=0; i < 4; i++)
1060  jacMap[i]=i;
1061  jacMap[4]=0;
1062  jacMap[5]=2;
1063  jacMap[6]=4;
1064  jacMap[7]=5;
1065  jacMap[8]=6;
1066  jacMap[9]=7;
1067  jacMap[10]=4;
1068  jacMap[11]=6;
1069 
1070  jacMap2.resize(12);
1071  jacMap2[0].resize(2);
1072  jacMap2[0][0]=0;
1073  jacMap2[0][1]=0;
1074  jacMap2[1].resize(8);
1075  jacMap2[1][0]=1;
1076  jacMap2[1][1]=3;
1077  jacMap2[1][2]=0;
1078  jacMap2[1][3]=2;
1079  jacMap2[1][4]=5;
1080  jacMap2[1][5]=7;
1081  jacMap2[1][6]=4;
1082  jacMap2[1][7]=6;
1083  jacMap2[2].resize(2);
1084  jacMap2[2][0]=0;
1085  jacMap2[2][1]=0;
1086  jacMap2[3].resize(8);
1087  jacMap2[3][0]=1;
1088  jacMap2[3][1]=3;
1089  jacMap2[3][2]=0;
1090  jacMap2[3][3]=2;
1091  jacMap2[3][4]=5;
1092  jacMap2[3][5]=7;
1093  jacMap2[3][6]=4;
1094  jacMap2[3][7]=6;
1095  jacMap2[4].resize(8);
1096  jacMap2[4][0]=0;
1097  jacMap2[4][1]=1;
1098  jacMap2[4][2]=3;
1099  jacMap2[4][3]=0;
1100  jacMap2[4][4]=2;
1101  jacMap2[4][5]=5;
1102  jacMap2[4][6]=6;
1103  jacMap2[4][7]=4;
1104  jacMap2[5].resize(8);
1105  jacMap2[5][0]=1;
1106  jacMap2[5][1]=2;
1107  jacMap2[5][2]=3;
1108  jacMap2[5][3]=0;
1109  jacMap2[5][4]=2;
1110  jacMap2[5][5]=4;
1111  jacMap2[5][6]=6;
1112  jacMap2[5][7]=5;
1113  for (int i=6; i < 12; i++)
1114  {
1115  jacMap2[i].resize(2);
1116  for (int j=0; j < 2; j++)
1117  {
1118  jacMap2[i][j]=j;
1119  }
1120  }
1121  }
1122  }
1123  else
1124  {
1125  if( jacStamp.empty() )
1126  {
1127  // stamp for RS!=0, RD!=0
1128  jacStamp_DC_SC.resize(6);
1129  jacStamp_DC_SC[0].resize(2); // Drain row
1130  jacStamp_DC_SC[0][0]=0; // d-d
1131  jacStamp_DC_SC[0][1]=4; // d-d'
1132  jacStamp_DC_SC[1].resize(4); // Gate row
1133  jacStamp_DC_SC[1][0]=1; // g-g
1134  jacStamp_DC_SC[1][1]=3; // g-b
1135  jacStamp_DC_SC[1][2]=4; // g-d'
1136  jacStamp_DC_SC[1][3]=5; // g-s'
1137  jacStamp_DC_SC[2].resize(2); // Source row
1138  jacStamp_DC_SC[2][0]=2; // s-s
1139  jacStamp_DC_SC[2][1]=5; // s-s'
1140  jacStamp_DC_SC[3].resize(4); // Bulk row
1141  jacStamp_DC_SC[3][0]=1; // b-g
1142  jacStamp_DC_SC[3][1]=3; // b-b
1143  jacStamp_DC_SC[3][2]=4; // b-d'
1144  jacStamp_DC_SC[3][3]=5; // b-s'
1145  jacStamp_DC_SC[4].resize(5); // Drain' row
1146  jacStamp_DC_SC[4][0]=0; // d'-d
1147  jacStamp_DC_SC[4][1]=1; // d'-g
1148  jacStamp_DC_SC[4][2]=3; // d'-b
1149  jacStamp_DC_SC[4][3]=4; // d'-d'
1150  jacStamp_DC_SC[4][4]=5; // d'-s'
1151  jacStamp_DC_SC[5].resize(5); // Source' row
1152  jacStamp_DC_SC[5][0]=1; // s'-g
1153  jacStamp_DC_SC[5][1]=2; // s'-s
1154  jacStamp_DC_SC[5][2]=3; // s'-b
1155  jacStamp_DC_SC[5][3]=4; // s'-d'
1156  jacStamp_DC_SC[5][4]=5; // s'-s'
1157 
1158  jacMap_DC_SC.clear();
1160  jacStamp_DC, jacMap_DC, jacMap2_DC, 5, 2, 6);
1161 
1163  jacStamp_SC, jacMap_SC, jacMap2_SC, 4, 0, 6);
1164 
1166  jacStamp, jacMap, jacMap2, 4, 0, 6);
1167 
1168  }
1169  }
1170 
1171  // Set params to constant default values:
1172  setDefaultParams ();
1173 
1174  // Set params according to instance line and constant defaults from metadata:
1175  setParams (IB.params);
1176 
1177  // Set any non-constant parameter defaults:
1178  if (!given("TEMP"))
1179  temp = getDeviceOptions().temp.getImmutableValue<double>();
1180  if (!given("L"))
1181  l =model_.model_l;
1182  if (!given("W"))
1183  w = model_.model_w;
1184 
1185  // process source/drain series resistance (from mos1temp)
1186  if(model_.drainResistance != 0)
1187  {
1189  }
1190  else if (model_.given("RSH"))
1191  {
1192  if(model_.sheetResistance != 0)
1193  {
1196  }
1197  else
1198  {
1199  drainConductance = 0;
1200  }
1201  }
1202  else
1203  {
1204  drainConductance = 0;
1205  }
1206  if(model_.sourceResistance != 0)
1207  {
1209  }
1210  else if (model_.given("RSH"))
1211  {
1212  if(model_.sheetResistance != 0)
1213  {
1216  }
1217  else
1218  {
1219  sourceConductance = 0;
1220  }
1221  }
1222  else
1223  {
1224  sourceConductance = 0;
1225  }
1226 
1227  if (!given("AD"))
1229  if (!given("AS"))
1231 
1232  // Calculate any parameters specified as expressions:
1233 
1235 
1236  // calculate dependent (ie computed) params and check for errors:
1237 
1238  if(l - 2 * model_.latDiff <=0)
1239  {
1240  UserError0(*this) << "Effective channel length less than zero.";
1241  }
1242 
1248 
1249  //Again, have to augment depending on old/new dae:
1250  if (getDeviceOptions().newMeyerFlag)
1251  {
1252  numIntVars = 2*(((sourceConductance == 0.0)?0:1)+((drainConductance == 0.0) ? 0:1));
1253  numIntVars += 4;
1254  }
1255  else
1256  {
1257  numIntVars = (((sourceConductance == 0.0)?0:1)+((drainConductance == 0.0) ? 0:1));
1258  }
1259  processParams ();
1260 }
1261 
1262 //-----------------------------------------------------------------------------
1263 // Function : Instance::~Instance
1264 // Purpose : destructor
1265 // Special Notes :
1266 // Scope : public
1267 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1268 // Creation Date : 3/16/00
1269 //-----------------------------------------------------------------------------
1271 {
1272 }
1273 
1274 //-----------------------------------------------------------------------------
1275 // Function : Instance::registerLIDs
1276 // Purpose :
1277 // Special Notes :
1278 // Scope : public
1279 // Creator : Robert Hoekstra, Computational Sciences
1280 // Creation Date : 6/21/02
1281 //-----------------------------------------------------------------------------
1282 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
1283  const std::vector<int> & extLIDVecRef )
1284 {
1285  // Again, need to change code depending on old/new dae:
1286  if (getDeviceOptions().newMeyerFlag)
1287  {
1288  numIntVars = 2*(((sourceConductance == 0.0)?0:1)+((drainConductance == 0.0) ? 0:1));
1289  numIntVars += 4;
1290  }
1291  else
1292  {
1293  numIntVars = (((sourceConductance == 0.0)?0:1)+((drainConductance == 0.0) ? 0:1));
1294  }
1295 
1296  AssertLIDs(intLIDVecRef.size() == numIntVars);
1297  AssertLIDs(extLIDVecRef.size() == numExtVars);
1298 
1299 #ifdef Xyce_DEBUG_DEVICE
1300  if (getDeviceOptions().debugLevel > 0)
1301  {
1302  Xyce::dout() << section_divider << std::endl;
1303  Xyce::dout() << " In Instance::register LIDs\n\n";
1304  Xyce::dout() << " name = " << getName() << std::endl;
1305  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
1306  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
1307  }
1308 #endif
1309 
1310  // copy over the global ID lists.
1311  intLIDVec = intLIDVecRef;
1312  extLIDVec = extLIDVecRef;
1313 
1314  // now use these lists to obtain the indices into the
1315  // linear algebra entities. This assumes an order.
1316  // For the matrix indices, first do the rows.
1317 
1318  li_Drain = extLIDVec[0];
1319  li_Gate = extLIDVec[1];
1320  li_Source = extLIDVec[2];
1321  li_Bulk = extLIDVec[3];
1322 
1323  int intLoc = 0;
1324 
1325  if( drainConductance )
1326  li_DrainPrime = intLIDVec[intLoc++];
1327  else
1329 
1330  if( sourceConductance )
1331  li_SourcePrime = intLIDVec[intLoc++];
1332  else
1334 
1335  //more augmentation for new Meyer!
1336  if (getDeviceOptions().newMeyerFlag)
1337  {
1338  li_Draindot = intLIDVec[intLoc++];
1339  li_Gatedot = intLIDVec[intLoc++];
1340  li_Sourcedot = intLIDVec[intLoc++];
1341  li_Bulkdot = intLIDVec[intLoc++];
1342 
1343  if( drainConductance )
1344  li_DrainPrimedot = intLIDVec[intLoc++];
1345  else
1347 
1348  if( sourceConductance )
1349  li_SourcePrimedot = intLIDVec[intLoc++];
1350  else
1352  }
1353 
1354 #ifdef Xyce_DEBUG_DEVICE
1355  if (getDeviceOptions().debugLevel > 0)
1356  {
1357  Xyce::dout() << "\n variable local indices:\n";
1358  Xyce::dout() << " li_Drain = " << li_Drain << std::endl;
1359  Xyce::dout() << " li_DrainPrime = " << li_DrainPrime << std::endl;
1360  Xyce::dout() << " li_Source = " << li_Source << std::endl;
1361  Xyce::dout() << " li_SourcePrime = " << li_SourcePrime << std::endl;
1362  Xyce::dout() << " li_Gate = " << li_Gate << std::endl;
1363  Xyce::dout() << " li_Bulk = " << li_Bulk << std::endl;
1364 
1365  Xyce::dout() << " li_Draindot = " << li_Draindot << std::endl;
1366  Xyce::dout() << " li_Gatedot = " << li_Gatedot << std::endl;
1367  Xyce::dout() << " li_Sourcedot = " << li_Sourcedot << std::endl;
1368  Xyce::dout() << " li_Bulkdot = " << li_Bulkdot << std::endl;
1369  Xyce::dout() << " li_DrainPrimedot = " << li_DrainPrimedot << std::endl;
1370  Xyce::dout() << " li_SourcePrimedot = " << li_SourcePrimedot << std::endl;
1371 
1372  Xyce::dout() << section_divider << std::endl;
1373  }
1374 #endif
1375 
1376 }
1377 
1378 //-----------------------------------------------------------------------------
1379 // Function : Instance::getIntNameMap
1380 // Purpose :
1381 // Special Notes :
1382 // Scope : public
1383 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1384 // Creation Date : 05/13/05
1385 //-----------------------------------------------------------------------------
1386 std::map<int,std::string> & Instance::getIntNameMap ()
1387 {
1388  // set up the internal name map, if it hasn't been already.
1389  if (intNameMap.empty ())
1390  {
1391  // set up the internal name map:
1392  std::string tmpstr;
1393  if ( li_DrainPrime != li_Drain )
1394  {
1395  tmpstr = getName()+"_drainprime";
1396  spiceInternalName (tmpstr);
1397  intNameMap[ li_DrainPrime ] = tmpstr;
1398  }
1399 
1400  if ( li_SourcePrime != li_Source )
1401  {
1402  tmpstr = getName()+"_sourceprime";
1403  spiceInternalName (tmpstr);
1404  intNameMap[ li_SourcePrime ] = tmpstr;
1405  }
1406 
1407  //Add more stuff for new meyer!
1408  if (getDeviceOptions().newMeyerFlag)
1409  {
1410  tmpstr = getName()+"_draindot";
1411  spiceInternalName (tmpstr);
1412  intNameMap[ li_Draindot ] = tmpstr;
1413 
1414  tmpstr = getName()+"_gatedot";
1415  spiceInternalName (tmpstr);
1416  intNameMap[ li_Gatedot ] = tmpstr;
1417 
1418  tmpstr = getName()+"_sourcedot";
1419  spiceInternalName (tmpstr);
1420  intNameMap[ li_Sourcedot ] = tmpstr;
1421 
1422  tmpstr = getName()+"_bulkdot";
1423  spiceInternalName (tmpstr);
1424  intNameMap[ li_Bulkdot ] = tmpstr;
1425 
1426  if ( li_DrainPrime != li_Drain )
1427  {
1428  tmpstr = getName()+"_drainprimedot";
1429  spiceInternalName (tmpstr);
1430  intNameMap[ li_DrainPrimedot ] = tmpstr;
1431  }
1432 
1433  if ( li_SourcePrime != li_Source )
1434  {
1435  tmpstr = getName()+"_sourceprimedot";
1436  spiceInternalName (tmpstr);
1437  intNameMap[ li_SourcePrimedot ] = tmpstr;
1438  }
1439  }
1440  }
1441 
1442  return intNameMap;
1443 }
1444 
1445 
1446 //-----------------------------------------------------------------------------
1447 // Function : N_DEV_MOSFET1Instance::getStoreNameMap
1448 // Purpose :
1449 // Special Notes :
1450 // Scope : public
1451 // Creator : Richard Schiek, Electrical Systems Modeling
1452 // Creation Date : 4/3/2013
1453 //-----------------------------------------------------------------------------
1454 std::map<int,std::string> & Instance::getStoreNameMap ()
1455 {
1456  // set up the internal name map, if it hasn't been already.
1457  if( loadLeadCurrent && storeNameMap.empty ())
1458  {
1459  // change subcircuitname:devicetype_deviceName to
1460  // devicetype:subcircuitName:deviceName
1461  std::string modName(getName());
1462  spiceInternalName(modName);
1463  std::string tmpstr;
1464  tmpstr = modName+":DEV_ID";
1465  storeNameMap[ li_store_dev_id ] = tmpstr;
1466  tmpstr = modName+":DEV_IG";
1467  storeNameMap[ li_store_dev_ig ] = tmpstr;
1468  tmpstr = modName+":DEV_IS";
1469  storeNameMap[ li_store_dev_is ] = tmpstr;
1470  tmpstr = modName+":DEV_IB";
1471  storeNameMap[ li_store_dev_ib ] = tmpstr;
1472  }
1473 
1474  return storeNameMap;
1475 }
1476 
1477 
1478 //-----------------------------------------------------------------------------
1479 // Function : N_DEV_MOSFET1Instance::registerStateLIDs
1480 // Purpose :
1481 // Special Notes :
1482 // Scope : public
1483 // Creator : Robert Hoekstra, Computational Sciences
1484 // Creation Date : 6/21/02
1485 //-----------------------------------------------------------------------------
1486 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
1487 {
1488  AssertLIDs(staLIDVecRef.size() == numStateVars);
1489 
1490 #ifdef Xyce_DEBUG_DEVICE
1491  if (getDeviceOptions().debugLevel > 0)
1492  {
1493  Xyce::dout() << std::endl;
1494  Xyce::dout() << section_divider << std::endl;
1495  Xyce::dout() << " In Instance::registerStateLIDs\n\n";
1496  Xyce::dout() << " name = " << getName() << std::endl;
1497  Xyce::dout() << " Number of State LIDs: " << numStateVars << std::endl;
1498  }
1499 #endif
1500 
1501  // Copy over the global ID lists:
1502  staLIDVec = staLIDVecRef;
1503 
1504  int lid=0;
1505 
1506  li_state_qgs = staLIDVec[lid++];
1507  li_state_qgd = staLIDVec[lid++];
1508  li_state_qgb = staLIDVec[lid++];
1509 
1510  li_state_capgs = staLIDVec[lid++];
1511  li_state_capgd = staLIDVec[lid++];
1512  li_state_capgb = staLIDVec[lid++];
1513 
1514  li_state_qbd = staLIDVec[lid++];
1515  li_state_qbs = staLIDVec[lid++];
1516 
1517 
1518 #ifdef Xyce_DEBUG_DEVICE
1519  if (getDeviceOptions().debugLevel > 0)
1520  {
1521  Xyce::dout() << " State local indices:" << std::endl;
1522  Xyce::dout() << std::endl;
1523 
1524  Xyce::dout() << " li_state_qgs = " << li_state_qgs ;
1525  Xyce::dout() << " li_state_capgs = " << li_state_capgs;
1526  Xyce::dout() << " li_state_capgd = " << li_state_capgd;
1527  Xyce::dout() << " li_state_capgb = " << li_state_capgb;
1528  Xyce::dout() << " li_state_qgd = " << li_state_qgd;
1529  Xyce::dout() << " li_state_qgb = " << li_state_qgb;
1530  Xyce::dout() << " li_state_qbs = " << li_state_qbs;
1531  Xyce::dout() << " li_state_qbd = " << li_state_qbd;
1532  Xyce::dout() << std::endl;
1533  Xyce::dout() << section_divider << std::endl;
1534  }
1535 #endif
1536 
1537 }
1538 
1539 //-----------------------------------------------------------------------------
1540 // Function : Instance::registerStoreLIDs
1541 // Purpose :
1542 // Special Notes :
1543 // Scope : public
1544 // Creator : Eric Keiter, SNL
1545 // Creation Date :
1546 //-----------------------------------------------------------------------------
1547 void Instance::registerStoreLIDs( const std::vector<int> & stoLIDVecRef )
1548 {
1549  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
1550 
1551  // Copy over the global ID lists:
1552  stoLIDVec = stoLIDVecRef;
1553 
1554  int lid=0;
1555 
1556  li_store_vbd = stoLIDVec[lid++];
1557  li_store_vbs = stoLIDVec[lid++];
1558  li_store_vgs = stoLIDVec[lid++];
1559  li_store_vds = stoLIDVec[lid++];
1560  li_store_von = stoLIDVec[lid++];
1561 
1562  if( loadLeadCurrent )
1563  {
1564  li_store_dev_id = stoLIDVec[lid++];
1565  li_store_dev_ig = stoLIDVec[lid++];
1566  li_store_dev_is = stoLIDVec[lid++];
1567  li_store_dev_ib = stoLIDVec[lid++];
1568  }
1569 }
1570 
1571 //-----------------------------------------------------------------------------
1572 // Function : Instance::jacobianStamp
1573 // Purpose :
1574 // Special Notes :
1575 // Scope : public
1576 // Creator : Robert Hoekstra, Computational Sciences
1577 // Creation Date : 9/3/02
1578 //-----------------------------------------------------------------------------
1579 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
1580 {
1581  if( drainConductance != 0.0 && sourceConductance != 0.0 )
1582  return jacStamp_DC_SC;
1583  else if( drainConductance != 0.0 && sourceConductance == 0.0 )
1584  return jacStamp_DC;
1585  else if( drainConductance == 0.0 && sourceConductance != 0.0 )
1586  return jacStamp_SC;
1587 
1588  return jacStamp;
1589 }
1590 
1591 //-----------------------------------------------------------------------------
1592 // Function : Instance::registerJacLIDs
1593 // Purpose :
1594 // Special Notes :
1595 // Scope : public
1596 // Creator : Robert Hoekstra, Computational Sciences
1597 // Creation Date : 9/3/02
1598 //-----------------------------------------------------------------------------
1599 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
1600 {
1601  DeviceInstance::registerJacLIDs( jacLIDVec );
1602  std::vector<int> map;
1603  std::vector< std::vector<int> > map2;
1604 
1605  if (drainConductance != 0.0)
1606  {
1607  if (sourceConductance != 0.0)
1608  {
1609  map = jacMap_DC_SC;
1610  map2 = jacMap2_DC_SC;
1611  }
1612  else
1613  {
1614  map = jacMap_DC;
1615  map2 = jacMap2_DC;
1616  }
1617  }
1618  else
1619  {
1620  if (sourceConductance != 0.0)
1621  {
1622  map = jacMap_SC;
1623  map2 = jacMap2_SC;
1624  }
1625  else
1626  {
1627  map = jacMap;
1628  map2 = jacMap2;
1629  }
1630 }
1631  ADrainEquDrainNodeOffset = jacLIDVec[map[0]][map2[0][0]];
1632  ADrainEquDrainPrimeNodeOffset = jacLIDVec[map[0]][map2[0][1]];
1633 
1634  AGateEquGateNodeOffset = jacLIDVec[map[1]][map2[1][0]];
1635  AGateEquBulkNodeOffset = jacLIDVec[map[1]][map2[1][1]];
1636  AGateEquDrainPrimeNodeOffset = jacLIDVec[map[1]][map2[1][2]];
1637  AGateEquSourcePrimeNodeOffset = jacLIDVec[map[1]][map2[1][3]];
1638 
1639  ASourceEquSourceNodeOffset = jacLIDVec[map[2]][map2[2][0]];
1640  ASourceEquSourcePrimeNodeOffset = jacLIDVec[map[2]][map2[2][1]];
1641 
1642  ABulkEquGateNodeOffset = jacLIDVec[map[3]][map2[3][0]];
1643  ABulkEquBulkNodeOffset = jacLIDVec[map[3]][map2[3][1]];
1644  ABulkEquDrainPrimeNodeOffset = jacLIDVec[map[3]][map2[3][2]];
1645  ABulkEquSourcePrimeNodeOffset = jacLIDVec[map[3]][map2[3][3]];
1646 
1647  ADrainPrimeEquDrainNodeOffset = jacLIDVec[map[4]][map2[4][0]];
1648  ADrainPrimeEquGateNodeOffset = jacLIDVec[map[4]][map2[4][1]];
1649  ADrainPrimeEquBulkNodeOffset = jacLIDVec[map[4]][map2[4][2]];
1650  ADrainPrimeEquDrainPrimeNodeOffset = jacLIDVec[map[4]][map2[4][3]];
1651  ADrainPrimeEquSourcePrimeNodeOffset = jacLIDVec[map[4]][map2[4][4]];
1652 
1653  ASourcePrimeEquGateNodeOffset = jacLIDVec[map[5]][map2[5][0]];
1654  ASourcePrimeEquSourceNodeOffset = jacLIDVec[map[5]][map2[5][1]];
1655  ASourcePrimeEquBulkNodeOffset = jacLIDVec[map[5]][map2[5][2]];
1656  ASourcePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[5]][map2[5][3]];
1657  ASourcePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[5]][map2[5][4]];
1658 
1659  // For the new Meyer stuff, we have to add in a bunch of extra rows
1660  // and columns into the Jacobian matrix:
1661 
1662  if (getDeviceOptions().newMeyerFlag)
1663  {
1664  //Additional gate equations:
1665  AGateEquVGatedotNodeOffset = jacLIDVec[map[1]][map2[1][4]];
1666  AGateEquVBulkdotNodeOffset = jacLIDVec[map[1]][map2[1][5]];
1667  AGateEquVDrainPrimedotNodeOffset = jacLIDVec[map[1]][map2[1][6]];
1668  AGateEquVSourcePrimedotNodeOffset = jacLIDVec[map[1]][map2[1][7]];
1669 
1670  //Additional bulk equations:
1671  ABulkEquVGatedotNodeOffset = jacLIDVec[map[3]][map2[3][4]];
1672  ABulkEquVBulkdotNodeOffset = jacLIDVec[map[3]][map2[3][5]];
1673  ABulkEquVDrainPrimedotNodeOffset = jacLIDVec[map[3]][map2[3][6]];
1674  ABulkEquVSourcePrimedotNodeOffset = jacLIDVec[map[3]][map2[3][7]];
1675 
1676  //Additional DrainPrime equations:
1677  ADrainPrimeEquVGatedotNodeOffset = jacLIDVec[map[4]][map2[4][5]];
1678  ADrainPrimeEquVBulkdotNodeOffset = jacLIDVec[map[4]][map2[4][6]];
1679  ADrainPrimeEquVDrainPrimedotNodeOffset = jacLIDVec[map[4]][map2[4][7]];
1680 
1681  //Additional SourcePrime equations:
1682  ASourcePrimeEquVGatedotNodeOffset = jacLIDVec[map[5]][map2[5][5]];
1683  ASourcePrimeEquVBulkdotNodeOffset = jacLIDVec[map[5]][map2[5][6]];
1684  ASourcePrimeEquVSourcePrimedotNodeOffset = jacLIDVec[map[5]][map2[5][7]];
1685 
1686  //Additional Nodedot equations:
1687  ADraindotEquVDrainNodeOffset = jacLIDVec[map[6]][map2[6][0]];
1688  ADraindotEquVDraindotNodeOffset = jacLIDVec[map[6]][map2[6][1]];
1689  AGatedotEquVGateNodeOffset = jacLIDVec[map[7]][map2[7][0]];
1690  AGatedotEquVGatedotNodeOffset = jacLIDVec[map[7]][map2[7][1]];
1691  ASourcedotEquVSourceNodeOffset = jacLIDVec[map[8]][map2[8][0]];
1692  ASourcedotEquVSourcedotNodeOffset = jacLIDVec[map[8]][map2[8][1]];
1693  ABulkdotEquVBulkNodeOffset = jacLIDVec[map[9]][map2[9][0]];
1694  ABulkdotEquVBulkdotNodeOffset = jacLIDVec[map[9]][map2[9][1]];
1695  ADrainPrimedotEquVDrainPrimeNodeOffset = jacLIDVec[map[10]][map2[10][0]];
1696  ADrainPrimedotEquVDrainPrimedotNodeOffset = jacLIDVec[map[10]][map2[10][1]];
1697  ASourcePrimedotEquVSourcePrimeNodeOffset = jacLIDVec[map[11]][map2[11][0]];
1698  ASourcePrimedotEquVSourcePrimedotNodeOffset = jacLIDVec[map[11]][map2[11][1]];
1699  }
1700 }
1701 
1702 //-----------------------------------------------------------------------------
1703 // Function : Instance::setupPointers
1704 // Purpose :
1705 // Special Notes :
1706 // Scope : public
1707 // Creator : Eric Keiter, SNL
1708 // Creation Date : 12/06/08
1709 //-----------------------------------------------------------------------------
1711 {
1712 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1713  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
1714  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
1715 
1716  // F-pointers:
1719 
1724 
1727 
1732 
1738 
1744 
1746  {
1747  // Additional gate equations:
1752 
1753  // Additional bulk equations:
1758 
1759  // Additional DrainPrime equations:
1763 
1764  // Additional SourcePrime equations:
1768 
1769  // Additional Nodedot equations:
1782  }
1783 
1784  // Q-pointers:
1787 
1792 
1795 
1800 
1806 
1812 
1814  {
1815  // Additional gate equations:
1820 
1821  // Additional bulk equations:
1826 
1827  // Additional DrainPrime equations:
1831 
1832  // Additional SourcePrime equations:
1836 
1837  // Additional Nodedot equations:
1850  }
1851 
1852 #endif
1853 }
1854 
1855 //-----------------------------------------------------------------------------
1856 // Function : Instance::loadDAEQVector
1857 //
1858 // Purpose : Loads the Q-vector contributions for a single
1859 // diode instance.
1860 //
1861 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1862 // which the system of equations is represented as:
1863 //
1864 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1865 //
1866 // This is similar to the loadRHS function, only this function
1867 // only loads capacitor charges, and loads them into the daeQ vector.
1868 //
1869 // KRS, 3/10/08: changing this to accomodate the new Meyer implementation,
1870 // as well. Both the stamp and the load change significantly for the new
1871 // Meyer implementation and, hence, this code is divided into two major
1872 // sections which are selected via boolean flags (if either MPDE is one, or
1873 // new Meyer is on, we use the new implemenation; otherwise
1874 // we use the old one).
1875 //
1876 // Scope : public
1877 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1878 // Creation Date : 03/06/04
1879 //-----------------------------------------------------------------------------
1881 {
1882  double * qVec = extData.daeQVectorRawPtr;
1883  double coef(0.0);
1884 
1885  //Here's where we do the new Meyer stuff if selected:
1886  if (getDeviceOptions().newMeyerFlag)
1887  {
1888  //The first 6 eqns---representing the equations for the gate, drain, bulk,
1889  //source, drain', and source' nodes---are all zero here, so we don't need
1890  //to add any code for those. We just need to add stuff for the last six
1891  //variables.
1892 
1893  //qVec[li_Draindot] += OxideCap*Vd;
1894  //qVec[li_Gatedot] += OxideCap*Vg;
1895  //qVec[li_Bulkdot] += OxideCap*Vb;
1896  //qVec[li_Sourcedot] += OxideCap*Vs;
1897  //if (drainConductance != 0.0)
1898  // qVec[li_DrainPrimedot] += OxideCap*Vdp;
1899  //if (sourceConductance != 0.0)
1900  // qVec[li_SourcePrimedot] += OxideCap*Vsp;
1901 
1902  qVec[li_Draindot] += Vd;
1903  qVec[li_Gatedot] += Vg;
1904  qVec[li_Bulkdot] += Vb;
1905  qVec[li_Sourcedot] += Vs;
1906  if (drainConductance != 0.0)
1907  {
1908  qVec[li_DrainPrimedot] += Vdp;
1909  }
1910  if (sourceConductance != 0.0)
1911  {
1912  qVec[li_SourcePrimedot] += Vsp;
1913  }
1914 
1915  //NOTE: typically, there are some coef_Jdxp terms that are added after
1916  //these statements to take voltage limiting into account. Because voltage
1917  //limiting is performed on *junction* voltages rather than node voltages, I
1918  //don't think those terms are appropriate to add here. Hopefully, I'm not
1919  //wrong...
1920  }
1921  else
1922  {
1923  double Qeqbs,Qeqbd,Qeqgb, Qeqgs, Qeqgd;
1924  //double ceqbs,ceqbd,ceqgb, ceqgs, ceqgd; // 3f5 vars
1925  int Dtype;
1926 
1927  Dtype=model_.dtype;
1928 
1929  // do the same Dtype corrections on the charges that
1930  // are performed on the currents in the loadRHS function.
1931 
1932  // What is cbs and cbd? They are diode currents (from exponentials),
1933  // so they are left out of this function.
1934  Qeqbs = Dtype*(qbs);
1935  Qeqbd = Dtype*(qbd);
1936  // These need "Dtype" here because we use them later *without*
1937  // Dtype, where SPICE uses it *with*
1938  Qeqgb = Dtype*(qgb);
1939  Qeqgs = Dtype*(qgs);
1940  Qeqgd = Dtype*(qgd);
1941 
1942  // 2 KCL for gate node
1943  coef = (Qeqgs+Qeqgd+Qeqgb);
1944  qVec[li_Gate] += coef*numberParallel;
1945 
1946  // 4 KCL for bulk node
1947  coef = Qeqbs + Qeqbd - Qeqgb;
1948  qVec[li_Bulk] += coef*numberParallel;
1949 
1950  // 5 KCL for drain' node
1951  coef = -(Qeqbd + Qeqgd);
1952  qVec[li_DrainPrime] += coef*numberParallel;
1953 
1954  // 6 KCL for source' node
1955  coef = -(Qeqbs + Qeqgs);
1956  qVec[li_SourcePrime] += coef*numberParallel;
1957 
1958  // Same as for the loadRHS function, but with capacitive terms:
1959  // gcgd = Capgd;
1960  // gcgs = Capgs;
1961  // gcgb = Capgb;
1962  // gcbs = capbs;
1963  // gcbd = capbd;
1964  if(!origFlag)
1965  {
1966  // THe setup of gcgd, etc. is the same as in the loadDAEdQdxVector
1967  // function.
1968  double gcgd, gcgs, gcgb, gcbs, gcbd;
1970  {
1971  gcgd = Capgd;
1972  gcgs = Capgs;
1973  gcgb = Capgb;
1974  // get at the two parasitic caps the same way
1975  gcbs = capbs;
1976  gcbd = capbd;
1977  }
1978  else
1979  {
1980  gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
1981  }
1982 
1983  // KCL 2
1984  double coef_Jdxp2 = Dtype*(gcgd*(vgd-vgd_orig)+gcgs*(vgs-vgs_orig)+
1985  gcgb*(vgs-vgs_orig-vbs+vbs_orig));
1986 
1987  // 4 KCL for bulk node
1988  double coef_Jdxp4 = Dtype*(
1989  - (gcgb)*(vgs-vgs_orig-vbs+vbs_orig)
1990  + (gcgb)*(vbd-vbd_orig)
1991  + (gcbs)*(vbs-vbs_orig));
1992 
1993  // 5 KCL for drain' node
1994  double coef_Jdxp5 = Dtype*(
1995  -(gcgd)*(vgd-vgd_orig)
1996  -(gcbd)*(vbd-vbd_orig));
1997 
1998  // 6 KCL for source' node
1999  double coef_Jdxp6 = Dtype*(-gcgs*(vgs-vgs_orig)-(gcbs)*(vbs-vbs_orig));
2000 
2001  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
2002  dQdxdVp[li_Gate ] += coef_Jdxp2*numberParallel;
2003  dQdxdVp[li_Bulk ] += coef_Jdxp4*numberParallel;
2004  dQdxdVp[li_DrainPrime ] += coef_Jdxp5*numberParallel;
2005  dQdxdVp[li_SourcePrime] += coef_Jdxp6*numberParallel;
2006  }
2007 
2008  if( loadLeadCurrent )
2009  {
2010  double * storeLeadQ = extData.storeLeadCurrQCompRawPtr;
2011  if (drainConductance == 0.0)
2012  {
2013  storeLeadQ[li_store_dev_id] = (-(Qeqbd + Qeqgd))*numberParallel;
2014  }
2015  if (sourceConductance == 0.0)
2016  {
2017  storeLeadQ[li_store_dev_is] = (-(Qeqbs + Qeqgs))*numberParallel;
2018  }
2019  storeLeadQ[li_store_dev_ig] = (Qeqgs+Qeqgd+Qeqgb)*numberParallel;
2020  storeLeadQ[li_store_dev_ib] = (Qeqbs + Qeqbd - Qeqgb)*numberParallel;
2021  }
2022  }
2023 
2024 
2025  return true;
2026 }
2027 
2028 
2029 //-----------------------------------------------------------------------------
2030 // Function : Instance::loadDAEQVector
2031 //
2032 // Purpose : Loads the Q-vector contributions for a single
2033 // diode instance.
2034 //
2035 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2036 // which the system of equations is represented as:
2037 //
2038 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2039 //
2040 // This version is different from the original version written by Eric to
2041 // account for the new way we need to handle Meyer capacitors with MPDE.
2042 // In most devices, the Q vector contains charges (which are time-
2043 // differentiated to form currents). Here, the Q vector has the form [0 v]'
2044 // where the "0" is a block of six zeros, and "v" is a block of voltages
2045 // (drain, gate, bulk, source, drain', source').
2046 //
2047 // Scope : public
2048 // Creator : Keith Santarelli, SNL, Electrical & Microsystems Modeling
2049 // Creation Date : 02/12/08
2050 //-----------------------------------------------------------------------------
2051 //bool Instance::loadDAEQVector ()
2052 //{
2053 //
2054 // N_LAS_Vector * daeQVecPtr;
2055 // daeQVecPtr = extData.daeQVectorPtr;
2056 // double coef;
2057 // double gmin1 = getDeviceOptions().gmin;
2058 //
2059 // //The first 6 eqns---representing the equations for the gate, drain, bulk,
2060 // //source, drain', and source' nodes---are all zero here, so we don't need to
2061 // //add any code for those. We just need to add stuff for the last six
2062 // //variables.
2063 //
2064 // (*daeQVecPtr)[li_Draindot] += Vd;
2065 // (*daeQVecPtr)[li_Gatedot] += Vg;
2066 // (*daeQVecPtr)[li_Bulkdot] += Vb;
2067 // (*daeQVecPtr)[li_Sourcedot] += Vs;
2068 // if (drainConductance != 0.0)
2069 // (*daeQVecPtr)[li_DrainPrimedot] += Vdp;
2070 // if (sourceConductance != 0.0)
2071 // (*daeQVecPtr)[li_SourcePrimedot] += Vsp;
2072 //
2073 // //NOTE: typically, there are some coef_Jdxp terms that are added after these
2074 // //statements to take voltage limiting into account. Because voltage limiting
2075 // //is performed on *junction* voltages rather than node voltages, I don't
2076 // //think those terms are appropriate to add here. Hopefully, I'm not wrong...
2077 //
2078 //}
2079 
2080 //-----------------------------------------------------------------------------
2081 // Function : Instance::loadDAEFVector
2082 //
2083 // Purpose : Loads the F-vector contributions for a single
2084 // diode instance.
2085 //
2086 // Special Notes : Modifying to be compatible with new Meyer.
2087 //
2088 // Scope : public
2089 // Creator : Keith Santarelli, SNL, Electrical & Microsystems Modeling
2090 // Creation Date : 02/12/08
2091 //-----------------------------------------------------------------------------
2093 {
2094  double * fVec = extData.daeFVectorRawPtr;
2095  double coef(0.0);
2096  double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0); // 3f5 vars
2097  double gmin1 = getDeviceOptions().gmin;
2098 
2099  int Dtype=model_.dtype;
2100 
2101  // The next few lines are the same as for loadRHS, except
2102  // the capcitor current terms have been set to zero here.
2103  // KRS, 02/12/08: now we *do* include capacitive currents here, at
2104  // least when we're not in DC op mode.
2105 
2106  if (getDeviceOptions().newMeyerFlag)
2107  {
2108  if (!getSolverState().dcopFlag)
2109  {
2110  double vbsdot = Dtype*(Vbdot - Vspdot);
2111  double vbddot = Dtype*(Vbdot - Vdpdot);
2112  double vgbdot = Dtype*(Vgdot - Vbdot);
2113  double vgsdot = Dtype*(Vgdot - Vspdot);
2114  double vgddot = Dtype*(Vgdot - Vdpdot);
2115 
2116  ceqbs = Dtype*(cbs+capbs*vbsdot);
2117  ceqbd = Dtype*(cbd+capbd*vbddot);
2118  ceqgb = Dtype*(Capgb*vgbdot);
2119  ceqgs = Dtype*(Capgs*vgsdot);
2120  ceqgd = Dtype*(Capgd*vgddot);
2121  }
2122  else
2123  {
2124  ceqbs = Dtype*(cbs);
2125  ceqbd = Dtype*(cbd);
2126 
2127 
2128  // These need "Dtype" here because we use them later *without*
2129  // Dtype, where SPICE uses it *with*
2130  ceqgb = 0.0;
2131  ceqgs = 0.0;
2132  ceqgd = 0.0;
2133  }
2134  }
2135  else
2136  {
2137  ceqbs = Dtype*(cbs);
2138  ceqbd = Dtype*(cbd);
2139 
2140  // These need "Dtype" here because we use them later *without*
2141  // Dtype, where SPICE uses it *with*
2142  ceqgb = 0.0;
2143  ceqgs = 0.0;
2144  ceqgd = 0.0;
2145  }
2146 
2147  // 1 KCL for drain node
2148  if (drainConductance != 0.0)
2149  {
2150  coef = Idrain;
2151  fVec[li_Drain] += coef*numberParallel;
2152  }
2153 
2154  // 2 KCL for gate node
2155  coef = (ceqgs+ceqgd+ceqgb);
2156  fVec[li_Gate] += coef*numberParallel;
2157 
2158  // 3 KCL for source node
2159  if (sourceConductance != 0.0)
2160  {
2161  coef = Isource;
2162  fVec[li_Source] += coef*numberParallel;
2163  }
2164 
2165  // 4 KCL for bulk node
2166  coef = ceqbs + ceqbd - ceqgb;
2167  fVec[li_Bulk] += coef*numberParallel;
2168 
2169  // 5 KCL for drain' node
2170  coef = -Idrain-(ceqbd - cdreq + ceqgd);
2171  fVec[li_DrainPrime] += coef*numberParallel;
2172 
2173  // 6 KCL for source' node
2174  coef = -Isource-(ceqbs + cdreq + ceqgs);
2175  fVec[li_SourcePrime] += coef*numberParallel;
2176 
2177  // For new Meyer, we need to add in some equations that essentially
2178  // say that the derivative of the node voltages are equal to the vdot terms:
2179 
2181  {
2182  fVec[li_Draindot] -= Vddot;
2183  fVec[li_Gatedot] -= Vgdot;
2184  fVec[li_Bulkdot] -= Vbdot;
2185  fVec[li_Sourcedot] -= Vsdot;
2186  if (drainConductance != 0.0)
2187  {
2188  fVec[li_DrainPrimedot] -= Vdpdot;
2189  }
2190  if (sourceConductance != 0.0)
2191  {
2192  fVec[li_SourcePrimedot] -= Vspdot;
2193  }
2194  }
2195 
2196  // Same as for the loadRHS function, but without capacitive terms:
2197  // gcgd = Capgd;
2198  // gcgs = Capgs;
2199  // gcgb = Capgb;
2200  // gcbs = capbs;
2201  // gcbd = capbd;
2202  if (!origFlag)
2203  {
2204  // 4 KCL for bulk node
2205  double coef_Jdxp4 = Dtype*(
2206  + ((gbd-gmin1))*(vbd-vbd_orig)
2207  + ((gbs-gmin1))*(vbs-vbs_orig));
2208 
2209  // 5 KCL for drain' node
2210  double coef_Jdxp5 = Dtype*(
2211  -((gbd-gmin1))*(vbd-vbd_orig)
2212  +gds*(vds-vds_orig)
2213  +Gm*((mode>0)?(vgs-vgs_orig):(vgd-vgd_orig))
2214  +Gmbs*((mode>0)?(vbs-vbs_orig):(vbd-vbd_orig)));
2215 
2216  // 6 KCL for source' node
2217  double coef_Jdxp6 = Dtype*(
2218  -((gbs-gmin1))*(vbs-vbs_orig)
2219  -gds*(vds-vds_orig)
2220  -Gm*((mode>0)?(vgs-vgs_orig):(vgd-vgd_orig))
2221  -Gmbs*((mode>0)?(vbs-vbs_orig):(vbd-vbd_orig)));
2222 
2223  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
2224  dFdxdVp[li_Bulk ] += coef_Jdxp4*numberParallel;
2225  dFdxdVp[li_DrainPrime ] += coef_Jdxp5*numberParallel;
2226  dFdxdVp[li_SourcePrime] += coef_Jdxp6*numberParallel;
2227  }
2228 
2229  if( loadLeadCurrent )
2230  {
2231  double * storeLeadF = extData.nextStoVectorRawPtr;
2232  if (drainConductance != 0.0)
2233  {
2234  storeLeadF[li_store_dev_id] = Idrain*numberParallel;
2235  }
2236  else
2237  {
2238  storeLeadF[li_store_dev_id] = (-Idrain-(ceqbd - cdreq + ceqgd))*numberParallel;
2239  }
2240  if (sourceConductance != 0.0)
2241  {
2242  storeLeadF[li_store_dev_is] = Isource*numberParallel;
2243  }
2244  else
2245  {
2246  storeLeadF[li_store_dev_is] = (-Isource-(ceqbs + cdreq + ceqgs))*numberParallel;
2247  }
2248  storeLeadF[li_store_dev_ig] = (ceqgs+ceqgd+ceqgb)*numberParallel;
2249  storeLeadF[li_store_dev_ib] = (ceqbs + ceqbd - ceqgb)*numberParallel;
2250  }
2251 
2252  return true;
2253 }
2254 
2255 //-----------------------------------------------------------------------------
2256 // Function : Instance::loadDAEdQdx
2257 //
2258 // Purpose : Loads the Q-vector contributions for a single
2259 // diode instance.
2260 //
2261 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2262 // which the system of equations is represented as:
2263 //
2264 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2265 //
2266 // KRS, 3/10/08: changing this to accomodate the new Meyer implementation,
2267 // as well. Both the stamp and the load change significantly for the new
2268 // Meyer implementation and, hence, this code is divided into two major
2269 // sections which are selected via boolean flags (if either MPDE is one, or
2270 // new Meyer is on, we use the new implemenation; otherwise
2271 // we use the old one).
2272 //
2273 // Scope : public
2274 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2275 // Creation Date : 03/06/04
2276 //-----------------------------------------------------------------------------
2278 {
2279  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2280 
2281  //Here's where we implement the new Meyer formulation:
2283  {
2284  //Jacobian matrix is 0 for upper half, 6x6 identity matrix for lower half
2285  //dQdx[li_Draindot][ADraindotEquVDrainNodeOffset] += OxideCap*1.0;
2286  //dQdx[li_Gatedot][AGatedotEquVGateNodeOffset] += OxideCap*1.0;
2287  //dQdx[li_Sourcedot][ASourcedotEquVSourceNodeOffset] += OxideCap*1.0;
2288  //dQdx[li_Bulkdot][ABulkdotEquVBulkNodeOffset] += OxideCap*1.0;
2289  //if (drainConductance != 0.0)
2290  // dQdx[li_DrainPrimedot][ADrainPrimedotEquVDrainPrimeNodeOffset] += OxideCap*1.0;
2291  //if (sourceConductance != 0.0)
2292  // dQdx[li_SourcePrimedot][ASourcePrimedotEquVSourcePrimeNodeOffset] += OxideCap*1.0;
2293 
2295  dQdx[li_Gatedot][AGatedotEquVGateNodeOffset] += 1.0;
2297  dQdx[li_Bulkdot][ABulkdotEquVBulkNodeOffset] += 1.0;
2298  if (drainConductance != 0.0)
2300  if (sourceConductance != 0.0)
2302  }
2303  else
2304  {
2305  double gcgd(0.0); // d(cqgd)/dVgd
2306  double gcgs(0.0); // d(cqgs)/dVgs
2307  double gcgb(0.0); // d(cqgb)/dVgb
2308  double gcbs(0.0); // d(cqbs)/dVbs
2309  double gcbd(0.0); // d(cqbd)/dVbd
2310 
2311  // get at the "conductances" for the gate capacitors with this trick
2312  // gcgd = model_.dtype*Capgd;
2313  // gcgs = model_.dtype*Capgs;
2314  // gcgb = model_.dtype*Capgb;
2315  //
2316  // In the loadRHS function, these would all be multiplied by
2317  // getSolverState().pdt. Here, for dQdx, the pdt term is left out.
2318  if ( getSolverState().tranopFlag || getSolverState().acopFlag || getSolverState().transientFlag)
2319  {
2320  gcgd = Capgd;
2321  gcgs = Capgs;
2322  gcgb = Capgb;
2323  // get at the two parasitic caps the same way
2324  gcbs = capbs;
2325  gcbd = capbd;
2326  }
2327 
2329  (gcgd+gcgs+gcgb)*numberParallel;
2333 
2336  (+gcbs+gcbd+gcgb)*numberParallel;
2339  +gcbs*numberParallel;
2340 
2342  -gcgd*numberParallel;
2344  -gcbd*numberParallel;
2346  (+gcbd+gcgd)*numberParallel;
2347 
2349  gcgs*numberParallel;
2351  +gcbs*numberParallel;
2353  (+gcbs+gcgs)*numberParallel;
2354  }
2355  return true;
2356 }
2357 
2358 //-----------------------------------------------------------------------------
2359 // Function : Instance::loadDAEdQdx
2360 //
2361 // Purpose : Loads the Q-vector Jacobian contributions for a single
2362 // instance.
2363 //
2364 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2365 // which the system of equations is represented as:
2366 //
2367 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2368 //
2369 // This version is different from the original version written by Eric to
2370 // account for the new way we need to handle Meyer capacitors with MPDE.
2371 // In most devices, the Q vector contains charges (which are time-
2372 // differentiated to form currents). Here, the Q vector has the form [0 v]'
2373 // where the "0" is a block of six zeros, and "v" is a block of voltages
2374 // (drain, gate, bulk, source, drain', source').
2375 //
2376 // Scope : public
2377 // Creator : Keith Santarelli, SNL, Electrical & Microsystems Modeling
2378 // Creation Date : 02/13/08
2379 //-----------------------------------------------------------------------------
2380 //bool Instance::loadDAEdQdx ()
2381 //{
2382 // bool bsuccess = true;
2383 //
2384 // N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2385 //
2386 // //Jacobian matrix is 0 for upper half, 6x6 identity matrix for lower half
2387 // dQdx[li_Draindot][ADraindotEquVDrainNodeOffset] += 1;
2388 // dQdx[li_Gatedot][AGatedotEquVGateNodeOffset] += 1;
2389 // dQdx[li_Sourcedot][ASourcedotEquVSourceNodeOffset] += 1;
2390 // dQdx[li_Bulkdot][ABulkdotEquVBulkNodeOffset] += 1;
2391 // if (drainConductance != 0.0)
2392 // dQdx[li_DrainPrimedot][ADrainPrimedotEquVDrainPrimeNodeOffset] += 1;
2393 // if (sourceConductance != 0.0)
2394 // dQdx[li_SourcePrimedot][ASourcePrimedotEquVSourcePrimeNodeOffset] += 1;
2395 //
2396 //
2397 // return bsuccess;
2398 //}
2399 
2400 
2401 //-----------------------------------------------------------------------------
2402 // Function : Instance::loadDAEdFdx ()
2403 //
2404 // Purpose : Loads the F-vector contributions for a single
2405 // diode instance.
2406 //
2407 // Special Notes :
2408 //
2409 // Scope : public
2410 // Creator : Keith Santarelli, SNL, Electrical & Microsystems Modeling
2411 // Creation Date : 02/13/08
2412 //-----------------------------------------------------------------------------
2414 {
2415  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2416 
2417  //introduce terms for capacitances, partial derivs. of capacitances,
2418  //and derivatives of differential voltages. "l" stands for "local"
2419 
2420  double l_capgs(0.0),l_capgd(0.0), l_capgb(0.0), l_capbd(0.0), l_capbs(0.0);
2421  double l_dcapgsdvgs(0.0),l_dcapgsdvgb(0.0),l_dcapgsdvgd(0.0);
2422  double l_dcapgbdvgs(0.0),l_dcapgbdvgb(0.0),l_dcapgbdvgd(0.0);
2423  double l_dcapgddvgs(0.0),l_dcapgddvgb(0.0),l_dcapgddvgd(0.0);
2424  double l_vgsdot(0.0), l_vgddot(0.0), l_vgbdot(0.0);
2425 
2426  if (getDeviceOptions().newMeyerFlag)
2427  {
2428  if (!getSolverState().dcopFlag)
2429  {
2430  l_capgs=Capgs;
2431  l_capgd=Capgd;
2432  l_capgb=Capgb;
2433  l_capbd=capbd;
2434  l_capbs=capbs;
2435 
2436  l_dcapgsdvgs=dcapgsdvgs;
2437  l_dcapgsdvgb=dcapgsdvgb;
2438  l_dcapgsdvgd=dcapgsdvgd;
2439  l_dcapgbdvgs=dcapgbdvgs;
2440  l_dcapgbdvgb=dcapgbdvgb;
2441  l_dcapgbdvgd=dcapgbdvgd;
2442  l_dcapgddvgd=dcapgddvgd;
2443  l_dcapgddvgs=dcapgddvgs;
2444  l_dcapgddvgb=dcapgddvgb;
2445 
2446  l_vgsdot=model_.dtype*(Vgdot-Vspdot);
2447  l_vgddot=model_.dtype*(Vgdot-Vdpdot);
2448  l_vgbdot=model_.dtype*(Vgdot-Vbdot);
2449  }
2450  }
2451 
2456 
2458  {
2460  ((l_dcapgsdvgs+l_dcapgsdvgb+l_dcapgsdvgd)*l_vgsdot +
2461  (l_dcapgbdvgs+l_dcapgbdvgb+l_dcapgbdvgd)*l_vgbdot +
2462  (l_dcapgddvgs+l_dcapgddvgb+l_dcapgddvgd)*l_vgddot)*numberParallel;
2464  (l_dcapgsdvgd*l_vgsdot + l_dcapgbdvgd*l_vgbdot +
2465  l_dcapgddvgd*l_vgddot)*numberParallel;
2467  (l_dcapgsdvgs*l_vgsdot + l_dcapgbdvgs*l_vgbdot +
2468  l_dcapgddvgs*l_vgddot)*numberParallel;
2470  (l_dcapgsdvgb*l_vgsdot + l_dcapgbdvgb*l_vgbdot +
2471  l_dcapgddvgb*l_vgddot)*numberParallel;
2472  // Additional gate equations for new Meyer stuff:
2474  (l_capgs + l_capgd + l_capgb)*numberParallel;
2476  l_capgb*numberParallel;
2478  l_capgd*numberParallel;
2480  l_capgs*numberParallel;
2481  }
2482 
2487 
2489  {
2491  (l_dcapgbdvgb+l_dcapgbdvgs+l_dcapgbdvgd)*l_vgbdot*numberParallel;
2493  (gbs+gbd+l_dcapgbdvgb*l_vgbdot)*numberParallel;
2495  (gbd-l_dcapgbdvgd*l_vgbdot)*numberParallel;
2497  (gbs-l_dcapgbdvgs*l_vgbdot )*numberParallel;
2498 
2499  // Additional bulk equations:
2501  l_capgb*numberParallel;
2503  (l_capbs+l_capgb+l_capbd)*numberParallel;
2505  l_capbd*numberParallel;
2507  l_capbs*numberParallel;
2508  }
2509  else
2510  {
2512  (gbs+gbd)*numberParallel;
2515  }
2516 
2517 
2519  {
2523  (Gm-(l_dcapgddvgb+l_dcapgddvgs+l_dcapgddvgd)*l_vgddot)*numberParallel;
2525  (-gbd+Gmbs+l_dcapgddvgb*l_vgddot)*numberParallel;
2527  (drainConductance+gds+gbd+revsum+l_dcapgddvgd*l_vgddot)*numberParallel;
2529  (-gds-nrmsum+l_dcapgddvgs*l_vgddot)*numberParallel;
2530 
2531  // Additional DrainPrime Equations:
2533  l_capgd*numberParallel;
2535  l_capbd*numberParallel;
2537  (l_capgd+l_capbd)*numberParallel;
2538  }
2539  else
2540  {
2544  (Gm)*numberParallel;
2546  (-gbd+Gmbs)*numberParallel;
2548  (drainConductance+gds+gbd+revsum)*numberParallel;
2550  (-gds-nrmsum)*numberParallel;
2551  }
2552 
2554  {
2556  (Gm+(l_dcapgsdvgd+l_dcapgsdvgs+l_dcapgsdvgb)*l_vgsdot)*numberParallel;
2560  (gbs+Gmbs-l_dcapgsdvgb*l_vgsdot)*numberParallel;
2562  (gds+revsum-l_dcapgsdvgd*l_vgsdot)*numberParallel;
2564  (sourceConductance+gds+gbs+nrmsum+l_dcapgsdvgs*l_vgsdot)*numberParallel;
2565 
2566  // Additional SourcePrime equations:
2568  l_capgs*numberParallel;
2570  l_capbs*numberParallel;
2572  += (l_capgs+l_capbs)*numberParallel;
2573  }
2574  else
2575  {
2577  (Gm)*numberParallel;
2581  (gbs+Gmbs)*numberParallel;
2583  (gds+revsum)*numberParallel;
2585  (sourceConductance+gds+gbs+nrmsum)*numberParallel;
2586  }
2587 
2588  //Now we have to add a bunch of terms for the nodedot equations:
2590  {
2595 
2596  if (drainConductance != 0.0)
2597  {
2599  }
2600 
2601  if (sourceConductance != 0.0)
2602  {
2604  }
2605  }
2606 
2607  return true;
2608 }
2609 
2610 //-----------------------------------------------------------------------------
2611 // Function : Instance::updateIntermediateVars
2612 // Purpose :
2613 // Special Notes :
2614 // Scope : public
2615 // Creator : Tom Russo
2616 // Creation Date : 03/01/01
2617 //-----------------------------------------------------------------------------
2619 {
2620  bool bsuccess = true;
2621  // 3f5 likes to use the same variable names in local variables and in
2622  // structures. Messes with us! Define some local versions with capitals
2623  // instead
2624  double Von;
2625  double Vdsat;
2626  double Beta;
2627  //
2628  double evbs;
2629  double evbd;
2630  double sarg;
2631  double sargsw;
2632  // double vgs1;
2633  // double vgd1;
2634  // double vgb1;
2635  double arg;
2636  int Check = 1;
2637 
2638  double capgs_old;
2639  double capgd_old;
2640  double capgb_old;
2641 
2642  // temporary storage for vgs/vgd/vds so that homotopy doesn't impact
2643  // voltage limiting "jdxp" terms
2644 
2645  double vgs_save;
2646  double vgd_save;
2647  double vds_save;
2648 
2649  // This is one of the vars that are set up at the top of mos1load that
2650  // should *not* be moved to the instance constructor! tTransconductance
2651  // is set by updateTemperature. Perhaps I should remove it from the
2652  // instance variables, too, since now it's pretty much a local thing.
2653  // same goes for the other things that depend on the t* variables!
2654 
2655  if( (tSatCurDens == 0) || (drainArea == 0) || (sourceArea == 0))
2656  {
2657  DrainSatCur = tSatCur;
2659  }
2660  else
2661  {
2664  }
2666 
2667  // we need our solution variables for any of this stuff
2674 
2675  // More stuff for new Meyer:
2677  {
2684  }
2685 
2686 
2687  // now we need voltage drops
2688  Vddp = Vd - Vdp;
2689  Vssp = Vs - Vsp;
2690  Vbsp = Vb - Vsp;
2691  Vbdp = Vb - Vdp;
2692  Vgsp = Vg - Vsp;
2693  Vgdp = Vg - Vdp;
2694  Vgb = Vg - Vb;
2695  Vdpsp = Vdp - Vsp;
2696 
2697  // Now the things that the 3f5 code really uses (from mos1load's
2698  // "general iteration" part at lines 276-295
2699  vbs = model_.dtype * Vbsp;
2700  vgs = model_.dtype * Vgsp;
2701  vds = model_.dtype * Vdpsp;
2702 
2703  vbd = vbs-vds;
2704  vgd = vgs-vds;
2705 
2706  origFlag = 1;
2707  limitedFlag=false;
2708  vgs_orig = vgs;
2709  vds_orig = vds;
2710  vbs_orig = vbs;
2711  vbd_orig = vbd;
2712  vgd_orig = vgd;
2713 
2715  {
2716  if (IC_GIVEN)
2717  {
2718  vds = model_.dtype*icVDS;
2719  vgs = model_.dtype*icVGS;
2720  vbs = model_.dtype*icVBS;
2721  vbd = vbs - vds;
2722  vgd = vgs - vds;
2723  origFlag = false;
2724  }
2725  else
2726  {
2728  {
2729  N_LAS_Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
2730  if ((*flagSolVectorPtr)[li_Drain] == 0 || (*flagSolVectorPtr)[li_Gate] == 0 ||
2731  (*flagSolVectorPtr)[li_Source] == 0 || (*flagSolVectorPtr)[li_SourcePrime] ||
2732  (*flagSolVectorPtr)[li_DrainPrime] || (*flagSolVectorPtr)[li_Bulk] )
2733  {
2734  vbs = -1;
2735  vgs = model_.dtype*tVto;
2736  vds = 0;
2737  vbd = vbs-vds;
2738  vgd = vgs-vds;
2739  }
2740  }
2741  else
2742  {
2743  vbs = -1;
2744  vgs = model_.dtype*tVto;
2745  vds = 0;
2746  vbd = vbs-vds;
2747  vgd = vgs-vds;
2748  }
2749  }
2750  }
2751  else if ((getSolverState().initFixFlag || getSolverState().initJctFlag) && OFF)
2752  {
2753  vbs = vgs = vds = 0;
2754  vbd = vgd = 0;
2755  }
2756 
2757  if (getSolverState().newtonIter == 0)
2758  {
2759 
2761  {
2766  Von = model_.dtype *
2768  }
2769  else
2770  { // otherwise there is no history
2771  vbs_old = vbs;
2772  vbd_old = vbd;
2773  vgs_old = vgs;
2774  vds_old = vds;
2775  Von = 0.0;
2776  }
2778  }
2779  else
2780  {
2785  Von = model_.dtype *
2788  }
2789 
2790  ////////////////////////////////////////////
2791  // SPICE-type Voltage Limiting
2792  ////////////////////////////////////////////
2794  {
2795  // Do not do limiting if mode initfix and OFF:
2796  if (! (getSolverState().initFixFlag && OFF))
2797  {
2798  if (vds_old >= 0)
2799  {
2800  vgs = devSupport.fetlim( vgs, vgs_old, Von);
2801  vds = vgs - vgd;
2802  vds = devSupport.limvds( vds, vds_old);
2803  vgd = vgs - vds;
2804  }
2805  else
2806  {
2807  vgd = devSupport.fetlim( vgd, vgd_old, Von);
2808  vds = vgs - vgd;
2809  vds = -devSupport.limvds( -vds, -vds_old );
2810  vgs = vgd + vds;
2811  }
2812 
2813  if (vds >= 0.0)
2814  {
2815  vbs = devSupport.pnjlim( vbs, vbs_old, vt, sourceVcrit, &Check);
2816  vbd = vbs - vds;
2817  }
2818  else
2819  {
2820  vbd = devSupport.pnjlim( vbd, vbd_old, vt, drainVcrit, &Check);
2821  vbs = vbd + vds;
2822  }
2823 
2824  // for convergence:
2825  if (Check == 1) limitedFlag=true;
2826 
2827  }
2828  }
2829 
2830  ////
2831  // now all the preliminaries are over - we can start doing the
2832  // real work
2833  ////
2834  vbd = vbs - vds;
2835  vgd = vgs - vds;
2836  Vgb = vgs - vbs;
2837 
2838  // Now set the origFlag
2839  if (vgs_orig != vgs || vds_orig != vds ||
2840  vbs_orig != vbs || vbd_orig != vbd || vgd_orig != vgd) origFlag = 0;
2841 
2842 
2843  ////
2844  // bulk-source and bulk-drain diodes
2845  // here we just evaluate the ideal diode current and the
2846  // corresponding derivative (conductance).
2847  ////
2848  if(vbs <= 0)
2849  {
2850  gbs = SourceSatCur/vt;
2851  gbs += getDeviceOptions().gmin;
2852  cbs = gbs*vbs;
2853  }
2854  else
2855  {
2856  evbs = exp(Xycemin(CONSTMAX_EXP_ARG,vbs/vt));
2857  gbs = (SourceSatCur*evbs/vt + getDeviceOptions().gmin);
2858  cbs = (SourceSatCur * (evbs-1) + getDeviceOptions().gmin*vbs);
2859  }
2860  if(vbd <= 0)
2861  {
2862  gbd = DrainSatCur/vt;
2863  gbd += getDeviceOptions().gmin;
2864  cbd = gbd *vbd;
2865  }
2866  else
2867  {
2868  evbd = exp(Xycemin(CONSTMAX_EXP_ARG,vbd/vt));
2869  gbd = (DrainSatCur*evbd/vt + getDeviceOptions().gmin);
2870  cbd = (DrainSatCur *(evbd-1) + getDeviceOptions().gmin*vbd);
2871  }
2872 
2873  // 3f5 does this simple stuff
2874  if (vds >= 0)
2875  mode = 1;
2876  else
2877  mode = -1;
2878 
2879  {
2880  //
2881  // this block of code evaluates the drain current and its
2882  // derivatives using the shichman-hodges model and the
2883  // charges associated with the gate, channel and bulk for
2884  // mosfets
2885  //
2886  //
2887 
2888  // the following 4 variables are local to this code block until
2889  // it is obvious that they can be made global
2890  //
2891  double arg;
2892  double betap;
2893  double sarg;
2894  double vgst;
2895 
2896  // Begin block of mosfet continuation code.
2897  // This idea is based, loosely, on a paper by Jaijeet
2898  // Roychowdhury.
2899 #ifdef Xyce_DEBUG_DEVICE
2901  {
2902  Xyce::dout() << "HOMOTOPY INFO: Von = " << Von <<std::endl;
2903  Xyce::dout() << "HOMOTOPY INFO: gainscale = "
2904  << getSolverState().gainScale[blockHomotopyID] << std::endl;
2905  Xyce::dout() << "HOMOTOPY INFO: before vds = " << vds << std::endl;
2906  Xyce::dout() << "HOMOTOPY INFO: before vgs = " << vgs << std::endl;
2907  }
2908 #endif
2909 
2910  // Save these before allowing homotopy to tweak them. It
2911  // is important to restore them before moving on to
2912  // calculate RHS, because then the Jdxp terms will attempt to force
2913  // the external circuit to make these voltage drops the real thing!
2914  vds_save=vds;
2915  vgs_save=vgs;
2916  vgd_save=vgd;
2917 
2918  if (getSolverState().artParameterFlag)
2919  {
2920  double alpha = getSolverState().gainScale[blockHomotopyID];
2921  if (getDeviceOptions().staggerGainScale)
2922  {
2923  alpha *= (0.3 * randomPerturb + 1.0);
2924  if (alpha > 1.0)
2925  {
2926  alpha = 1.0;
2927  }
2928  }
2929  double vgstConst = getDeviceOptions().vgstConst;
2930  if (getDeviceOptions().randomizeVgstConst)
2931  {
2932  vgstConst *= randomPerturb;
2933  }
2934 
2935  vds = devSupport.contVds (vds, getSolverState().nltermScale, getDeviceOptions().vdsScaleMin);
2936 
2937  if (mode==1)
2938  {
2939  vgs = devSupport.contVgst (vgs, alpha, vgstConst);
2940  }
2941  else
2942  {
2943  vgd = devSupport.contVgst (vgd, alpha, vgstConst);
2944  }
2945  }
2946 
2947 #ifdef Xyce_DEBUG_DEVICE
2948  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2949  {
2950  Xyce::dout() << "HOMOTOPY INFO: after vds = " << vds << std::endl;
2951  Xyce::dout() << "HOMOTOPY INFO: after vgs = " << vgs << std::endl;
2952  }
2953 #endif
2954  // End of block of mosfet continuation code.
2955 
2956  if ((mode==1?vbs:vbd) <= 0 ) {
2957  sarg=sqrt(tPhi-(mode==1?vbs:vbd));
2958  } else {
2959  sarg=sqrt(tPhi);
2960  sarg=sarg-(mode==1?vbs:vbd)/(sarg+sarg);
2961  sarg=Xycemax(0.0,sarg);
2962  }
2963  Von=(tVbi*model_.dtype)+model_.gamma*sarg;
2964  vgst=(mode==1?vgs:vgd)-Von;
2965  Vdsat=Xycemax(vgst,0.0);
2966  if (sarg <= 0) {
2967  arg=0;
2968  } else {
2969  arg=model_.gamma/(sarg+sarg);
2970  }
2971 
2972  if (vgst <= 0)
2973  {
2974  //
2975  // cutoff region
2976  //
2977  cdrain=0;
2978  gm=0;
2979  gds=0;
2980  gmbs=0;
2981  }
2982  else
2983  {
2984  //
2985  // saturation region
2986  //
2987  betap=Beta*(1+model_.lambda*(vds*mode));
2988  if (vgst <= (vds*mode))
2989  {
2990  cdrain=betap*vgst*vgst*.5;
2991  gm=betap*vgst;
2992  gds=model_.lambda*Beta*vgst*vgst*.5;
2993  gmbs=gm*arg;
2994 
2995  //cout << "I'm here! And gm = " << gm << std::endl;
2996  }
2997  else
2998  {
2999  //
3000  // linear region
3001  //
3002  cdrain=betap*(vds*mode)*
3003  (vgst-.5*(vds*mode));
3004  gm=betap*(vds*mode);
3005  gds=betap*(vgst-(vds*mode))+
3006  model_.lambda*Beta*
3007  (vds*mode)*
3008  (vgst-.5*(vds*mode));
3009  gmbs=gm*arg;
3010  }
3011  }
3012  //
3013  // finished
3014  //
3015  }
3016 
3017  // now deal with n vs p polarity
3018 
3019  von = model_.dtype * Von;
3020  vdsat = model_.dtype * Vdsat;
3021 
3022  ////
3023  // * COMPUTE EQUIVALENT DRAIN CURRENT SOURCE
3024  ////
3025 
3026  cd = mode * cdrain - cbd;
3027 
3028  // in 3f5 this is all in a block conditioned on CKTmode, but since
3029  // it's valid for MODETRAN and MODETRANOP we'll just always do it
3030 
3031  ////
3032  // * now we do the hard part of the bulk-drain and bulk-source
3033  // * diode - we evaluate the non-linear capacitance and
3034  // * charge
3035  // *
3036  // * the basic equations are not hard, but the implementation
3037  // * is somewhat long in an attempt to avoid log/exponential
3038  // * evaluations
3039  ////
3040  ////
3041  // * charge storage elements
3042  // *
3043  // *.. bulk-drain and bulk-source depletion capacitances
3044  ////
3045  // I took out all the CAPBYPASS stuff, and the
3046  // unnecessary curly braces that wind up there if you do
3047 
3048  // can't bypass the diode capacitance calculations
3049  if(Cbs != 0 || Cbssw != 0 )
3050  {
3051  if (vbs < tDepCap)
3052  {
3053  arg=1-vbs/tBulkPot;
3054  ////
3055  // * the following block looks somewhat long and messy,
3056  // * but since most users use the default grading
3057  // * coefficients of .5, and sqrt is MUCH faster than an
3058  // * exp(log()) we use this special case code to buy time.
3059  // * (as much as 10% of total job time!)
3060  ////
3062  {
3063  if(model_.bulkJctBotGradingCoeff == .5)
3064  {
3065  sarg = sargsw = 1/sqrt(arg);
3066  }
3067  else
3068  {
3069  sarg = sargsw = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3070  }
3071  }
3072  else
3073  {
3074  if(model_.bulkJctBotGradingCoeff == .5)
3075  {
3076  sarg = 1/sqrt(arg);
3077  }
3078  else
3079  {
3080  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3081  }
3083  {
3084  sargsw = 1/sqrt(arg);
3085  }
3086  else
3087  {
3088  sargsw =exp(-model_.bulkJctSideGradingCoeff* log(arg));
3089  }
3090  }
3091  qbs = tBulkPot*(Cbs*(1-arg*sarg)/(1-model_.bulkJctBotGradingCoeff)
3092  +Cbssw*(1-arg*sargsw)/(1-model_.bulkJctSideGradingCoeff));
3093  capbs=Cbs*sarg+ Cbssw*sargsw;
3094  }
3095  else
3096  {
3097  qbs = f4s + vbs*(f2s+vbs*(f3s/2));
3098  capbs=f2s+f3s*vbs;
3099  }
3100  }
3101  else
3102  {
3103  qbs = 0;
3104  capbs=0;
3105  }
3106 
3107  //// can't bypass the diode capacitance calculations
3108  if(Cbd != 0 || Cbdsw != 0 )
3109  {
3110 
3111  if (vbd < tDepCap)
3112  {
3113  arg=1-vbd/tBulkPot;
3114  ////
3115  // * the following block looks somewhat long and messy,
3116  // * but since most users use the default grading
3117  // * coefficients of .5, and sqrt is MUCH faster than an
3118  // * exp(log()) we use this special case code to buy time.
3119  // * (as much as 10% of total job time!)
3120  ////
3121  if(model_.bulkJctBotGradingCoeff == .5 &&
3123  {
3124  sarg = sargsw = 1/sqrt(arg);
3125  }
3126  else
3127  {
3128  if(model_.bulkJctBotGradingCoeff == .5)
3129  {
3130  sarg = 1/sqrt(arg);
3131  }
3132  else
3133  {
3134  sarg = exp(-model_.bulkJctBotGradingCoeff*log(arg));
3135  }
3137  {
3138  sargsw = 1/sqrt(arg);
3139  }
3140  else
3141  {
3142  sargsw =exp(-model_.bulkJctSideGradingCoeff*log(arg));
3143  }
3144  }
3145  qbd =
3146  tBulkPot*(Cbd*
3147  (1-arg*sarg)
3149  +Cbdsw*
3150  (1-arg*sargsw)
3152  capbd=Cbd*sarg+
3153  Cbdsw*sargsw;
3154  }
3155  else
3156  {
3157  qbd = f4d +
3158  vbd * (f2d + vbd * f3d/2);
3159  capbd=f2d + vbd * f3d;
3160  }
3161  }
3162  else
3163  {
3164  qbd = 0;
3165  capbd = 0;
3166  }
3167 
3168  // Now after a mess of convergence stuff that seems not to apply to us
3169  // 3f5 saves the vbs, vbd, etc. in the state vector (we don't, it gets
3170  // saved in updatePrimaryState)
3171 
3172  // Then 3f5 calculates meyer capacitances, capgs, capgb and capgd
3173  // Careful! They use the local von and vdsat, which haven't got dtype
3174  // multiplying them!
3175 
3176  ////
3177  // * calculate meyer's capacitors
3178  ////
3179  ////
3180  // * new cmeyer - this just evaluates at the current time,
3181  // * expects you to remember values from previous time
3182  // * returns 1/2 of non-constant portion of capacitance
3183  // * you must add in the other half from previous time
3184  // * and the constant part
3185  ////
3186 
3187  if (mode > 0)
3188  { //add OxideCap back in to last arg if this doesn't work!
3189  //if ((getDeviceOptions().newMeyerFlag))
3190  //{
3191  devSupport.qmeyer (vgs,vgd,Vgb,Von,Vdsat,
3193 
3194  int Dtype = model_.dtype;
3195 
3196  //Need to pass Dtype to qmeyerderivs to get the right sign!
3197  devSupport.qmeyerderivs (vgs,vgd,Vgb,Von,Vdsat,
3201  tPhi,OxideCap,Dtype);
3202  //}
3203  //else
3204  //devSupport.qmeyer (vgs,vgd,Vgb,Von,Vdsat,
3205  // capgd, capgs, capgb, tPhi,OxideCap);
3206  }
3207  else
3208  {
3209  //if ((getDeviceOptions().newMeyerFlag))
3210  //{
3211  devSupport.qmeyer (vgd,vgs,Vgb,Von,Vdsat,
3213 
3214  int Dtype = model_.dtype;
3215 
3216  //Need to pass Dtype to qmeyerderivs to get the right sign!
3217  //Also, need to interchange the order of vgd and vgs from the
3218  //NMOS versions!
3219  devSupport.qmeyerderivs (vgd,vgs,Vgb,Von,Vdsat,
3223  tPhi,OxideCap,Dtype);
3224  //}
3225  //else
3226  //devSupport.qmeyer (vgd,vgs,Vgb,Von,Vdsat,
3227  // capgd, capgs, capgb, tPhi,OxideCap);
3228  }
3229 
3230 
3231  // vgs1 = vgs_old;
3232  // vgd1 = vgs1 - vds_old;
3233  // vgb1 = vgs1 - vbs_old;
3234 
3235  ////
3236  // TVR: Note! Caution with Capgs vs. capgs. If I used the instance var
3237  // capgs on the left hand side, it's OK as long as we never try to implement
3238  // meyer back averaging, since capgs is going to be recalculated each
3239  // time through. But if we do the averaging, the old one will have the
3240  // constant part and old old part added in, which is not what we wanted.
3241  // So I'll continue 3f5's way of having a local Capgs that's actually used
3242  // for the charge computation, and an instance capgs that's saved as state.
3243  ////
3244 
3245 
3246  //1/29/07, KRS: Can't use Meyer back-averaging with MPDE! For MPDE, we
3247  //don't integrate the current to get a charge and then differentiate it to
3248  //get the current back; we implement Cdv/dt directly.
3249 
3250  if (getDeviceOptions().newMeyerFlag)
3251  {
3252  Capgs = 2.0 * capgs + GateSourceOverlapCap ;
3253  Capgd = 2.0 * capgd + GateDrainOverlapCap ;
3254  Capgb = 2.0 * capgb + GateBulkOverlapCap ;
3255  }
3256  else // Otherwise, do back-averaging
3257  {
3258  if((getSolverState().dcopFlag))
3259  {
3260  Capgs = 2.0 * capgs + GateSourceOverlapCap ;
3261  Capgd = 2.0 * capgd + GateDrainOverlapCap ;
3262  Capgb = 2.0 * capgb + GateBulkOverlapCap ;
3263  }
3264  else
3265  {
3266  capgs_old = (*extData.currStaVectorPtr)[li_state_capgs];
3267  capgd_old = (*extData.currStaVectorPtr)[li_state_capgd];
3268  capgb_old = (*extData.currStaVectorPtr)[li_state_capgb];
3269 
3270 #ifdef Xyce_DEBUG_DEVICE
3272  {
3273  Xyce::dout() << "Doing meyer back averaging..."<< std::endl;
3274  Xyce::dout() << " capgs = " << capgs << " capgs_old = " << capgs_old << std::endl;
3275  Xyce::dout() << " capgd = " << capgd << " capgd_old = " << capgd_old << std::endl;
3276  Xyce::dout() << " capgb = " << capgb << " capgb_old = " << capgb_old << std::endl;
3277  }
3278 #endif
3279 
3280  Capgs = ( capgs+ capgs_old + GateSourceOverlapCap );
3281  Capgd = ( capgd+ capgd_old + GateDrainOverlapCap );
3282  Capgb = ( capgb+ capgb_old + GateBulkOverlapCap );
3283  }
3284  }
3285 
3286 #ifdef Xyce_DEBUG_DEVICE
3288  {
3289  Xyce::dout() << "Capgs = " << Capgs << std::endl;
3290  Xyce::dout() << "Capgd = " << Capgd << std::endl;
3291  Xyce::dout() << "Capgb = " << Capgb << std::endl;
3292  Xyce::dout() << "capgs = " << capgs << std::endl;
3293  Xyce::dout() << "capgd = " << capgd << std::endl;
3294  Xyce::dout() << "capgb = " << capgb << std::endl;
3295  }
3296 #endif
3297 
3298  // Eric does this kludge in level 1, so I'll do it to make sure capacitances
3299  // are positive
3300  Capgs *= (Capgs < 0.0)?-1.0:1.0;
3301  Capgd *= (Capgd < 0.0)?-1.0:1.0;
3302  Capgb *= (Capgb < 0.0)?-1.0:1.0;
3303 
3304 
3305  // in the sequel, I'll refer to all derivatives of currents w.r.t. voltages
3306  // as conductances, whether they really are or not.
3307 
3308  // when we get here, cdrain has the channel current
3309  // cbd and cbs have the currents through the diodes
3310  // cd has the drain current minus the diode current and seems only to be used
3311  // for 3f5 convergence stuff
3312  // qbs and qbd have the charges on the parasitic capacitors
3313  // capbs and capbd have the capacitances of the parasitics.
3314 
3315  // none of the charges for the gate capacitors have been calculated yet.
3316  // We've saved the capacitances, so we can get the charges in
3317  // updatePrimaryState later.
3318 
3319  // Conductances:
3320  // gbd: the bulk-drain' conductance without the capacitor components
3321  // We'll need to get the capacitor contribution in the actual load
3322  // using C*dt
3323  // gbs: bulk-source' without capacitor
3324  // gm = derivative of channel current w.r.t. gate-source voltage --- gotta
3325  // account for mode=normal or mode=reverse when using this!
3326  // gmbs = derivative of channel current w.r.t bulk-source voltage
3327  // gds = derivative of channel current w.r.t. drain-source voltage
3328 
3329  // the variables gcgs, gcgb, gcgd should be the conductances for the gate
3330  // capacitors, but we won't do those here (vide supra), we'll do them
3331  // in the jacobian load given the capacitances.
3332 
3333  // Now 3f5 doesn't do the resistor currents in the RHS load, because of
3334  // how they do their numerics. We do, so let's save those here.
3335 
3338 
3339  if (mode >= 0) // Normal mode
3340  {
3341  Gm = gm; // (xnrm-xrev)*gm in 3f5
3342  Gmbs = gmbs; // (xnrm-xrev)*gmbs in 3f5
3343  nrmsum = Gm+Gmbs; // xnrm*(gm+gmbs)
3344  revsum = 0; // xrev*(gm+gmbs)
3346  }
3347  else
3348  {
3349  Gm = -gm;
3350  Gmbs = -gmbs;
3351  nrmsum = 0;
3352  revsum = -(Gm+Gmbs); // because Gm and Gmbs already have - in them!
3353  cdreq = -(model_.dtype)*cdrain;
3354  }
3355 
3356  // It is now essential to restore the vds/vgs/vgd variables that might
3357  // have been tweaked by homotopy, lest they have an effect on RHS
3358  // Jdxp terms.
3359 
3360  vds=vds_save;
3361  vgs=vgs_save;
3362  vgd=vgd_save;
3363 
3364  /// CURRENTS to load into RHS:
3365 
3366  // so at this point:
3367 
3368  // current out of drain is
3369  // Idrain
3370 
3371  // current out of gate:
3372  // dtype*( (deriv of qgs) + (deriv of qgd) + (deriv of qgb))
3373 
3374  // the current *out of* the source should be simply
3375  // Isource.
3376 
3377  // current out of bulk is
3378  // dtype*(deriv of qbd) + dtype*cbd + dtype*cbs + dtype*(deriv of qbs)
3379  // - dtype*(deriv of qgb)
3380 
3381  // current out of drain' is
3382  // -Idrain - dtype*(deriv of qgd) - (deriv of qbd) - dtype*cbd +
3383  // mode*dtype*cdrain
3384 
3385  // the current out of the source' is
3386  // -Isource - dtype*(deriv of qgs) - dtype*cbs - (deriv of qbs) -
3387  // mode*dtype*cdrain
3388 
3389  //////Conductances to load into Jacobian as they relate to things here:
3390  /// all of the places where I say Cap/dt I really mean dtype*Cap/dt for
3391  // the meyer capacitors. No dtype for the parasitics, though
3392 
3393  // 3f5 handles the mode by doing:
3394  // where xnrm=1, xrev=0 if mode>=0, xnrm=0,xrev=1 if mode<0
3395 
3396  // drain-drain = a = drainConductance
3397  // drain-drain' = b = -drainConductance
3398 
3399  // gate-gate = c = "gcgd+gcgs+gcgb" = Capgd/dt+Capgs/dt+Capgb/dt
3400  // gate-bulk = d = -gcgb = -Capgb/dt
3401  // gate-drain' = e = -gcgd = -Capgd/dt
3402  // gate-source' = f = -gcgs = -Capgs/dt
3403 
3404  // source-source = g = sourceConductance
3405  // source-source' = h = -sourceConductance
3406 
3407  // bulk-gate = i = -gcgb = -Capgb/dt
3408  // bulk-bulk = j = gbs+gbd+gcgb+parasitics=gbs+gbd+Capgb/dt+capbs/dt+capbd/dt
3409  // bulk-drain' = k= -gbd-capbd/dt
3410  // bulk-source' = l= -gbs-capbs/dt
3411 
3412  // drain'-drain = m = -drainConductance
3413  // drain'-gate = n = (xnrm-xrev)*gm-Capgd/dt
3414  // drain'-bulk = o = -gbd-capbd/dt+(xnrm-xrev)*gmbs
3415  // drain'-drain' = p = drainConductance+gds+gbd+capbd/dt+
3416  // xrev*(gm+gmbs)+ Capgd/dt
3417  // drain'-source' = q = -gds-xnrm*(gm+gmbs)
3418 
3419  // source'-gate = r = -(xnrm-xrev)*gm-Capgs/dt
3420  // source'-source = s = -sourceConductance
3421  // source'-bulk = t = -gbs-capbs/dt-(xnrm-xrev)*gmbs
3422  // source'-drain' = u= -gds-xrev*(gm+gmbs)
3423  // source'-source' = v = sourceConductance+gds+gbs+capbs/dt+xnrm*(gm+gmbs)+
3424  // Capgs/dt
3425 
3426  return bsuccess;
3427 }
3428 
3429 //-----------------------------------------------------------------------------
3430 // Function : Instance::updateTemperature
3431 // Purpose :
3432 // Special Notes :
3433 // Scope : public
3434 // Creator : Tom Russo, Component Information and Models
3435 // Creation Date : 02/27/01
3436 //-----------------------------------------------------------------------------
3437 bool Instance::updateTemperature ( const double & temp_tmp)
3438 {
3439  // mos3temp vars
3440  double czbd; // zero voltage bulk-drain capacitance
3441  double czbdsw; // zero voltage bulk-drain sidewall capacitance
3442  double czbs; // zero voltage bulk-source capacitance
3443  double czbssw; // zero voltage bulk-source sidewall capacitance
3444  double arg; // 1 - fc
3445  double sarg; // (1-fc) ^^ (-mj)
3446  double sargsw; // (1-fc) ^^ (-mjsw)
3447  double ratio,ratio4;
3448  double fact2;
3449  double kt;
3450  double egfet;
3451  double pbfact;
3452  double capfact;
3453  double phio;
3454  double pbo;
3455  double gmanew,gmaold;
3456  // end of mos3temp stuff
3457 
3458  double tnom;
3459 
3460 #ifdef Xyce_DEBUG_DEVICE
3461  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3462  {
3463  Xyce::dout() << subsection_divider << std::endl;
3464  Xyce::dout() << " Instance::Begin of updateTemperature. \n";
3465  Xyce::dout() <<" name = " << getName() << std::endl;
3466  Xyce::dout() << std::endl;
3467  }
3468 #endif
3469 
3470  // first set the instance temperature to the new temperature:
3471  if (temp_tmp != -999.0) temp = temp_tmp;
3472 
3474  {
3476  }
3477 
3478  tnom = model_.tnom;
3479  ratio = temp/tnom;
3480 
3481 #ifdef Xyce_DEBUG_DEVICE
3482  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
3483  {
3484  Xyce::dout() << "Temperature = "<< temp << std::endl;
3485  Xyce::dout() << "tnom = " << tnom << std::endl;
3486  Xyce::dout() << "ratio = " << ratio << std::endl;
3487  }
3488 #endif
3489 
3490  vt = temp * CONSTKoverQ;
3491  ratio = temp/tnom;
3492  fact2 = temp/CONSTREFTEMP;
3493  kt = temp * CONSTboltz;
3494  egfet = 1.16-(7.02e-4*temp*temp)/(temp+1108);
3495  arg = -egfet/(kt+kt)+1.1150877/(CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3496  pbfact = -2*vt *(1.5*log(fact2)+CONSTQ*arg);
3497 
3498 #ifdef Xyce_DEBUG_DEVICE
3500  {
3501  Xyce::dout() << "vt = " << vt << std::endl;
3502  Xyce::dout() << "ratio = " << ratio << std::endl;
3503  Xyce::dout() << "fact2 = " << fact2 << std::endl;
3504  Xyce::dout() << "kt = " << kt << std::endl;
3505  Xyce::dout() << "egfet = " << egfet << std::endl;
3506  Xyce::dout() << "arg = " << arg << std::endl;
3507  Xyce::dout() << "pbfact = " << pbfact << std::endl;
3508  }
3509 #endif
3510 
3511  // in mos3temp 3f5 does a bunch of parameter defaulting (lines 155-163)
3512  // but we assume that our various parameters have been set already in
3513  // the constructors
3514 
3515  // lines 164-203 of mos3temp moved to instance block constructor
3516 
3517  // Here's the entire guts of the mos3temp instance loop, with obvious
3518  // modifications (here->MOS3 goes away, model->MOS3 turns into model_.)
3519 
3520  ratio4 = ratio * sqrt(ratio);
3522  tSurfMob = model_.surfaceMobility/ratio4;
3523  phio= (model_.phi-model_.pbfact1)/model_.fact1;
3524  tPhi = fact2 * phio + pbfact;
3525  tVbi = model_.vt0 - model_.dtype *
3526  (model_.gamma* sqrt(model_.phi))+.5*(model_.egfet1-egfet)
3527  + model_.dtype*.5* (tPhi-model_.phi);
3528  tVto = tVbi + model_.dtype * model_.gamma * sqrt(tPhi);
3532  gmaold = (model_.bulkJctPotential-pbo)/pbo;
3533  capfact = 1/(1+model_.bulkJctBotGradingCoeff*
3534  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3535  tCbd = model_.capBD * capfact;
3536  tCbs = model_.capBS * capfact;
3537  tCj = model_.bulkCapFactor * capfact;
3538  capfact = 1/(1+model_.bulkJctSideGradingCoeff*
3539  (4e-4*(model_.tnom-CONSTREFTEMP)-gmaold));
3540  tCjsw = model_.sideWallCapFactor * capfact;
3541  tBulkPot = fact2 * pbo+pbfact;
3542  gmanew = (tBulkPot-pbo)/pbo;
3543  capfact = (1+model_.bulkJctBotGradingCoeff*(4e-4*(temp-CONSTREFTEMP)-gmanew));
3544  tCbd *= capfact;
3545  tCbs *= capfact;
3546  tCj *= capfact;
3547  capfact = (1+model_.bulkJctSideGradingCoeff*(4e-4*(temp-CONSTREFTEMP)-gmanew));
3548  tCjsw *= capfact;
3550 
3551 #ifdef Xyce_DEBUG_DEVICE
3553  {
3554  Xyce::dout() << " ratio4 = " << ratio4 << std::endl;
3555  Xyce::dout() << " tTransconductance = " << tTransconductance << std::endl;
3556  Xyce::dout() << " tSurfMob = " << tSurfMob << std::endl;
3557  Xyce::dout() << " phio = " << phio << std::endl;
3558  Xyce::dout() << " tPhi = " << tPhi << std::endl;
3559  Xyce::dout() << " tVbi = " << tVbi << std::endl;
3560  Xyce::dout() << " tVto = " << tVto << std::endl;
3561  Xyce::dout() << " tSatCur = " << tSatCur << std::endl;
3562  Xyce::dout() << " tSatCurDens = " << tSatCurDens << std::endl;
3563  Xyce::dout() << " pbo = " << pbo << std::endl;
3564  Xyce::dout() << " gmaold = " << gmaold << std::endl;
3565  Xyce::dout() << " tBulkPot = " << tBulkPot << std::endl;
3566  Xyce::dout() << " gmanew = " << gmanew << std::endl;
3567  Xyce::dout() << " capfact = " << capfact << std::endl;
3568  Xyce::dout() << " tCbd = " << tCbd << std::endl;
3569  Xyce::dout() << " tCbs = " << tCbs << std::endl;
3570  Xyce::dout() << " tCj = " << tCj << std::endl;
3571  Xyce::dout() << " capfact = " << capfact << std::endl;
3572  Xyce::dout() << " tCjsw = " << tCjsw << std::endl;
3573  Xyce::dout() << " tDepCap = " << tDepCap << std::endl;
3574  }
3575 #endif
3576 
3577  if( (model_.jctSatCurDensity == 0) || (drainArea == 0) ||
3578  (sourceArea == 0) )
3579  {
3581  vt*log(vt/(CONSTroot2*model_.jctSatCur));
3582  }
3583  else
3584  {
3585  drainVcrit = vt * log( vt / (CONSTroot2 *
3587  sourceVcrit = vt * log( vt / (CONSTroot2 *
3589  }
3590  if(model_.capBDGiven)
3591  {
3592  czbd = tCbd;
3593  }
3594  else
3595  {
3597  {
3598  czbd=tCj*drainArea;
3599  }
3600  else
3601  {
3602  czbd=0;
3603  }
3604  }
3606  {
3607  czbdsw= tCjsw * drainPerimeter;
3608  }
3609  else
3610  {
3611  czbdsw=0;
3612  }
3613  arg = 1-model_.fwdCapDepCoeff;
3614  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3615  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3616  Cbd = czbd;
3617  Cbdsw = czbdsw;
3618  f2d = czbd*(1-model_.fwdCapDepCoeff*
3619  (1+model_.bulkJctBotGradingCoeff))* sarg/arg
3620  + czbdsw*(1-model_.fwdCapDepCoeff*
3622  sargsw/arg;
3623  f3d = czbd * model_.bulkJctBotGradingCoeff * sarg/arg/
3624  tBulkPot
3625  + czbdsw * model_.bulkJctSideGradingCoeff * sargsw/arg /
3626  tBulkPot;
3627  f4d = czbd*tBulkPot*(1-arg*sarg)/
3629  + czbdsw*tBulkPot*(1-arg*sargsw)/
3631  -f3d/2*
3632  (tDepCap*tDepCap)
3633  -tDepCap * f2d;
3634  if(model_.capBSGiven)
3635  {
3636  czbs=tCbs;
3637  }
3638  else
3639  {
3641  {
3642  czbs=tCj*sourceArea;
3643  }
3644  else
3645  {
3646  czbs=0;
3647  }
3648  }
3650  {
3651  czbssw = tCjsw * sourcePerimeter;
3652  }
3653  else
3654  {
3655  czbssw=0;
3656  }
3657  arg = 1-model_.fwdCapDepCoeff;
3658  sarg = exp( (-model_.bulkJctBotGradingCoeff) * log(arg) );
3659  sargsw = exp( (-model_.bulkJctSideGradingCoeff) * log(arg) );
3660  Cbs = czbs;
3661  Cbssw = czbssw;
3662  f2s = czbs*(1-model_.fwdCapDepCoeff*
3663  (1+model_.bulkJctBotGradingCoeff))* sarg/arg
3664  + czbssw*(1-model_.fwdCapDepCoeff*
3666  sargsw/arg;
3667  f3s = czbs * model_.bulkJctBotGradingCoeff * sarg/arg/
3668  tBulkPot
3669  + czbssw * model_.bulkJctSideGradingCoeff * sargsw/arg /
3670  tBulkPot;
3671  f4s = czbs*tBulkPot*(1-arg*sarg)/
3673  + czbssw*tBulkPot*(1-arg*sargsw)/
3675  -f3s/2*
3676  (tDepCap*tDepCap)
3677  -tDepCap * f2s;
3678 
3679  return true;
3680 }
3681 
3682 //-----------------------------------------------------------------------------
3683 // Function : Instance::updatePrimaryState
3684 // Purpose :
3685 // Special Notes :
3686 // Scope : public
3687 // Creator : Tom Russo, Component Information and Models
3688 // Creation Date : 02/28/01
3689 //-----------------------------------------------------------------------------
3691 {
3692  double * staVector = extData.nextStaVectorRawPtr;
3693  double * oldstaVector = extData.currStaVectorRawPtr;
3694  double * stoVector = extData.nextStoVectorRawPtr;
3695  double * oldstoVector = extData.currStoVectorRawPtr;
3696  double vgs1, vgd1, vbs1,vgb1, vds1;
3697 
3698  bool bsuccess = updateIntermediateVars ();
3699 
3700  // voltage drops:
3701  stoVector[li_store_vbd] = vbd;
3702  stoVector[li_store_vbs] = vbs;
3703  stoVector[li_store_vgs] = vgs;
3704  stoVector[li_store_vds] = vds;
3705  stoVector[li_store_von] = von;
3706 
3707  // now the meyer capacitances
3708  // we didn't calculate these charges in update IntermediateVars
3709  // but we did calculate the voltage drops and capacitances.
3710  // first store the capacitances themselves:
3711  staVector[li_state_capgs] = capgs;
3712  staVector[li_state_capgd] = capgd;
3713  staVector[li_state_capgb] = capgb;
3714 
3715  //1/29/08, KRS: When we're NOT doing Meyer back-averaging, we put the
3716  //differential voltages into the "charge" vector:
3717  if (getDeviceOptions().newMeyerFlag)
3718  {
3719  qgs=vgs;
3720  qgd=vgd;
3721  qgb=Vgb;
3722  }
3723  else //Otherwise, do Meyer back-averaging:
3724  {
3725  // now the charges
3726  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
3727  // supposed to be *INTEGRATED*:
3728  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
3729  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
3730  // Now with Meyer back averaging, Capxx is the average between the last
3731  // time step and this one. So we gotta do the right thing for non-DCOP
3732  // when backaverage is on.
3733 
3734 
3735  if((getSolverState().dcopFlag))
3736  {
3737  qgs = Capgs*vgs;
3738  qgd = Capgd*vgd;
3739  qgb = Capgb*Vgb;
3740  }
3741  else
3742  {
3743  // get the ones from last time step
3744  qgs = oldstaVector[li_state_qgs];
3745  qgd = oldstaVector[li_state_qgd];
3746  qgb = oldstaVector[li_state_qgb];
3747  // get the voltage drops, too
3748  vgs1 = oldstoVector[li_store_vgs];
3749  vbs1 = oldstoVector[li_store_vbs];
3750  vds1 = oldstoVector[li_store_vds];
3751 
3752  vgb1 = vgs1-vbs1;
3753  vgd1 = vgs1-vds1;
3754 
3755  // NOW we can calculate the charge update
3756  qgs += Capgs*(vgs-vgs1);
3757  qgd += Capgd*(vgd-vgd1);
3758  qgb += Capgb*((vgs-vbs)-vgb1);
3759  }
3760  }
3761 
3762  staVector[li_state_qgs] = qgs;
3763  staVector[li_state_qgd] = qgd;
3764  staVector[li_state_qgb] = qgb;
3765 
3766  // and the diode parasitic capacitors
3767  // these charges were set in updateIntermediateVars
3768  staVector[li_state_qbd] = qbd;
3769  staVector[li_state_qbs] = qbs;
3770 
3771  return bsuccess;
3772 }
3773 
3774 // Additional Declarations
3775 
3776 // Class Model
3777 
3778 //-----------------------------------------------------------------------------
3779 // Function : Model::processParams
3780 // Purpose :
3781 // Special Notes :
3782 // Scope : public
3783 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3784 // Creation Date : 6/03/02
3785 //-----------------------------------------------------------------------------
3787 {
3788  double wkfngs;
3789  double wkfng;
3790  double fermig;
3791  double fermis;
3792  double vfb;
3793  double kt1;
3794  double arg1;
3795 
3798  kt1 = CONSTboltz * tnom;
3799  egfet1 = 1.16-(7.02e-4*tnom*tnom)/(tnom+1108);
3800  arg1 = -egfet1/(kt1+kt1)+1.1150877/(CONSTboltz*(CONSTREFTEMP+CONSTREFTEMP));
3801  pbfact1 = -2*vtnom *(1.5*log(fact1)+CONSTQ*arg1);
3802 
3803  if(!given("TOX") || oxideThickness == 0)
3804  {
3805  oxideCapFactor = 0;
3806  }
3807  else
3808  {
3809  oxideCapFactor = 3.9 * 8.854214871e-12/oxideThickness;
3810  if(!given("KP"))
3811  {
3812  if(!given("UO") && !given("U0")) surfaceMobility=600;
3814  oxideCapFactor * 1e-4;
3815  }
3816  if(given("NSUB"))
3817  {
3818  if(substrateDoping*1e6 >1.45e16)
3819  {
3820  if(!given("PHI"))
3821  {
3822  phi = 2*vtnom*
3823  log(substrateDoping*1e6/1.45e16);
3824  phi = Xycemax(0.1,phi);
3825  }
3826  fermis = dtype * .5 * phi;
3827  wkfng = 3.2;
3828  if(!given("TPG")) gateType=1;
3829  if(gateType != 0)
3830  {
3831  fermig = dtype *gateType*.5*egfet1;
3832  wkfng = 3.25 + .5 * egfet1 - fermig;
3833  }
3834  wkfngs = wkfng - (3.25 + .5 * egfet1 +fermis);
3835  if(!given("GAMMA"))
3836  {
3837  gamma = sqrt(2 * 11.70 * 8.854214871e-12 *
3838  CONSTQ * substrateDoping*1e6)/
3840  }
3841  if(!given("VTO"))
3842  {
3843  if(!given("NSS"))
3845  vfb = wkfngs - surfaceStateDensity*1e4*CONSTQ/oxideCapFactor;
3846  vt0 = vfb + dtype * (gamma * sqrt(phi)+ phi);
3847  }
3848  }
3849  else
3850  {
3851  UserError0(*this) << "Nsub < Ni";
3852 
3853  substrateDoping = 0;
3854  }
3855  }
3856  }
3857  return true;
3858 }
3859 
3860 //----------------------------------------------------------------------------
3861 // Function : Model::processInstanceParams
3862 // Purpose :
3863 // Special Notes :
3864 // Scope : public
3865 // Creator : Dave Shirely, PSSI
3866 // Creation Date : 03/23/06
3867 //----------------------------------------------------------------------------
3869 {
3870  std::vector<Instance*>::iterator iter;
3871  std::vector<Instance*>::iterator first = instanceContainer.begin();
3872  std::vector<Instance*>::iterator last = instanceContainer.end();
3873 
3874  for (iter=first; iter!=last; ++iter)
3875  {
3876  (*iter)->processParams();
3877  }
3878 
3879  return true;
3880 }
3881 
3882 //-----------------------------------------------------------------------------
3883 // Function : Model::Model
3884 // Purpose :
3885 // Special Notes :
3886 // Scope : public
3887 // Creator : Tom Russo, Component Information and Models
3888 // Creation Date : 2/26/01
3889 //-----------------------------------------------------------------------------
3891  const Configuration & configuration,
3892  const ModelBlock & MB,
3893  const FactoryBlock & factory_block)
3894  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
3895  dtype(CONSTNMOS),
3896  tnom(getDeviceOptions().tnom),
3897  latDiff(0.0),
3898  jctSatCurDensity(0.0),
3899  jctSatCur(0.0),
3900  drainResistance(0.0),
3901  sourceResistance(0.0),
3902  sheetResistance(0.0),
3903  transconductance(0.0),
3904  gateSourceOverlapCapFactor(0.0),
3905  gateDrainOverlapCapFactor(0.0),
3906  gateBulkOverlapCapFactor(0.0),
3907  oxideCapFactor(0.0),
3908  vt0(0.0),
3909  capBD(0.0),
3910  capBS(0.0),
3911  bulkCapFactor(0.0),
3912  sideWallCapFactor(0.0),
3913  bulkJctPotential(0.0),
3914  bulkJctBotGradingCoeff(0.0),
3915  bulkJctSideGradingCoeff(0.0),
3916  fwdCapDepCoeff(0.0),
3917  phi(0.0),
3918  gamma(0.0),
3919  lambda(0.0),
3920  substrateDoping(0.0),
3921  gateType(0),
3922  surfaceStateDensity(0.0),
3923  oxideThickness(0.0),
3924  surfaceMobility(0.0),
3925  fNcoef(0.0),
3926  fNexp(0.0),
3927  capBDGiven(0),
3928  capBSGiven(0),
3929  bulkCapFactorGiven(0),
3930  sideWallCapFactorGiven(0)
3931 {
3932  if (getType() != "")
3933  {
3934  if (getType() == "NMOS") {
3935  dtype = CONSTNMOS;
3936  }
3937  else if (getType() == "PMOS") {
3938  dtype = CONSTPMOS;
3939  }
3940  else
3941  {
3942  UserError0(*this) << "Could not recognize the type for model " << getName();
3943  }
3944  }
3945 
3946 
3947  // Set params to constant default values:
3948  setDefaultParams ();
3949 
3950  // Set params according to .model line and constant defaults from metadata:
3951  setModParams (MB.params);
3952 
3953  // Set any non-constant parameter defaults:
3954  if (!given("L"))
3956  if (!given("W"))
3958  if (!given("TNOM"))
3960  if (capBD != 0)
3961  capBDGiven = true;
3962  if (capBS != 0)
3963  capBSGiven = true;
3964 
3965  // Calculate any parameters specified as expressions:
3967 
3968  // calculate dependent (ie computed) params and check for errors:
3969  if (given("U0"))
3970  {
3971  if (given("UO"))
3972  UserError0(*this) << "You have specified both uo and u0, which is not allowed.";
3973 
3974  UserWarning0(*this) << "You have specified the surface mobility as u0 instead of uo. This is supported, but ill-advised.";
3975 
3977  }
3978 
3979  processParams ();
3980 }
3981 
3982 //-----------------------------------------------------------------------------
3983 // Function : Model::~Model
3984 // Purpose : destructor
3985 // Special Notes :
3986 // Scope : public
3987 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3988 // Creation Date : 3/16/00
3989 //-----------------------------------------------------------------------------
3991 {
3992  std::vector<Instance*>::iterator iter;
3993  std::vector<Instance*>::iterator first = instanceContainer.begin();
3994  std::vector<Instance*>::iterator last = instanceContainer.end();
3995 
3996  for (iter=first; iter!=last; ++iter)
3997  {
3998  delete (*iter);
3999  }
4000 
4001 }
4002 
4003 //-----------------------------------------------------------------------------
4004 // Function : Model::printOutInstances
4005 // Purpose : debugging tool.
4006 // Special Notes :
4007 // Scope : public
4008 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
4009 // Creation Date : 4/03/00
4010 //-----------------------------------------------------------------------------
4011 std::ostream &Model::printOutInstances(std::ostream &os) const
4012 {
4013  std::vector<Instance*>::const_iterator iter;
4014  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
4015  std::vector<Instance*>::const_iterator last = instanceContainer.end();
4016 
4017  int i;
4018  os << std::endl;
4019  os << " name model name Parameters" << std::endl;
4020  for (i=0, iter=first; iter!=last; ++iter, ++i)
4021  {
4022  os << " " << i << ": " << (*iter)->getName() << "\t";
4023  os << getName();
4024  os << std::endl;
4025  }
4026 
4027  os << std::endl;
4028  return os;
4029 }
4030 
4031 //-----------------------------------------------------------------------------
4032 // Function : Model::forEachInstance
4033 // Purpose :
4034 // Special Notes :
4035 // Scope : public
4036 // Creator : David Baur
4037 // Creation Date : 2/4/2014
4038 //-----------------------------------------------------------------------------
4039 /// Apply a device instance "op" to all instances associated with this
4040 /// model
4041 ///
4042 /// @param[in] op Operator to apply to all instances.
4043 ///
4044 ///
4045 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
4046 {
4047  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
4048  op(*it);
4049 }
4050 
4051 
4052 //-----------------------------------------------------------------------------
4053 // Function : Instance::loadDeviceMask
4054 //
4055 // Purpose : Loads the zero elements of the device mask
4056 //
4057 // Special Notes : elements of the error vector associated with zero
4058 // elements of the mask will not be included in weighted
4059 // norms by the time integrator.
4060 //
4061 // Scope : public
4062 // Creator : Keith Santarelli, SNL, Electrical and Microsystems Modeling
4063 // Creation Date : 03/12/08
4064 //-----------------------------------------------------------------------------
4066 {
4067  bool returnVal=false;
4068  if (getDeviceOptions().newMeyerFlag)
4069  {
4070  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
4071 
4072  (*maskVectorPtr)[li_Draindot] = 0.0;
4073  (*maskVectorPtr)[li_DrainPrimedot] = 0.0;
4074  (*maskVectorPtr)[li_Sourcedot] = 0.0;
4075  (*maskVectorPtr)[li_SourcePrimedot] = 0.0;
4076  (*maskVectorPtr)[li_Gatedot] = 0.0;
4077  (*maskVectorPtr)[li_Bulkdot] = 0.0;
4078  (*maskVectorPtr)[li_Drain] = 0.0;
4079  (*maskVectorPtr)[li_DrainPrime] = 0.0;
4080  (*maskVectorPtr)[li_Source] = 0.0;
4081  (*maskVectorPtr)[li_SourcePrime] = 0.0;
4082  (*maskVectorPtr)[li_Gate] = 0.0;
4083  (*maskVectorPtr)[li_Bulk] = 0.0;
4084 
4085  returnVal = true;
4086  }
4087 
4088  return (returnVal);
4089 }
4090 
4091 //-----------------------------------------------------------------------------
4092 // MOSFET1 Master functions:
4093 //-----------------------------------------------------------------------------
4094 
4095 //-----------------------------------------------------------------------------
4096 // Function : Master::updateState
4097 // Purpose :
4098 // Special Notes :
4099 // Scope : public
4100 // Creator : Eric Keiter, SNL
4101 // Creation Date : 11/26/08
4102 //-----------------------------------------------------------------------------
4103 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
4104 {
4105  bool bsuccess = true;
4106 
4107  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4108  {
4109  Instance & mi = *(*it);
4110  double * oldstaVec = mi.extData.currStaVectorRawPtr;
4111  double * stoVec = mi.extData.nextStoVectorRawPtr;
4112  double * oldstoVec = mi.extData.currStoVectorRawPtr;
4113 
4114  double vgs1(0.0), vgd1(0.0), vbs1(0.0),vgb1(0.0), vds1(0.0);
4115 
4116  bool btmp = mi.updateIntermediateVars ();
4117  bsuccess = bsuccess && btmp;
4118 
4119  // voltage drops:
4120  stoVec[mi.li_store_vbd] = mi.vbd;
4121  stoVec[mi.li_store_vbs] = mi.vbs;
4122  stoVec[mi.li_store_vgs] = mi.vgs;
4123  stoVec[mi.li_store_vds] = mi.vds;
4124  stoVec[mi.li_store_von] = mi.von;
4125 
4126  // now the meyer capacitances
4127  // we didn't calculate these charges in update IntermediateVars
4128  // but we did calculate the voltage drops and capacitances.
4129  // first store the capacitances themselves:
4130  staVec[mi.li_state_capgs] = mi.capgs;
4131  staVec[mi.li_state_capgd] = mi.capgd;
4132  staVec[mi.li_state_capgb] = mi.capgb;
4133 
4134  //1/29/08, KRS: When we're NOT doing Meyer back-averaging, we put the
4135  //differential voltages into the "charge" vector:
4136  if (getDeviceOptions().newMeyerFlag)
4137  {
4138  mi.qgs=mi.vgs;
4139  mi.qgd=mi.vgd;
4140  mi.qgb=mi.Vgb;
4141  }
4142  else //Otherwise, do Meyer back-averaging:
4143  {
4144  // now the charges
4145  // BE CAREFUL! We can only do Q=CV for DCOP! Otherwise it's
4146  // supposed to be *INTEGRATED*:
4147  // Q = int(t0,t1)C(V)*dV --- and we approximate that by
4148  // Q(t1)-Q(t0) = CBar*(V(t1)-V(t0)) where CBar is the average.
4149  // Now with Meyer back averaging, Capxx is the average between the last
4150  // time step and this one. So we gotta do the right thing for non-DCOP
4151  // when backaverage is on.
4152 
4153 
4154  if((getSolverState().dcopFlag))
4155  {
4156  mi.qgs = mi.Capgs*mi.vgs;
4157  mi.qgd = mi.Capgd*mi.vgd;
4158  mi.qgb = mi.Capgb*mi.Vgb;
4159  }
4160  else
4161  {
4162  // get the ones from last time step
4163  mi.qgs = oldstaVec[mi.li_state_qgs];
4164  mi.qgd = oldstaVec[mi.li_state_qgd];
4165  mi.qgb = oldstaVec[mi.li_state_qgb];
4166  // get the voltage drops, too
4167  vgs1 = oldstoVec[mi.li_store_vgs];
4168  vbs1 = oldstoVec[mi.li_store_vbs];
4169  vds1 = oldstoVec[mi.li_store_vds];
4170 
4171  vgb1 = vgs1-vbs1;
4172  vgd1 = vgs1-vds1;
4173 
4174  // NOW we can calculate the charge update
4175  mi.qgs += mi.Capgs*(mi.vgs-vgs1);
4176  mi.qgd += mi.Capgd*(mi.vgd-vgd1);
4177  mi.qgb += mi.Capgb*((mi.vgs-mi.vbs)-vgb1);
4178  }
4179  }
4180 
4181  staVec[mi.li_state_qgs] = mi.qgs;
4182  staVec[mi.li_state_qgd] = mi.qgd;
4183  staVec[mi.li_state_qgb] = mi.qgb;
4184 
4185  // and the diode parasitic capacitors
4186  // these charges were set in updateIntermediateVars
4187  staVec[mi.li_state_qbd] = mi.qbd;
4188  staVec[mi.li_state_qbs] = mi.qbs;
4189  }
4190 
4191  return bsuccess;
4192 }
4193 
4194 //-----------------------------------------------------------------------------
4195 // Function : Master::loadDAEVectors
4196 // Purpose :
4197 // Special Notes :
4198 // Scope : public
4199 // Creator : Eric Keiter, SNL
4200 // Creation Date : 11/26/08
4201 //-----------------------------------------------------------------------------
4202 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * storeLeadF, double * storeLeadQ)
4203 {
4204  double gmin1 = getDeviceOptions().gmin;
4205  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4206  {
4207  Instance & mi = *(*it);
4208 
4209  int Dtype=mi.getModel().dtype;
4210  double ceqbs(0.0),ceqbd(0.0),ceqgb(0.0), ceqgs(0.0), ceqgd(0.0);
4211  double Qeqbs(0.0),Qeqbd(0.0),Qeqgb(0.0), Qeqgs(0.0), Qeqgd(0.0);
4212  double coef(0.0);
4213 
4214  // F-Vector:
4215  if (getDeviceOptions().newMeyerFlag)
4216  {
4217  if (!getSolverState().dcopFlag)
4218  {
4219  double vbsdot = Dtype*(mi.Vbdot - mi.Vspdot);
4220  double vbddot = Dtype*(mi.Vbdot - mi.Vdpdot);
4221  double vgbdot = Dtype*(mi.Vgdot - mi.Vbdot);
4222  double vgsdot = Dtype*(mi.Vgdot - mi.Vspdot);
4223  double vgddot = Dtype*(mi.Vgdot - mi.Vdpdot);
4224 
4225  ceqbs = Dtype*(mi.cbs+mi.capbs*vbsdot);
4226  ceqbd = Dtype*(mi.cbd+mi.capbd*vbddot);
4227  ceqgb = Dtype*(mi.Capgb*vgbdot);
4228  ceqgs = Dtype*(mi.Capgs*vgsdot);
4229  ceqgd = Dtype*(mi.Capgd*vgddot);
4230  }
4231  else
4232  {
4233  ceqbs = Dtype*(mi.cbs);
4234  ceqbd = Dtype*(mi.cbd);
4235 
4236  // These need "Dtype" here because we use them later *without*
4237  // Dtype, where SPICE uses it *with*
4238  ceqgb = 0.0;
4239  ceqgs = 0.0;
4240  ceqgd = 0.0;
4241  }
4242  }
4243  else
4244  {
4245  ceqbs = Dtype*(mi.cbs);
4246  ceqbd = Dtype*(mi.cbd);
4247  // These need "Dtype" here because we use them later *without*
4248  // Dtype, where SPICE uses it *with*
4249  ceqgb = 0.0;
4250  ceqgs = 0.0;
4251  ceqgd = 0.0;
4252  }
4253 
4254  if (mi.drainConductance != 0.0)
4255  {
4256  fVec[mi.li_Drain] += mi.Idrain*mi.numberParallel;
4257  }
4258 
4259  coef = (ceqgs+ceqgd+ceqgb);
4260  fVec[mi.li_Gate] += coef*mi.numberParallel;
4261  if (mi.sourceConductance != 0.0)
4262  {
4263  fVec[mi.li_Source] += mi.Isource*mi.numberParallel;
4264  }
4265  coef = ceqbs + ceqbd - ceqgb;
4266  fVec[mi.li_Bulk] += coef*mi.numberParallel;
4267  coef = -mi.Idrain-(ceqbd - mi.cdreq + ceqgd);
4268  fVec[mi.li_DrainPrime] += coef*mi.numberParallel;
4269  coef = -mi.Isource-(ceqbs + mi.cdreq + ceqgs);
4270  fVec[mi.li_SourcePrime] += coef*mi.numberParallel;
4271 
4272  // Q-Vector:
4273  //Here's where we do the new Meyer stuff if selected:
4275  {
4276  //The first 6 eqns---representing the equations for the gate, drain, bulk,
4277  //source, drain', and source' nodes---are all zero here, so we don't need
4278  //to add any code for those. We just need to add stuff for the last six
4279  //variables.
4280 
4281  //qVec[li_Draindot] += OxideCap*Vd;
4282  //qVec[li_Gatedot] += OxideCap*Vg;
4283  //qVec[li_Bulkdot] += OxideCap*Vb;
4284  //qVec[mi.li_Sourcedot] += OxideCap*Vs;
4285  //if (drainConductance != 0.0)
4286  // qVec[mi.li_DrainPrimedot] += OxideCap*Vdp;
4287  //if (sourceConductance != 0.0)
4288  // qVec[mi.li_SourcePrimedot] += OxideCap*Vsp;
4289 
4290  qVec[mi.li_Draindot] += mi.Vd;
4291  qVec[mi.li_Gatedot] += mi.Vg;
4292  qVec[mi.li_Bulkdot] += mi.Vb;
4293  qVec[mi.li_Sourcedot] += mi.Vs;
4294 
4295  if (mi.drainConductance != 0.0)
4296  {
4297  qVec[mi.li_DrainPrimedot] += mi.Vdp;
4298  }
4299  if (mi.sourceConductance != 0.0)
4300  {
4301  qVec[mi.li_SourcePrimedot] += mi.Vsp;
4302  }
4303 
4304  //NOTE: typically, there are some coef_Jdxp terms that are added after
4305  //these statements to take voltage limiting into account. Because voltage
4306  //limiting is performed on *junction* voltages rather than node voltages, I
4307  //don't think those terms are appropriate to add here. Hopefully, I'm not
4308  //wrong...
4309  }
4310  else
4311  {
4312  Qeqbs = Dtype*(mi.qbs);
4313  Qeqbd = Dtype*(mi.qbd);
4314  // These need "Dtype" here because we use them later *without*
4315  // Dtype, where SPICE uses it *with*
4316  Qeqgb = Dtype*(mi.qgb);
4317  Qeqgs = Dtype*(mi.qgs);
4318  Qeqgd = Dtype*(mi.qgd);
4319 
4320  coef = (Qeqgs+Qeqgd+Qeqgb);
4321  qVec[mi.li_Gate] += coef*mi.numberParallel;
4322 
4323  coef = Qeqbs + Qeqbd - Qeqgb;
4324  qVec[mi.li_Bulk] += coef*mi.numberParallel;
4325 
4326  coef = -(Qeqbd + Qeqgd);
4327  qVec[mi.li_DrainPrime] += coef*mi.numberParallel;
4328 
4329  coef = -(Qeqbs + Qeqgs);
4330  qVec[mi.li_SourcePrime] += coef*mi.numberParallel;
4331  }
4332 
4333  // voltage limiters:
4334  if (!mi.origFlag)
4335  {
4336  // F-limiters:
4337  double coef_Jdxp4 = Dtype*(
4338  + ((mi.gbd-gmin1))*(mi.vbd-mi.vbd_orig)
4339  + ((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig));
4340 
4341  double coef_Jdxp5 = Dtype*(
4342  -((mi.gbd-gmin1))*(mi.vbd-mi.vbd_orig)
4343  +mi.gds*(mi.vds-mi.vds_orig)
4344  +mi.Gm*((mi.mode>0)?(mi.vgs-mi.vgs_orig):(mi.vgd-mi.vgd_orig))
4345  +mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbd-mi.vbd_orig)));
4346 
4347  double coef_Jdxp6 = Dtype*(
4348  -((mi.gbs-gmin1))*(mi.vbs-mi.vbs_orig)
4349  -mi.gds*(mi.vds-mi.vds_orig)
4350  -mi.Gm*((mi.mode>0)?(mi.vgs-mi.vgs_orig):(mi.vgd-mi.vgd_orig))
4351  -mi.Gmbs*((mi.mode>0)?(mi.vbs-mi.vbs_orig):(mi.vbd-mi.vbd_orig)));
4352 
4353  double * dFdxdVp = mi.extData.dFdxdVpVectorRawPtr;
4354 
4355  dFdxdVp[mi.li_Bulk ] += coef_Jdxp4*mi.numberParallel;
4356  dFdxdVp[mi.li_DrainPrime ] += coef_Jdxp5*mi.numberParallel;
4357  dFdxdVp[mi.li_SourcePrime] += coef_Jdxp6*mi.numberParallel;
4358 
4359  // Q-limiters:
4361  {
4362  double gcgd(0.0), gcgs(0.0), gcgb(0.0), gcbs(0.0), gcbd(0.0);
4363  if ( getSolverState().tranopFlag || getSolverState().acopFlag || getSolverState().transientFlag)
4364  {
4365  gcgd = mi.Capgd;
4366  gcgs = mi.Capgs;
4367  gcgb = mi.Capgb;
4368  // get at the two parasitic caps the same way
4369  gcbs = mi.capbs;
4370  gcbd = mi.capbd;
4371  }
4372  else
4373  {
4374  gcgd = 0.0; gcgs = 0.0; gcgb = 0.0; gcbs = 0.0; gcbd = 0.0;
4375  }
4376 
4377  double coef_Jdxp2 =
4378  Dtype*(gcgd*(mi.vgd-mi.vgd_orig)+gcgs*(mi.vgs-mi.vgs_orig)+
4379  gcgb*(mi.vgs-mi.vgs_orig-mi.vbs+mi.vbs_orig));
4380 
4381  double coef_Jdxp4 = Dtype*(
4382  - (gcgb)*(mi.vgs-mi.vgs_orig-mi.vbs+mi.vbs_orig)
4383  + (gcgb)*(mi.vbd-mi.vbd_orig)
4384  + (gcbs)*(mi.vbs-mi.vbs_orig));
4385 
4386  double coef_Jdxp5 = Dtype*(
4387  -(gcgd)*(mi.vgd-mi.vgd_orig)
4388  -(gcbd)*(mi.vbd-mi.vbd_orig));
4389 
4390  // 6 KCL for source' node
4391  double coef_Jdxp6 = Dtype*
4392  (-gcgs*(mi.vgs-mi.vgs_orig)-(gcbs)*(mi.vbs-mi.vbs_orig));
4393 
4394 
4395  double * dQdxdVp = mi.extData.dQdxdVpVectorRawPtr;
4396  dQdxdVp[mi.li_Gate ] += coef_Jdxp2*mi.numberParallel;
4397  dQdxdVp[mi.li_Bulk ] += coef_Jdxp4*mi.numberParallel;
4398  dQdxdVp[mi.li_DrainPrime ] += coef_Jdxp5*mi.numberParallel;
4399  dQdxdVp[mi.li_SourcePrime] += coef_Jdxp6*mi.numberParallel;
4400  }
4401  }
4402 
4403  if( mi.loadLeadCurrent )
4404  {
4405  if (mi.drainConductance != 0.0)
4406  {
4407  storeLeadF[mi.li_store_dev_id] = mi.Idrain*mi.numberParallel;
4408  }
4409  else
4410  {
4411  storeLeadF[mi.li_store_dev_id] = (-mi.Idrain-(ceqbd - mi.cdreq + ceqgd))*mi.numberParallel;
4412  storeLeadQ[mi.li_store_dev_id] = (-(Qeqbd + Qeqgd))*mi.numberParallel;
4413  }
4414  if (mi.sourceConductance != 0.0)
4415  {
4416  storeLeadF[mi.li_store_dev_is] = mi.Isource*mi.numberParallel;
4417  }
4418  else
4419  {
4420  storeLeadF[mi.li_store_dev_is] = (-mi.Isource-(ceqbs + mi.cdreq + ceqgs))*mi.numberParallel;
4421  storeLeadQ[mi.li_store_dev_is] = (-(Qeqbs + Qeqgs))*mi.numberParallel;
4422  }
4423  storeLeadF[mi.li_store_dev_ig] = (ceqgs+ceqgd+ceqgb)*mi.numberParallel;
4424  storeLeadQ[mi.li_store_dev_ig] = (Qeqgs+Qeqgd+Qeqgb)*mi.numberParallel;
4425  storeLeadF[mi.li_store_dev_ib] = (ceqbs + ceqbd - ceqgb)*mi.numberParallel;
4426  storeLeadQ[mi.li_store_dev_ib] = (Qeqbs + Qeqbd - Qeqgb)*mi.numberParallel;
4427  }
4428  }
4429  return true;
4430 }
4431 
4432 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
4433 //-----------------------------------------------------------------------------
4434 // Function : Master::loadDAEMatrices
4435 // Purpose :
4436 // Special Notes :
4437 // Scope : public
4438 // Creator : Eric Keiter, SNL
4439 // Creation Date : 11/26/08
4440 //-----------------------------------------------------------------------------
4441 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
4442 {
4443  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4444  {
4445  Instance & mi = *(*it);
4446 
4447  //introduce terms for capacitances, partial derivs. of capacitances,
4448  //and derivatives of differential voltages. "l" stands for "local"
4449 
4450  double l_capgs(0.0),l_capgd(0.0), l_capgb(0.0), l_capbd(0.0), l_capbs(0.0);
4451  double l_dcapgsdvgs(0.0),l_dcapgsdvgb(0.0),l_dcapgsdvgd(0.0);
4452  double l_dcapgbdvgs(0.0),l_dcapgbdvgb(0.0),l_dcapgbdvgd(0.0);
4453  double l_dcapgddvgs(0.0),l_dcapgddvgb(0.0),l_dcapgddvgd(0.0);
4454  double l_vgsdot(0.0), l_vgddot(0.0), l_vgbdot(0.0);
4455 
4456  if (getDeviceOptions().newMeyerFlag)
4457  {
4458  if (!getSolverState().dcopFlag)
4459  {
4460  l_capgs=mi.Capgs;
4461  l_capgd=mi.Capgd;
4462  l_capgb=mi.Capgb;
4463  l_capbd=mi.capbd;
4464  l_capbs=mi.capbs;
4465 
4466  l_dcapgsdvgs=mi.dcapgsdvgs;
4467  l_dcapgsdvgb=mi.dcapgsdvgb;
4468  l_dcapgsdvgd=mi.dcapgsdvgd;
4469  l_dcapgbdvgs=mi.dcapgbdvgs;
4470  l_dcapgbdvgb=mi.dcapgbdvgb;
4471  l_dcapgbdvgd=mi.dcapgbdvgd;
4472  l_dcapgddvgd=mi.dcapgddvgd;
4473  l_dcapgddvgs=mi.dcapgddvgs;
4474  l_dcapgddvgb=mi.dcapgddvgb;
4475 
4476  l_vgsdot=mi.getModel().dtype*(mi.Vgdot-mi.Vspdot);
4477  l_vgddot=mi.getModel().dtype*(mi.Vgdot-mi.Vdpdot);
4478  l_vgbdot=mi.getModel().dtype*(mi.Vgdot-mi.Vbdot);
4479  }
4480  }
4481 
4482 
4483  *mi.f_DrainEquDrainNodePtr +=
4485 
4488 
4490  {
4491  *mi.f_GateEquGateNodePtr +=
4492  ((l_dcapgsdvgs+l_dcapgsdvgb+l_dcapgsdvgd)*l_vgsdot +
4493  (l_dcapgbdvgs+l_dcapgbdvgb+l_dcapgbdvgd)*l_vgbdot +
4494  (l_dcapgddvgs+l_dcapgddvgb+l_dcapgddvgd)*l_vgddot)*mi.numberParallel;
4496  (l_dcapgsdvgd*l_vgsdot + l_dcapgbdvgd*l_vgbdot +
4497  l_dcapgddvgd*l_vgddot)*mi.numberParallel;
4499  (l_dcapgsdvgs*l_vgsdot + l_dcapgbdvgs*l_vgbdot +
4500  l_dcapgddvgs*l_vgddot)*mi.numberParallel;
4501  *mi.f_GateEquBulkNodePtr -=
4502  (l_dcapgsdvgb*l_vgsdot + l_dcapgbdvgb*l_vgbdot +
4503  l_dcapgddvgb*l_vgddot)*mi.numberParallel;
4504  // Additional gate equations for new Meyer stuff:
4506  (l_capgs + l_capgd + l_capgb)*mi.numberParallel;
4508  l_capgb*mi.numberParallel;
4510  l_capgd*mi.numberParallel;
4512  l_capgs*mi.numberParallel;
4513  }
4514 
4515 
4518 
4521 
4523  {
4524  *mi.f_BulkEquGateNodePtr -=
4525  (l_dcapgbdvgb+l_dcapgbdvgs+l_dcapgbdvgd)*l_vgbdot*mi.numberParallel;
4526  *mi.f_BulkEquBulkNodePtr +=
4527  (mi.gbs+mi.gbd+l_dcapgbdvgb*l_vgbdot)*mi.numberParallel;
4529  (mi.gbd-l_dcapgbdvgd*l_vgbdot)*mi.numberParallel;
4531  (mi.gbs-l_dcapgbdvgs*l_vgbdot )*mi.numberParallel;
4532 
4533  // Additional bulk equations:
4535  l_capgb*mi.numberParallel;
4537  (l_capbs+l_capgb+l_capbd)*mi.numberParallel;
4539  l_capbd*mi.numberParallel;
4541  l_capbs*mi.numberParallel;
4542  }
4543  else
4544  {
4545  *mi.f_BulkEquBulkNodePtr +=
4546  (mi.gbs+mi.gbd)*mi.numberParallel;
4549  }
4550 
4551 
4553  {
4557  (mi.Gm-(l_dcapgddvgb+l_dcapgddvgs+l_dcapgddvgd)*l_vgddot)*mi.numberParallel;
4559  (-mi.gbd+mi.Gmbs+l_dcapgddvgb*l_vgddot)*mi.numberParallel;
4561  (mi.drainConductance+mi.gds+mi.gbd+mi.revsum+l_dcapgddvgd*l_vgddot)*mi.numberParallel;
4563  (-mi.gds-mi.nrmsum+l_dcapgddvgs*l_vgddot)*mi.numberParallel;
4564 
4565  // Additional DrainPrime Equations:
4567  l_capgd*mi.numberParallel;
4569  l_capbd*mi.numberParallel;
4571  (l_capgd+l_capbd)*mi.numberParallel;
4572  }
4573  else
4574  {
4578  (mi.Gm)*mi.numberParallel;
4580  (-mi.gbd+mi.Gmbs)*mi.numberParallel;
4582  (mi.drainConductance+mi.gds+mi.gbd+mi.revsum)*mi.numberParallel;
4584  (-mi.gds-mi.nrmsum)*mi.numberParallel;
4585  }
4586 
4588  {
4590  (mi.Gm+(l_dcapgsdvgd+l_dcapgsdvgs+l_dcapgsdvgb)*l_vgsdot)*mi.numberParallel;
4594  (mi.gbs+mi.Gmbs-l_dcapgsdvgb*l_vgsdot)*mi.numberParallel;
4596  (mi.gds+mi.revsum-l_dcapgsdvgd*l_vgsdot)*mi.numberParallel;
4598  (mi.sourceConductance+mi.gds+mi.gbs+mi.nrmsum+l_dcapgsdvgs*l_vgsdot)*mi.numberParallel;
4599 
4600  // Additional SourcePrime equations:
4602  l_capgs*mi.numberParallel;
4604  l_capbs*mi.numberParallel;
4606  += (l_capgs+l_capbs)*mi.numberParallel;
4607  }
4608  else
4609  {
4611  (mi.Gm)*mi.numberParallel;
4615  (mi.gbs+mi.Gmbs)*mi.numberParallel;
4617  (mi.gds+mi.revsum)*mi.numberParallel;
4619  (mi.sourceConductance+mi.gds+mi.gbs+mi.nrmsum)*mi.numberParallel;
4620  }
4621 
4622  //Now we have to add a bunch of terms for the nodedot equations:
4624  {
4625  *mi.f_DraindotEquVDraindotNodePtr -= 1.0;
4626  *mi.f_GatedotEquVGatedotNodePtr -= 1.0;
4627  *mi.f_BulkdotEquVBulkdotNodePtr -= 1.0;
4629 
4630  if (mi.drainConductance != 0.0)
4631  {
4633  }
4634 
4635  if (mi.sourceConductance != 0.0)
4636  {
4638  }
4639  }
4640 
4641  // Q-matrix:
4642  //Here's where we implement the new Meyer formulation:
4644  {
4645  //Jacobian matrix is 0 for upper half, 6x6 identity matrix for lower half
4646  //*mi.q_DraindotEquVDrainNodePtr += OxideCap*1.0;
4647  //*mi.q_GatedotEquVGateNodePtr += OxideCap*1.0;
4648  //*mi.q_SourcedotEquVSourceNodePtr += OxideCap*1.0;
4649  //*mi.q_BulkdotEquVBulkNodePtr += OxideCap*1.0;
4650  //if (drainConductance != 0.0)
4651  // *mi.q_DrainPrimedotEquVDrainPrimeNodePtr += OxideCap*1.0;
4652  //if (sourceConductance != 0.0)
4653  // *mi.q_SourcePrimedotEquVSourcePrimeNodePtr += OxideCap*1.0;
4654 
4655  *mi.q_DraindotEquVDrainNodePtr += 1.0;
4656  *mi.q_GatedotEquVGateNodePtr += 1.0;
4657  *mi.q_SourcedotEquVSourceNodePtr += 1.0;
4658  *mi.q_BulkdotEquVBulkNodePtr += 1.0;
4659  if (mi.drainConductance != 0.0)
4660  {
4662  }
4663  if (mi.sourceConductance != 0.0)
4664  {
4666  }
4667  }
4668  else
4669  {
4670  double gcgd(0.0); // d(cqgd)/dVgd
4671  double gcgs(0.0); // d(cqgs)/dVgs
4672  double gcgb(0.0); // d(cqgb)/dVgb
4673  double gcbs(0.0); // d(cqbs)/dVbs
4674  double gcbd(0.0); // d(cqbd)/dVbd
4675 
4676  // get at the "conductances" for the gate capacitors with this trick
4677  // gcgd = model_.dtype*Capgd;
4678  // gcgs = model_.dtype*Capgs;
4679  // gcgb = model_.dtype*Capgb;
4680  //
4681  // In the loadRHS function, these would all be multiplied by
4682  // getSolverState().pdt. Here, for *mi.q_, the pdt term is left out.
4683  if ( getSolverState().tranopFlag || getSolverState().acopFlag || getSolverState().transientFlag)
4684  {
4685  gcgd = mi.Capgd;
4686  gcgs = mi.Capgs;
4687  gcgb = mi.Capgb;
4688  // get at the two parasitic caps the same way
4689  gcbs = mi.capbs;
4690  gcbd = mi.capbd;
4691  }
4692 
4693  *mi.q_GateEquGateNodePtr +=
4694  (gcgd+gcgs+gcgb)*mi.numberParallel;
4695  *mi.q_GateEquBulkNodePtr -= gcgb*mi.numberParallel;
4698 
4699  *mi.q_BulkEquGateNodePtr -= gcgb*mi.numberParallel;
4700  *mi.q_BulkEquBulkNodePtr +=
4701  (+gcbs+gcbd+gcgb)*mi.numberParallel;
4704  +gcbs*mi.numberParallel;
4705 
4707  -gcgd*mi.numberParallel;
4709  -gcbd*mi.numberParallel;
4711  (+gcbd+gcgd)*mi.numberParallel;
4712 
4714  gcgs*mi.numberParallel;
4716  +gcbs*mi.numberParallel;
4718  (+gcbs+gcgs)*mi.numberParallel;
4719  }
4720  }
4721  return true;
4722 }
4723 #else
4724 //-----------------------------------------------------------------------------
4725 // Function : Master::loadDAEMatrices
4726 // Purpose :
4727 // Special Notes :
4728 // Scope : public
4729 // Creator : Eric Keiter, SNL
4730 // Creation Date : 11/26/08
4731 //-----------------------------------------------------------------------------
4732 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
4733 {
4734  int sizeInstances = instanceContainer_.size();
4735  for (int i=0; i<sizeInstances; ++i)
4736  {
4737  Instance & mi = *(instanceContainer_.at(i));
4738 
4739  //introduce terms for capacitances, partial derivs. of capacitances,
4740  //and derivatives of differential voltages. "l" stands for "local"
4741 
4742  double l_capgs(0.0),l_capgd(0.0), l_capgb(0.0), l_capbd(0.0), l_capbs(0.0);
4743  double l_dcapgsdvgs(0.0),l_dcapgsdvgb(0.0),l_dcapgsdvgd(0.0);
4744  double l_dcapgbdvgs(0.0),l_dcapgbdvgb(0.0),l_dcapgbdvgd(0.0);
4745  double l_dcapgddvgs(0.0),l_dcapgddvgb(0.0),l_dcapgddvgd(0.0);
4746  double l_vgsdot(0.0), l_vgddot(0.0), l_vgbdot(0.0);
4747 
4748  if (getDeviceOptions().newMeyerFlag)
4749  {
4750  if (!getSolverState().dcopFlag)
4751  {
4752  l_capgs=mi.Capgs;
4753  l_capgd=mi.Capgd;
4754  l_capgb=mi.Capgb;
4755  l_capbd=mi.capbd;
4756  l_capbs=mi.capbs;
4757 
4758  l_dcapgsdvgs=mi.dcapgsdvgs;
4759  l_dcapgsdvgb=mi.dcapgsdvgb;
4760  l_dcapgsdvgd=mi.dcapgsdvgd;
4761  l_dcapgbdvgs=mi.dcapgbdvgs;
4762  l_dcapgbdvgb=mi.dcapgbdvgb;
4763  l_dcapgbdvgd=mi.dcapgbdvgd;
4764  l_dcapgddvgd=mi.dcapgddvgd;
4765  l_dcapgddvgs=mi.dcapgddvgs;
4766  l_dcapgddvgb=mi.dcapgddvgb;
4767 
4768  l_vgsdot=mi.getModel().dtype*(mi.Vgdot-mi.Vspdot);
4769  l_vgddot=mi.getModel().dtype*(mi.Vgdot-mi.Vdpdot);
4770  l_vgbdot=mi.getModel().dtype*(mi.Vgdot-mi.Vbdot);
4771  }
4772  }
4773 
4774  // F-matrix:
4775 
4776  dFdx[mi.li_Drain][mi.ADrainEquDrainNodeOffset] +=
4778 
4779  dFdx[mi.li_Drain][mi.ADrainEquDrainPrimeNodeOffset] -=
4781 
4783  {
4784  dFdx[mi.li_Gate][mi.AGateEquGateNodeOffset] +=
4785  ((l_dcapgsdvgs+l_dcapgsdvgb+l_dcapgsdvgd)*l_vgsdot +
4786  (l_dcapgbdvgs+l_dcapgbdvgb+l_dcapgbdvgd)*l_vgbdot +
4787  (l_dcapgddvgs+l_dcapgddvgb+l_dcapgddvgd)*l_vgddot)*mi.numberParallel;
4788  dFdx[mi.li_Gate][mi.AGateEquDrainPrimeNodeOffset] -=
4789  (l_dcapgsdvgd*l_vgsdot + l_dcapgbdvgd*l_vgbdot +
4790  l_dcapgddvgd*l_vgddot)*mi.numberParallel;
4791  dFdx[mi.li_Gate][mi.AGateEquSourcePrimeNodeOffset] -=
4792  (l_dcapgsdvgs*l_vgsdot + l_dcapgbdvgs*l_vgbdot +
4793  l_dcapgddvgs*l_vgddot)*mi.numberParallel;
4794  dFdx[mi.li_Gate][mi.AGateEquBulkNodeOffset] -=
4795  (l_dcapgsdvgb*l_vgsdot + l_dcapgbdvgb*l_vgbdot +
4796  l_dcapgddvgb*l_vgddot)*mi.numberParallel;
4797  // Additional gate equations for new Meyer stuff:
4798  dFdx[mi.li_Gate][mi.AGateEquVGatedotNodeOffset] +=
4799  (l_capgs + l_capgd + l_capgb)*mi.numberParallel;
4800  dFdx[mi.li_Gate][mi.AGateEquVBulkdotNodeOffset] -=
4801  l_capgb*mi.numberParallel;
4803  l_capgd*mi.numberParallel;
4805  l_capgs*mi.numberParallel;
4806  }
4807 
4808 
4809  dFdx[mi.li_Source][mi.ASourceEquSourceNodeOffset] +=
4811 
4814 
4816  {
4817  dFdx[mi.li_Bulk][mi.ABulkEquGateNodeOffset] -=
4818  (l_dcapgbdvgb+l_dcapgbdvgs+l_dcapgbdvgd)*l_vgbdot*mi.numberParallel;
4819  dFdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] +=
4820  (mi.gbs+mi.gbd+l_dcapgbdvgb*l_vgbdot)*mi.numberParallel;
4821  dFdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -=
4822  (mi.gbd-l_dcapgbdvgd*l_vgbdot)*mi.numberParallel;
4823  dFdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -=
4824  (mi.gbs-l_dcapgbdvgs*l_vgbdot )*mi.numberParallel;
4825 
4826  // Additional bulk equations:
4827  dFdx[mi.li_Bulk][mi.ABulkEquVGatedotNodeOffset] -=
4828  l_capgb*mi.numberParallel;
4829  dFdx[mi.li_Bulk][mi.ABulkEquVBulkdotNodeOffset] +=
4830  (l_capbs+l_capgb+l_capbd)*mi.numberParallel;
4832  l_capbd*mi.numberParallel;
4834  l_capbs*mi.numberParallel;
4835  }
4836  else
4837  {
4838  dFdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] +=
4839  (mi.gbs+mi.gbd)*mi.numberParallel;
4842  }
4843 
4844 
4846  {
4850  (mi.Gm-(l_dcapgddvgb+l_dcapgddvgs+l_dcapgddvgd)*l_vgddot)*mi.numberParallel;
4852  (-mi.gbd+mi.Gmbs+l_dcapgddvgb*l_vgddot)*mi.numberParallel;
4854  (mi.drainConductance+mi.gds+mi.gbd+mi.revsum+l_dcapgddvgd*l_vgddot)*mi.numberParallel;
4856  (-mi.gds-mi.nrmsum+l_dcapgddvgs*l_vgddot)*mi.numberParallel;
4857 
4858  // Additional DrainPrime Equations:
4860  l_capgd*mi.numberParallel;
4862  l_capbd*mi.numberParallel;
4864  (l_capgd+l_capbd)*mi.numberParallel;
4865  }
4866  else
4867  {
4871  (mi.Gm)*mi.numberParallel;
4873  (-mi.gbd+mi.Gmbs)*mi.numberParallel;
4875  (mi.drainConductance+mi.gds+mi.gbd+mi.revsum)*mi.numberParallel;
4877  (-mi.gds-mi.nrmsum)*mi.numberParallel;
4878  }
4879 
4881  {
4883  (mi.Gm+(l_dcapgsdvgd+l_dcapgsdvgs+l_dcapgsdvgb)*l_vgsdot)*mi.numberParallel;
4887  (mi.gbs+mi.Gmbs-l_dcapgsdvgb*l_vgsdot)*mi.numberParallel;
4889  (mi.gds+mi.revsum-l_dcapgsdvgd*l_vgsdot)*mi.numberParallel;
4891  (mi.sourceConductance+mi.gds+mi.gbs+mi.nrmsum+l_dcapgsdvgs*l_vgsdot)*mi.numberParallel;
4892 
4893  // Additional SourcePrime equations:
4895  l_capgs*mi.numberParallel;
4897  l_capbs*mi.numberParallel;
4899  += (l_capgs+l_capbs)*mi.numberParallel;
4900  }
4901  else
4902  {
4904  (mi.Gm)*mi.numberParallel;
4908  (mi.gbs+mi.Gmbs)*mi.numberParallel;
4910  (mi.gds+mi.revsum)*mi.numberParallel;
4912  (mi.sourceConductance+mi.gds+mi.gbs+mi.nrmsum)*mi.numberParallel;
4913  }
4914 
4915  //Now we have to add a bunch of terms for the nodedot equations:
4917  {
4918  dFdx[mi.li_Draindot][mi.ADraindotEquVDraindotNodeOffset] -= 1.0;
4919  dFdx[mi.li_Gatedot][mi.AGatedotEquVGatedotNodeOffset] -= 1.0;
4920  dFdx[mi.li_Bulkdot][mi.ABulkdotEquVBulkdotNodeOffset] -= 1.0;
4921  dFdx[mi.li_Sourcedot][mi.ASourcedotEquVSourcedotNodeOffset] -= 1.0;
4922 
4923  if (mi.drainConductance != 0.0)
4924  {
4926  }
4927 
4928  if (mi.sourceConductance != 0.0)
4929  {
4931  }
4932  }
4933 
4934  // Q-matrix:
4935  //Here's where we implement the new Meyer formulation:
4937  {
4938  //Jacobian matrix is 0 for upper half, 6x6 identity matrix for lower half
4939  //dQdx[mi.li_Draindot][mi.ADraindotEquVDrainNodeOffset] += OxideCap*1.0;
4940  //dQdx[mi.li_Gatedot][mi.AGatedotEquVGateNodeOffset] += OxideCap*1.0;
4941  //dQdx[mi.li_Sourcedot][mi.ASourcedotEquVSourceNodeOffset] += OxideCap*1.0;
4942  //dQdx[mi.li_Bulkdot][mi.ABulkdotEquVBulkNodeOffset] += OxideCap*1.0;
4943  //if (drainConductance != 0.0)
4944  // dQdx[mi.li_DrainPrimedot][mi.ADrainPrimedotEquVDrainPrimeNodeOffset] += OxideCap*1.0;
4945  //if (sourceConductance != 0.0)
4946  // dQdx[mi.li_SourcePrimedot][mi.ASourcePrimedotEquVSourcePrimeNodeOffset] += OxideCap*1.0;
4947 
4948  dQdx[mi.li_Draindot][mi.ADraindotEquVDrainNodeOffset] += 1.0;
4949  dQdx[mi.li_Gatedot][mi.AGatedotEquVGateNodeOffset] += 1.0;
4950  dQdx[mi.li_Sourcedot][mi.ASourcedotEquVSourceNodeOffset] += 1.0;
4951  dQdx[mi.li_Bulkdot][mi.ABulkdotEquVBulkNodeOffset] += 1.0;
4952  if (mi.drainConductance != 0.0)
4953  {
4955  }
4956  if (mi.sourceConductance != 0.0)
4957  {
4959  }
4960  }
4961  else
4962  {
4963  double gcgd(0.0); // d(cqgd)/dVgd
4964  double gcgs(0.0); // d(cqgs)/dVgs
4965  double gcgb(0.0); // d(cqgb)/dVgb
4966  double gcbs(0.0); // d(cqbs)/dVbs
4967  double gcbd(0.0); // d(cqbd)/dVbd
4968 
4969  // get at the "conductances" for the gate capacitors with this trick
4970  // gcgd = model_.dtype*Capgd;
4971  // gcgs = model_.dtype*Capgs;
4972  // gcgb = model_.dtype*Capgb;
4973  //
4974  // In the loadRHS function, these would all be multiplied by
4975  // getSolverState().pdt. Here, for dQdx, the pdt term is left out.
4976  if ( getSolverState().tranopFlag || getSolverState().acopFlag || getSolverState().transientFlag)
4977  {
4978  gcgd = mi.Capgd;
4979  gcgs = mi.Capgs;
4980  gcgb = mi.Capgb;
4981  // get at the two parasitic caps the same way
4982  gcbs = mi.capbs;
4983  gcbd = mi.capbd;
4984  }
4985 
4986  dQdx[mi.li_Gate][mi.AGateEquGateNodeOffset] +=
4987  (gcgd+gcgs+gcgb)*mi.numberParallel;
4988  dQdx[mi.li_Gate][mi.AGateEquBulkNodeOffset] -= gcgb*mi.numberParallel;
4989  dQdx[mi.li_Gate][mi.AGateEquDrainPrimeNodeOffset] -= gcgd*mi.numberParallel;
4990  dQdx[mi.li_Gate][mi.AGateEquSourcePrimeNodeOffset] -= gcgs*mi.numberParallel;
4991 
4992  dQdx[mi.li_Bulk][mi.ABulkEquGateNodeOffset] -= gcgb*mi.numberParallel;
4993  dQdx[mi.li_Bulk][mi.ABulkEquBulkNodeOffset] +=
4994  (+gcbs+gcbd+gcgb)*mi.numberParallel;
4995  dQdx[mi.li_Bulk][mi.ABulkEquDrainPrimeNodeOffset] -= +gcbd*mi.numberParallel;
4996  dQdx[mi.li_Bulk][mi.ABulkEquSourcePrimeNodeOffset] -=
4997  +gcbs*mi.numberParallel;
4998 
5000  -gcgd*mi.numberParallel;
5002  -gcbd*mi.numberParallel;
5004  (+gcbd+gcgd)*mi.numberParallel;
5005 
5007  gcgs*mi.numberParallel;
5009  +gcbs*mi.numberParallel;
5011  (+gcbs+gcgs)*mi.numberParallel;
5012  }
5013  }
5014  return true;
5015 }
5016 #endif
5017 
5018 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
5019 {
5020 
5021  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
5022 }
5023 
5025 {
5027  .registerDevice("m", 1)
5028  .registerModelType("pmos", 1)
5029  .registerModelType("nmos", 1);
5030 }
5031 
5032 } // namespace MOSFET1
5033 } // namespace Device
5034 } // namespace Xyce