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