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