Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_BJT.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_BJT.C,v $
27 //
28 // Purpose :
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.381.2.4 $
40 //
41 // Revision Date : $Date: 2014/03/06 23:33:43 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 #include <N_UTL_Misc.h>
49 
50 #ifdef HAVE_CMATH
51 #include <cmath>
52 #else
53 #include <math.h>
54 #endif
55 
56 #ifdef Xyce_DEBUG_DEVICE
57 #ifdef HAVE_CSTDIO
58 #include <cstdio>
59 #else
60 #include <stdio.h>
61 #endif
62 #endif
63 
64 // ---------- Xyce Includes ----------
65 #include <N_DEV_BJT.h>
66 #include <N_DEV_Const.h>
67 #include <N_DEV_DeviceOptions.h>
68 #include <N_DEV_ExternData.h>
69 #include <N_DEV_MatrixLoadData.h>
70 #include <N_DEV_SolverState.h>
71 #include <N_DEV_Message.h>
72 #include <N_ERH_ErrorMgr.h>
73 
74 #include <N_LAS_Matrix.h>
75 #include <N_LAS_MultiVector.h>
76 #include <N_LAS_Vector.h>
77 
78 namespace Xyce {
79 namespace Device {
80 
81 
82 namespace BJT {
83 
84 
86 {
87  // Set up configuration constants:
88 // Set up double precision variables:
89  p.addPar ("AREA", 1.0, false, NO_DEP,
90  &BJT::Instance::AREA, NULL,
91  U_NONE, CAT_GEOMETRY, "Relative device area");
92 
93  p.addPar ("IC1", 0.0, false, NO_DEP,
96  U_VOLT, CAT_VOLT, "Vector of initial values: Vbe, Vce. Vbe=IC1");
97 
98  p.addPar ("IC2", 0.0, false, NO_DEP,
101  U_VOLT, CAT_VOLT, "Vector of initial values: Vbe, Vce. Vce=IC2");
102 
103  p.addPar ("TEMP", 0.0, false, TIME_DEP,
104  &BJT::Instance::TEMP, NULL,
105  STANDARD, CAT_UNKNOWN, "Device temperature");
106 
107  // Set up non-double precision variables:
108  p.addPar ("OFF", false, false, NO_DEP,
109  &BJT::Instance::OFF, NULL,
110  U_LOGIC, CAT_VOLT, "Initial condition of no voltage drops accross device");
111 
112  p.addPar ("LAMBERTW", false, false, NO_DEP,
114  U_LOGIC, CAT_NONE, "Flag for toggling the use of the lambert-W function instead of exponentials.");
115 
116  p.makeVector ("IC", 2);
117 }
118 
120 {
121  // Set up double precision variables:
122  p.addPar ("TNOM", 0.0, false, NO_DEP,
123  &BJT::Model::TNOM, NULL,
124  U_DEGC, CAT_UNKNOWN, "Parameter measurement temperature");
125 
126  p.addPar ("IS", 1.e-16, false, LOG_T_DEP,
127  &BJT::Model::satCur, NULL,
128  U_AMP, CAT_UNKNOWN, "Transport saturation current");
129 
130  p.addPar ("BF", 100.0, true, NO_DEP,
133  U_NONE, CAT_UNKNOWN, "Ideal maximum foward beta");
134 
135  p.addPar ("BFM", 100.0, true, NO_DEP, // hspice
138  U_NONE, CAT_UNKNOWN, "Ideal maximum foward beta");
139 
140  p.addPar ("NF", 1.0, true, NO_DEP,
142  U_NONE, CAT_UNKNOWN, "Foward current emission coefficient");
143 
144  // forward early voltage has aliases for different spice flavors.
145  p.addPar ("VA", 0.0, false, NO_DEP, // Hspice/Pspice
148  U_VOLT, CAT_UNKNOWN, "Foward early voltage");
149 
150  p.addPar ("VBF", 0.0, false, NO_DEP, // Hspice
153  U_VOLT, CAT_UNKNOWN, "Foward early voltage");
154 
155  p.addPar ("VAF", 0.0, false, NO_DEP, // spice3
158  U_VOLT, CAT_UNKNOWN, "Foward early voltage");
159 
160  p.addPar ("IKF", 0.0, false, NO_DEP,
163  U_AMP, CAT_UNKNOWN, "Corner for foward-beta high-current roll-off");
164 
165  p.addPar ("IK", 0.0, false, NO_DEP,
168  U_AMP, CAT_UNKNOWN, "Corner for foward-beta high-current roll-off");
169 
170  p.addPar ("JBF", 0.0, false, NO_DEP,
173  U_AMP, CAT_UNKNOWN, "Corner for foward-beta high-current roll-off");
174 
175  // base-emitter leakage sat current has aliases for different spice flavors.
176  p.addPar ("ISE", 0.0, false, LOG_T_DEP,
179  U_AMP, CAT_UNKNOWN, "Base-emitter leakage saturation current");
180 
181  p.addPar ("JLE", 0.0, false, LOG_T_DEP, // Hspice
184  U_AMP, CAT_UNKNOWN, "Base-emitter leakage saturation current");
185 
186  p.addPar ("NE", 1.5, false, NO_DEP,
189  U_NONE, CAT_UNKNOWN, "Base-emitter leakage emission coefficient");
190 
191  p.addPar ("NLE", 1.5, false, NO_DEP,
194  U_NONE, CAT_UNKNOWN, "Base-emitter leakage emission coefficient");
195 
196  // BR/BRM alias:
197  p.addPar ("BR", 1.0, false, NO_DEP,
200  U_NONE, CAT_UNKNOWN, "Ideal maximum reverse beta");
201 
202  p.addPar ("BRM", 1.0, false, NO_DEP,
205  U_NONE, CAT_UNKNOWN, "Ideal maximum reverse beta");
206 
207  p.addPar ("NR", 1.0, true, NO_DEP,
209  U_NONE, CAT_UNKNOWN, "Reverse current emission coefficient");
210 
211  // reverse early voltage has several aliases:
212  // Interestingly, more aliases than for the forward early voltage.
213  p.addPar ("VAR", 0.0, false, NO_DEP, // spice
216  U_VOLT, CAT_UNKNOWN, "Reverse early voltage");
217 
218  p.addPar ("VB", 0.0, false, NO_DEP, // pspice, hspice
221  U_VOLT, CAT_UNKNOWN, "Reverse early voltage");
222 
223  p.addPar ("VRB", 0.0, false, NO_DEP, // hspice
226  U_VOLT, CAT_UNKNOWN, "Reverse early voltage");
227 
228  p.addPar ("BV", 0.0, false, NO_DEP, // hspice
231  U_VOLT, CAT_UNKNOWN, "Reverse early voltage");
232 
233  // Corner for reverse-beta high-current roll-off has an alias:
234  p.addPar ("IKR", 0.0, false, NO_DEP,
237  U_AMP, CAT_UNKNOWN, "Corner for reverse-beta high-current roll-off");
238 
239  p.addPar ("JBR", 0.0, false, NO_DEP, // hspice
242  U_AMP, CAT_UNKNOWN, "Corner for reverse-beta high-current roll-off");
243 
244  // Base-collector leakage saturation current has an alias:
245  p.addPar ("ISC", 0.0, false, NO_DEP, //spice/pspice
248  U_AMP, CAT_UNKNOWN, "Base-collector leakage saturation current");
249 
250  p.addPar ("JLC", 0.0, false, NO_DEP, // hspice
253  U_AMP, CAT_UNKNOWN, "Base-collector leakage saturation current");
254 
255  p.addPar ("NC", 2.0, false, NO_DEP,
257  U_NONE, CAT_UNKNOWN, "Base-collector leakage emission coefficient");
258 
259  p.addPar ("RB", 0.0, false, NO_DEP,
260  &BJT::Model::baseResist, NULL,
261  U_OHM, CAT_UNKNOWN, "Zero-bias (maximum) base resistance");
262 
263  // IRB (Current at which RB falls off by half)") has an alias:
264  p.addPar ("IRB", 0.0, false, NO_DEP, //spice/pspice
267  U_AMP, CAT_UNKNOWN, "Current at which RB falls off by half");
268 
269  p.addPar ("JRB", 0.0, false, NO_DEP, // hspice
272  U_AMP, CAT_UNKNOWN, "Current at which RB falls off by half");
273 
274  p.addPar ("IOB", 0.0, false, NO_DEP, // hspice
277  U_AMP, CAT_UNKNOWN, "Current at which RB falls off by half");
278 
279  p.addPar ("RBM", 0.0, false, NO_DEP,
282  U_OHM, CAT_UNKNOWN, "Maximum base resistance");
283 
284  p.addPar ("RE", 0.0, false, MIN_RES,
286  U_OHM, CAT_UNKNOWN, "Emitter ohmic resistance");
287 
288  p.addPar ("RC", 0.0, false, MIN_RES,
290  U_OHM, CAT_UNKNOWN, "Collector ohmic resistance");
291 
292  p.addPar ("CJE", 0.0, false, MIN_CAP,
293  &BJT::Model::depCapBE, NULL,
294  U_FARAD, CAT_UNKNOWN, "Base-emitter zero-bias p-n capacitance");
295 
296  // alias for VJE:
297  p.addPar ("VJE", 0.75, false, NO_DEP, //spice
300  U_VOLT, CAT_UNKNOWN, "Base-emitter built-in potential");
301 
302  p.addPar ("PE", 0.75, false, NO_DEP, //pspice/hspice
305  U_VOLT, CAT_UNKNOWN, "Base-emitter built-in potential");
306 
307  // alias for MJE:
308  p.addPar ("MJE", 0.33, false, NO_DEP, //spice
311  U_NONE, CAT_UNKNOWN, "Base-emitter p-n grading factor");
312 
313  p.addPar ("ME", 0.33, false, NO_DEP, //pspice/hspice
316  U_NONE, CAT_UNKNOWN, "Base-emitter p-n grading factor");
317 
318  p.addPar ("TF", 0.0, false, NO_DEP,
319  &BJT::Model::transTimeF, NULL,
320  U_SECOND, CAT_UNKNOWN, "Ideal foward transit time");
321 
322  p.addPar ("XTF", 0.0, false, NO_DEP,
324  U_NONE, CAT_UNKNOWN, "Transit time bias dependence coefficient");
325 
326  p.addPar ("VTF", 0.0, false, NO_DEP,
328  U_VOLT, CAT_UNKNOWN, "Transit time dependancy on Vbc");
329 
330  // alias for ITF:
331  p.addPar ("ITF", 0.0, false, NO_DEP, // spice
334  U_UNKNOWN, CAT_UNKNOWN, "Transit time dependancy on IC");
335 
336  p.addPar ("JTF", 0.0, false, NO_DEP, // hspice
339  U_UNKNOWN, CAT_UNKNOWN, "Transit time dependancy on IC");
340 
341  p.addPar ("PTF", 0.0, false, NO_DEP,
343  U_DEGREE, CAT_UNKNOWN, "Excess Phase at 1/(2pi*TF) Hz");
344 
345  p.addPar ("CJC", 0.0, false, MIN_CAP,
346  &BJT::Model::depCapBC, NULL,
347  U_FARAD, CAT_UNKNOWN, "Base-collector zero-bias p-n capacitance");
348 
349  // alias for VJC:
350  p.addPar ("VJC", 0.75, false, NO_DEP, // spice
353  U_VOLT, CAT_UNKNOWN, "Base-collector built-in potential");
354 
355  p.addPar ("PC", 0.75, false, NO_DEP, // pspice, hspice
358  U_VOLT, CAT_UNKNOWN, "Base-collector built-in potential");
359 
360  // alias for MJC:
361  p.addPar ("MJC", 0.33, false, NO_DEP, // spice
364  U_NONE, CAT_UNKNOWN, "Base-collector p-n grading factor");
365 
366  p.addPar ("MC", 0.33, false, NO_DEP, //pspice/hspice
369  U_NONE, CAT_UNKNOWN, "Base-collector p-n grading factor");
370 
371  // alias for XCJC:
372  p.addPar ("XCJC", 1.0, false, NO_DEP,
375  U_NONE, CAT_UNKNOWN, "Fraction of CJC connected internally to RB");
376  p.addPar ("CDIS", 1.0, false, NO_DEP,
379  U_NONE, CAT_UNKNOWN, "Fraction of CJC connected internally to RB");
380 
381  p.addPar ("TR", 0.0, false, NO_DEP,
382  &BJT::Model::transTimeR, NULL,
383  U_SECOND, CAT_UNKNOWN, "Ideal reverse transit time");
384 
385  // substrate zero bias capacitance has several aliases for different spice flavors.
386  p.addPar ("CJS", 0.0, false, NO_DEP, // spice
389  U_FARAD, CAT_UNKNOWN, "Substrate zero-bias p-n capacitance");
390 
391  p.addPar ("CCS", 0.0, false, NO_DEP, // Pspice/Hspice
394  U_FARAD, CAT_UNKNOWN, "Substrate zero-bias p-n capacitance");
395 
396  p.addPar ("CSUB", 0.0, false, NO_DEP, // Hspice
399  U_FARAD, CAT_UNKNOWN, "Substrate zero-bias p-n capacitance");
400 
401  // aliases for VJS:
402  p.addPar ("VJS", 0.75, false, NO_DEP, // spice
405  U_VOLT, CAT_UNKNOWN, "Substrate built-in potential");
406 
407  p.addPar ("PS", 0.75, false, NO_DEP, // pspice
410  U_VOLT, CAT_UNKNOWN, "Substrate built-in potential");
411 
412  p.addPar ("PSUB", 0.75, false, NO_DEP, // hspice
415  U_VOLT, CAT_UNKNOWN, "Substrate built-in potential");
416 
417  // aliases for MJS:
418  p.addPar ("MJS", 0.0, false, NO_DEP,
421  U_NONE, CAT_UNKNOWN, "Substrate p-n grading factor");
422 
423  p.addPar ("MS", 0.0, false, NO_DEP,
426  U_NONE, CAT_UNKNOWN, "Substrate p-n grading factor");
427 
428  p.addPar ("ESUB", 0.0, false, NO_DEP,
431  U_NONE, CAT_UNKNOWN, "Substrate p-n grading factor");
432 
433  // alias for XTB:
434  p.addPar ("XTB", 0.0, false, NO_DEP, //spice/pspice
437  U_NONE, CAT_UNKNOWN, "Foward and reverse beta temperature coefficient");
438 
439  p.addPar ("TB", 0.0, false, NO_DEP, // hspice
442  U_NONE, CAT_UNKNOWN, "Foward and reverse beta temperature coefficient");
443 
444  p.addPar ("TCB", 0.0, false, NO_DEP, // hspice
447  U_NONE, CAT_UNKNOWN, "Foward and reverse beta temperature coefficient");
448 
449  p.addPar ("EG", 1.11, false, NO_DEP,
450  &BJT::Model::energyGap, NULL,
451  U_EV, CAT_UNKNOWN, "Bandgap voltage (barrier highth)");
452 
453  // alias for XTI:
454  p.addPar ("XTI", 3.0, false, NO_DEP, // spice/hspice
457  U_UNKNOWN, CAT_UNKNOWN, "Temperature exponent for IS. (synonymous with PT)");
458 
459  p.addPar ("PT", 3.0, false, NO_DEP, // pspice
462  U_UNKNOWN, CAT_UNKNOWN, "Temperature exponent for IS. (synonymous with XTI)");
463 
464  p.addPar ("KF", 0.0, false, NO_DEP,
465  &BJT::Model::fNCoeff, NULL,
466  U_NONE, CAT_UNKNOWN, "Flicker noise coefficient");
467 
468  p.addPar ("AF", 1.0, false, NO_DEP,
469  &BJT::Model::fNExp, NULL,
470  U_UNKNOWN, CAT_UNKNOWN, "Flicker noise exponent");
471 
472  p.addPar ("FC", 0.5, false, NO_DEP,
474  U_NONE, CAT_UNKNOWN, "Foward-bias depletion capacitor coefficient");
475 
476  p.addPar ("C2", 0.0, false, NO_DEP,
479  U_UNKNOWN, CAT_UNKNOWN, "Coefficient for base-emitter leak current.");
480 
481  p.addPar ("C4", 0.0, false, NO_DEP,
484  U_UNKNOWN, CAT_UNKNOWN, "Coefficient for base-collector leak current.");
485 
486  // alias for NK/NKF:
487  p.addPar ("NK", 0.5, false, NO_DEP,
490  U_NONE, CAT_UNKNOWN, "High current rolloff coefficient");
491 
492  p.addPar ("NKF", 0.5, false, NO_DEP,
495  U_NONE, CAT_UNKNOWN, "High current rolloff coefficient");
496 
497  // Set up non-double precision variables:
498 
499  // Thermal model setup:
501 }
502 
503 
504 
505 std::vector< std::vector<int> > Instance::jacStamp_RB_RC_RE_;
506 std::vector< std::vector<int> > Instance::jacStamp_RB_RC_;
507 std::vector< std::vector<int> > Instance::jacStamp_RB_RE_;
508 std::vector< std::vector<int> > Instance::jacStamp_RC_RE_;
509 std::vector< std::vector<int> > Instance::jacStamp_RB_;
510 std::vector< std::vector<int> > Instance::jacStamp_RC_;
511 std::vector< std::vector<int> > Instance::jacStamp_RE_;
512 std::vector< std::vector<int> > Instance::jacStamp_;
513 
514 std::vector<int> Instance::jacMap_RB_RC_RE_;
515 std::vector<int> Instance::jacMap_RB_RC_;
516 std::vector<int> Instance::jacMap_RB_RE_;
517 std::vector<int> Instance::jacMap_RC_RE_;
518 std::vector<int> Instance::jacMap_RB_;
519 std::vector<int> Instance::jacMap_RC_;
520 std::vector<int> Instance::jacMap_RE_;
521 std::vector<int> Instance::jacMap_;
522 
523 std::vector< std::vector<int> > Instance::jacMap2_RB_RC_RE_;
524 std::vector< std::vector<int> > Instance::jacMap2_RB_RC_;
525 std::vector< std::vector<int> > Instance::jacMap2_RB_RE_;
526 std::vector< std::vector<int> > Instance::jacMap2_RC_RE_;
527 std::vector< std::vector<int> > Instance::jacMap2_RB_;
528 std::vector< std::vector<int> > Instance::jacMap2_RC_;
529 std::vector< std::vector<int> > Instance::jacMap2_RE_;
530 std::vector< std::vector<int> > Instance::jacMap2_;
531 
532 //-----------------------------------------------------------------------------
533 // Function : Instance::processParams
534 // Purpose :
535 // Special Notes :
536 // Scope : public
537 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
538 // Creation Date : 6/03/02
539 //-----------------------------------------------------------------------------
541 {
543  return true;
544 }
545 
546 //----------------------------------------------------------------------------
547 // Function : Instance::Instance
548 // Purpose : instance block constructor
549 // Special Notes :
550 // Scope : public
551 // Creator : Robert Hoekstra
552 // Creation Date : 11/30/00
553 //----------------------------------------------------------------------------
554 
556  const Configuration & configuration,
557  const InstanceBlock & IB,
558  Model & model,
559  const FactoryBlock & factory_block)
560  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
561  model_(model),
562  AREA(1.0),
563  icVBE(0.0),
564  icVCE(0.0),
565  TEMP(300.0),
566  OFF(false),
567  lambertWFlag(false),
568  IC_GIVEN(false),
569  externalNodeMode(false),
570  offFlag(false),
571  vt (0.0),
572  tSatCur (0.0),
573  tBetaF (0.0),
574  tBetaR (0.0),
575  tBELeakCur (0.0),
576  tBCLeakCur (0.0),
577  tBECap (0.0),
578  tBCCap (0.0),
579  tBEPot (0.0),
580  tBCPot (0.0),
581  tDepCap (0.0),
582  tF1 (0.0),
583  tF4 (0.0),
584  tF5 (0.0),
585  tVCrit (0.0),
586  tleakBEEmissionCoeff(1.5),
587  tleakBCEmissionCoeff(2.0),
588  tRollOffExp (0.5),
589  tInvRollOffF(0.0),
590  tInvRollOffR(0.0),
591  tInvEarlyVoltF(0.0),
592  tInvEarlyVoltR(0.0),
593  vEEp (0.0),
594  vBBp (0.0),
595  vCCp (0.0),
596  vBE (0.0),
597  vBC (0.0),
598  vBX (0.0),
599  vCS (0.0),
600  vBE_old (0.0),
601  vBC_old (0.0),
602  vBE_orig (0.0),
603  vBC_orig (0.0),
604  qB (0.0),
605  invqB (0.0),
606  dqBdvEp (0.0),
607  dqBdvBp (0.0),
608  dqBdvCp (0.0),
609  iBE (0.0),
610  iBC (0.0),
611  iBEleak (0.0),
612  iBCleak (0.0),
613  iCE (0.0),
614  iB (0.0),
615  iC (0.0),
616  iE (0.0),
617  iBEhighCurr (0.0),
618  gBEhighCurr (0.0),
619  gBE (0.0),
620  gBC (0.0),
621  gBEleak (0.0),
622  gBCleak (0.0),
623  gEpr (0.0),
624  gCpr (0.0),
625  gX (0.0),
626  geqCB (0.0),
627  capeqCB (0.0),
628  diBrdvB (0.0),
629  diBrdvEp (0.0),
630  diBrdvCp (0.0),
631  diBrdvBp (0.0),
632  diCEdvEp (0.0),
633  diCEdvCp (0.0),
634  diCEdvBp (0.0),
635 
636  diBEdvEp (0.0),
637  diBEdvCp (0.0),
638  diBEdvBp (0.0),
639 
640  gCapBEdiff (0.0),
641  gCapBEdep (0.0),
642  gCapBCdiff (0.0),
643  gCapBCdep (0.0),
644  gCapBX (0.0),
645  gCapCS (0.0),
646  gBEtot (0.0),
647  gBCtot (0.0),
648  qBEdiff (0.0),
649  iBEdiff (0.0),
650  capBEdiff (0.0),
651  qBEdep (0.0),
652  iBEdep (0.0),
653  capBEdep (0.0),
654  qCS (0.0),
655  iCS (0.0),
656  capCS (0.0),
657  qBCdiff (0.0),
658  iBCdiff (0.0),
659  capBCdiff (0.0),
660  qBCdep (0.0),
661  iBCdep (0.0),
662  capBCdep (0.0),
663  qBX (0.0),
664  iBX (0.0),
665  capBX (0.0),
666 
667 
668  li_Coll(-1),
669  li_CollP(-1),
670  li_Base(-1),
671  li_BaseP(-1),
672  li_Emit(-1),
673  li_EmitP(-1),
674  li_Subst(-1),
675  li_Ifx(-1),
676  li_dIfx(-1),
677  li_qstateBEdiff(-1),
678  li_qstateBEdep(-1),
679  li_qstateCS(-1),
680  li_qstateBCdiff(-1),
681  li_qstateBCdep(-1),
682  li_qstateBX(-1),
683  li_istateCEXBC(-1),
684 
685  li_storevBE(-1),
686  li_storevBC(-1),
687  li_store_capeqCB(-1),
688  li_store_dev_ib(-1),
689  li_store_dev_ie(-1),
690  li_store_dev_ic(-1),
691  li_store_dev_is(-1),
692 
693  gcpr (0.0),
694  gepr (0.0),
695  gx (0.0),
696  gm (0.0),
697  go (0.0),
698  gmu (0.0),
699  gpi (0.0),
700  gccs (0.0),
701  geqbx (0.0),
702  geqbc (0.0),
703  nextCexbc(0.0),
704  currCexbc(0.0),
705  lastCexbc(0.0),
706  phaseScalar(0.0),
707  dt0 (0.0),
708  dt1 (0.0),
709  AEmitEquEmitPNodeOffset(-1),
710  AEmitPEquEmitNodeOffset(-1),
711  ABaseEquBasePNodeOffset(-1),
712  ABasePEquBaseNodeOffset(-1),
713  ACollEquCollPNodeOffset(-1),
714  ACollPEquCollNodeOffset(-1),
715  AEmitEquEmitNodeOffset(-1),
716  AEmitPEquEmitPNodeOffset(-1),
717  ABaseEquBaseNodeOffset(-1),
718  ABasePEquBasePNodeOffset(-1),
719  ACollEquCollNodeOffset(-1),
720  ACollPEquCollPNodeOffset(-1),
721  AEmitPEquBasePNodeOffset(-1),
722  ABasePEquEmitPNodeOffset(-1),
723  AEmitPEquCollPNodeOffset(-1),
724  ACollPEquEmitPNodeOffset(-1),
725  ABasePEquCollPNodeOffset(-1),
726  ACollPEquBasePNodeOffset(-1),
727  ABaseEquCollPNodeOffset(-1),
728  ACollPEquBaseNodeOffset(-1),
729  ASubstEquSubstNodeOffset(-1),
730  ASubstEquCollPNodeOffset(-1),
731  ACollPEquSubstNodeOffset(-1),
732  ABaseEquEmitPNodeOffset(-1) ,
733  ACollPEquIfxNodeOffset(-1),
734  AEmitPEquIfxNodeOffset(-1),
735  AIfxEquCollPNodeOffset(-1),
736  AIfxEquBasePNodeOffset(-1),
737  AIfxEquEmitPNodeOffset(-1),
738  AIfxEquIfxNodeOffset(-1),
739  AIfxEqudIfxNodeOffset(-1),
740  AdIfxEquCollPNodeOffset(-1),
741  AdIfxEquBasePNodeOffset(-1),
742  AdIfxEquEmitPNodeOffset(-1),
743  AdIfxEquIfxNodeOffset(-1),
744  AdIfxEqudIfxNodeOffset(-1),
745 
747  // f-matrix pointers:
748  f_EmitEquEmitPNodePtr(0),
749  f_EmitPEquEmitNodePtr(0),
750  f_BaseEquBasePNodePtr(0),
751  f_BasePEquBaseNodePtr(0),
752  f_CollEquCollPNodePtr(0),
753  f_CollPEquCollNodePtr(0),
754  f_EmitEquEmitNodePtr(0),
755  f_EmitPEquEmitPNodePtr(0),
756  f_BaseEquBaseNodePtr(0),
757  f_BasePEquBasePNodePtr(0),
758  f_CollEquCollNodePtr(0),
759  f_CollPEquCollPNodePtr(0),
760  f_EmitPEquBasePNodePtr(0),
761  f_BasePEquEmitPNodePtr(0),
762  f_EmitPEquCollPNodePtr(0),
763  f_CollPEquEmitPNodePtr(0),
764  f_BasePEquCollPNodePtr(0),
765  f_CollPEquBasePNodePtr(0),
766  f_BaseEquCollPNodePtr(0),
767  f_CollPEquBaseNodePtr(0),
768  f_SubstEquSubstNodePtr(0),
769  f_SubstEquCollPNodePtr(0),
770  f_CollPEquSubstNodePtr(0),
771  f_BaseEquEmitPNodePtr(0),
772 
773  //new offsets for full integration of excess phase term
774  f_CollPEquIfxNodePtr(0),
775  f_EmitPEquIfxNodePtr(0),
776 
777  // ERK. These 3 are only needed for dcop.
778  f_IfxEquCollPNodePtr(0),
779  f_IfxEquBasePNodePtr(0),
780  f_IfxEquEmitPNodePtr(0),
781 
782  f_IfxEquIfxNodePtr(0),
783  f_IfxEqudIfxNodePtr(0),
784 
785  f_dIfxEquCollPNodePtr(0),
786  f_dIfxEquBasePNodePtr(0),
787  f_dIfxEquEmitPNodePtr(0),
788  f_dIfxEquIfxNodePtr(0),
789  f_dIfxEqudIfxNodePtr(0),
790 
791 
792  // q-matrix pointers:
793  q_EmitEquEmitPNodePtr(0),
794  q_EmitPEquEmitNodePtr(0),
795  q_BaseEquBasePNodePtr(0),
796  q_BasePEquBaseNodePtr(0),
797  q_CollEquCollPNodePtr(0),
798  q_CollPEquCollNodePtr(0),
799  q_EmitEquEmitNodePtr(0),
800  q_EmitPEquEmitPNodePtr(0),
801  q_BaseEquBaseNodePtr(0),
802  q_BasePEquBasePNodePtr(0),
803  q_CollEquCollNodePtr(0),
804  q_CollPEquCollPNodePtr(0),
805  q_EmitPEquBasePNodePtr(0),
806  q_BasePEquEmitPNodePtr(0),
807  q_EmitPEquCollPNodePtr(0),
808  q_CollPEquEmitPNodePtr(0),
809  q_BasePEquCollPNodePtr(0),
810  q_CollPEquBasePNodePtr(0),
811  q_BaseEquCollPNodePtr(0),
812  q_CollPEquBaseNodePtr(0),
813  q_SubstEquSubstNodePtr(0),
814  q_SubstEquCollPNodePtr(0),
815  q_CollPEquSubstNodePtr(0),
816  q_BaseEquEmitPNodePtr(0),
817 
818  //new offsets for full integration of excess phase term
819  q_CollPEquIfxNodePtr(0),
820  q_EmitPEquIfxNodePtr(0),
821 
822  // ERK. These 3 are only needed for dcop.
823  q_IfxEquCollPNodePtr(0),
824  q_IfxEquBasePNodePtr(0),
825  q_IfxEquEmitPNodePtr(0),
826 
827  q_IfxEquIfxNodePtr(0),
828  q_IfxEqudIfxNodePtr(0),
829 
830  q_dIfxEquCollPNodePtr(0),
831  q_dIfxEquBasePNodePtr(0),
832  q_dIfxEquEmitPNodePtr(0),
833  q_dIfxEquIfxNodePtr(0),
834  q_dIfxEqudIfxNodePtr(0),
835 #endif
836 
837  callsOutputPlot (0)
838 
839 {
840  // This basically says, numExtVars = the number of vars specified
841  // by the user on the netlist instance line.
842  numExtVars = IB.numExtVars;
843 
844  numStateVars = 7;
845  setNumStoreVars(3);
846  numLeadCurrentStoreVars = 4; // lead current dev_ib, dev_ie, dev_ic and dev_is
847 
848  devConMap.resize(4);
849  devConMap[0] = 1;
850  devConMap[1] = 1;
851  devConMap[2] = 1;
852  devConMap[3] = 2;
853 
854  if (numExtVars > 4)
855  {
856  devConMap.resize(numExtVars);
857  }
858  for (int i1=4;i1<numExtVars;++i1)
859  {
860  devConMap[i1] = 1; // map all the extra ones to the base.
861  // That way I don't have to figure out
862  // which optional nodes have been set
863  // by the user.
864  }
865 
866  // set up the jacStamp:
867  if( jacStamp_.empty() )
868  {
869  jacStamp_RB_RC_RE_.resize(7);
870  jacStamp_RB_RC_RE_[0].resize(2); // Collector Row
871  jacStamp_RB_RC_RE_[0][0] = 0; // C-C
872  jacStamp_RB_RC_RE_[0][1] = 4; // C-C'
873 
874  jacStamp_RB_RC_RE_[1].resize(4); // Base row
875  jacStamp_RB_RC_RE_[1][0] = 1; // B-B
876  jacStamp_RB_RC_RE_[1][1] = 4; // B-C'
877  jacStamp_RB_RC_RE_[1][2] = 5; // B-B'
878  jacStamp_RB_RC_RE_[1][3] = 6; // B-E'
879 
880  jacStamp_RB_RC_RE_[2].resize(2); // Emitter row
881  jacStamp_RB_RC_RE_[2][0] = 2; // E-E
882  jacStamp_RB_RC_RE_[2][1] = 6; // E-E'
883 
884  jacStamp_RB_RC_RE_[3].resize(2); // Substrate row
885  jacStamp_RB_RC_RE_[3][0] = 3; // S-S
886  jacStamp_RB_RC_RE_[3][1] = 4; // S-C'
887 
888  jacStamp_RB_RC_RE_[4].resize(6); // Collector'
889  jacStamp_RB_RC_RE_[4][0] = 0; // C'-C
890  jacStamp_RB_RC_RE_[4][1] = 1; // C'-B
891  jacStamp_RB_RC_RE_[4][2] = 3; // C'-S
892  jacStamp_RB_RC_RE_[4][3] = 4; // C'-C'
893  jacStamp_RB_RC_RE_[4][4] = 5; // C'-B'
894  jacStamp_RB_RC_RE_[4][5] = 6; // C'-E'
895 
896  jacStamp_RB_RC_RE_[5].resize(4); // Base'
897  jacStamp_RB_RC_RE_[5][0] = 1; // B'-B
898  jacStamp_RB_RC_RE_[5][1] = 4; // B'-C'
899  jacStamp_RB_RC_RE_[5][2] = 5; // B'-B'
900  jacStamp_RB_RC_RE_[5][3] = 6; // B'-E'
901 
902  jacStamp_RB_RC_RE_[6].resize(4); // Emitter'
903  jacStamp_RB_RC_RE_[6][0] = 2; // E'-E
904  jacStamp_RB_RC_RE_[6][1] = 4; // E'-C'
905  jacStamp_RB_RC_RE_[6][2] = 5; // E'-B'
906  jacStamp_RB_RC_RE_[6][3] = 6; // E'-E'
907 
908  if (getDeviceOptions().newExcessPhase)
909  {
910  //Excess Phase Terms
911  jacStamp_RB_RC_RE_.resize(9);
912 
913  jacStamp_RB_RC_RE_[4].resize(7); // Collector' row
914  jacStamp_RB_RC_RE_[4][6] = 7; // C'-Ifx
915 
916  jacStamp_RB_RC_RE_[6].resize(5); // Emitter' row
917  jacStamp_RB_RC_RE_[6][4] = 7; // E'-Ifx
918 
919  jacStamp_RB_RC_RE_[7].resize(5); // Ifx row
920  jacStamp_RB_RC_RE_[7][0] = 4; // dIfx-C'
921  jacStamp_RB_RC_RE_[7][1] = 5; // dIfx-B'
922  jacStamp_RB_RC_RE_[7][2] = 6; // dIfx-E'
923  jacStamp_RB_RC_RE_[7][3] = 7; // Ifx-Ifx
924  jacStamp_RB_RC_RE_[7][4] = 8; // Ifx-dIfx
925 
926  jacStamp_RB_RC_RE_[8].resize(5); // dIfx row
927  jacStamp_RB_RC_RE_[8][0] = 4; // dIfx-C'
928  jacStamp_RB_RC_RE_[8][1] = 5; // dIfx-B'
929  jacStamp_RB_RC_RE_[8][2] = 6; // dIfx-E'
930  jacStamp_RB_RC_RE_[8][3] = 7; // dIfx-Ifx
931  jacStamp_RB_RC_RE_[8][4] = 8; // dIfx-dIfx
932  }
933 
934  jacMap_RB_RC_RE_.clear();
935 
936  int StampSize = 0;
937  if (getDeviceOptions().newExcessPhase)
938  {
939  StampSize = 9;
940  }
941  else
942  {
943  StampSize = 7;
944  }
945 
947  jacStamp_RB_RE_, jacMap_RB_RE_, jacMap2_RB_RE_, 4, 0, StampSize );
948 
950  jacStamp_RC_RE_, jacMap_RC_RE_, jacMap2_RC_RE_, 5, 1, StampSize );
951 
953  jacStamp_RB_RC_, jacMap_RB_RC_, jacMap2_RB_RC_, 6, 2, StampSize );
954 
956  jacStamp_RB_, jacMap_RB_, jacMap2_RB_, 4, 0, StampSize );
957 
959  jacStamp_RE_, jacMap_RE_, jacMap2_RE_, 4, 1, StampSize );
960 
962  jacStamp_RC_, jacMap_RC_, jacMap2_RC_, 5, 2, StampSize );
963 
965  jacStamp_, jacMap_, jacMap2_, 4, 0, StampSize );
966  }
967 
968  // Set params to constant default values:
969  setDefaultParams ();
970 
971  // Set params according to instance line and constant defaults from metadata:
972  setParams (IB.params);
973 
974  // Set any non-constant parameter defaults:
975  if (!given("TEMP"))
976  TEMP = getDeviceOptions().temp.getImmutableValue<double>();
977 
978  // Calculate any parameters specified as expressions:
980 
981  // calculate dependent (ie computed) params and check for errors:
982  processParams ();
983 
984  // This is tricky. The prime nodes have 2 issues:
985  // 1) do they exist?
986  // 2) are they internal or external?
987  //
988  // The default BJT behavior is for them to be internal,
989  // if they exist.
990  //
991  // Also, node 4 is always "external" even if not specified
992  // by the user! If the user doesn't specify it, it gets set
993  // to gnd, as an external node.
994  //
995  // Nominal order in the netlist, after the original 4 nodes
996  // is collector', base', emitter'.
997  //
998  // I've chosen to only allow 2 modes: all optional variables
999  // are internal, or all optional nodes (that exist) are
1000  // external. No mixing and matching. This is toggled by the
1001  // flag, externalNodeMode.
1002 
1003  int cNode=0;
1004  int eNode=0;
1005  int bNode=0;
1006 
1007  cNode = ((model_.collectorResist==0.0)?0:1);
1008  eNode = ((model_.emitterResist==0.0)?0:1);
1009  bNode = ((model_.baseResist==0.0)?0:1);
1010 
1011  int numExist = cNode + eNode + bNode;
1012 
1013  if (numExtVars <= 4)
1014  {
1015  numExtVars = 4;
1016  externalNodeMode = false;
1017  numIntVars = cNode + eNode + bNode;
1018  }
1019  else
1020  {
1021  if (numExtVars != 4 + numExist)
1022  {
1023  std::string msg = ":";
1024  msg += " name = " + getName();
1025  msg += " wrong number of external nodes are set!";
1026  msg += " Either set none of them, or set them all.";
1027  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
1028  }
1029 
1030  externalNodeMode = true;
1031  //numExtVars += cNode + eNode + bNode; // This is already set in netlist.
1032  }
1033 
1034 
1035  if (getDeviceOptions().newExcessPhase)
1036  {
1037  //add in 2 variables for excess phase calc.
1038  numIntVars += 2;
1039  }
1040 
1041 }
1042 
1043 //-----------------------------------------------------------------------------
1044 // Function : Instance::~Instance
1045 // Purpose : destructor
1046 // Special Notes :
1047 // Scope : public
1048 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1049 // Creation Date : 3/16/00
1050 //-----------------------------------------------------------------------------
1052 {
1053 
1054 }
1055 
1056 //-----------------------------------------------------------------------------
1057 // Function : Instance::registerLIDs
1058 // Purpose :
1059 // Special Notes :
1060 // Scope : public
1061 // Creator : Robert Hoekstra
1062 // Creation Date : 6/13/02
1063 //-----------------------------------------------------------------------------
1064 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
1065  const std::vector<int> & extLIDVecRef )
1066 {
1067  AssertLIDs(intLIDVecRef.size() == numIntVars);
1068  AssertLIDs(extLIDVecRef.size() == numExtVars);
1069 
1070 #ifdef Xyce_DEBUG_DEVICE
1071  if (getDeviceOptions().debugLevel > 0)
1072  {
1073  Xyce::dout() << section_divider << std::endl;
1074  Xyce::dout() << " BJTInstance::registerLIDs" <<std::endl;
1075  Xyce::dout() << " name = " << getName() << std::endl;
1076  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
1077  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
1078  Xyce::dout() << " numIntVars = " << numIntVars << std::endl;
1079  Xyce::dout() << " numExtVars = " << numExtVars << std::endl;
1080  }
1081 #endif
1082 
1083  // Copy over the global ID lists.
1084  intLIDVec = intLIDVecRef;
1085  extLIDVec = extLIDVecRef;
1086 
1087 #ifdef Xyce_DEBUG_DEVICE
1088  if (getDeviceOptions().debugLevel > 0)
1089  {
1090  Xyce::dout() << " Internal LID List" << std::endl;
1091  for( int i = 0; i < intLIDVec.size(); ++i )
1092  Xyce::dout() << " " << intLIDVec[i] << std::endl;
1093  Xyce::dout() << " External LID List" << std::endl;
1094  for( int i = 0; i < extLIDVec.size(); ++i )
1095  Xyce::dout() << " " << extLIDVec[i] << std::endl;
1096  }
1097 #endif
1098 
1099  // Now use these lists to obtain the indices into the linear algebra
1100  // entities. This assumes an order. For the matrix indices, first do the
1101  // rows.
1102 
1103  // First do external variables:
1104  // it1 at collector, it2 at collectorPrime
1105  int intIndex = 0;
1106  int extIndex = 0;
1107 
1108  li_Coll = extLIDVec[extIndex++];
1109  li_Base = extLIDVec[extIndex++];
1110  li_Emit = extLIDVec[extIndex++];
1111  li_Subst = extLIDVec[extIndex++];
1112 
1113  if( model_.collectorResist == 0.0 )
1114  {
1115  li_CollP = li_Coll;
1116  }
1117  else
1118  {
1119  if (externalNodeMode)
1120  li_CollP = extLIDVec[extIndex++];
1121  else
1122  li_CollP = intLIDVec[intIndex++];
1123  }
1124 
1125 
1126  if( model_.baseResist == 0.0 )
1127  {
1128  li_BaseP = li_Base;
1129  }
1130  else
1131  {
1132  if (externalNodeMode)
1133  li_BaseP = extLIDVec[extIndex++];
1134  else
1135  li_BaseP = intLIDVec[intIndex++];
1136  }
1137 
1138 
1139  if( model_.emitterResist == 0.0 )
1140  {
1141  li_EmitP = li_Emit;
1142  }
1143  else
1144  {
1145  if (externalNodeMode)
1146  li_EmitP = extLIDVec[extIndex++];
1147  else
1148  li_EmitP = intLIDVec[intIndex++];
1149  }
1150 
1151 
1153  {
1154  li_Ifx = intLIDVec[intIndex++];
1155  li_dIfx = intLIDVec[intIndex++];
1156  }
1157 
1158 #ifdef Xyce_DEBUG_DEVICE
1159  if (getDeviceOptions().debugLevel > 0)
1160  {
1161  Xyce::dout() << " li_Coll = " << li_Coll << std::endl;
1162  Xyce::dout() << " li_CollP = " << li_CollP << std::endl;
1163  Xyce::dout() << " li_Base = " << li_Base << std::endl;
1164  Xyce::dout() << " li_BaseP = " << li_BaseP << std::endl;
1165  Xyce::dout() << " li_Emit = " << li_Emit << std::endl;
1166  Xyce::dout() << " li_EmitP = " << li_EmitP << std::endl;
1167  Xyce::dout() << " li_Subst = " << li_Subst << std::endl;
1168 
1169  if (getDeviceOptions().newExcessPhase)
1170  {
1171  Xyce::dout() << " li_Ifx = " << li_Ifx << std::endl;
1172  Xyce::dout() << " li_dIfx = " << li_dIfx << std::endl;
1173  }
1174 
1175  Xyce::dout() << section_divider << std::endl;
1176  }
1177 #endif
1178 
1179 }
1180 
1181 //-----------------------------------------------------------------------------
1182 // Function : Instance::getIntNameMap
1183 // Purpose :
1184 // Special Notes :
1185 // Scope : public
1186 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1187 // Creation Date : 05/13/05
1188 //-----------------------------------------------------------------------------
1189 std::map<int,std::string> & Instance::getIntNameMap ()
1190 {
1191  // set up the internal name map, if it hasn't been already.
1192  std::string tmpstr;
1193  if (intNameMap.empty () && !externalNodeMode)
1194  {
1195  // Setup the internal node name map:
1196  if( model_.collectorResist != 0.0 )
1197  {
1198  tmpstr = getName()+"_collectorprime";
1199  spiceInternalName (tmpstr);
1200  intNameMap[ li_CollP ] = tmpstr;
1201  }
1202 
1203  if( model_.baseResist != 0.0 )
1204  {
1205  tmpstr = getName()+"_baseprime";
1206  spiceInternalName (tmpstr);
1207  intNameMap[ li_BaseP ] = tmpstr;
1208  }
1209 
1210  if( model_.emitterResist != 0.0 )
1211  {
1212  tmpstr = getName()+"_emitterprime";
1213  spiceInternalName (tmpstr);
1214  intNameMap[ li_EmitP ] = tmpstr;
1215  }
1216  }
1217 
1218  if (getDeviceOptions().newExcessPhase)
1219  {
1220  tmpstr = getName()+"_ExcessPhase_Ifx";
1221  spiceInternalName (tmpstr);
1222  intNameMap [ li_Ifx ] = tmpstr;
1223 
1224  tmpstr = getName()+"_ExcessPhase_dIfx";
1225  spiceInternalName (tmpstr);
1226  intNameMap [ li_dIfx ] = tmpstr;
1227  }
1228 
1229  return intNameMap;
1230 }
1231 
1232 
1233 //-----------------------------------------------------------------------------
1234 // Function : Instance::getStoreNameMap
1235 // Purpose :
1236 // Special Notes :
1237 // Scope : public
1238 // Creator : Richard Schiek, SNL, Electrical Systems Modeling
1239 // Creation Date : 01/23/13
1240 //-----------------------------------------------------------------------------
1241 std::map<int,std::string> & Instance::getStoreNameMap ()
1242 {
1243  // set up the internal name map, if it hasn't been already.
1244  if (storeNameMap.empty ())
1245  {
1246  // change subcircuitname:devicetype_deviceName to
1247  // devicetype:subcircuitName:deviceName
1248  std::string modName(getName());
1249  spiceInternalName(modName);
1250  std::string tmpstr;
1251 
1252  tmpstr = modName+":VBE";
1253  storeNameMap[ li_storevBE ] = tmpstr;
1254  tmpstr = modName+":VBC";
1255  storeNameMap[ li_storevBC ] = tmpstr;
1256  tmpstr = modName+":CAPEQCB";
1257  storeNameMap[ li_store_capeqCB ] = tmpstr;
1258  if( loadLeadCurrent )
1259  {
1260  tmpstr = modName+":DEV_IB";
1261  storeNameMap[ li_store_dev_ib ] = tmpstr;
1262  tmpstr = modName+":DEV_IE";
1263  storeNameMap[ li_store_dev_ie ] = tmpstr;
1264  tmpstr = modName+":DEV_IC";
1265  storeNameMap[ li_store_dev_ic ] = tmpstr;
1266  tmpstr = modName+":DEV_IS";
1267  storeNameMap[ li_store_dev_is ] = tmpstr;
1268  }
1269  }
1270 
1271  return storeNameMap;
1272 }
1273 
1274 //-----------------------------------------------------------------------------
1275 // Function : Instance::registerStateLIDs
1276 // Purpose :
1277 // Special Notes :
1278 // Scope : public
1279 // Creator : Robert Hoekstra
1280 // Creation Date : 6/13/02
1281 //-----------------------------------------------------------------------------
1282 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
1283 {
1284  AssertLIDs(staLIDVecRef.size() == numStateVars);
1285 
1286  // Copy over the global ID lists:
1287  staLIDVec = staLIDVecRef;
1288 
1289  int i=0;
1290  li_qstateBEdiff = staLIDVec[i++];
1291  li_qstateBEdep = staLIDVec[i++];
1292  li_qstateCS = staLIDVec[i++];
1293  li_qstateBCdiff = staLIDVec[i++];
1294  li_qstateBCdep = staLIDVec[i++];
1295  li_qstateBX = staLIDVec[i++];
1296  li_istateCEXBC = staLIDVec[i++];
1297 }
1298 
1299 
1300 //-----------------------------------------------------------------------------
1301 // Function : Instance::registerStoreLIDs
1302 // Purpose :
1303 // Special Notes :
1304 // Scope : public
1305 // Creator : Eric Keiter, SNL
1306 // Creation Date : 12/09/11
1307 //-----------------------------------------------------------------------------
1308 void Instance::registerStoreLIDs( const std::vector<int> & stoLIDVecRef )
1309 {
1310  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
1311 
1312  // Copy over the global ID lists:
1313  stoLIDVec = stoLIDVecRef;
1314 
1315  int i=0;
1316  li_storevBE = stoLIDVec[i++];
1317  li_storevBC = stoLIDVec[i++];
1318  li_store_capeqCB = stoLIDVec[i++];
1319  if( loadLeadCurrent )
1320  {
1321  li_store_dev_ib = stoLIDVec[i++];
1322  li_store_dev_ie = stoLIDVec[i++];
1323  li_store_dev_ic = stoLIDVec[i++];
1324  li_store_dev_is = stoLIDVec[i++];
1325  }
1326 
1327 }
1328 
1329 //-----------------------------------------------------------------------------
1330 // Function : Instance::jacobianStamp
1331 // Purpose :
1332 // Special Notes :
1333 // Scope : public
1334 // Creator : Robert Hoekstra
1335 // Creation Date : 8/21/02
1336 //-----------------------------------------------------------------------------
1337 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
1338 {
1339  if (model_.baseResist)
1340  {
1341  if (model_.collectorResist)
1342  {
1343  if (model_.emitterResist)
1344  return jacStamp_RB_RC_RE_;
1345  else
1346  return jacStamp_RB_RC_;
1347  }
1348  else
1349  {
1350  if (model_.emitterResist)
1351  return jacStamp_RB_RE_;
1352  else
1353  return jacStamp_RB_;
1354  }
1355  }
1356  else
1357  {
1358  if (model_.collectorResist)
1359  {
1360  if (model_.emitterResist)
1361  return jacStamp_RC_RE_;
1362  else
1363  return jacStamp_RC_;
1364  }
1365  else
1366  {
1367  if (model_.emitterResist)
1368  return jacStamp_RE_;
1369  else
1370  return jacStamp_;
1371  }
1372  }
1373 }
1374 
1375 //-----------------------------------------------------------------------------
1376 // Function : Instance::registerJacLIDs
1377 // Purpose :
1378 // Special Notes :
1379 // Scope : public
1380 // Creator : Robert Hoekstra
1381 // Creation Date : 8/27/02
1382 //-----------------------------------------------------------------------------
1383 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
1384 {
1385  DeviceInstance::registerJacLIDs( jacLIDVec );
1386 
1387  std::vector<int> map;
1388  std::vector< std::vector<int> > map2;
1389 
1390  if (model_.baseResist)
1391  {
1392  if (model_.collectorResist)
1393  {
1394  if (model_.emitterResist)
1395  {
1396  map = jacMap_RB_RC_RE_;
1397  map2 = jacMap2_RB_RC_RE_;
1398  }
1399  else
1400  {
1401  map = jacMap_RB_RC_;
1402  map2 = jacMap2_RB_RC_;
1403  }
1404  }
1405  else
1406  {
1407  if (model_.emitterResist)
1408  {
1409  map = jacMap_RB_RE_;
1410  map2 = jacMap2_RB_RE_;
1411  }
1412  else
1413  {
1414  map = jacMap_RB_;
1415  map2 = jacMap2_RB_;
1416  }
1417  }
1418  }
1419  else
1420  {
1421  if (model_.collectorResist)
1422  {
1423  if (model_.emitterResist)
1424  {
1425  map = jacMap_RC_RE_;
1426  map2 = jacMap2_RC_RE_;
1427  }
1428  else
1429  {
1430  map = jacMap_RC_;
1431  map2 = jacMap2_RC_;
1432  }
1433  }
1434  else
1435  {
1436  if (model_.emitterResist)
1437  {
1438  map = jacMap_RE_;
1439  map2 = jacMap2_RE_;
1440  }
1441  else
1442  {
1443  map = jacMap_;
1444  map2 = jacMap2_;
1445  }
1446  }
1447  }
1448 
1449  ACollEquCollNodeOffset = jacLIDVec[map[0]][map2[0][0]];
1450  ACollEquCollPNodeOffset = jacLIDVec[map[0]][map2[0][1]];
1451 
1452  ABaseEquBaseNodeOffset = jacLIDVec[map[1]][map2[1][0]];
1453  ABaseEquCollPNodeOffset = jacLIDVec[map[1]][map2[1][1]];
1454  ABaseEquBasePNodeOffset = jacLIDVec[map[1]][map2[1][2]];
1455  ABaseEquEmitPNodeOffset = jacLIDVec[map[1]][map2[1][3]];
1456 
1457  AEmitEquEmitNodeOffset = jacLIDVec[map[2]][map2[2][0]];
1458  AEmitEquEmitPNodeOffset = jacLIDVec[map[2]][map2[2][1]];
1459 
1460  ASubstEquSubstNodeOffset = jacLIDVec[map[3]][map2[3][0]];
1461  ASubstEquCollPNodeOffset = jacLIDVec[map[3]][map2[3][1]];
1462 
1463  ACollPEquCollNodeOffset = jacLIDVec[map[4]][map2[4][0]];
1464  ACollPEquBaseNodeOffset = jacLIDVec[map[4]][map2[4][1]];
1465  ACollPEquSubstNodeOffset = jacLIDVec[map[4]][map2[4][2]];
1466  ACollPEquCollPNodeOffset = jacLIDVec[map[4]][map2[4][3]];
1467  ACollPEquBasePNodeOffset = jacLIDVec[map[4]][map2[4][4]];
1468  ACollPEquEmitPNodeOffset = jacLIDVec[map[4]][map2[4][5]];
1469 
1470  ABasePEquBaseNodeOffset = jacLIDVec[map[5]][map2[5][0]];
1471  ABasePEquCollPNodeOffset = jacLIDVec[map[5]][map2[5][1]];
1472  ABasePEquBasePNodeOffset = jacLIDVec[map[5]][map2[5][2]];
1473  ABasePEquEmitPNodeOffset = jacLIDVec[map[5]][map2[5][3]];
1474 
1475  AEmitPEquEmitNodeOffset = jacLIDVec[map[6]][map2[6][0]];
1476  AEmitPEquCollPNodeOffset = jacLIDVec[map[6]][map2[6][1]];
1477  AEmitPEquBasePNodeOffset = jacLIDVec[map[6]][map2[6][2]];
1478  AEmitPEquEmitPNodeOffset = jacLIDVec[map[6]][map2[6][3]];
1479 
1480  if (getDeviceOptions().newExcessPhase)
1481  {
1482  //Excess Phase Terms
1483  ACollPEquIfxNodeOffset = jacLIDVec[map[4]][map2[4][6]];
1484 
1485  AEmitPEquIfxNodeOffset = jacLIDVec[map[6]][map2[6][4]];
1486 
1487  AIfxEquCollPNodeOffset = jacLIDVec[map[7]][map2[7][0]];
1488  AIfxEquBasePNodeOffset = jacLIDVec[map[7]][map2[7][1]];
1489  AIfxEquEmitPNodeOffset = jacLIDVec[map[7]][map2[7][2]];
1490  AIfxEquIfxNodeOffset = jacLIDVec[map[7]][map2[7][3]];
1491  AIfxEqudIfxNodeOffset = jacLIDVec[map[7]][map2[7][4]];
1492 
1493  AdIfxEquCollPNodeOffset = jacLIDVec[map[8]][map2[8][0]];
1494  AdIfxEquBasePNodeOffset = jacLIDVec[map[8]][map2[8][1]];
1495  AdIfxEquEmitPNodeOffset = jacLIDVec[map[8]][map2[8][2]];
1496  AdIfxEquIfxNodeOffset = jacLIDVec[map[8]][map2[8][3]];
1497  AdIfxEqudIfxNodeOffset = jacLIDVec[map[8]][map2[8][4]];
1498  }
1499 
1500 }
1501 
1502 //-----------------------------------------------------------------------------
1503 // Function : Instance::setupPointers
1504 // Purpose :
1505 // Special Notes :
1506 // Scope : public
1507 // Creator : Eric Keiter, SNL
1508 // Creation Date : 12/01/08
1509 //-----------------------------------------------------------------------------
1511 {
1512 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1513  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
1514  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
1515 
1516  // F-matrix
1519 
1524 
1527 
1530 
1537 
1542 
1547 
1548 
1549  // Q-matrix:
1552 
1557 
1560 
1563 
1570 
1575 
1580 
1582  {
1583  //F-matrix excess phase Terms
1585 
1587 
1593 
1599 
1600 
1601  // Q-matrix excess phase terms
1603 
1605 
1611 
1617  }
1618 
1619 #endif
1620 }
1621 
1622 //-----------------------------------------------------------------------------
1623 // Function : Instance::updateTemperature
1624 // Purpose :
1625 // Special Notes :
1626 // Scope : public
1627 // Creator : Robert Hoekstra
1628 // Creation Date : 11/30/00
1629 //-----------------------------------------------------------------------------
1630 bool Instance::updateTemperature( const double & temp )
1631 {
1632 
1633 #ifdef Xyce_DEBUG_DEVICE
1634  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1635  {
1636  Xyce::dout() << "Start BJTInst::updateTemperature" << std::endl;
1637  Xyce::dout() << "temp = "<<temp << std::endl;
1638  }
1639 #endif
1640  if( temp != -999.0 ) TEMP = temp;
1642  {
1643  // make sure interpolation doesn't take any resistance negative
1644  if(model_.baseResist < 0) model_.baseResist = 0;
1647 
1648  // some params may have changed during interpolation
1650  }
1651 
1652  //Generation of temperature based factors
1653  vt = TEMP * CONSTKoverQ;
1654  double TNOM = model_.TNOM;
1655  double fact2 = TEMP / CONSTREFTEMP;
1656  double egfet = CONSTEg0 - ( CONSTalphaEg * TEMP * TEMP ) /
1657  ( TEMP + CONSTbetaEg );
1658  double arg = -egfet / ( 2.0 * CONSTboltz * TEMP ) +
1659  CONSTEg300 / ( CONSTboltz * ( 2.0 * CONSTREFTEMP ) );
1660  double pbfact = -2.0 * vt * ( 1.5 * log( fact2 ) + CONSTQ * arg );
1661  double ratlog = log( TEMP / model_.TNOM );
1662  double ratio1 = TEMP / model_.TNOM - 1.0;
1663  double factlog = ratio1 * model_.energyGap / vt
1664  + model_.tempExpIS * ratlog;
1665  double factor = exp( factlog );
1666  double bfactor = exp( ratlog * model_.betaExp );
1667 
1668  // Temp. adj. saturation current
1669 #ifdef Xyce_DEBUG_DEVICE
1670  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1671  {
1672  Xyce::dout() << " Factor is " << factor << std::endl;
1673  Xyce::dout() << " Bfactor is " << bfactor << std::endl;
1674  Xyce::dout() << " factlog is " << factlog << std::endl;
1675  Xyce::dout() << " ratio1 is " << ratio1 << std::endl;
1676  Xyce::dout() << " TEMP is " << TEMP << std::endl;
1677  Xyce::dout() << " TNOM is " << model_.TNOM << std::endl;
1678  Xyce::dout() << " Energy gap is " << model_.energyGap << std::endl;
1679  Xyce::dout() << " tempExpIS is " << model_.tempExpIS << std::endl;
1680  }
1681 #endif
1682 
1683  // Temp. adj. zero-bias junction capacitances and built-in potentials
1684  double fact1 = model_.TNOM / CONSTREFTEMP;
1685  double pbo = ( model_.potBE - pbfact ) / fact1;
1686  double gmaold = ( model_.potBE - pbo ) / pbo;
1687 
1688  tBECap = model_.depCapBE / ( 1.0 + model_.juncExpBE *
1689  ( 4.e-4 * ( model_.TNOM - CONSTREFTEMP ) - gmaold ) );
1690  tBEPot = fact2 * pbo + pbfact;
1691 
1692  double gmanew = ( tBEPot - pbo ) / pbo;
1693 
1694  tBECap *= 1.0 + model_.juncExpBE *
1695  ( 4.e-4 * ( TEMP - CONSTREFTEMP ) - gmanew );
1696 
1697  pbo = ( model_.potBC - pbfact ) / fact1;
1698  gmaold = ( model_.potBC - pbo ) / pbo;
1699 
1700  tBCCap = model_.depCapBC / ( 1.0 + model_.juncExpBC *
1701  ( 4.e-4 * ( model_.TNOM - CONSTREFTEMP ) - gmaold ) );
1702  tBCPot = fact2 * pbo + pbfact;
1703 
1704  gmanew = ( tBCPot - pbo ) / pbo;
1705 
1706  tBCCap *= 1.0 + model_.juncExpBC *
1707  ( 4.e-4 * ( TEMP - CONSTREFTEMP ) - gmanew );
1708 
1709  // Temp. adj. depletion capacitance
1711 
1712  // Temp. adj. polynomial factors
1713  double xfc = log( 1.0 - model_.depCapCoeff );
1714  tF1 = tBEPot * ( 1.0 - exp( ( 1.0 - model_.juncExpBE ) * xfc ) ) /
1715  ( 1.0 - model_.juncExpBE );
1716 
1718  tF5 = tBCPot * ( 1.0 - exp( ( 1.0 - model_.juncExpBC ) * xfc ) ) /
1719  ( 1.0 - model_.juncExpBC );
1720 
1721  // Temp. adj. critical voltage
1722  // tVCrit = vt * log( vt / ( 1.41414 * model_.satCur ) );
1723  tVCrit = vt * log( vt / ( CONSTroot2 * model_.satCur ) );
1724 
1725  tSatCur = model_.satCur * factor;
1726  // Temp. adj. beta's
1727  tBetaF = model_.betaF * bfactor;
1728  tBetaR = model_.betaR * bfactor;
1729  // Temp. adj. leakage currents
1734  tBELeakCur = model_.leakBECurrent * exp( factlog / model_.leakBEEmissionCoeff ) / bfactor;
1735  tBCLeakCur = model_.leakBCCurrent * exp( factlog / model_.leakBCEmissionCoeff ) / bfactor;
1736 
1743 
1744  if (model_.rollOffF != 0)
1746  else
1747  tInvRollOffF = 0;
1748  if (model_.rollOffR != 0)
1750  else
1751  tInvRollOffR = 0;
1752  if (model_.earlyVoltF != 0)
1754  else
1755  tInvEarlyVoltF = 0;
1756  if (model_.earlyVoltR != 0)
1758  else
1759  tInvEarlyVoltR = 0;
1760 
1761 #ifdef Xyce_DEBUG_DEVICE
1762  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1763  {
1764 
1765  Xyce::dout() << section_divider << std::endl;
1766  Xyce::dout() << "In BJTInst::updateTemperature" << std::endl;
1767  Xyce::dout() << section_divider << std::endl;
1768  Xyce::dout() << "TEMP = " << TEMP << std::endl;
1769  Xyce::dout() << "TNOM = " << TNOM << std::endl;
1770  Xyce::dout() << "vt = " << vt << std::endl;
1771  Xyce::dout() << "tSatCur = " << tSatCur << std::endl;
1772  Xyce::dout() << "tBetaF = " << tBetaF << std::endl;
1773  Xyce::dout() << "tBetaR = " << tBetaR << std::endl;
1774  Xyce::dout() << "tBELeakCur = " << tBELeakCur << std::endl;
1775  Xyce::dout() << "tBCLeakCur = " << tBELeakCur << std::endl;
1776  Xyce::dout() << "tBEPot = " << tBEPot << std::endl;
1777  Xyce::dout() << "tBECap = " << tBECap << std::endl;
1778  Xyce::dout() << "tBCPot = " << tBCPot << std::endl;
1779  Xyce::dout() << "tBCCap = " << tBCCap << std::endl;
1780  Xyce::dout() << "tDepCap = " << tDepCap << std::endl;
1781  Xyce::dout() << "tF1 = " << tF1 << std::endl;
1782  Xyce::dout() << "tF4 = " << tF4 << std::endl;
1783  Xyce::dout() << "tF5 = " << tF5 << std::endl;
1784  Xyce::dout() << "tleakBEEmissionCoeff = " << tleakBEEmissionCoeff << std::endl;
1785  Xyce::dout() << "tleakBCEmissionCoeff = " << tleakBCEmissionCoeff << std::endl;
1786  Xyce::dout() << "tRollOffExp = " << tRollOffExp << std::endl;
1787  Xyce::dout() << "tInvRollOffF = " << tInvRollOffF << std::endl;
1788  Xyce::dout() << "tInvRollOffR = " << tInvRollOffR << std::endl;
1789  Xyce::dout() << "tInvEarlyVoltF = " << tInvEarlyVoltF << std::endl;
1790  Xyce::dout() << "tInvEarlyVoltR = " << tInvEarlyVoltR << std::endl;
1791  Xyce::dout() << "tBaseResist = " << tBaseResist << std::endl;
1792  Xyce::dout() << "tCollectorResist = " << tCollectorResist << std::endl;
1793  Xyce::dout() << "tEmitterResist = " << tEmitterResist << std::endl;
1794  Xyce::dout() << section_divider << std::endl;
1795  Xyce::dout() << std::endl;
1796  }
1797 #endif
1798 
1799  return true;
1800 }
1801 
1802 
1803 //----------------------------------------------------------------------------
1804 // Function : Instance::lambertWCurrent
1805 // Purpose : Determine the current through an individual BJT
1806 // Special Notes :
1807 // Scope : public
1808 // Creator : Nick Johnson, Summer Intern
1809 // Creation Date : 7/30/02
1810 //---------------------------------------------------------------------------
1811 bool Instance::lambertWCurrent(double &Id, double &Gd, double Vd, double Vte, double Isat)
1812 {
1813  double RS = 1.0e-12;
1814  double arg1 = (Vd + Isat*RS)/Vte;
1815  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
1816  double evd = exp(arg1);
1817  double lambWArg = Isat*RS*evd/Vte;
1818  double lambWReturn;
1819  int ierr;
1820  double lambWError;
1821  devSupport.lambertw(lambWArg, lambWReturn, ierr, lambWError);
1822 
1823  Id = -Isat+Vte*(lambWReturn)/RS;
1824  Gd = lambWReturn / ((1 + lambWReturn)*RS);
1825 
1826  return true;
1827 }
1828 
1829 //-----------------------------------------------------------------------------
1830 // Function : Instance::loadDeviceMask
1831 //
1832 // Purpose : Loads the zero elements of the device mask
1833 //
1834 // Special Notes : elements of the error vector associated with zero
1835 // elements of the mask will not be included in weighted
1836 // norms by the time integrator.
1837 //
1838 // Scope : public
1839 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1840 // Creation Date : 01/19/07
1841 //-----------------------------------------------------------------------------
1843 {
1844  bool returnVal=false;
1845  if (getDeviceOptions().newExcessPhase)
1846  {
1847  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
1848 
1849  (*maskVectorPtr)[li_Ifx] = 0.0;
1850  (*maskVectorPtr)[li_dIfx] = 0.0;
1851  returnVal = true;
1852  }
1853  return (returnVal);
1854 }
1855 
1856 //-----------------------------------------------------------------------------
1857 // Function : Instance::loadDAEQVector
1858 //
1859 // Purpose : Loads the Q-vector contributions for a single
1860 // BJT instance.
1861 //
1862 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1863 // which the system of equations is represented as:
1864 //
1865 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1866 //
1867 // Scope : public
1868 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1869 // Creation Date : 01/26/03
1870 //-----------------------------------------------------------------------------
1872 {
1873  double td = model_.excessPhaseFac;
1874  double vbe_diff = vBE - vBE_orig;
1875  double vbc_diff = vBC - vBC_orig;
1876 
1877  double * solVec = extData.nextSolVectorRawPtr;
1878  double * qVec = extData.daeQVectorRawPtr;
1879 
1880  qVec[li_Base] -= - model_.TYPE * qBX;
1881  qVec[li_Subst] -= -model_.TYPE * qCS;
1882  qVec[li_CollP] -= model_.TYPE * ( qCS + qBX + qBCdep + qBCdiff );
1883  qVec[li_BaseP] -= -model_.TYPE * ( qBEdep + qBEdiff + qBCdep + qBCdiff );
1884  qVec[li_EmitP] -= model_.TYPE*( qBEdep + qBEdiff );
1885 
1886  // excess phase ERK-dcop
1887  if (td != 0 && getDeviceOptions().newExcessPhase)
1888  {
1889  qVec[li_Ifx] += solVec[li_Ifx];
1890 
1891  if (!(getSolverState().dcopFlag) )
1892  {
1893  qVec[li_dIfx] += solVec[li_dIfx]*td*td;
1894  }
1895  else
1896  {
1897  qVec[li_dIfx] = 0.0;
1898  }
1899  }
1900 
1901  // load up the jdxp terms
1903  {
1904  double Cp_Jdxp_q = 0.0;
1905  double Ep_Jdxp_q = 0.0;
1906  double Bp_Jdxp_q = 0.0;
1907 
1908  if (!origFlag)
1909  {
1910  Cp_Jdxp_q = -(capBCdep + capBCdiff)*vbc_diff;
1911  Cp_Jdxp_q *= model_.TYPE;
1912 
1913  Bp_Jdxp_q = (capBEdep + capBEdiff)*vbe_diff
1914  + (capBCdiff + capBCdep + capeqCB) *vbc_diff;
1915  Bp_Jdxp_q *= model_.TYPE;
1916 
1917  Ep_Jdxp_q = - capeqCB * vbc_diff - (capBEdiff + capBEdep)* vbe_diff;
1918  Ep_Jdxp_q *= model_.TYPE;
1919  }
1920 
1921  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
1922  dQdxdVp[li_CollP] += Cp_Jdxp_q;
1923  dQdxdVp[li_BaseP] += Bp_Jdxp_q;
1924  dQdxdVp[li_EmitP] += Ep_Jdxp_q;
1925  }
1926 
1927  if( loadLeadCurrent )
1928  {
1929  double * storeLeadQ = extData.storeLeadCurrQCompRawPtr;
1930 
1931  storeLeadQ[li_store_dev_ic] = -model_.TYPE * ( qCS + qBX + qBCdep + qBCdiff );
1932  storeLeadQ[li_store_dev_ib] = model_.TYPE * ( qBX + qBEdep + qBEdiff + qBCdep + qBCdiff );
1933  storeLeadQ[li_store_dev_ie] = -model_.TYPE*( qBEdep + qBEdiff );
1934  storeLeadQ[li_store_dev_is] = model_.TYPE * qCS;
1935  }
1936 
1937  return true;
1938 }
1939 
1940 //-----------------------------------------------------------------------------
1941 // Function : Instance::auxDAECalculations
1942 //
1943 // Purpose : This function is supposed to handle a lot of the final
1944 // "cleanup" calculations that were done, in the old-DAE
1945 // formulation, at the end of updateSecondaryState.
1946 //
1947 // For the new-DAE form, they need to be done elsewhere, as
1948 // updateSecondaryState isn't called for new-DAE.
1949 //
1950 // Special Notes :
1951 // Scope : public
1952 // Creator : Eric Keiter, 9233, Computational Sciences.
1953 // Creation Date : 04/15/04
1954 //-----------------------------------------------------------------------------
1956 {
1957  double i_fx;
1958  double td = model_.excessPhaseFac;
1959  double * solVec = extData.nextSolVectorRawPtr;
1960 
1961  if ( td != 0 && !(getSolverState().dcopFlag) )
1962  {
1963  i_fx = solVec[li_Ifx];
1964  iCE = i_fx - iBC / qB;
1965  }
1966  else
1967  {
1968  iCE = (iBE - iBC)/ qB;
1969  }
1970 
1971  iC = iCE - iBC / tBetaR - iBCleak;
1972  iB = iBE / tBetaF + iBEleak + iBC / tBetaR + iBCleak;
1973  iE = -iC-iB;
1974 
1975  if (td != 0)
1976  {
1977  if (!(getSolverState().dcopFlag) )
1978  {
1979  diCEdvBp = invqB * (-invqB * iBC * dqBdvBp - gBC);
1980  diCEdvCp = invqB * (-invqB * iBC * dqBdvCp + gBC);
1981  diCEdvEp = -invqB * invqB * iBC * dqBdvEp;
1982  }
1983  else // ERK-dcop: if dcop, use the td=0 case (copied from below)
1984  {
1985  diCEdvBp = invqB * (iCE * dqBdvBp + gBE - gBC);
1986  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
1987  diCEdvEp = invqB * (iCE * dqBdvEp - gBE);
1988  }
1989 
1990  diBEdvBp = invqB *(invqB* iBE * dqBdvBp + gBE);
1991  diBEdvCp = invqB * invqB * iBE * dqBdvCp;
1992  diBEdvEp = invqB * (invqB * iBE * dqBdvEp - gBE);
1993  }
1994  else
1995  {
1996  diCEdvBp = invqB * (iCE * dqBdvBp + gBE - gBC);
1997  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
1998  diCEdvEp = invqB * (iCE * dqBdvEp - gBE);
1999  }
2000 
2001  return;
2002 }
2003 
2004 //-----------------------------------------------------------------------------
2005 // Function : Instance::loadDAEFVector
2006 //
2007 // Purpose : Loads the F-vector contributions for a single
2008 // BJT instance.
2009 //
2010 // Special Notes :
2011 //
2012 // Scope : public
2013 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2014 // Creation Date : 01/26/03
2015 //-----------------------------------------------------------------------------
2017 {
2018  double coefC, coefB, coefE, coefCp, coefBp, coefEp;
2019 
2020  double td = model_.excessPhaseFac;
2021  double * solVec = extData.nextSolVectorRawPtr;
2022  double * fVec = extData.daeFVectorRawPtr;
2023 
2024  double vbe_diff = vBE - vBE_orig;
2025  double vbc_diff = vBC - vBC_orig;
2026  double vce_diff = vbe_diff - vbc_diff;
2027 
2028  fVec[li_Coll] -= -vCCp * gCpr;
2029  fVec[li_Base] -= -vBBp * gX;
2030  fVec[li_Emit] -= -vEEp * gEpr;
2031  fVec[li_CollP] -= vCCp * gCpr + model_.TYPE * ( - iC );
2032  fVec[li_BaseP] -= vBBp * gX - model_.TYPE * ( iB );
2033  fVec[li_EmitP] -= vEEp * gEpr + model_.TYPE * ( - iE );
2034 
2035  // excess phase ERK-dcop.
2036  double i_fx = 0.0;
2037  double di_fx = 0.0;
2038 
2040  {
2041  i_fx = solVec[li_Ifx];
2042  di_fx = solVec[li_dIfx];
2043 
2044  if (td != 0)
2045  {
2046  if (!(getSolverState().dcopFlag) )
2047  {
2048  // omega0 = 1/td;
2049  fVec[li_Ifx] += - di_fx;
2050  fVec[li_dIfx] += 3 * di_fx*td + 3*i_fx -3 * iBE / qB;
2051  }
2052  else
2053  {
2054  fVec[li_Ifx] += i_fx -iBE/qB;
2055  fVec[li_dIfx] = 0.0;
2056  }
2057  }
2058  else
2059  {
2060  fVec[li_Ifx] += i_fx;
2061  fVec[li_dIfx] += di_fx;
2062  }
2063  }
2064 
2065  double Cp_Jdxp_f=0.0;
2066  double Bp_Jdxp_f=0.0;
2067  double Ep_Jdxp_f=0.0;
2068  double dIfx_Jdxp_f=0.0 ;
2069  double Ifx_Jdxp_f=0.0 ;
2070 
2071  // Now for the jdxp terms
2073  {
2074  if (!origFlag)
2075  {
2076  Cp_Jdxp_f = + diCEdvBp * vbe_diff
2077  + diCEdvCp * vce_diff
2078  - gBCtot * vbc_diff;
2079 
2080  Cp_Jdxp_f *= model_.TYPE;
2081 
2082  Bp_Jdxp_f = gBEtot * vbe_diff + gBCtot * vbc_diff;
2083  Bp_Jdxp_f *= model_.TYPE;
2084 
2085  Ep_Jdxp_f = - diCEdvCp * vce_diff - (diCEdvBp + gBEtot) * vbe_diff;
2086  Ep_Jdxp_f *= model_.TYPE;
2087 
2088  // ERK-dcop.
2089  if ( td != 0 && getDeviceOptions().newExcessPhase )
2090  {
2091  if ( !(getSolverState().dcopFlag) )
2092  {
2093  dIfx_Jdxp_f = -3 *( diBEdvBp*vbe_diff + diBEdvCp * vce_diff);
2094  dIfx_Jdxp_f *= model_.TYPE;
2095  }
2096  else
2097  {
2098  Ifx_Jdxp_f = ( diBEdvBp*vbe_diff + diBEdvCp * vce_diff);
2099  Ifx_Jdxp_f *= model_.TYPE;
2100  }
2101  }
2102  }
2103 
2104  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
2105  dFdxdVp[li_CollP] += Cp_Jdxp_f;
2106  dFdxdVp[li_BaseP] += Bp_Jdxp_f;
2107  dFdxdVp[li_EmitP] += Ep_Jdxp_f;
2108 
2109  // ERK-dcop.
2110  if ( td != 0 && getDeviceOptions().newExcessPhase )
2111  {
2112  if ( !(getSolverState().dcopFlag) )
2113  {
2114  dFdxdVp[li_dIfx] += dIfx_Jdxp_f;
2115  }
2116  else
2117  {
2118  dFdxdVp[li_Ifx] += Ifx_Jdxp_f;
2119  }
2120  }
2121  }
2122 
2123  if( loadLeadCurrent )
2124  {
2125  double * storeLeadF = extData.nextStoVectorRawPtr;
2126 
2127  storeLeadF[li_store_dev_ic] = model_.TYPE * ( iC );
2128  storeLeadF[li_store_dev_is] = 0;
2129  storeLeadF[li_store_dev_ie] = model_.TYPE * ( iE );
2130  storeLeadF[li_store_dev_ib] = model_.TYPE * ( iB );
2131  }
2132  return true;
2133 }
2134 
2135 //-----------------------------------------------------------------------------
2136 // Function : Instance::loadDAEdQdx
2137 //
2138 // Purpose : Loads the Q-vector contributions for a single
2139 // BJT instance.
2140 //
2141 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2142 // which the system of equations is represented as:
2143 //
2144 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2145 //
2146 // The "Q" vector contains charges and fluxes. So, this
2147 // matrix will contain only the capacitance terms.
2148 //
2149 // Scope : public
2150 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2151 // Creation Date : 03/05/04
2152 //-----------------------------------------------------------------------------
2154 {
2155  double td = model_.excessPhaseFac;
2156 
2157  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2158 
2160 
2164 
2168  += capCS + capBX + capBCdep + capBCdiff;
2169 
2171  += -capBCdep - capBCdiff;
2172 
2174  += -capBCdiff - capBCdep - capeqCB;
2175 
2177  += capBEdiff + capBEdep + capBCdiff + capBCdep + capeqCB;
2178 
2180  += -capBEdiff - capBEdep;
2183  += -capBEdiff - capBEdep - capeqCB;
2185  += capBEdiff + capBEdep;
2186 
2187  // excess phase terms. ERK-dcop
2188  if ( td != 0 && getDeviceOptions().newExcessPhase )
2189  {
2190  if (!(getSolverState().dcopFlag) )
2191  {
2192  dQdx[li_Ifx][AIfxEquIfxNodeOffset] += 1;
2193  dQdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1*td*td;
2194  }
2195  }
2196 
2197  return true;
2198 }
2199 
2200 //-----------------------------------------------------------------------------
2201 // Function : Instance::loadDAEdFdx ()
2202 //
2203 // Purpose : Loads the F-vector contributions for a single
2204 // BJT instance.
2205 //
2206 // Special Notes : See the special notes for loadDAEFVector.
2207 //
2208 // This is an algebraic constaint.
2209 //
2210 // Scope : public
2211 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2212 // Creation Date : 03/05/04
2213 //-----------------------------------------------------------------------------
2215 {
2216  double td = model_.excessPhaseFac;
2217 
2218  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2219 
2226 
2228 
2230 
2231 
2235  += diCEdvBp - gBCtot;
2237 
2238  // excess phase terms. ERK-dcop
2239  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
2240  dFdx[li_CollP][ACollPEquIfxNodeOffset] += 1.0 * model_.TYPE;
2241 
2244  += -diBrdvCp - gBCtot;
2245 
2247  += -diBrdvBp + gBEtot + gBCtot;
2248 
2250  += -diBrdvEp - gBEtot;
2251 
2255  += - diCEdvBp - gBEtot;
2256 
2257  // ERK Note: -diCEdvEp should equal + diCEdvBp + diCEdvCp. In the
2258  // original old-DAE form, + diCEdvBp + diCEdvCp is used. In
2259  // the more recent new-DAE form, we've used diCEdvEp, but it sometimes
2260  // results in subtle differences between old- and new-DAE jacobians.
2261  // This should matter, but .....
2263  //+= gBEtot + gEpr - diCEdvEp;
2264  += gBEtot + gEpr + diCEdvBp + diCEdvCp; // this is a test.
2265 
2266  // excess phase terms. ERK-dcop
2267  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
2268  dFdx[li_EmitP][AEmitPEquIfxNodeOffset] += -1.0 * model_.TYPE;
2269 
2270  // excess phase terms. ERK-dcop
2272  {
2273  if ( td != 0 )
2274  {
2275  if ( !(getSolverState().dcopFlag) )
2276  {
2277  dFdx[li_Ifx][AIfxEqudIfxNodeOffset]+= -1;
2281  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 3* td;
2282  dFdx[li_dIfx][AdIfxEquIfxNodeOffset] += 3;
2283  }
2284  else
2285  {
2289  dFdx[li_Ifx][AIfxEquIfxNodeOffset]+= 1;
2290  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1;
2291  }
2292  }
2293  else
2294  {
2295  dFdx[li_Ifx][AIfxEquIfxNodeOffset]+= 1;
2296  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1;
2297  }
2298  }
2299 
2300  return true;
2301 }
2302 
2303 //-----------------------------------------------------------------------------
2304 // Function : Instance::updatePrimaryState
2305 // Purpose :
2306 // Special Notes :
2307 // Scope : public
2308 // Creator : Robert J. Hoekstra
2309 // Creation Date : 1/13/00
2310 //-----------------------------------------------------------------------------
2312 {
2313  // Do the bulk of the work in updateIntermediateVars:
2314  bool bsuccess = updateIntermediateVars();
2315 
2316  double * staVec = extData.nextStaVectorRawPtr;
2317  double * currStaVec = extData.currStaVectorRawPtr;
2318 
2319  // save voltage drops
2320 
2321  double * stoVec = extData.nextStoVectorRawPtr;
2322  stoVec[li_storevBE] = vBE;
2323  stoVec[li_storevBC] = vBC;
2324  stoVec[li_store_capeqCB] = capeqCB;
2325 
2326  staVec[li_qstateBEdiff] = qBEdiff;
2327  staVec[li_qstateBEdep] = qBEdep;
2328  staVec[li_qstateBCdiff] = qBCdiff;
2329  staVec[li_qstateBCdep] = qBCdep;
2330  staVec[li_qstateBX] = qBX;
2331  staVec[li_qstateCS] = qCS;
2332 
2333 
2334  // if this is the first newton step of the first time step
2335  // of the transient simulation, we need to enforce that the
2336  // time derivatives w.r.t. charge are zero. This is to maintain 3f5
2337  // compatibility. ERK.
2338 
2339  if (!(getSolverState().dcopFlag) && (getSolverState().initTranFlag) && getSolverState().newtonIter==0)
2340  {
2341  currStaVec[li_qstateBEdiff] = qBEdiff;
2342  currStaVec[li_qstateBEdep] = qBEdep;
2343  currStaVec[li_qstateBCdiff] = qBCdiff;
2344  currStaVec[li_qstateBCdep] = qBCdep;
2345  currStaVec[li_qstateBX] = qBX;
2346  currStaVec[li_qstateCS] = qCS;
2347  }
2348 
2349  return bsuccess;
2350 }
2351 
2352 //-----------------------------------------------------------------------------
2353 // Function : Instance::updateSecondaryState
2354 // Purpose :
2355 // Special Notes :
2356 // Scope : public
2357 // Creator : Robert J. Hoekstra
2358 // Creation Date : 1/13/00
2359 //-----------------------------------------------------------------------------
2361 {
2362  double * staDerivVec = extData.nextStaDerivVectorRawPtr;
2363 
2364  // Now that the state vector for time=0 is up-to-date, get the derivative
2365  // with respect to time of the charge, to obtain the best estimate for
2366  // the current in the capacitor.
2367 
2368  iBEdiff = staDerivVec[li_qstateBEdiff];
2369  iBEdep = staDerivVec[li_qstateBEdep ];
2370  iCS = staDerivVec[li_qstateCS ];
2371  iBCdiff = staDerivVec[li_qstateBCdiff];
2372  iBCdep = staDerivVec[li_qstateBCdep ];
2373  iBX = staDerivVec[li_qstateBX ];
2374 
2375  return true;
2376 }
2377 
2378 //-----------------------------------------------------------------------------
2379 // Function : Instance::oldDAEExcessPhaseCalculation1
2380 //
2381 // Purpose : This handles the parts of the calculation of excess phase
2382 // terms that need to be done in the
2383 // updatePrimaryState function.
2384 //
2385 // Special Notes : The excess phase calculation is based on a second-order
2386 // time derivative.
2387 //
2388 // Most of the excess phase work is done in the companion
2389 // function, oldDAEExcessPhaseCalculation2.
2390 //
2391 // This function mainly enforces a constant history.
2392 //
2393 // Scope : public
2394 // Creator : Eric Keiter, 9233, Computational Sciences.
2395 // Creation Date : 04/11/04
2396 //-----------------------------------------------------------------------------
2398 {
2399  // do excess phase stuff if we are in transient mode and td is nonzero.
2400  double td = model_.excessPhaseFac;
2401 
2402  currCexbc = lastCexbc = 0.0;
2403 
2404  if (!(getSolverState().dcopFlag) && td != 0)
2405  {
2406  // If there is no cexbc history, create one and use it.
2407  if (getSolverState().beginIntegrationFlag)
2408  {
2409  currCexbc = lastCexbc = iBE/qB;
2412  }
2413  }
2414 
2415  return;
2416 }
2417 
2418 //-----------------------------------------------------------------------------
2419 // Function : Instance::oldDAEExcessPhaseCalculation2
2420 //
2421 // Purpose : This handles the parts of the calculation of excess phase
2422 // terms that need to be done in the
2423 // updateSecondaryState function.
2424 //
2425 // Special Notes : This function has a companion function,
2426 // oldDAEExcessPhaseCalculation1. Most of the work is done
2427 // in this one.
2428 //
2429 // Scope : public
2430 // Creator : Eric Keiter, 9233, Computational Sciences.
2431 // Creation Date : 04/11/04
2432 //-----------------------------------------------------------------------------
2434  (double & iEX, double & gEX, double & iC_local)
2435 {
2436  ////////////////////////////////////////////////////////////////
2437  double td = model_.excessPhaseFac;
2438 
2439 #ifdef Xyce_DEBUG_DEVICE
2440  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2441  {
2442  Xyce::dout() << std::endl;
2443  Xyce::dout() << " Excess Phase stuff:" <<std::endl;
2444  Xyce::dout() << " name = " << getName() <<std::endl;
2445  Xyce::dout() << " td = " << td <<std::endl;
2446  }
2447 #endif
2448 
2449  ////////////////////////////////////////////////////////////////
2450  // ERK: 07/13/01
2451  //
2452  // weil's approx. for excess phase applied with backward-
2453  // euler integration
2454  // (copied over from chilespice).
2455  //
2456  ////////////////////////////////////////////////////////////////
2457 
2458  iEX=iBE;
2459  gEX=gBE;
2460 
2461  dt0 = getSolverState().currTimeStep;
2462  dt1 = getSolverState().lastTimeStep;
2463 
2464  iC_local = 0.0;
2465 
2466  // do excess phase stuff if we are in transient mode and td is nonzero.
2467  if (!(getSolverState().dcopFlag) && td != 0)
2468  {
2469  double arg1, arg2, denom;
2470 
2471  arg1 = dt0 / td;
2472  arg2 = 3.0 * arg1;
2473  arg1 = arg2 * arg1;
2474  denom = 1.0 + arg1 + arg2;
2475  phaseScalar = arg1 / denom;
2476 
2477  // Secondary state stuff:
2478  if (!getSolverState().beginIntegrationFlag)
2479  {
2480  currCexbc = (*extData.currStaVectorPtr)[li_istateCEXBC];
2481  lastCexbc = (*extData.lastStaVectorPtr)[li_istateCEXBC];
2482  }
2483 
2484  iC_local = ((currCexbc) * (1 + dt0 / dt1 + arg2) - (lastCexbc) * dt0 / dt1) / denom;
2485  iEX = iBE * phaseScalar;
2486  gEX = gBE * phaseScalar;
2487 
2488  nextCexbc = iC_local + iEX / qB;
2489  (*extData.nextStaVectorPtr)[li_istateCEXBC] = nextCexbc;
2490  }
2491 
2492  return;
2493 }
2494 
2495 //-----------------------------------------------------------------------------
2496 // Function : Instance::updateIntermediateVars
2497 // Purpose :
2498 // Special Notes :
2499 // Scope : public
2500 // Creator : Robert J. Hoekstra
2501 // Creation Date : 1/13/00
2502 //-----------------------------------------------------------------------------
2504 {
2505 
2506  bool bsuccess = true;
2507 
2508  double v_emit, v_emitP;
2509  double v_base, v_baseP;
2510  double v_coll, v_collP;
2511  double v_subst;
2512 
2513  double q1, q2;
2514  double * solVec = extData.nextSolVectorRawPtr;
2515 
2516 #ifdef Xyce_DEBUG_DEVICE
2517  if (getDeviceOptions().debugLevel>0 && getSolverState().debugTimeFlag)
2518  {
2519  Xyce::dout() << Xyce::section_divider << std::endl;
2520  Xyce::dout() << "Instance::updateIntermediateVars " << getName() <<std::endl;
2521  }
2522 #endif
2523 
2524  // obtain voltages:
2525  v_emit = solVec[li_Emit];
2526  v_emitP = solVec[li_EmitP];
2527  v_base = solVec[li_Base];
2528  v_baseP = solVec[li_BaseP];
2529  v_coll = solVec[li_Coll];
2530  v_collP = solVec[li_CollP];
2531  v_subst = solVec[li_Subst];
2532 
2533  vEEp = (v_emit - v_emitP);
2534  vBBp = (v_base - v_baseP);
2535  vCCp = (v_coll - v_collP);
2536 
2537  vBE = model_.TYPE * (v_baseP - v_emitP);
2538  vBC = model_.TYPE * (v_baseP - v_collP);
2539  vBX = model_.TYPE * (v_base - v_collP);
2540  //vCS = model_.TYPE * (v_collP - v_subst);
2541  vCS = model_.TYPE * (v_subst - v_collP);
2542 
2543  vBE_orig = vBE;
2544  vBC_orig = vBC;
2545 
2546  // Reset this to show we're starting from the originals
2547  origFlag = true;
2548  offFlag = false;
2549 
2551  {
2552  if( IC_GIVEN )
2553  {
2554  vBE = model_.TYPE * icVBE;
2555  double vCE = model_.TYPE * icVCE;
2556  vBC = vBE - vCE;
2557  vBX = vBC;
2558  origFlag = false;
2559  }
2560  else
2561  {
2563  {
2564  N_LAS_Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
2565  if ((*flagSolVectorPtr)[li_Emit] == 0 || (*flagSolVectorPtr)[li_EmitP] == 0 ||
2566  (*flagSolVectorPtr)[li_Base] == 0 || (*flagSolVectorPtr)[li_BaseP] == 0 ||
2567  (*flagSolVectorPtr)[li_Coll] == 0 || (*flagSolVectorPtr)[li_CollP] == 0 ||
2568  (*flagSolVectorPtr)[li_Subst] == 0 )
2569  {
2570  vBC = 0;
2571  vBE = tVCrit;
2572  vBX = vBC;
2573  origFlag = false;
2574  }
2575  }
2576  else
2577  {
2578  vBE=tVCrit;
2579  vBX = vBC;
2580  origFlag = false;
2581 #ifdef Xyce_DEBUG_DEVICE
2583  {
2584  Xyce::dout() << " Setting device initial condition to Base-Emitter drop=tVCrit (" << tVCrit << ")"<<std::endl;
2585  }
2586 #endif
2587  }
2588  }
2589 
2590 
2591 #ifdef Xyce_DEBUG_DEVICE
2592  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2593  {
2594  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2595  Xyce::dout() << " " <<std::endl;
2596  Xyce::dout() << " using UIC.\n";
2597  Xyce::dout() << " vBE = " << vBE << std::endl;
2598  Xyce::dout() << " vBC = " << vBC << std::endl;
2599  Xyce::dout() << " vBX = " << vBX << std::endl;
2600  Xyce::dout() << " vCS = " << vCS << std::endl;
2601  }
2602 #endif
2603  }
2604  else if ((getSolverState().initFixFlag || getSolverState().initJctFlag) && OFF)
2605  {
2606  vBX = vBC = vBE = 0.0 ;
2607  // NOTE: Must not set "origFlag" here, because that flags "non-converged"
2608  // which causes initFixFlag always to be set, which causes this section
2609  // always to be executed. Bad!
2610  // instead, flag with "offFlag" that will not be used in convergence
2611  // testing, but WILL be used in the voltage limiting machinery to make
2612  // this work properly.
2613  offFlag = true;
2614 
2615 #ifdef Xyce_DEBUG_DEVICE
2616  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2617  {
2618  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2619  Xyce::dout() << " " <<std::endl;
2620  Xyce::dout() << " BJT explicitly set OFF, zeroing all junction drops.\n";
2621  }
2622 #endif
2623  }
2624 
2625 
2626  if (getSolverState().newtonIter == 0)
2627  {
2628  if (!(getSolverState().dcopFlag)||(getSolverState().locaEnabledFlag && getSolverState().dcopFlag))
2629  {
2633  }
2634  else
2635  {
2636  vBE_old = vBE; // otherwise we have no history
2637  vBC_old = vBC;
2638  capeqCB = 0.0;
2639  }
2640  }
2641  else
2642  {
2646  }
2647 
2648 #ifdef Xyce_DEBUG_DEVICE
2650  {
2651  Xyce::dout() << " tVCrit = " << tVCrit << std::endl;
2652  Xyce::dout().width(3);
2653  Xyce::dout() << getSolverState().newtonIter;
2654  Xyce::dout().width(5); Xyce::dout() << getName();
2655  Xyce::dout() << " Blim: ";
2656  Xyce::dout() << " vBE=";
2657  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2658  Xyce::dout() << vBE;
2659  Xyce::dout() << " vBC=";
2660  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2661  Xyce::dout() << vBC << std::endl;
2662  }
2663 #endif
2664 
2665  // if we had bypass implemented, most of it would be here.
2666  // don't bother limiting voltages if we've already forced OFF.
2667 
2668  if (getDeviceOptions().voltageLimiterFlag && !(getSolverState().initFixFlag&&OFF))
2669  {
2670  // "reset" the junction voltages to keep them from changing too much.
2671  // only do this if this is not the first newton iteration, and not
2672  // a by pass step.
2673  int ichk1, icheck;
2674 
2675  if (getSolverState().newtonIter >= 0)
2676  {
2677  ichk1=1; // don't know what this is for...
2678 
2679  vBE = devSupport.pnjlim(vBE, vBE_old, vt, tVCrit, &icheck);
2680  vBC = devSupport.pnjlim(vBC, vBC_old, vt, tVCrit, &ichk1);
2681 
2682  if (ichk1 == 1) icheck=1;
2683 
2684  // set the origFlag to zero if things have changed.
2685  if (icheck==1) origFlag = false;
2686  }
2687 
2688 #ifdef Xyce_DEBUG_DEVICE
2689  if (getDeviceOptions().debugLevel > -2 && getSolverState().debugTimeFlag)
2690  {
2691  Xyce::dout().width(3);
2692  Xyce::dout() << getSolverState().newtonIter;
2693  Xyce::dout().width(5); Xyce::dout() << getName() ;
2694  Xyce::dout() << " Alim: ";
2695  Xyce::dout() << " vBE=";
2696  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2697  Xyce::dout() << vBE;
2698  Xyce::dout() << " vBC=";
2699  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2700  Xyce::dout() << vBC;
2701 
2702  //cout << " vBE_orig = " << vBE_orig << std::endl;
2703  //cout << " vBC_orig = " << vBC_orig << std::endl <<std::endl;
2704  //cout << " origFlag = " << origFlag << std::endl;
2705 
2706  if (origFlag) Xyce::dout() << " SAME";
2707  else Xyce::dout() << " DIFF";
2708  Xyce::dout() << std::endl;
2709  }
2710 #endif
2711  }
2712 
2713  //Junction Current Calculations
2714 
2715  double csat = tSatCur * AREA;
2716  double vtF = vt * model_.emissionCoeffF;
2717  double vtR = vt * model_.emissionCoeffR;
2718  double vtE = vt * tleakBEEmissionCoeff;
2719  double vtC = vt * tleakBCEmissionCoeff;
2720  double iLeakBE = tBELeakCur * AREA;
2721  double iLeakBC = tBCLeakCur * AREA;
2722 
2723  // determine currents using LambertW
2724  if (lambertWFlag)
2725  {
2726  if( vBE > -5.0 * vtF )
2727  {
2728  lambertWCurrent(iBE, gBE, vBE, vtF, csat);
2729 
2730  if( iLeakBE == 0.0 )
2731  iBEleak = gBEleak = 0.0;
2732  else
2733  {
2734  lambertWCurrent(iBEleak, gBEleak, vBE, vtE, iLeakBE);
2735  }
2736  }
2737  else
2738  {
2739  gBE = -csat / vBE + getDeviceOptions().gmin;
2740  iBE = gBE * vBE;
2741  gBEleak = -iLeakBE / vBE;
2742  iBEleak = gBEleak * vBE;
2743  }
2744 
2745  if( vBC > -5.0 * vtR )
2746  {
2747  lambertWCurrent(iBC, gBC, vBC, vtR, csat);
2748 
2749  if( iLeakBC == 0.0 )
2750  iBCleak = gBCleak = 0.0;
2751  else
2752  {
2753  lambertWCurrent(iBCleak, gBCleak, vBC, vtC, iLeakBC);
2754  }
2755  }
2756  else
2757  {
2758  gBC = -csat / vBC + getDeviceOptions().gmin;
2759  iBC = gBC * vBC;
2760  gBCleak = -iLeakBC / vBC;
2761  iBCleak = gBCleak * vBC;
2762  }
2763  }
2764 
2765  // determine currents using normal exponential
2766  else
2767  {
2768  if (vBE > -5.0 * vtF)
2769  {
2770  double arg1 = vBE / vtF ;
2771  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2772  double devBE;
2773  double evBE;
2774  if (getSolverState().bjtArtParameterFlag)
2775  {
2776  evBE = devSupport.Xexp( arg1 , devBE, getDeviceOptions().exp_order );
2777  }
2778  else
2779  {
2780  evBE = exp( arg1 );
2781  devBE=evBE;
2782  }
2783  iBE = csat * ( evBE - 1.0 ) + getDeviceOptions().gmin * vBE;
2784  gBE = csat * devBE / vtF + getDeviceOptions().gmin;
2785 
2786  if (iLeakBE == 0.0)
2787  iBEleak = gBEleak = 0.0;
2788  else
2789  {
2790  double arg1 = vBE / vtE ;
2791  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2792  double devBEleak;
2793  double evBEleak;
2794  if (getSolverState().bjtArtParameterFlag)
2795  {
2796  evBEleak =devSupport.Xexp(arg1,devBEleak,getDeviceOptions().exp_order );
2797  }
2798  else
2799  {
2800  evBEleak = exp(arg1);
2801  devBEleak=evBEleak;
2802  }
2803  iBEleak = iLeakBE * (evBEleak - 1.0);
2804  gBEleak = iLeakBE * devBEleak / vtE;
2805  }
2806  }
2807  else
2808  {
2809  gBE = -csat / vBE + getDeviceOptions().gmin;
2810  iBE = gBE * vBE;
2811  gBEleak = -iLeakBE / vBE;
2812  iBEleak = gBEleak * vBE;
2813  }
2814 
2815  if( vBC > -5.0 * vtR )
2816  {
2817  double arg1 = vBC / vtR ;
2818  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2819  double devBC;
2820  double evBC;
2821  if (getSolverState().bjtArtParameterFlag)
2822  {
2823  evBC = devSupport.Xexp( arg1 , devBC, getDeviceOptions().exp_order );
2824  }
2825  else
2826  {
2827  evBC = exp( arg1 );
2828  devBC=evBC;
2829  }
2830  iBC = csat * ( evBC - 1.0 ) + getDeviceOptions().gmin * vBC;
2831  gBC = csat * devBC / vtR + getDeviceOptions().gmin;
2832 
2833  if (iLeakBC == 0.0)
2834  iBCleak = gBCleak = 0.0;
2835  else
2836  {
2837  double arg1 = vBC / vtC ;
2838  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2839  double devBCleak;
2840  double evBCleak;
2841  if (getSolverState().bjtArtParameterFlag)
2842  {
2843  evBCleak= devSupport.Xexp(arg1,devBCleak,getDeviceOptions().exp_order);
2844  }
2845  else
2846  {
2847  evBCleak = exp(arg1);
2848  devBCleak=evBCleak;
2849  }
2850  iBCleak = iLeakBC * (evBCleak - 1.0);
2851  gBCleak = iLeakBC * devBCleak / vtC;
2852  }
2853  }
2854  else
2855  {
2856  gBC = -csat / vBC + getDeviceOptions().gmin;
2857  iBC = gBC * vBC;
2858  gBCleak = -iLeakBC / vBC;
2859  iBCleak = gBCleak * vBC;
2860  }
2861  }
2862 
2863  // base charge calculations:
2864  double rofF = tInvRollOffF / AREA;
2865  double rofR = tInvRollOffR / AREA;
2866 
2867  q1 = 1.0 / ( 1.0 - tInvEarlyVoltF * vBC - tInvEarlyVoltR * vBE );
2868 
2869  if (rofF == 0.0 && rofR == 0.0)
2870  {
2871  qB = q1;
2872  double q1_qB = q1 * qB;
2873 
2874  dqBdvEp = q1_qB * tInvEarlyVoltR;
2875  dqBdvCp = q1_qB * tInvEarlyVoltF;
2876 /* replaced with simpler expression after if block
2877  dqBdvBp = -q1_qB * (model_.invEarlyVoltR + model_.invEarlyVoltF);
2878 */
2879  }
2880  else
2881  {
2882  q2 = rofF * iBE + rofR * iBC;
2883 
2884  // Difference from SPICE: spice puts a max(0,) around the arg definition,
2885  // which means we use the square root expression all the way down to
2886  // q2= -1/4. This is not really good, because it means that the derivative
2887  // of the square root term goes to negative infinity at the break point
2888  // between the expressions, and qB will be very discontinuous.
2889  // This doesn't have a huge effect on the solutions, but can possibly
2890  // lead to convergence issues (see bug 1214). This fix hasn't yet
2891  // been shown to help anything, but it has not hurt anything either.
2892  if (q2 >= 0)
2893  {
2894 
2895  double arg = 1.0 + 4.0 * q2;
2896  double sqarg = 1.0;
2897 
2898  // if (fabs(arg) > 0.0) sqarg = sqrt(arg);
2899  // double rofF_gBE_invSqarg = rofF * gBE / sqarg;
2900  // double rofR_gBC_invSqarg = rofR * gBC / sqarg;
2901  // add Pspice compatible rolloff parameter NK = tRollOffExp
2902 
2903  if (fabs(arg) > 0.0) sqarg = pow(arg,tRollOffExp);
2904  double rofF_gBE_invSqarg = 0.0;
2905  double rofR_gBC_invSqarg = 0.0;
2906  if(arg != 0) rofF_gBE_invSqarg = rofF*gBE*2*tRollOffExp*sqarg/arg;
2907  if(arg != 0) rofR_gBC_invSqarg = rofR*gBC*2*tRollOffExp*sqarg/arg;
2908 
2909  qB = 0.5 * q1 * (1.0 + sqarg);
2910 
2911  dqBdvEp = q1 * (qB * tInvEarlyVoltR + rofF_gBE_invSqarg);
2912  dqBdvCp = q1 * (qB * tInvEarlyVoltF + rofR_gBC_invSqarg);
2913 
2914  /* replaced with simpler expression after if block
2915  dqBdvBp = -q1 * (qB * ( model_.invEarlyVoltF + model_.invEarlyVoltR) +
2916  rofF_gBE_invSqarg + rofR_gBC_invSqarg);
2917  */
2918  }
2919  else
2920  {
2921  qB = q1;
2922  dqBdvEp = q1*qB*tInvEarlyVoltR;
2923  dqBdvCp = q1*qB*tInvEarlyVoltF;
2924  }
2925  }
2926  dqBdvBp = - (dqBdvEp + dqBdvCp);
2927 
2928  invqB = 1.0 / qB;
2929 
2930 
2931  // NOTE: this is a block that (for some reason) was originally in the
2932  // updatePrimaryState function. It got moved as in general, the "state"
2933  // functions are only for manipulating the state vector.
2934  // NOTE: brackets are around this block of code to preserve variable scope.
2935 
2936  double arg, sarg;
2937  double ctot;
2938  double czBC;
2939  double czBX;
2940  double czBE;
2941  double czCS;
2942  double fcpc;
2943  double fcpe;
2944 
2945  // capacitance calculations and "current" charge value calculations:
2946  ctot = tBCCap * AREA;
2947  czBC = ctot * model_.baseFracBCCap;
2948  czBX = ctot - czBC;
2949  czBE = tBECap * AREA;
2950  czCS = model_.CJS * AREA;
2951  fcpc = model_.depCapCoeff * model_.potBC;
2952  fcpe = tDepCap;
2953 
2954  // High current perturbation to BE current
2955  // The high current perturbation to the BE current is only
2956  // used in determining capacitance values. It does not enter
2957  // directly into the RHS KCL equations, or the Jacobian.
2958  iBEhighCurr = iBE;
2959  gBEhighCurr = gBE;
2960 
2961  // geqCB is only calculated sometimes (based on the if-statement).
2962  // If it is not calculated, then the value used will be the one from
2963  // the state vector, that was pulled out already.
2964  bool geqCB_recalc(false);
2965  if (model_.transTimeF != 0.0 && vBE > 0.0 &&
2966  ((!getSolverState().dcopFlag)||getSolverState().tranopFlag||getSolverState().acopFlag))
2967  {
2968  double argtf = 0.0;
2969  double arg2 = 0.0;
2970  double arg3 = 0.0;
2971 
2972  if ( model_.transTimeBiasCoeffF != 0.0)
2973  {
2974  argtf = model_.transTimeBiasCoeffF;
2975 
2976  if (model_.transTimeVBCFac != 0.0)
2977  argtf *= exp(vBC * model_.transTimeVBCFac);
2978 
2979  arg2 = argtf;
2980 
2981  if (model_.transTimeHighCurrF != 0.0)
2982  {
2983  double tmp = iBEhighCurr /
2985 
2986  argtf *= tmp * tmp;
2987  arg2 = argtf * (3.0 - 2.0 * tmp);
2988  }
2989  arg3 = iBEhighCurr * argtf * model_.transTimeVBCFac;
2990  }
2991 
2992  iBEhighCurr *= (1.0 + argtf) / qB;
2993  gBEhighCurr = (gBEhighCurr * (1.0 + arg2) - iBEhighCurr * dqBdvEp) / qB;
2994 
2995  capeqCB = model_.transTimeF * (arg3 - iBEhighCurr * dqBdvCp) / qB;
2997  geqCB_recalc = true;
2998  }
2999 
3000  // baseP-emitP depletion capacitance
3001  if( czBE == 0.0 )
3002  {
3003  qBEdep = 0.0;
3004  capBEdep = 0.0;
3005  }
3006  else
3007  {
3008  if ( vBE < fcpe )
3009  {
3010  arg = 1.0 - vBE / tBEPot;
3011  sarg = exp( -model_.juncExpBE * log( arg ) );
3012 
3013  qBEdep = tBEPot * czBE * ( 1.0 - arg * sarg ) /
3014  ( 1.0 - model_.juncExpBE );
3015  capBEdep = czBE * sarg;
3016  }
3017  else
3018  {
3019  double czBEf2 = czBE / model_.f2;
3020 
3021  qBEdep = czBE * tF1 + czBEf2 * ( model_.f3 * ( vBE -
3022  fcpe ) + ( model_.juncExpBE / ( 2.0 *
3023  tBEPot ) ) * ( vBE * vBE - fcpe * fcpe ) );
3024  capBEdep = czBEf2 * ( model_.f3 + model_.juncExpBE * vBE /
3025  tBEPot );
3026  }
3027  }
3028 
3029  // baseP-emitP diffusion capacitance
3030  if (model_.transTimeF == 0.0)
3031  {
3032  qBEdiff = capBEdiff = 0.0;
3033  }
3034  else
3035  {
3038  }
3039 
3040  // baseP-collP depletion capacitance
3041  if( czBC == 0.0 )
3042  {
3043  qBCdep = 0.0;
3044  capBCdep = 0.0;
3045  }
3046  else
3047  {
3048  if ( vBC < fcpc )
3049  {
3050  arg = 1.0 - vBC / tBCPot;
3051  sarg = exp( -model_.juncExpBC * log( arg ) );
3052 
3053  qBCdep = tBCPot * czBC * ( 1.0 - arg * sarg ) /
3054  ( 1.0 - model_.juncExpBC );
3055  capBCdep = czBC * sarg;
3056  }
3057  else
3058  {
3059  double czBCf2 = czBC / model_.f6;
3060 
3061  qBCdep = czBC * tF5 + czBCf2 * ( model_.f7 * ( vBC -
3062  fcpc ) + ( model_.juncExpBC / ( 2.0 *
3063  tBCPot ) ) * ( vBC * vBC - fcpc * fcpc ) );
3064  capBCdep = czBCf2 * ( model_.f7 + model_.juncExpBC * vBC / tBCPot );
3065  }
3066  }
3067 
3068  // baseP-collP diffusion capacitance
3069  if (model_.transTimeR == 0.0)
3070  {
3071  qBCdiff = capBCdiff = 0.0;
3072  }
3073  else
3074  {
3077  }
3078 
3079  // base-collP depletion capacitance
3080  if( czBX == 0.0 )
3081  {
3082  qBX = 0.0;
3083  capBX = 0.0;
3084  }
3085  else
3086  {
3087  if (vBX < fcpc)
3088  {
3089  arg = 1.0 - vBX / tBCPot;
3090  sarg = exp( -model_.juncExpBC * log( arg ) );
3091 
3092  qBX = tBCPot * czBX * ( 1.0 - arg * sarg ) /
3093  ( 1.0 - model_.juncExpBC );
3094  capBX = czBX * sarg;
3095  }
3096  else
3097  {
3098  double czBXf2 = czBX / model_.f6;
3099 
3100  qBX = czBX * tF5 + czBXf2 * ( model_.f7 * ( vBX -
3101  fcpc ) + ( model_.juncExpBC / ( 2.0 *
3102  tBCPot ) ) * ( vBX * vBX - fcpc * fcpc ) );
3103  capBX = czBXf2 * ( model_.f7 + model_.juncExpBC * vBX /
3104  tBCPot );
3105  }
3106  }
3107 
3108  // collP-subst depletion capacitance
3109  if( czCS == 0.0 )
3110  {
3111  qCS = 0.0;
3112  capCS = 0.0;
3113  }
3114  else
3115  {
3116  if ( vCS < 0.0 )
3117  {
3118  arg = 1.0 - vCS / model_.potSubst;
3119  sarg = exp( -model_.expSubst * log( arg ) );
3120 
3121  qCS = model_.potSubst * czCS * ( 1.0 - arg * sarg ) /
3122  ( 1.0 - model_.expSubst );
3123  capCS = czCS * sarg;
3124  }
3125  else
3126  {
3127  qCS = vCS * czCS * ( 1.0 + model_.expSubst * vCS / ( 2.0 *
3128  model_.potSubst ) );
3129  capCS = czCS * ( 1.0 + model_.expSubst * vCS / model_.potSubst );
3130  }
3131  }
3132 
3133  // Here things get a little confusing. Generally, this is a logical place
3134  // to calculate iB, iC, and iE. iC and iE include the excess phase current.
3135 
3136  // Doing the old excess phase calculation, for both new and old-DAE, out
3137  // of curiousity to see that they match. However, if running new-DAE, these
3138  // calculations will only be used in diagnostics, not the actual loads.
3139  double iEX_tmp = 0.0; double gEX_tmp = 0.0; double iC_tmp = 0.0;
3141  oldDAEExcessPhaseCalculation2 (iEX_tmp,gEX_tmp,iC_tmp);
3142 
3143  if (getDeviceOptions().newExcessPhase)
3144  {
3145  auxDAECalculations (); // iB, iC and iE calculated here.
3146 
3147  }
3148  else
3149  {
3150  if (!(getSolverState().dcopFlag))
3151  {
3152  double pdt = getSolverState().pdt;
3153 
3154  // ERK. 12/17/2006.
3155  // It is necessary to set pdt=0.0, because for the first time step out of
3156  // the DCOP, all the time derivatives are forced to be zero. Thus, all
3157  // their derivatives should also be zero. If it wasn't for that, then pdt
3158  // could always be pdt. (it used to be, before the -jacobian_test capability).
3159  if (getSolverState().initTranFlag && getSolverState().newtonIter==0)
3160  {
3161  pdt = 0.0;
3162  }
3163 
3164  gCapBEdiff = capBEdiff * pdt;
3165  gCapBEdep = capBEdep * pdt;
3166  gCapBCdiff = capBCdiff * pdt;
3167  gCapBCdep = capBCdep * pdt;
3168  gCapBX = capBX * pdt;
3169  gCapCS = capCS * pdt;
3170  }
3171  else
3172  {
3173  gCapBEdiff = 0.0;
3174  gCapBEdep = 0.0;
3175  gCapBCdiff = 0.0;
3176  gCapBCdep = 0.0;
3177  gCapBX = 0.0;
3178  gCapCS = 0.0;
3179  }
3180 
3181  // Do the iB, iC, and iE calculations for the old-DAE case here.
3182  double iEX = 0.0;
3183  double gEX = 0.0;
3184 
3185  iC = iC_tmp;
3186  iEX = iEX_tmp;
3187  gEX = gEX_tmp;
3188 
3189  iCE = ( iEX - iBC ) / qB;
3190  iC += iCE - iBC / tBetaR - iBCleak;
3191 
3192  iB = iBE / tBetaF + iBEleak + iBC / tBetaR + iBCleak;
3193  iE = -iC-iB;
3194 
3195  // These 3 derivatives depend upon excess phase terms, old-DAE version, so
3196  // they have to be set up here.
3197  diCEdvEp = invqB * (iCE * dqBdvEp - gEX);
3198  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
3199  diCEdvBp = invqB * (iCE * dqBdvBp + gEX - gBC);
3200 
3201  }
3202 
3203  // Some derivatives setup:
3204  // Emitter and Conductor conductances
3207 
3208  // Generation of gX for b-b' resistance
3209  double rBpr = model_.minBaseResist / AREA;
3210  double rBpi = model_.baseResist / AREA - rBpr;
3211  double xjrB = model_.baseCurrHalfResist * AREA;
3212 
3213  gX = rBpr + rBpi / qB;
3214 
3215  if (fabs(xjrB) > 0.0)
3216  {
3217  double arg1 = Xycemax(iB / xjrB, 1.0e-09);
3218  double arg2 = (-1.0 + sqrt( 1.0 + 14.59025 * arg1)) / 2.4317 / sqrt(arg1);
3219  arg1 = tan(arg2);
3220  gX = rBpr + 3.0 * rBpi * (arg1 - arg2) / arg2 / arg1 / arg1;
3221  }
3222 
3223  if (fabs(gX) > 0.0) gX = 1.0 / gX;
3224 
3225  diBrdvB = gX;
3226  diBrdvCp = 0.0;
3227  diBrdvEp = 0.0;
3228  diBrdvBp = -gX;
3229 
3230  gBEtot = gBE / tBetaF + gBEleak;
3231  gBCtot = gBC / tBetaR + gBCleak;
3232 
3233  return bsuccess;
3234 }
3235 
3236 //-----------------------------------------------------------------------------
3237 // Function : Instance::outputPlotFiles
3238 // Purpose :
3239 // Special Notes :
3240 // Scope : public
3241 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3242 // Creation Date : 9/01/06
3243 //-----------------------------------------------------------------------------
3245 {
3246  bool bsuccess = true;
3247 
3248  int i;
3249  char filename[32]; for(i=0;i<32;++i) filename[i] = static_cast<char>(0);
3250 
3251  sprintf(filename,"Q_%s.dat",getName().c_str());
3252 
3253  double time = getSolverState().currTime;
3254  FILE *fp1;
3255 
3256  if (callsOutputPlot <= 0)
3257  {
3258  fp1 = fopen(filename,"w");
3259  }
3260  else
3261  {
3262  fp1 = fopen(filename,"a");
3263  }
3264 
3265  if (callsOutputPlot <= 0)
3266  {
3267  fprintf(fp1,
3268  " TITLE = \"Debug Excess Phase data: %s \"\n", getName().c_str());
3269  }
3270 
3271  if (callsOutputPlot <= 0)
3272  {
3273  fprintf(fp1,"%s","\tVARIABLES = \"TIME (S)\",\n");
3274 
3275  fprintf(fp1,"%s","\t \"iBE/qB \",\n");
3276  fprintf(fp1,"%s","\t \"currCexbc \",\n");
3277  fprintf(fp1,"%s","\t \"lastCexbc \",\n");
3278  if (getDeviceOptions().newExcessPhase)
3279  {
3280  fprintf(fp1,"%s","\t \"i_fx \",\n");
3281  fprintf(fp1,"%s","\t \"di_fx \",\n");
3282  }
3283 
3284  fprintf(fp1,"%s","\tZONE F=POINT T=\"Excess Phase Data\"\n");
3285  }
3286 
3287  fprintf(fp1," %12.4e",time);
3288  fprintf(fp1," %12.4e",(iBE/qB));
3289  fprintf(fp1," %12.4e",currCexbc);
3290  fprintf(fp1," %12.4e",nextCexbc);
3291 
3292  if (getDeviceOptions().newExcessPhase)
3293  {
3294  double * solVec = extData.nextSolVectorRawPtr;
3295  double i_fx = solVec[li_Ifx];
3296  double di_fx = solVec[li_dIfx];
3297  fprintf(fp1," %12.4e",i_fx);
3298  fprintf(fp1," %12.4e",di_fx);
3299  }
3300 
3301  fprintf(fp1,"%s","\n");
3302 
3303  ++callsOutputPlot;
3304  fclose(fp1);
3305 
3306  return bsuccess;
3307 }
3308 
3309 //-----------------------------------------------------------------------------
3310 // Function : Model::processParams
3311 // Purpose :
3312 // Special Notes :
3313 // Scope : public
3314 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3315 // Creation Date : 6/03/02
3316 //-----------------------------------------------------------------------------
3318 {
3319 
3320  if (!leakBECurrentGiven && c2Given)
3321  leakBECurrent = c2 * satCur;
3322 
3323  if (!leakBCCurrentGiven && c4Given)
3324  leakBCCurrent = c4 * satCur;
3325 
3326  if (!minBaseResistGiven)
3328 
3329  if (VAFgiven && ( earlyVoltF != 0.0 ) )
3330  invEarlyVoltF = 1.0 / earlyVoltF;
3331  else
3332  invEarlyVoltF = 0.0;
3333 
3334  if( IKFgiven && ( rollOffF != 0.0 ) )
3335  invRollOffF = 1.0 / rollOffF;
3336  else
3337  invRollOffF = 0.0;
3338 
3339  if( VARgiven && ( earlyVoltR != 0.0 ) )
3340  invEarlyVoltR = 1.0 / earlyVoltR;
3341  else
3342  invEarlyVoltR = 0.0;
3343 
3344  if( IKRgiven && ( rollOffR != 0.0 ) )
3345  invRollOffR = 1.0 / rollOffR;
3346  else
3347  invRollOffR = 0.0;
3348 
3349  if( collectorResist != 0.0 )
3351  else
3352  collectorConduct = 0;
3353 
3354  if( emitterResist != 0.0 )
3355  emitterConduct = 1.0 / emitterResist;
3356  else
3357  emitterConduct = 0;
3358 
3359  if( given("VTF") && ( transTimeFVBC != 0.0 ) )
3360  transTimeVBCFac = 1.0 / ( transTimeFVBC * 1.44 );
3361  else
3362  transTimeVBCFac = 0.0;
3363 
3364  double mpi = M_PI;
3365  excessPhaseFac = ( excessPhase / ( 180.0 / mpi ) ) * transTimeF;
3366 
3367  if( given("FC") )
3368  {
3369  if( depCapCoeff > 0.9999 )
3370  {
3371  depCapCoeff = 0.9999;
3372  Xyce::dout() << "Bad Depletion Capacitance Coefficient" << std::endl;
3373  }
3374  }
3375  else
3376  {
3377  depCapCoeff = 0.5;
3378  }
3379 
3380  double xfc = log( 1.0 - depCapCoeff );
3381 
3382  f2 = exp( ( 1.0 + juncExpBE ) * xfc );
3383  f3 = 1.0 - depCapCoeff * ( 1.0 + juncExpBE );
3384  f6 = exp( ( 1.0 + juncExpBC ) * xfc );
3385  f7 = 1.0 - depCapCoeff * ( 1.0 + juncExpBC );
3386 
3387  return true;
3388 }
3389 
3390 //----------------------------------------------------------------------------
3391 // Function : Model::processInstanceParams
3392 // Purpose :
3393 // Special Notes :
3394 // Scope : public
3395 // Creator : Dave Shirely, PSSI
3396 // Creation Date : 03/23/06
3397 //----------------------------------------------------------------------------
3399 {
3400 
3401  std::vector<Instance*>::iterator iter;
3402  std::vector<Instance*>::iterator first = instanceContainer.begin();
3403  std::vector<Instance*>::iterator last = instanceContainer.end();
3404 
3405  for (iter=first; iter!=last; ++iter)
3406  {
3407  (*iter)->processParams();
3408  }
3409 
3410  return true;
3411 }
3412 
3413 //-----------------------------------------------------------------------------
3414 // Function : Model::Model
3415 // Purpose : modelblock constructor
3416 // Special Notes :
3417 // Scope : public
3418 // Creator : Laura Boucheron
3419 // Creation Date : 7/12/00
3420 //-----------------------------------------------------------------------------
3422  const Configuration & configuration,
3423  const ModelBlock & MB,
3424  const FactoryBlock & factory_block)
3425  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
3426  TYPE(1),
3427  TNOM(300.0),
3428  satCur(1.0e-16),
3429  betaF(100.0),
3430  BFgiven(false),
3431  BFMgiven(false),
3432  emissionCoeffF(1.0),
3433  earlyVoltF(1e99),
3434  VAgiven(false),
3435  VAFgiven(false),
3436  VBFgiven(false),
3437  rollOffF(1e99),
3438  IKFgiven(false),
3439  IKgiven(false),
3440  JBFgiven(false),
3441  leakBECurrent(0.0),
3442  leakBEEmissionCoeff(1.5),
3443  NEgiven(false),
3444  NLEgiven(false),
3445  betaR(1.0),
3446  BRgiven(false),
3447  BRMgiven(false),
3448  emissionCoeffR(1.0),
3449  earlyVoltR(1e99),
3450  VARgiven(false),
3451  VBgiven(false),
3452  VRBgiven(false),
3453  BVgiven(false),
3454  rollOffR(1e99),
3455  IKRgiven(false),
3456  JBRgiven(false),
3457 
3458  leakBCCurrent(0.0),
3459  leakBCEmissionCoeff(2.0),
3460  baseResist(0.0),
3461  baseCurrHalfResist(0.0),
3462  IRBgiven(false),
3463  JRBgiven(false),
3464  IOBgiven(false),
3465  minBaseResist(baseResist),
3466  emitterResist(0.0),
3467  collectorResist(0.0),
3468  depCapBE(0.0),
3469  potBE(0.75),
3470  VJEgiven(false),
3471  PEgiven(false),
3472 
3473  juncExpBE(0.33),
3474  MJEgiven(false),
3475  MEgiven(false),
3476 
3477  transTimeF(0.0),
3478  transTimeBiasCoeffF(0.0),
3479  transTimeFVBC(1.e99),
3480  transTimeHighCurrF(0.0),
3481  ITFgiven(false),
3482  JTFgiven(false),
3483 
3484  excessPhase(0.0),
3485  depCapBC(0.0),
3486  potBC(0.75),
3487  VJCgiven(false),
3488  PCgiven(false),
3489 
3490  juncExpBC(0.33),
3491  MJCgiven(false),
3492  MCgiven(false),
3493 
3494  baseFracBCCap(1.0),
3495  XCJCgiven(false),
3496  CDISgiven(false),
3497  transTimeR(0.0),
3498  CJS(0.0),
3499  CJSgiven(false),
3500  CCSgiven(false),
3501  CSUBgiven(false),
3502  potSubst(0.75),
3503  VJSgiven(false),
3504  PSgiven(false),
3505  PSUBgiven(false),
3506 
3507  expSubst(0.0),
3508  MJSgiven(false),
3509  MSgiven(false),
3510  ESUBgiven(false),
3511 
3512  betaExp(0.0),
3513  XTBgiven(false),
3514  TBgiven(false),
3515  TCBgiven(false),
3516 
3517  energyGap(1.11),
3518  tempExpIS(3.0),
3519  XTIgiven(false),
3520  PTgiven(false),
3521 
3522  depCapCoeff(0.5),
3523  fNCoeff(0.0),
3524  fNExp(1.0),
3525  c2(0.0),
3526  c4(0.0),
3527  rollOffExp(0.5),
3528  NKgiven(false),
3529  NKFgiven(false),
3530 
3531  leakBCCurrentGiven(false),
3532  JLCgiven(false),
3533  leakBECurrentGiven(false),
3534  JLEgiven(false),
3535  minBaseResistGiven(false),
3536  c2Given(false),
3537  c4Given(false)
3538 {
3539  // Default value is type=1 (NPN) so only check for pnp
3540  if (getType() == "pnp" || getType() == "PNP")
3541  {
3542  TYPE = -1;
3543  }
3544 
3545  ////////////////////////////////////////////////////////////////////////////////
3546  // trap for redunantly specified parameters (some can be specified by several different names)
3547  // forward beta (BF/BFM)
3548  if (BFgiven && BFMgiven)
3549  {
3550  UserError0(*this) << "Both BF and BFM are set, which is redundant.";
3551  }
3552  if (BFgiven || BFMgiven)
3553  {
3554  BFgiven = true; // this is the given flag that is actually used later.
3555  }
3556 
3557  // reverse beta (Re/BRM)
3558  if (BRgiven && BRMgiven)
3559  {
3560  UserError0(*this) << "Both BR and BRM are set, which is redundant.";
3561  }
3562  if (BRgiven || BRMgiven)
3563  {
3564  BRgiven = true; // this is the given flag that is actually used later.
3565  }
3566 
3567  // forward early voltage (VA/VAF/VBF)
3568  int VAFgivenCount = 0;
3569  VAFgivenCount += VAgiven?1:0;
3570  VAFgivenCount += VAFgiven?1:0;
3571  VAFgivenCount += VBFgiven?1:0;
3572  if (VAFgivenCount > 1)
3573  {
3574  UserError0(*this) << "The forward early voltage is set more than once. VA, VAF and VBF are aliases.";
3575  }
3576  if (VAFgivenCount > 0)
3577  {
3578  VAFgiven = true; // this is the given flag that is actually used later.
3579  }
3580 
3581  // reverse early voltage (VAR/VB/VRB/BV)
3582  int VARgivenCount = 0;
3583  VARgivenCount += VARgiven?1:0;
3584  VARgivenCount += VRBgiven?1:0;
3585  VARgivenCount += VBgiven?1:0;
3586  VARgivenCount += BVgiven?1:0;
3587  if (VARgivenCount > 1)
3588  {
3589  UserError0(*this) << "The reverse early voltage is set more than once. VAR,VB,VRB and BV are aliases.";
3590  }
3591  if (VARgivenCount > 0)
3592  {
3593  VARgiven = true; // this is the given flag that is actually used later.
3594  }
3595 
3596  // high current roll-off (IKF/IK/JBF)
3597  int IKFgivenCount = 0;
3598  IKFgivenCount += IKgiven?1:0;
3599  IKFgivenCount += IKFgiven?1:0;
3600  IKFgivenCount += JBFgiven?1:0;
3601  if (IKFgivenCount > 1)
3602  {
3603  UserError0(*this) << "High current roll-off is set more than once (IKF, JBF or IK).";
3604  }
3605  if (IKFgivenCount > 0)
3606  {
3607  IKFgiven = true; // this is the given flag that is actually used later.
3608  }
3609 
3610  // reverse high current roll-off (IKR/JBR)
3611  if (IKRgiven && JBRgiven)
3612  {
3613  UserError0(*this) << "Both IKR and JBRgiven are set, which is redundant.";
3614  }
3615  if (IKRgiven || JBRgiven)
3616  {
3617  IKRgiven = true; // this is the flag actually used later.
3618  }
3619 
3620  // BE leakage saturation current (ISE/JLE). C2 is sometimes thougt of as equivalent,
3621  // but it is not.
3623  {
3624  UserError0(*this) << "Both JLE and ISE are set, which is redundant.";
3625  }
3627  {
3628  leakBECurrentGiven = true; // this is the flag actually used later.
3629  }
3630 
3631  // BC leakage saturation current (ISC/JLC). C4 is sometimes thougt of as equivalent,
3632  // but it is not.
3634  {
3635  UserError0(*this) << "Both JLC and ISC are set, which is redundant.";
3636  }
3638  {
3639  leakBCCurrentGiven = true; // this is the flag actually used later.
3640  }
3641 
3642  // leakage emission coefficient (NE/NLE)
3643  if (NLEgiven && NEgiven)
3644  {
3645  UserError0(*this) << "Both NLE and NE are set, which is redundant.";
3646  }
3647  if (NLEgiven || NEgiven)
3648  {
3649  NEgiven = true; // this is the flag actually used later.
3650  }
3651 
3652  // BE exponential factor (MJE/ME)
3653  if (MJEgiven && MEgiven)
3654  {
3655  UserError0(*this) << " Both MJE and ME are set, which is redundant.";
3656  }
3657  if (MJEgiven || MEgiven)
3658  {
3659  MJEgiven = true; // this is the flag actually used later.
3660  }
3661 
3662  // BC exponential factor (MJC/MC)
3663  if (MJCgiven && MCgiven)
3664  {
3665  UserError0(*this) << "Both MJC and MC are set, which is redundant.";
3666  }
3667  if (MJCgiven || MCgiven)
3668  {
3669  MJCgiven = true; // this is the flag actually used later.
3670  }
3671 
3672  // zero-bias coll-subst capacitance (CJS/CCS/CSUB)
3673  int CJSgivenCount = 0;
3674  CJSgivenCount += CJSgiven?1:0;
3675  CJSgivenCount += CCSgiven?1:0;
3676  CJSgivenCount += CSUBgiven?1:0;
3677  if (CJSgivenCount > 1)
3678  {
3679  UserError0(*this) << "The zero-bias collector-substrate capacitance (CJS, CCS or CSUB) is set more than once.";
3680  }
3681  if (CJSgivenCount > 0)
3682  {
3683  CJSgiven = true; // this is the given flag that is actually used later.
3684  }
3685 
3686  // current for 1/2 base resist. (IRB/JRB/IOB)
3687  int IRBgivenCount = 0;
3688  IRBgivenCount += IRBgiven?1:0;
3689  IRBgivenCount += JRBgiven?1:0;
3690  IRBgivenCount += IOBgiven?1:0;
3691  if (IRBgivenCount > 1)
3692  {
3693  UserError0(*this) << "The current for 1/2 base resistance (IRB, JRB or IOB) is set more than once.";
3694  }
3695  if (IRBgivenCount > 0)
3696  {
3697  IRBgiven = true; // this is the given flag that is actually used later.
3698  }
3699 
3700  // BE built-in potential (VJE/PE)
3701  if (VJEgiven && PEgiven)
3702  {
3703  UserError0(*this) << "The BE built-in potential (VJE or PE) is set more than once.";
3704  }
3705  if (VJEgiven && PEgiven)
3706  {
3707  VJEgiven = true; // this is the given flag that is actually used later.
3708  }
3709 
3710  // BC built-in potential (VJC/PC)
3711  if (VJCgiven && PCgiven)
3712  {
3713  UserError0(*this) << "The BC built-in potential (VJC or PC) is set more than once.";
3714  }
3715  if (VJCgiven && PCgiven)
3716  {
3717  VJCgiven = true; // this is the given flag that is actually used later.
3718  }
3719 
3720  // fraction of BC capacitance to int. base node (XCJC/CDIS)
3721  if (XCJCgiven && CDISgiven)
3722  {
3723  UserError0(*this) << "XCJC and CDIS are both set (they are aliases).";
3724  }
3725  if (XCJCgiven && CDISgiven)
3726  {
3727  XCJCgiven = true; // this is the given flag that is actually used later.
3728  }
3729 
3730  // substrate junction built-in potential (VJS/PS/PSUB)
3731  int VJSgivenCount = 0;
3732  VJSgivenCount += PSgiven?1:0;
3733  VJSgivenCount += VJSgiven?1:0;
3734  VJSgivenCount += PSUBgiven?1:0;
3735  if (VJSgivenCount > 1)
3736  {
3737  UserError0(*this) << "The forward early voltage is set more than once. PS, VJS and PSUB are aliases.";
3738  }
3739  if (VJSgivenCount > 0)
3740  {
3741  VJSgiven = true; // this is the given flag that is actually used later.
3742  }
3743 
3744  // substrate junction built-in potential (MJS/MS/ESUB)
3745  int MJSgivenCount = 0;
3746  MJSgivenCount += MSgiven?1:0;
3747  MJSgivenCount += MJSgiven?1:0;
3748  MJSgivenCount += ESUBgiven?1:0;
3749  if (MJSgivenCount > 1)
3750  {
3751  UserError0(*this) << "The forward early voltage is set more than once. MS, MJS and ESUB are aliases.";
3752  }
3753  if (MJSgivenCount > 0)
3754  {
3755  MJSgiven = true; // this is the given flag that is actually used later.
3756  }
3757 
3758  // (ITF/JTF)
3759  if (ITFgiven && JTFgiven)
3760  {
3761  UserError0(*this) << "ITF and JTF are both set (they are aliases).";
3762  }
3763  if (ITFgiven && JTFgiven)
3764  {
3765  ITFgiven = true; // this is the given flag that is actually used later.
3766  }
3767 
3768  // (NK/NKF)
3769  if (NKgiven && NKFgiven)
3770  {
3771  UserError0(*this) << "NK and NKF are both set (they are aliases).";
3772  }
3773  if (NKgiven && NKFgiven)
3774  {
3775  NKgiven = true; // this is the given flag that is actually used later.
3776  }
3777 
3778  // beta temperature exponent (XTB/TB/TCB)
3779  int XTBgivenCount = 0;
3780  XTBgivenCount += TBgiven?1:0;
3781  XTBgivenCount += XTBgiven?1:0;
3782  XTBgivenCount += TCBgiven?1:0;
3783  if (XTBgivenCount > 1)
3784  {
3785  UserError0(*this) << "The forward early voltage is set more than once. TB, XTB and TCB are aliases.";
3786  }
3787  if (XTBgivenCount > 0)
3788  {
3789  XTBgiven = true; // this is the given flag that is actually used later.
3790  }
3791 
3792 
3793  // (PT/XTI)
3794  if (PTgiven && XTIgiven)
3795  {
3796  UserError0(*this) << "PT and XTI are both set (they are aliases).";
3797  }
3798  if (PTgiven && XTIgiven)
3799  {
3800  XTIgiven = true; // this is the given flag that is actually used later.
3801  }
3802 
3803  // end of redundant parameter traps
3804  ////////////////////////////////////////////////////////////////////////////////
3805 
3806 
3807  // Set params to constant default values:
3808  setDefaultParams ();
3809 
3810  // Set params according to .model line and constant defaults from metadata:
3811  setModParams (MB.params);
3812 
3813  // Set any non-constant parameter defaults:
3814  if (!given("TNOM"))
3816 
3817  if( !NKgiven)
3818  rollOffExp = 0.5;
3819 
3820  // Calculate any parameters specified as expressions:
3822 
3823  // calculate dependent (ie computed) params and check for errors:
3824  processParams ();
3825 }
3826 
3827 //-----------------------------------------------------------------------------
3828 // Function : Model::~Model
3829 // Purpose : destructor
3830 // Special Notes :
3831 // Scope : public
3832 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3833 // Creation Date : 3/16/00
3834 //-----------------------------------------------------------------------------
3836 {
3837  std::vector<Instance*>::iterator iterI;
3838  std::vector<Instance*>::iterator firstI = instanceContainer.begin ();
3839  std::vector<Instance*>::iterator lastI = instanceContainer.end ();
3840 
3841  // loop over instances:
3842  for (iterI = firstI; iterI != lastI; ++iterI)
3843  {
3844  delete (*iterI);
3845  }
3846 
3847 }
3848 
3849 //-----------------------------------------------------------------------------
3850 // Function : Model::printOutInstances
3851 // Purpose : debugging tool.
3852 // Special Notes :
3853 // Scope : public
3854 // Creator : Laura Boucheron
3855 // Creation Date : 7/11/00
3856 //-----------------------------------------------------------------------------
3857 std::ostream &Model::printOutInstances(std::ostream &os) const
3858 {
3859  std::vector<Instance*>::const_iterator iter;
3860  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
3861  std::vector<Instance*>::const_iterator last = instanceContainer.end();
3862 
3863  int i;
3864  os << " name modelName Parameters" << std::endl;
3865  for (i = 0, iter = first; iter != last; ++iter, ++i)
3866  {
3867  os << " " << i << ": " << (*iter)->getName() << " ";
3868  os << getName();
3869 
3870  os << std::endl;
3871  os << " AREA = " << (*iter)->AREA << std::endl;
3872  os << " icVBE = " << (*iter)->icVBE << std::endl;
3873  os << " icVCE = " << (*iter)->icVCE << std::endl;
3874  os << " TEMP = " << (*iter)->TEMP << std::endl;
3875  os << " OFF = " << (*iter)->OFF << std::endl;
3876 
3877  os << std::endl;
3878  }
3879 
3880  os << std::endl;
3881 
3882  return os;
3883 }
3884 
3885 //-----------------------------------------------------------------------------
3886 // Function : Model::forEachInstance
3887 // Purpose :
3888 // Special Notes :
3889 // Scope : public
3890 // Creator : David Baur
3891 // Creation Date : 2/4/2014
3892 //-----------------------------------------------------------------------------
3893 /// Apply a device instance "op" to all instances associated with this
3894 /// model
3895 ///
3896 /// @param[in] op Operator to apply to all instances.
3897 ///
3898 ///
3899 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
3900 {
3901  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3902  op(*it);
3903 }
3904 
3905 
3906 //-----------------------------------------------------------------------------
3907 // BJT Master functions:
3908 //-----------------------------------------------------------------------------
3909 
3910 //-----------------------------------------------------------------------------
3911 // Function : Master::updateState
3912 // Purpose :
3913 // Special Notes :
3914 // Scope : public
3915 // Creator : Eric Keiter, SNL
3916 // Creation Date : 11/26/08
3917 //-----------------------------------------------------------------------------
3918 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
3919 {
3920  bool bsuccess = true;
3921 
3922  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3923  {
3924  Instance & bi = *(*it);
3925 
3926  double * stoVec = bi.extData.nextStoVectorRawPtr;
3927 
3928  // Do the bulk of the work in updateIntermediateVars:
3929  bool btmp = bi.updateIntermediateVars ();
3930  bsuccess = bsuccess && btmp;
3931 
3932  // save voltage drops
3933  stoVec[bi.li_storevBE] = bi.vBE;
3934  stoVec[bi.li_storevBC] = bi.vBC;
3935  stoVec[bi.li_store_capeqCB] = bi.capeqCB;
3936 
3937  staVec[bi.li_qstateBEdiff] = bi.qBEdiff;
3938  staVec[bi.li_qstateBEdep] = bi.qBEdep;
3939  staVec[bi.li_qstateBCdiff] = bi.qBCdiff;
3940  staVec[bi.li_qstateBCdep] = bi.qBCdep;
3941  staVec[bi.li_qstateBX] = bi.qBX;
3942  staVec[bi.li_qstateCS] = bi.qCS;
3943 
3944 
3945  // if this is the first newton step of the first time step
3946  // of the transient simulation, we need to enforce that the
3947  // time derivatives w.r.t. charge are zero. This is to maintain 3f5
3948  // compatibility. ERK.
3949 
3950  if (!(getSolverState().dcopFlag) && (getSolverState().initTranFlag) && getSolverState().newtonIter==0)
3951  {
3952  double * currStaVec = (bi.extData.currStaVectorRawPtr);
3953 
3954  currStaVec[bi.li_qstateBEdiff] = bi.qBEdiff;
3955  currStaVec[bi.li_qstateBEdep] = bi.qBEdep;
3956  currStaVec[bi.li_qstateBCdiff] = bi.qBCdiff;
3957  currStaVec[bi.li_qstateBCdep] = bi.qBCdep;
3958  currStaVec[bi.li_qstateBX] = bi.qBX;
3959  currStaVec[bi.li_qstateCS] = bi.qCS;
3960  }
3961  }
3962 
3963  return bsuccess;
3964 }
3965 
3966 //-----------------------------------------------------------------------------
3967 // Function : Master::updateSecondaryState
3968 // Purpose :
3969 // Special Notes :
3970 // Scope : public
3971 // Creator : Eric Keiter, SNL
3972 // Creation Date : 11/26/08
3973 //-----------------------------------------------------------------------------
3974 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
3975 {
3976  bool bsuccess = true;
3977 
3978  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3979  {
3980  Instance & bi = *(*it);
3981 
3982  // Now that the state vector for time=0 is up-to-date, get the derivative
3983  // with respect to time of the charge, to obtain the best estimate for
3984  // the current in the capacitor.
3985 
3986  bi.iBEdiff = staDerivVec[bi.li_qstateBEdiff];
3987  bi.iBEdep = staDerivVec[bi.li_qstateBEdep ];
3988  bi.iCS = staDerivVec[bi.li_qstateCS ];
3989  bi.iBCdiff = staDerivVec[bi.li_qstateBCdiff];
3990  bi.iBCdep = staDerivVec[bi.li_qstateBCdep ];
3991  bi.iBX = staDerivVec[bi.li_qstateBX ];
3992  }
3993 
3994  return bsuccess;
3995 }
3996 
3997 //-----------------------------------------------------------------------------
3998 // Function : Master::loadDAEVectors
3999 // Purpose :
4000 // Special Notes :
4001 // Scope : public
4002 // Creator : Eric Keiter, SNL
4003 // Creation Date : 11/26/08
4004 //-----------------------------------------------------------------------------
4005 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * storeLeadF, double * storeLeadQ)
4006 {
4007  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4008  {
4009  Instance & bi = *(*it);
4010 
4011  double td = bi.model_.excessPhaseFac;
4012  double vbe_diff = bi.vBE - bi.vBE_orig;
4013  double vbc_diff = bi.vBC - bi.vBC_orig;
4014  double vce_diff = vbe_diff - vbc_diff;
4015 
4016  // F-vector:
4017  fVec[bi.li_Coll] -= -bi.vCCp * bi.gCpr;
4018  fVec[bi.li_Base] -= -bi.vBBp * bi.gX;
4019  fVec[bi.li_Emit] -= -bi.vEEp * bi.gEpr;
4020  fVec[bi.li_CollP] -= bi.vCCp * bi.gCpr + bi.model_.TYPE * ( - bi.iC );
4021  fVec[bi.li_BaseP] -= bi.vBBp * bi.gX - bi.model_.TYPE * ( bi.iB );
4022  fVec[bi.li_EmitP] -= bi.vEEp * bi.gEpr + bi.model_.TYPE * ( - bi.iE );
4023 
4024  // excess phase ERK-dcop.
4025  double i_fx = 0.0;
4026  double di_fx = 0.0;
4027 
4029  {
4030  i_fx = solVec[bi.li_Ifx];
4031  di_fx = solVec[bi.li_dIfx];
4032 
4033  if (td != 0)
4034  {
4035  if (!(getSolverState().dcopFlag) )
4036  {
4037  // omega0 = 1/td;
4038  fVec[bi.li_Ifx] += - di_fx;
4039  fVec[bi.li_dIfx] += 3 * di_fx*td + 3*i_fx -3 * bi.iBE / bi.qB;
4040  }
4041  else
4042  {
4043  fVec[bi.li_Ifx] += i_fx -bi.iBE/bi.qB;
4044  fVec[bi.li_dIfx] = 0.0;
4045  }
4046  }
4047  else
4048  {
4049  fVec[bi.li_Ifx] += i_fx;
4050  fVec[bi.li_dIfx] += di_fx;
4051  }
4052  }
4053 
4054  // Q-vector:
4055  qVec[bi.li_Base] -= - bi.model_.TYPE * bi.qBX;
4056  qVec[bi.li_Subst] -= -bi.model_.TYPE * bi.qCS;
4057  qVec[bi.li_CollP] -= bi.model_.TYPE * ( bi.qCS + bi.qBX + bi.qBCdep + bi.qBCdiff );
4058  qVec[bi.li_BaseP] -= -bi.model_.TYPE * ( bi.qBEdep + bi.qBEdiff + bi.qBCdep + bi.qBCdiff );
4059  qVec[bi.li_EmitP] -= bi.model_.TYPE*( bi.qBEdep + bi.qBEdiff );
4060 
4061  // excess phase ERK-dcop
4062  if (td != 0 && getDeviceOptions().newExcessPhase)
4063  {
4064  qVec[bi.li_Ifx] += solVec[bi.li_Ifx];
4065 
4066  if (!(getSolverState().dcopFlag) )
4067  {
4068  qVec[bi.li_dIfx] += solVec[bi.li_dIfx]*td*td;
4069  }
4070  else
4071  {
4072  qVec[bi.li_dIfx] = 0.0;
4073  }
4074  }
4075 
4076  // voltage limiter terms:
4078  {
4079  double Cp_Jdxp_f(0.0), Bp_Jdxp_f(0.0), Ep_Jdxp_f(0.0),
4080  dIfx_Jdxp_f(0.0 ), Ifx_Jdxp_f(0.0 ),
4081  Cp_Jdxp_q ( 0.0), Ep_Jdxp_q ( 0.0), Bp_Jdxp_q ( 0.0);
4082 
4083  // F-limiters:
4084  if (!bi.origFlag || bi.offFlag)
4085  {
4086  Cp_Jdxp_f = + bi.diCEdvBp * vbe_diff
4087  + bi.diCEdvCp * vce_diff
4088  - bi.gBCtot * vbc_diff;
4089 
4090  Cp_Jdxp_f *= bi.model_.TYPE;
4091 
4092  Bp_Jdxp_f = bi.gBEtot * vbe_diff + bi.gBCtot * vbc_diff;
4093  Bp_Jdxp_f *= bi.model_.TYPE;
4094 
4095  Ep_Jdxp_f = - bi.diCEdvCp * vce_diff - (bi.diCEdvBp + bi.gBEtot) * vbe_diff;
4096  Ep_Jdxp_f *= bi.model_.TYPE;
4097 
4098  // ERK-dcop.
4099  if ( td != 0 && getDeviceOptions().newExcessPhase )
4100  {
4101  if ( !(getSolverState().dcopFlag) )
4102  {
4103  dIfx_Jdxp_f = -3 *( bi.diBEdvBp*vbe_diff + bi.diBEdvCp * vce_diff);
4104  dIfx_Jdxp_f *= bi.model_.TYPE;
4105  }
4106  else
4107  {
4108  Ifx_Jdxp_f = ( bi.diBEdvBp*vbe_diff + bi.diBEdvCp * vce_diff);
4109  Ifx_Jdxp_f *= bi.model_.TYPE;
4110  }
4111  }
4112  }
4113 
4114  double * dFdxdVp = bi.extData.dFdxdVpVectorRawPtr;
4115  dFdxdVp[bi.li_CollP] += Cp_Jdxp_f;
4116  dFdxdVp[bi.li_BaseP] += Bp_Jdxp_f;
4117  dFdxdVp[bi.li_EmitP] += Ep_Jdxp_f;
4118 
4119  // ERK-dcop.
4120  if ( td != 0 && getDeviceOptions().newExcessPhase )
4121  {
4122  if ( !(getSolverState().dcopFlag) )
4123  {
4124  dFdxdVp[bi.li_dIfx] += dIfx_Jdxp_f;
4125  }
4126  else
4127  {
4128  dFdxdVp[bi.li_Ifx] += Ifx_Jdxp_f;
4129  }
4130  }
4131 
4132  // Q-limiters:
4133  if (!bi.origFlag || bi.offFlag)
4134  {
4135  Cp_Jdxp_q = -(bi.capBCdep + bi.capBCdiff)*vbc_diff;
4136  Cp_Jdxp_q *= bi.model_.TYPE;
4137 
4138  Bp_Jdxp_q = (bi.capBEdep + bi.capBEdiff)*vbe_diff
4139  + (bi.capBCdiff + bi.capBCdep + bi.capeqCB) *vbc_diff;
4140  Bp_Jdxp_q *= bi.model_.TYPE;
4141 
4142  Ep_Jdxp_q = - bi.capeqCB * vbc_diff - (bi.capBEdiff + bi.capBEdep)* vbe_diff;
4143  Ep_Jdxp_q *= bi.model_.TYPE;
4144  }
4145 
4146  double * dQdxdVp = bi.extData.dQdxdVpVectorRawPtr;
4147  dQdxdVp[bi.li_CollP] += Cp_Jdxp_q;
4148  dQdxdVp[bi.li_BaseP] += Bp_Jdxp_q;
4149  dQdxdVp[bi.li_EmitP] += Ep_Jdxp_q;
4150  }
4151 
4152  if( bi.loadLeadCurrent )
4153  {
4154  storeLeadQ[bi.li_store_dev_ic] = -bi.model_.TYPE * ( bi.qCS + bi.qBX + bi.qBCdep + bi.qBCdiff );
4155  storeLeadQ[bi.li_store_dev_ib] = bi.model_.TYPE * ( bi.qBX + bi.qBEdep + bi.qBEdiff + bi.qBCdep + bi.qBCdiff );
4156  storeLeadQ[bi.li_store_dev_ie] = -bi.model_.TYPE*( bi.qBEdep + bi.qBEdiff );
4157  storeLeadQ[bi.li_store_dev_is] = bi.model_.TYPE * bi.qCS;
4158 
4159  storeLeadF[bi.li_store_dev_ic] = bi.model_.TYPE * ( bi.iC );
4160  storeLeadF[bi.li_store_dev_is] = 0;
4161  storeLeadF[bi.li_store_dev_ie] = bi.model_.TYPE * ( bi.iE );
4162  storeLeadF[bi.li_store_dev_ib] = bi.model_.TYPE * ( bi.iB );
4163 
4164  }
4165 
4166  }
4167 
4168  return true;
4169 }
4170 
4171 //-----------------------------------------------------------------------------
4172 // Function : Master::loadDAEMatrices
4173 // Purpose :
4174 // Special Notes :
4175 // Scope : public
4176 // Creator : Eric Keiter, SNL
4177 // Creation Date : 11/26/08
4178 //-----------------------------------------------------------------------------
4179 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
4180 {
4181  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4182  {
4183  Instance & bi = *(*it);
4184 
4185  double td = bi.model_.excessPhaseFac;
4186 
4187 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
4188  // F-matrix:
4189 
4190  *bi.f_CollEquCollNodePtr += bi.gCpr;
4191  *bi.f_CollEquCollPNodePtr -= bi.gCpr;
4192  *bi.f_BaseEquBaseNodePtr += bi.diBrdvB;
4193  *bi.f_BaseEquCollPNodePtr += bi.diBrdvCp;
4194  *bi.f_BaseEquBasePNodePtr += bi.diBrdvBp;
4195  *bi.f_BaseEquEmitPNodePtr += bi.diBrdvEp;
4196  *bi.f_EmitEquEmitNodePtr += bi.gEpr;
4197  *bi.f_EmitEquEmitPNodePtr -= bi.gEpr;
4198  *bi.f_CollPEquCollNodePtr -= bi.gCpr;
4199  *bi.f_CollPEquCollPNodePtr +=bi.diCEdvCp + bi.gBCtot + bi.gCpr;
4200  *bi.f_CollPEquBasePNodePtr += bi.diCEdvBp - bi.gBCtot;
4201  *bi.f_CollPEquEmitPNodePtr += bi.diCEdvEp;
4202 
4203  // excess phase terms. ERK-dcop
4204  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4205  {
4206  *bi.f_CollPEquIfxNodePtr += 1.0 * bi.model_.TYPE;
4207  }
4208  *bi.f_BasePEquBaseNodePtr -= bi.diBrdvB;
4209  *bi.f_BasePEquCollPNodePtr += -bi.diBrdvCp - bi.gBCtot;
4210  *bi.f_BasePEquBasePNodePtr += -bi.diBrdvBp + bi.gBEtot + bi.gBCtot;
4211  *bi.f_BasePEquEmitPNodePtr += -bi.diBrdvEp - bi.gBEtot;
4212  *bi.f_EmitPEquEmitNodePtr -= bi.gEpr;
4213  *bi.f_EmitPEquCollPNodePtr += -bi.diCEdvCp;
4214  *bi.f_EmitPEquBasePNodePtr += - bi.diCEdvBp - bi.gBEtot;
4215 
4216  // ERK Note: -bi.diCEdvEp should equal + bi.diCEdvBp + bi.diCEdvCp. In the
4217  // original old-DAE form, + bi.diCEdvBp + bi.diCEdvCp is used. In
4218  // the more recent new-DAE form, we've used bi.diCEdvEp, but it sometimes
4219  // results in subtle differences between old- and new-DAE jacobians.
4220  // This should matter, but .....
4221  *bi.f_EmitPEquEmitPNodePtr += bi.gBEtot + bi.gEpr + bi.diCEdvBp + bi.diCEdvCp; // this is a test.
4222  //+= bi.gBEtot + bi.gEpr - bi.diCEdvEp;
4223 
4224  // excess phase terms. ERK-dcop
4225  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4226  {
4227  *bi.f_EmitPEquIfxNodePtr += -1.0 * bi.model_.TYPE;
4228  }
4229 
4230  // excess phase terms. ERK-dcop
4232  {
4233  if ( td != 0 )
4234  {
4235  if ( !(getSolverState().dcopFlag) )
4236  {
4237  *bi.f_IfxEqudIfxNodePtr += -1;
4238 
4239  *bi.f_dIfxEquCollPNodePtr += -3*bi.diBEdvCp * bi.model_.TYPE;
4240  *bi.f_dIfxEquBasePNodePtr += -3*bi.diBEdvBp * bi.model_.TYPE;
4241  *bi.f_dIfxEquEmitPNodePtr += -3*bi.diBEdvEp * bi.model_.TYPE;
4242  *bi.f_dIfxEqudIfxNodePtr += 3* td;
4243  *bi.f_dIfxEquIfxNodePtr += 3;
4244  }
4245  else
4246  {
4247  *bi.f_IfxEquCollPNodePtr += -bi.diBEdvCp * bi.model_.TYPE;
4248  *bi.f_IfxEquBasePNodePtr += -bi.diBEdvBp * bi.model_.TYPE;
4249  *bi.f_IfxEquEmitPNodePtr += -bi.diBEdvEp * bi.model_.TYPE;
4250 
4251  *bi.f_IfxEquIfxNodePtr+= 1;
4252  *bi.f_dIfxEqudIfxNodePtr += 1;
4253  }
4254  }
4255  else
4256  {
4257  *bi.f_IfxEquIfxNodePtr += 1;
4258  *bi.f_dIfxEqudIfxNodePtr += 1;
4259  }
4260  }
4261 
4262  // Q-matrix:
4263 
4264  *bi.q_BaseEquBaseNodePtr += bi.capBX;
4265  *bi.q_BaseEquCollPNodePtr += -bi.capBX;
4266  *bi.q_SubstEquSubstNodePtr += bi.capCS;
4267  *bi.q_SubstEquCollPNodePtr -= bi.capCS;
4268  *bi.q_CollPEquBaseNodePtr -= bi.capBX;
4269  *bi.q_CollPEquSubstNodePtr -= bi.capCS;
4270  *bi.q_CollPEquCollPNodePtr += bi.capCS + bi.capBX + bi.capBCdep + bi.capBCdiff;
4271  *bi.q_CollPEquBasePNodePtr += -bi.capBCdep - bi.capBCdiff;
4272  *bi.q_BasePEquCollPNodePtr += -bi.capBCdiff - bi.capBCdep - bi.capeqCB;
4273  *bi.q_BasePEquBasePNodePtr += bi.capBEdiff + bi.capBEdep + bi.capBCdiff + bi.capBCdep + bi.capeqCB;
4274  *bi.q_BasePEquEmitPNodePtr += -bi.capBEdiff - bi.capBEdep;
4275  *bi.q_EmitPEquCollPNodePtr += bi.capeqCB;
4276  *bi.q_EmitPEquBasePNodePtr += -bi.capBEdiff - bi.capBEdep - bi.capeqCB;
4277  *bi.q_EmitPEquEmitPNodePtr += bi.capBEdiff + bi.capBEdep;
4278 
4279  // excess phase terms. ERK-dcop
4280  if ( td != 0 && getDeviceOptions().newExcessPhase )
4281  {
4282  if (!(getSolverState().dcopFlag) )
4283  {
4284  *bi.q_IfxEquIfxNodePtr += 1;
4285  *bi.q_dIfxEqudIfxNodePtr += 1*td*td;
4286  }
4287  }
4288 
4289 #else
4290  // F-matrix:
4291 
4292  dFdx[bi.li_Coll][bi.ACollEquCollNodeOffset] += bi.gCpr;
4293  dFdx[bi.li_Coll][bi.ACollEquCollPNodeOffset] -= bi.gCpr;
4294  dFdx[bi.li_Base][bi.ABaseEquBaseNodeOffset] += bi.diBrdvB;
4295  dFdx[bi.li_Base][bi.ABaseEquCollPNodeOffset] += bi.diBrdvCp;
4296  dFdx[bi.li_Base][bi.ABaseEquBasePNodeOffset] += bi.diBrdvBp;
4297  dFdx[bi.li_Base][bi.ABaseEquEmitPNodeOffset] += bi.diBrdvEp;
4298  dFdx[bi.li_Emit][bi.AEmitEquEmitNodeOffset] += bi.gEpr;
4299  dFdx[bi.li_Emit][bi.AEmitEquEmitPNodeOffset] -= bi.gEpr;
4300  dFdx[bi.li_CollP][bi.ACollPEquCollNodeOffset] -= bi.gCpr;
4301  dFdx[bi.li_CollP][bi.ACollPEquCollPNodeOffset] +=bi.diCEdvCp + bi.gBCtot + bi.gCpr;
4302  dFdx[bi.li_CollP][bi.ACollPEquBasePNodeOffset] += bi.diCEdvBp - bi.gBCtot;
4303  dFdx[bi.li_CollP][bi.ACollPEquEmitPNodeOffset] += bi.diCEdvEp;
4304 
4305  // excess phase terms. ERK-dcop
4306  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4307  {
4308  dFdx[bi.li_CollP][bi.ACollPEquIfxNodeOffset] += 1.0 * bi.model_.TYPE;
4309  }
4310 
4311  dFdx[bi.li_BaseP][bi.ABasePEquBaseNodeOffset] -= bi.diBrdvB;
4312  dFdx[bi.li_BaseP][bi.ABasePEquCollPNodeOffset] += -bi.diBrdvCp - bi.gBCtot;
4313  dFdx[bi.li_BaseP][bi.ABasePEquBasePNodeOffset] += -bi.diBrdvBp + bi.gBEtot + bi.gBCtot;
4314  dFdx[bi.li_BaseP][bi.ABasePEquEmitPNodeOffset] += -bi.diBrdvEp - bi.gBEtot;
4315  dFdx[bi.li_EmitP][bi.AEmitPEquEmitNodeOffset] -= bi.gEpr;
4316  dFdx[bi.li_EmitP][bi.AEmitPEquCollPNodeOffset] += -bi.diCEdvCp;
4317  dFdx[bi.li_EmitP][bi.AEmitPEquBasePNodeOffset] += - bi.diCEdvBp - bi.gBEtot;
4318 
4319  // ERK Note: -bi.diCEdvEp should equal + bi.diCEdvBp + bi.diCEdvCp. In the
4320  // original old-DAE form, + bi.diCEdvBp + bi.diCEdvCp is used. In
4321  // the more recent new-DAE form, we've used bi.diCEdvEp, but it sometimes
4322  // results in subtle differences between old- and new-DAE jacobians.
4323  // This should matter, but .....
4324 
4325  dFdx[bi.li_EmitP][bi.AEmitPEquEmitPNodeOffset] += bi.gBEtot + bi.gEpr + bi.diCEdvBp + bi.diCEdvCp; // this is a test.
4326  //+= bi.gBEtot + bi.gEpr - bi.diCEdvEp;
4327 
4328  // excess phase terms. ERK-dcop
4329  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4330  {
4331  dFdx[bi.li_EmitP][bi.AEmitPEquIfxNodeOffset] += -1.0 * bi.model_.TYPE;
4332  }
4333 
4334  // excess phase terms. ERK-dcop
4336  {
4337  if ( td != 0 )
4338  {
4339  if ( !(getSolverState().dcopFlag) )
4340  {
4341  dFdx[bi.li_Ifx][bi.AIfxEqudIfxNodeOffset]+= -1;
4342  dFdx[bi.li_dIfx][bi.AdIfxEquCollPNodeOffset] += -3*bi.diBEdvCp * bi.model_.TYPE;
4343  dFdx[bi.li_dIfx][bi.AdIfxEquBasePNodeOffset] += -3*bi.diBEdvBp * bi.model_.TYPE;
4344  dFdx[bi.li_dIfx][bi.AdIfxEquEmitPNodeOffset] += -3*bi.diBEdvEp * bi.model_.TYPE;
4345  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 3* td;
4346  dFdx[bi.li_dIfx][bi.AdIfxEquIfxNodeOffset] += 3;
4347  }
4348  else
4349  {
4350  dFdx[bi.li_Ifx][bi.AIfxEquCollPNodeOffset] += -bi.diBEdvCp * bi.model_.TYPE;
4351  dFdx[bi.li_Ifx][bi.AIfxEquBasePNodeOffset] += -bi.diBEdvBp * bi.model_.TYPE;
4352  dFdx[bi.li_Ifx][bi.AIfxEquEmitPNodeOffset] += -bi.diBEdvEp * bi.model_.TYPE;
4353  dFdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset]+= 1;
4354  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1;
4355  }
4356  }
4357  else
4358  {
4359  dFdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset]+= 1;
4360  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1;
4361  }
4362  }
4363 
4364  // Q-matrix:
4365 
4366  dQdx[bi.li_Base][bi.ABaseEquBaseNodeOffset] += bi.capBX;
4367  dQdx[bi.li_Base][bi.ABaseEquCollPNodeOffset] += -bi.capBX;
4368  dQdx[bi.li_Subst][bi.ASubstEquSubstNodeOffset] += bi.capCS;
4369  dQdx[bi.li_Subst][bi.ASubstEquCollPNodeOffset] -= bi.capCS;
4370  dQdx[bi.li_CollP][bi.ACollPEquBaseNodeOffset] -= bi.capBX;
4371  dQdx[bi.li_CollP][bi.ACollPEquSubstNodeOffset] -= bi.capCS;
4372  dQdx[bi.li_CollP][bi.ACollPEquCollPNodeOffset] += bi.capCS + bi.capBX + bi.capBCdep + bi.capBCdiff;
4373  dQdx[bi.li_CollP][bi.ACollPEquBasePNodeOffset] += -bi.capBCdep - bi.capBCdiff;
4374  dQdx[bi.li_BaseP][bi.ABasePEquCollPNodeOffset] += -bi.capBCdiff - bi.capBCdep - bi.capeqCB;
4375  dQdx[bi.li_BaseP][bi.ABasePEquBasePNodeOffset] += bi.capBEdiff + bi.capBEdep + bi.capBCdiff + bi.capBCdep + bi.capeqCB;
4376  dQdx[bi.li_BaseP][bi.ABasePEquEmitPNodeOffset] += -bi.capBEdiff - bi.capBEdep;
4377  dQdx[bi.li_EmitP][bi.AEmitPEquCollPNodeOffset] += bi.capeqCB;
4378  dQdx[bi.li_EmitP][bi.AEmitPEquBasePNodeOffset] += -bi.capBEdiff - bi.capBEdep - bi.capeqCB;
4379  dQdx[bi.li_EmitP][bi.AEmitPEquEmitPNodeOffset] += bi.capBEdiff + bi.capBEdep;
4380 
4381  // excess phase terms. ERK-dcop
4382  if ( td != 0 && getDeviceOptions().newExcessPhase )
4383  {
4384  if (!(getSolverState().dcopFlag) )
4385  {
4386  dQdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset] += 1;
4387  dQdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1*td*td;
4388  }
4389  }
4390  #endif
4391  }
4392  return true;
4393 }
4394 
4395 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
4396 {
4397 
4398  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
4399 }
4400 
4402 {
4404  .registerDevice("q", 1)
4405  .registerModelType("pnp", 1)
4406  .registerModelType("npn", 1);
4407 }
4408 
4409 } // namespace BJT
4410 } // namespace Device
4411 } // namespace Xyce