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