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.388 $
40 //
41 // Revision Date : $Date: 2014/05/22 17:40:29 $
42 //
43 // Current Owner : $Author: erkeite $
44 //-------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- 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  UserError(*this) << "Wrong number of external nodes are set!" << std::endl
1024  << "Either set none of them, or set them all.";
1025  }
1026 
1027  externalNodeMode = true;
1028  //numExtVars += cNode + eNode + bNode; // This is already set in netlist.
1029  }
1030 
1031 
1032  if (getDeviceOptions().newExcessPhase)
1033  {
1034  //add in 2 variables for excess phase calc.
1035  numIntVars += 2;
1036  }
1037 
1038 }
1039 
1040 //-----------------------------------------------------------------------------
1041 // Function : Instance::~Instance
1042 // Purpose : destructor
1043 // Special Notes :
1044 // Scope : public
1045 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1046 // Creation Date : 3/16/00
1047 //-----------------------------------------------------------------------------
1049 {
1050 
1051 }
1052 
1053 //-----------------------------------------------------------------------------
1054 // Function : Instance::registerLIDs
1055 // Purpose :
1056 // Special Notes :
1057 // Scope : public
1058 // Creator : Robert Hoekstra
1059 // Creation Date : 6/13/02
1060 //-----------------------------------------------------------------------------
1061 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
1062  const std::vector<int> & extLIDVecRef )
1063 {
1064  AssertLIDs(intLIDVecRef.size() == numIntVars);
1065  AssertLIDs(extLIDVecRef.size() == numExtVars);
1066 
1067 #ifdef Xyce_DEBUG_DEVICE
1068  if (getDeviceOptions().debugLevel > 0)
1069  {
1070  Xyce::dout() << section_divider << std::endl;
1071  Xyce::dout() << " BJTInstance::registerLIDs" <<std::endl;
1072  Xyce::dout() << " name = " << getName() << std::endl;
1073  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
1074  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
1075  Xyce::dout() << " numIntVars = " << numIntVars << std::endl;
1076  Xyce::dout() << " numExtVars = " << numExtVars << std::endl;
1077  }
1078 #endif
1079 
1080  // Copy over the global ID lists.
1081  intLIDVec = intLIDVecRef;
1082  extLIDVec = extLIDVecRef;
1083 
1084 #ifdef Xyce_DEBUG_DEVICE
1085  if (getDeviceOptions().debugLevel > 0)
1086  {
1087  Xyce::dout() << " Internal LID List" << std::endl;
1088  for( int i = 0; i < intLIDVec.size(); ++i )
1089  Xyce::dout() << " " << intLIDVec[i] << std::endl;
1090  Xyce::dout() << " External LID List" << std::endl;
1091  for( int i = 0; i < extLIDVec.size(); ++i )
1092  Xyce::dout() << " " << extLIDVec[i] << std::endl;
1093  }
1094 #endif
1095 
1096  // Now use these lists to obtain the indices into the linear algebra
1097  // entities. This assumes an order. For the matrix indices, first do the
1098  // rows.
1099 
1100  // First do external variables:
1101  // it1 at collector, it2 at collectorPrime
1102  int intIndex = 0;
1103  int extIndex = 0;
1104 
1105  li_Coll = extLIDVec[extIndex++];
1106  li_Base = extLIDVec[extIndex++];
1107  li_Emit = extLIDVec[extIndex++];
1108  li_Subst = extLIDVec[extIndex++];
1109 
1110  if( model_.collectorResist == 0.0 )
1111  {
1112  li_CollP = li_Coll;
1113  }
1114  else
1115  {
1116  if (externalNodeMode)
1117  li_CollP = extLIDVec[extIndex++];
1118  else
1119  li_CollP = intLIDVec[intIndex++];
1120  }
1121 
1122 
1123  if( model_.baseResist == 0.0 )
1124  {
1125  li_BaseP = li_Base;
1126  }
1127  else
1128  {
1129  if (externalNodeMode)
1130  li_BaseP = extLIDVec[extIndex++];
1131  else
1132  li_BaseP = intLIDVec[intIndex++];
1133  }
1134 
1135 
1136  if( model_.emitterResist == 0.0 )
1137  {
1138  li_EmitP = li_Emit;
1139  }
1140  else
1141  {
1142  if (externalNodeMode)
1143  li_EmitP = extLIDVec[extIndex++];
1144  else
1145  li_EmitP = intLIDVec[intIndex++];
1146  }
1147 
1148 
1150  {
1151  li_Ifx = intLIDVec[intIndex++];
1152  li_dIfx = intLIDVec[intIndex++];
1153  }
1154 
1155 #ifdef Xyce_DEBUG_DEVICE
1156  if (getDeviceOptions().debugLevel > 0)
1157  {
1158  Xyce::dout() << " li_Coll = " << li_Coll << std::endl;
1159  Xyce::dout() << " li_CollP = " << li_CollP << std::endl;
1160  Xyce::dout() << " li_Base = " << li_Base << std::endl;
1161  Xyce::dout() << " li_BaseP = " << li_BaseP << std::endl;
1162  Xyce::dout() << " li_Emit = " << li_Emit << std::endl;
1163  Xyce::dout() << " li_EmitP = " << li_EmitP << std::endl;
1164  Xyce::dout() << " li_Subst = " << li_Subst << std::endl;
1165 
1166  if (getDeviceOptions().newExcessPhase)
1167  {
1168  Xyce::dout() << " li_Ifx = " << li_Ifx << std::endl;
1169  Xyce::dout() << " li_dIfx = " << li_dIfx << std::endl;
1170  }
1171 
1172  Xyce::dout() << section_divider << std::endl;
1173  }
1174 #endif
1175 
1176 }
1177 
1178 //-----------------------------------------------------------------------------
1179 // Function : Instance::getIntNameMap
1180 // Purpose :
1181 // Special Notes :
1182 // Scope : public
1183 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1184 // Creation Date : 05/13/05
1185 //-----------------------------------------------------------------------------
1186 std::map<int,std::string> & Instance::getIntNameMap ()
1187 {
1188  // set up the internal name map, if it hasn't been already.
1189  std::string tmpstr;
1190  if (intNameMap.empty () && !externalNodeMode)
1191  {
1192  if( model_.collectorResist != 0.0 )
1193  {
1194  intNameMap[ li_CollP ] = spiceInternalName(getName(), "collectorprime");
1195  }
1196 
1197  if( model_.baseResist != 0.0 )
1198  {
1199  intNameMap[ li_BaseP ] = spiceInternalName(getName(), "baseprime");
1200  }
1201 
1202  if( model_.emitterResist != 0.0 )
1203  {
1204  intNameMap[ li_EmitP ] = spiceInternalName(getName(), "emitterprime");
1205  }
1206  }
1207 
1208  if (getDeviceOptions().newExcessPhase)
1209  {
1210  intNameMap [ li_Ifx ] = spiceInternalName(getName(), "ExcessPhase_Ifx");
1211  intNameMap [ li_dIfx ] = spiceInternalName(getName(), "ExcessPhase_dIfx");
1212  }
1213 
1214  return intNameMap;
1215 }
1216 
1217 
1218 //-----------------------------------------------------------------------------
1219 // Function : Instance::getStoreNameMap
1220 // Purpose :
1221 // Special Notes :
1222 // Scope : public
1223 // Creator : Richard Schiek, SNL, Electrical Systems Modeling
1224 // Creation Date : 01/23/13
1225 //-----------------------------------------------------------------------------
1226 std::map<int,std::string> & Instance::getStoreNameMap ()
1227 {
1228  // set up the internal name map, if it hasn't been already.
1229  if (storeNameMap.empty ())
1230  {
1234 
1235  if (loadLeadCurrent)
1236  {
1241  }
1242  }
1243 
1244  return storeNameMap;
1245 }
1246 
1247 //-----------------------------------------------------------------------------
1248 // Function : Instance::registerStateLIDs
1249 // Purpose :
1250 // Special Notes :
1251 // Scope : public
1252 // Creator : Robert Hoekstra
1253 // Creation Date : 6/13/02
1254 //-----------------------------------------------------------------------------
1255 void Instance::registerStateLIDs( const std::vector<int> & staLIDVecRef )
1256 {
1257  AssertLIDs(staLIDVecRef.size() == numStateVars);
1258 
1259  // Copy over the global ID lists:
1260  staLIDVec = staLIDVecRef;
1261 
1262  int i=0;
1263  li_qstateBEdiff = staLIDVec[i++];
1264  li_qstateBEdep = staLIDVec[i++];
1265  li_qstateCS = staLIDVec[i++];
1266  li_qstateBCdiff = staLIDVec[i++];
1267  li_qstateBCdep = staLIDVec[i++];
1268  li_qstateBX = staLIDVec[i++];
1269  li_istateCEXBC = staLIDVec[i++];
1270 }
1271 
1272 
1273 //-----------------------------------------------------------------------------
1274 // Function : Instance::registerStoreLIDs
1275 // Purpose :
1276 // Special Notes :
1277 // Scope : public
1278 // Creator : Eric Keiter, SNL
1279 // Creation Date : 12/09/11
1280 //-----------------------------------------------------------------------------
1281 void Instance::registerStoreLIDs( const std::vector<int> & stoLIDVecRef )
1282 {
1283  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
1284 
1285  // Copy over the global ID lists:
1286  stoLIDVec = stoLIDVecRef;
1287 
1288  int i=0;
1289  li_storevBE = stoLIDVec[i++];
1290  li_storevBC = stoLIDVec[i++];
1291  li_store_capeqCB = stoLIDVec[i++];
1292  if( loadLeadCurrent )
1293  {
1294  li_store_dev_ib = stoLIDVec[i++];
1295  li_store_dev_ie = stoLIDVec[i++];
1296  li_store_dev_ic = stoLIDVec[i++];
1297  li_store_dev_is = stoLIDVec[i++];
1298  }
1299 
1300 }
1301 
1302 //-----------------------------------------------------------------------------
1303 // Function : Instance::jacobianStamp
1304 // Purpose :
1305 // Special Notes :
1306 // Scope : public
1307 // Creator : Robert Hoekstra
1308 // Creation Date : 8/21/02
1309 //-----------------------------------------------------------------------------
1310 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
1311 {
1312  if (model_.baseResist)
1313  {
1314  if (model_.collectorResist)
1315  {
1316  if (model_.emitterResist)
1317  return jacStamp_RB_RC_RE_;
1318  else
1319  return jacStamp_RB_RC_;
1320  }
1321  else
1322  {
1323  if (model_.emitterResist)
1324  return jacStamp_RB_RE_;
1325  else
1326  return jacStamp_RB_;
1327  }
1328  }
1329  else
1330  {
1331  if (model_.collectorResist)
1332  {
1333  if (model_.emitterResist)
1334  return jacStamp_RC_RE_;
1335  else
1336  return jacStamp_RC_;
1337  }
1338  else
1339  {
1340  if (model_.emitterResist)
1341  return jacStamp_RE_;
1342  else
1343  return jacStamp_;
1344  }
1345  }
1346 }
1347 
1348 //-----------------------------------------------------------------------------
1349 // Function : Instance::registerJacLIDs
1350 // Purpose :
1351 // Special Notes :
1352 // Scope : public
1353 // Creator : Robert Hoekstra
1354 // Creation Date : 8/27/02
1355 //-----------------------------------------------------------------------------
1356 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
1357 {
1358  DeviceInstance::registerJacLIDs( jacLIDVec );
1359 
1360  std::vector<int> map;
1361  std::vector< std::vector<int> > map2;
1362 
1363  if (model_.baseResist)
1364  {
1365  if (model_.collectorResist)
1366  {
1367  if (model_.emitterResist)
1368  {
1369  map = jacMap_RB_RC_RE_;
1370  map2 = jacMap2_RB_RC_RE_;
1371  }
1372  else
1373  {
1374  map = jacMap_RB_RC_;
1375  map2 = jacMap2_RB_RC_;
1376  }
1377  }
1378  else
1379  {
1380  if (model_.emitterResist)
1381  {
1382  map = jacMap_RB_RE_;
1383  map2 = jacMap2_RB_RE_;
1384  }
1385  else
1386  {
1387  map = jacMap_RB_;
1388  map2 = jacMap2_RB_;
1389  }
1390  }
1391  }
1392  else
1393  {
1394  if (model_.collectorResist)
1395  {
1396  if (model_.emitterResist)
1397  {
1398  map = jacMap_RC_RE_;
1399  map2 = jacMap2_RC_RE_;
1400  }
1401  else
1402  {
1403  map = jacMap_RC_;
1404  map2 = jacMap2_RC_;
1405  }
1406  }
1407  else
1408  {
1409  if (model_.emitterResist)
1410  {
1411  map = jacMap_RE_;
1412  map2 = jacMap2_RE_;
1413  }
1414  else
1415  {
1416  map = jacMap_;
1417  map2 = jacMap2_;
1418  }
1419  }
1420  }
1421 
1422  ACollEquCollNodeOffset = jacLIDVec[map[0]][map2[0][0]];
1423  ACollEquCollPNodeOffset = jacLIDVec[map[0]][map2[0][1]];
1424 
1425  ABaseEquBaseNodeOffset = jacLIDVec[map[1]][map2[1][0]];
1426  ABaseEquCollPNodeOffset = jacLIDVec[map[1]][map2[1][1]];
1427  ABaseEquBasePNodeOffset = jacLIDVec[map[1]][map2[1][2]];
1428  ABaseEquEmitPNodeOffset = jacLIDVec[map[1]][map2[1][3]];
1429 
1430  AEmitEquEmitNodeOffset = jacLIDVec[map[2]][map2[2][0]];
1431  AEmitEquEmitPNodeOffset = jacLIDVec[map[2]][map2[2][1]];
1432 
1433  ASubstEquSubstNodeOffset = jacLIDVec[map[3]][map2[3][0]];
1434  ASubstEquCollPNodeOffset = jacLIDVec[map[3]][map2[3][1]];
1435 
1436  ACollPEquCollNodeOffset = jacLIDVec[map[4]][map2[4][0]];
1437  ACollPEquBaseNodeOffset = jacLIDVec[map[4]][map2[4][1]];
1438  ACollPEquSubstNodeOffset = jacLIDVec[map[4]][map2[4][2]];
1439  ACollPEquCollPNodeOffset = jacLIDVec[map[4]][map2[4][3]];
1440  ACollPEquBasePNodeOffset = jacLIDVec[map[4]][map2[4][4]];
1441  ACollPEquEmitPNodeOffset = jacLIDVec[map[4]][map2[4][5]];
1442 
1443  ABasePEquBaseNodeOffset = jacLIDVec[map[5]][map2[5][0]];
1444  ABasePEquCollPNodeOffset = jacLIDVec[map[5]][map2[5][1]];
1445  ABasePEquBasePNodeOffset = jacLIDVec[map[5]][map2[5][2]];
1446  ABasePEquEmitPNodeOffset = jacLIDVec[map[5]][map2[5][3]];
1447 
1448  AEmitPEquEmitNodeOffset = jacLIDVec[map[6]][map2[6][0]];
1449  AEmitPEquCollPNodeOffset = jacLIDVec[map[6]][map2[6][1]];
1450  AEmitPEquBasePNodeOffset = jacLIDVec[map[6]][map2[6][2]];
1451  AEmitPEquEmitPNodeOffset = jacLIDVec[map[6]][map2[6][3]];
1452 
1453  if (getDeviceOptions().newExcessPhase)
1454  {
1455  //Excess Phase Terms
1456  ACollPEquIfxNodeOffset = jacLIDVec[map[4]][map2[4][6]];
1457 
1458  AEmitPEquIfxNodeOffset = jacLIDVec[map[6]][map2[6][4]];
1459 
1460  AIfxEquCollPNodeOffset = jacLIDVec[map[7]][map2[7][0]];
1461  AIfxEquBasePNodeOffset = jacLIDVec[map[7]][map2[7][1]];
1462  AIfxEquEmitPNodeOffset = jacLIDVec[map[7]][map2[7][2]];
1463  AIfxEquIfxNodeOffset = jacLIDVec[map[7]][map2[7][3]];
1464  AIfxEqudIfxNodeOffset = jacLIDVec[map[7]][map2[7][4]];
1465 
1466  AdIfxEquCollPNodeOffset = jacLIDVec[map[8]][map2[8][0]];
1467  AdIfxEquBasePNodeOffset = jacLIDVec[map[8]][map2[8][1]];
1468  AdIfxEquEmitPNodeOffset = jacLIDVec[map[8]][map2[8][2]];
1469  AdIfxEquIfxNodeOffset = jacLIDVec[map[8]][map2[8][3]];
1470  AdIfxEqudIfxNodeOffset = jacLIDVec[map[8]][map2[8][4]];
1471  }
1472 
1473 }
1474 
1475 //-----------------------------------------------------------------------------
1476 // Function : Instance::setupPointers
1477 // Purpose :
1478 // Special Notes :
1479 // Scope : public
1480 // Creator : Eric Keiter, SNL
1481 // Creation Date : 12/01/08
1482 //-----------------------------------------------------------------------------
1484 {
1485 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
1486  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
1487  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
1488 
1489  // F-matrix
1492 
1497 
1500 
1503 
1510 
1515 
1520 
1521 
1522  // Q-matrix:
1525 
1530 
1533 
1536 
1543 
1548 
1553 
1555  {
1556  //F-matrix excess phase Terms
1558 
1560 
1566 
1572 
1573 
1574  // Q-matrix excess phase terms
1576 
1578 
1584 
1590  }
1591 
1592 #endif
1593 }
1594 
1595 //-----------------------------------------------------------------------------
1596 // Function : Instance::updateTemperature
1597 // Purpose :
1598 // Special Notes :
1599 // Scope : public
1600 // Creator : Robert Hoekstra
1601 // Creation Date : 11/30/00
1602 //-----------------------------------------------------------------------------
1603 bool Instance::updateTemperature( const double & temp )
1604 {
1605 
1606 #ifdef Xyce_DEBUG_DEVICE
1607  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1608  {
1609  Xyce::dout() << "Start BJTInst::updateTemperature" << std::endl;
1610  Xyce::dout() << "temp = "<<temp << std::endl;
1611  }
1612 #endif
1613  if( temp != -999.0 ) TEMP = temp;
1615  {
1616  // make sure interpolation doesn't take any resistance negative
1617  if(model_.baseResist < 0) model_.baseResist = 0;
1620 
1621  // some params may have changed during interpolation
1623  }
1624 
1625  //Generation of temperature based factors
1626  vt = TEMP * CONSTKoverQ;
1627  double TNOM = model_.TNOM;
1628  double fact2 = TEMP / CONSTREFTEMP;
1629  double egfet = CONSTEg0 - ( CONSTalphaEg * TEMP * TEMP ) /
1630  ( TEMP + CONSTbetaEg );
1631  double arg = -egfet / ( 2.0 * CONSTboltz * TEMP ) +
1632  CONSTEg300 / ( CONSTboltz * ( 2.0 * CONSTREFTEMP ) );
1633  double pbfact = -2.0 * vt * ( 1.5 * log( fact2 ) + CONSTQ * arg );
1634  double ratlog = log( TEMP / model_.TNOM );
1635  double ratio1 = TEMP / model_.TNOM - 1.0;
1636  double factlog = ratio1 * model_.energyGap / vt
1637  + model_.tempExpIS * ratlog;
1638  double factor = exp( factlog );
1639  double bfactor = exp( ratlog * model_.betaExp );
1640 
1641  // Temp. adj. saturation current
1642 #ifdef Xyce_DEBUG_DEVICE
1643  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1644  {
1645  Xyce::dout() << " Factor is " << factor << std::endl;
1646  Xyce::dout() << " Bfactor is " << bfactor << std::endl;
1647  Xyce::dout() << " factlog is " << factlog << std::endl;
1648  Xyce::dout() << " ratio1 is " << ratio1 << std::endl;
1649  Xyce::dout() << " TEMP is " << TEMP << std::endl;
1650  Xyce::dout() << " TNOM is " << model_.TNOM << std::endl;
1651  Xyce::dout() << " Energy gap is " << model_.energyGap << std::endl;
1652  Xyce::dout() << " tempExpIS is " << model_.tempExpIS << std::endl;
1653  }
1654 #endif
1655 
1656  // Temp. adj. zero-bias junction capacitances and built-in potentials
1657  double fact1 = model_.TNOM / CONSTREFTEMP;
1658  double pbo = ( model_.potBE - pbfact ) / fact1;
1659  double gmaold = ( model_.potBE - pbo ) / pbo;
1660 
1661  tBECap = model_.depCapBE / ( 1.0 + model_.juncExpBE *
1662  ( 4.e-4 * ( model_.TNOM - CONSTREFTEMP ) - gmaold ) );
1663  tBEPot = fact2 * pbo + pbfact;
1664 
1665  double gmanew = ( tBEPot - pbo ) / pbo;
1666 
1667  tBECap *= 1.0 + model_.juncExpBE *
1668  ( 4.e-4 * ( TEMP - CONSTREFTEMP ) - gmanew );
1669 
1670  pbo = ( model_.potBC - pbfact ) / fact1;
1671  gmaold = ( model_.potBC - pbo ) / pbo;
1672 
1673  tBCCap = model_.depCapBC / ( 1.0 + model_.juncExpBC *
1674  ( 4.e-4 * ( model_.TNOM - CONSTREFTEMP ) - gmaold ) );
1675  tBCPot = fact2 * pbo + pbfact;
1676 
1677  gmanew = ( tBCPot - pbo ) / pbo;
1678 
1679  tBCCap *= 1.0 + model_.juncExpBC *
1680  ( 4.e-4 * ( TEMP - CONSTREFTEMP ) - gmanew );
1681 
1682  // Temp. adj. depletion capacitance
1684 
1685  // Temp. adj. polynomial factors
1686  double xfc = log( 1.0 - model_.depCapCoeff );
1687  tF1 = tBEPot * ( 1.0 - exp( ( 1.0 - model_.juncExpBE ) * xfc ) ) /
1688  ( 1.0 - model_.juncExpBE );
1689 
1691  tF5 = tBCPot * ( 1.0 - exp( ( 1.0 - model_.juncExpBC ) * xfc ) ) /
1692  ( 1.0 - model_.juncExpBC );
1693 
1694  // Temp. adj. critical voltage
1695  // tVCrit = vt * log( vt / ( 1.41414 * model_.satCur ) );
1696  tVCrit = vt * log( vt / ( CONSTroot2 * model_.satCur ) );
1697 
1698  tSatCur = model_.satCur * factor;
1699  // Temp. adj. beta's
1700  tBetaF = model_.betaF * bfactor;
1701  tBetaR = model_.betaR * bfactor;
1702  // Temp. adj. leakage currents
1707  tBELeakCur = model_.leakBECurrent * exp( factlog / model_.leakBEEmissionCoeff ) / bfactor;
1708  tBCLeakCur = model_.leakBCCurrent * exp( factlog / model_.leakBCEmissionCoeff ) / bfactor;
1709 
1716 
1717  if (model_.rollOffF != 0)
1719  else
1720  tInvRollOffF = 0;
1721  if (model_.rollOffR != 0)
1723  else
1724  tInvRollOffR = 0;
1725  if (model_.earlyVoltF != 0)
1727  else
1728  tInvEarlyVoltF = 0;
1729  if (model_.earlyVoltR != 0)
1731  else
1732  tInvEarlyVoltR = 0;
1733 
1734 #ifdef Xyce_DEBUG_DEVICE
1735  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
1736  {
1737 
1738  Xyce::dout() << section_divider << std::endl;
1739  Xyce::dout() << "In BJTInst::updateTemperature" << std::endl;
1740  Xyce::dout() << section_divider << std::endl;
1741  Xyce::dout() << "TEMP = " << TEMP << std::endl;
1742  Xyce::dout() << "TNOM = " << TNOM << std::endl;
1743  Xyce::dout() << "vt = " << vt << std::endl;
1744  Xyce::dout() << "tSatCur = " << tSatCur << std::endl;
1745  Xyce::dout() << "tBetaF = " << tBetaF << std::endl;
1746  Xyce::dout() << "tBetaR = " << tBetaR << std::endl;
1747  Xyce::dout() << "tBELeakCur = " << tBELeakCur << std::endl;
1748  Xyce::dout() << "tBCLeakCur = " << tBELeakCur << std::endl;
1749  Xyce::dout() << "tBEPot = " << tBEPot << std::endl;
1750  Xyce::dout() << "tBECap = " << tBECap << std::endl;
1751  Xyce::dout() << "tBCPot = " << tBCPot << std::endl;
1752  Xyce::dout() << "tBCCap = " << tBCCap << std::endl;
1753  Xyce::dout() << "tDepCap = " << tDepCap << std::endl;
1754  Xyce::dout() << "tF1 = " << tF1 << std::endl;
1755  Xyce::dout() << "tF4 = " << tF4 << std::endl;
1756  Xyce::dout() << "tF5 = " << tF5 << std::endl;
1757  Xyce::dout() << "tleakBEEmissionCoeff = " << tleakBEEmissionCoeff << std::endl;
1758  Xyce::dout() << "tleakBCEmissionCoeff = " << tleakBCEmissionCoeff << std::endl;
1759  Xyce::dout() << "tRollOffExp = " << tRollOffExp << std::endl;
1760  Xyce::dout() << "tInvRollOffF = " << tInvRollOffF << std::endl;
1761  Xyce::dout() << "tInvRollOffR = " << tInvRollOffR << std::endl;
1762  Xyce::dout() << "tInvEarlyVoltF = " << tInvEarlyVoltF << std::endl;
1763  Xyce::dout() << "tInvEarlyVoltR = " << tInvEarlyVoltR << std::endl;
1764  Xyce::dout() << "tBaseResist = " << tBaseResist << std::endl;
1765  Xyce::dout() << "tCollectorResist = " << tCollectorResist << std::endl;
1766  Xyce::dout() << "tEmitterResist = " << tEmitterResist << std::endl;
1767  Xyce::dout() << section_divider << std::endl;
1768  Xyce::dout() << std::endl;
1769  }
1770 #endif
1771 
1772  return true;
1773 }
1774 
1775 
1776 //----------------------------------------------------------------------------
1777 // Function : Instance::lambertWCurrent
1778 // Purpose : Determine the current through an individual BJT
1779 // Special Notes :
1780 // Scope : public
1781 // Creator : Nick Johnson, Summer Intern
1782 // Creation Date : 7/30/02
1783 //---------------------------------------------------------------------------
1784 bool Instance::lambertWCurrent(double &Id, double &Gd, double Vd, double Vte, double Isat)
1785 {
1786  double RS = 1.0e-12;
1787  double arg1 = (Vd + Isat*RS)/Vte;
1788  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
1789  double evd = exp(arg1);
1790  double lambWArg = Isat*RS*evd/Vte;
1791  double lambWReturn;
1792  int ierr;
1793  double lambWError;
1794  devSupport.lambertw(lambWArg, lambWReturn, ierr, lambWError);
1795 
1796  Id = -Isat+Vte*(lambWReturn)/RS;
1797  Gd = lambWReturn / ((1 + lambWReturn)*RS);
1798 
1799  return true;
1800 }
1801 
1802 //-----------------------------------------------------------------------------
1803 // Function : Instance::loadDeviceMask
1804 //
1805 // Purpose : Loads the zero elements of the device mask
1806 //
1807 // Special Notes : elements of the error vector associated with zero
1808 // elements of the mask will not be included in weighted
1809 // norms by the time integrator.
1810 //
1811 // Scope : public
1812 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
1813 // Creation Date : 01/19/07
1814 //-----------------------------------------------------------------------------
1816 {
1817  bool returnVal=false;
1818  if (getDeviceOptions().newExcessPhase)
1819  {
1820  N_LAS_Vector * maskVectorPtr = extData.deviceMaskVectorPtr;
1821 
1822  (*maskVectorPtr)[li_Ifx] = 0.0;
1823  (*maskVectorPtr)[li_dIfx] = 0.0;
1824  returnVal = true;
1825  }
1826  return (returnVal);
1827 }
1828 
1829 //-----------------------------------------------------------------------------
1830 // Function : Instance::loadDAEQVector
1831 //
1832 // Purpose : Loads the Q-vector contributions for a single
1833 // BJT instance.
1834 //
1835 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1836 // which the system of equations is represented as:
1837 //
1838 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1839 //
1840 // Scope : public
1841 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1842 // Creation Date : 01/26/03
1843 //-----------------------------------------------------------------------------
1845 {
1846  double td = model_.excessPhaseFac;
1847  double vbe_diff = vBE - vBE_orig;
1848  double vbc_diff = vBC - vBC_orig;
1849 
1850  double * solVec = extData.nextSolVectorRawPtr;
1851  double * qVec = extData.daeQVectorRawPtr;
1852 
1853  qVec[li_Base] -= - model_.TYPE * qBX;
1854  qVec[li_Subst] -= -model_.TYPE * qCS;
1855  qVec[li_CollP] -= model_.TYPE * ( qCS + qBX + qBCdep + qBCdiff );
1856  qVec[li_BaseP] -= -model_.TYPE * ( qBEdep + qBEdiff + qBCdep + qBCdiff );
1857  qVec[li_EmitP] -= model_.TYPE*( qBEdep + qBEdiff );
1858 
1859  // excess phase ERK-dcop
1860  if (td != 0 && getDeviceOptions().newExcessPhase)
1861  {
1862  qVec[li_Ifx] += solVec[li_Ifx];
1863 
1864  if (!(getSolverState().dcopFlag) )
1865  {
1866  qVec[li_dIfx] += solVec[li_dIfx]*td*td;
1867  }
1868  else
1869  {
1870  qVec[li_dIfx] = 0.0;
1871  }
1872  }
1873 
1874  // load up the jdxp terms
1876  {
1877  double Cp_Jdxp_q = 0.0;
1878  double Ep_Jdxp_q = 0.0;
1879  double Bp_Jdxp_q = 0.0;
1880 
1881  if (!origFlag)
1882  {
1883  Cp_Jdxp_q = -(capBCdep + capBCdiff)*vbc_diff;
1884  Cp_Jdxp_q *= model_.TYPE;
1885 
1886  Bp_Jdxp_q = (capBEdep + capBEdiff)*vbe_diff
1887  + (capBCdiff + capBCdep + capeqCB) *vbc_diff;
1888  Bp_Jdxp_q *= model_.TYPE;
1889 
1890  Ep_Jdxp_q = - capeqCB * vbc_diff - (capBEdiff + capBEdep)* vbe_diff;
1891  Ep_Jdxp_q *= model_.TYPE;
1892  }
1893 
1894  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
1895  dQdxdVp[li_CollP] += Cp_Jdxp_q;
1896  dQdxdVp[li_BaseP] += Bp_Jdxp_q;
1897  dQdxdVp[li_EmitP] += Ep_Jdxp_q;
1898  }
1899 
1900  if( loadLeadCurrent )
1901  {
1902  double * storeLeadQ = extData.storeLeadCurrQCompRawPtr;
1903 
1904  storeLeadQ[li_store_dev_ic] = -model_.TYPE * ( qCS + qBX + qBCdep + qBCdiff );
1905  storeLeadQ[li_store_dev_ib] = model_.TYPE * ( qBX + qBEdep + qBEdiff + qBCdep + qBCdiff );
1906  storeLeadQ[li_store_dev_ie] = -model_.TYPE*( qBEdep + qBEdiff );
1907  storeLeadQ[li_store_dev_is] = model_.TYPE * qCS;
1908  }
1909 
1910  return true;
1911 }
1912 
1913 //-----------------------------------------------------------------------------
1914 // Function : Instance::auxDAECalculations
1915 //
1916 // Purpose : This function is supposed to handle a lot of the final
1917 // "cleanup" calculations that were done, in the old-DAE
1918 // formulation, at the end of updateSecondaryState.
1919 //
1920 // For the new-DAE form, they need to be done elsewhere, as
1921 // updateSecondaryState isn't called for new-DAE.
1922 //
1923 // Special Notes :
1924 // Scope : public
1925 // Creator : Eric Keiter, 9233, Computational Sciences.
1926 // Creation Date : 04/15/04
1927 //-----------------------------------------------------------------------------
1929 {
1930  double i_fx;
1931  double td = model_.excessPhaseFac;
1932  double * solVec = extData.nextSolVectorRawPtr;
1933 
1934  if ( td != 0 && !(getSolverState().dcopFlag) )
1935  {
1936  i_fx = solVec[li_Ifx];
1937  iCE = i_fx - iBC / qB;
1938  }
1939  else
1940  {
1941  iCE = (iBE - iBC)/ qB;
1942  }
1943 
1944  iC = iCE - iBC / tBetaR - iBCleak;
1945  iB = iBE / tBetaF + iBEleak + iBC / tBetaR + iBCleak;
1946  iE = -iC-iB;
1947 
1948  if (td != 0)
1949  {
1950  if (!(getSolverState().dcopFlag) )
1951  {
1952  diCEdvBp = invqB * (-invqB * iBC * dqBdvBp - gBC);
1953  diCEdvCp = invqB * (-invqB * iBC * dqBdvCp + gBC);
1954  diCEdvEp = -invqB * invqB * iBC * dqBdvEp;
1955  }
1956  else // ERK-dcop: if dcop, use the td=0 case (copied from below)
1957  {
1958  diCEdvBp = invqB * (iCE * dqBdvBp + gBE - gBC);
1959  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
1960  diCEdvEp = invqB * (iCE * dqBdvEp - gBE);
1961  }
1962 
1963  diBEdvBp = invqB *(invqB* iBE * dqBdvBp + gBE);
1964  diBEdvCp = invqB * invqB * iBE * dqBdvCp;
1965  diBEdvEp = invqB * (invqB * iBE * dqBdvEp - gBE);
1966  }
1967  else
1968  {
1969  diCEdvBp = invqB * (iCE * dqBdvBp + gBE - gBC);
1970  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
1971  diCEdvEp = invqB * (iCE * dqBdvEp - gBE);
1972  }
1973 
1974  return;
1975 }
1976 
1977 //-----------------------------------------------------------------------------
1978 // Function : Instance::loadDAEFVector
1979 //
1980 // Purpose : Loads the F-vector contributions for a single
1981 // BJT instance.
1982 //
1983 // Special Notes :
1984 //
1985 // Scope : public
1986 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1987 // Creation Date : 01/26/03
1988 //-----------------------------------------------------------------------------
1990 {
1991  double coefC, coefB, coefE, coefCp, coefBp, coefEp;
1992 
1993  double td = model_.excessPhaseFac;
1994  double * solVec = extData.nextSolVectorRawPtr;
1995  double * fVec = extData.daeFVectorRawPtr;
1996 
1997  double vbe_diff = vBE - vBE_orig;
1998  double vbc_diff = vBC - vBC_orig;
1999  double vce_diff = vbe_diff - vbc_diff;
2000 
2001  fVec[li_Coll] -= -vCCp * gCpr;
2002  fVec[li_Base] -= -vBBp * gX;
2003  fVec[li_Emit] -= -vEEp * gEpr;
2004  fVec[li_CollP] -= vCCp * gCpr + model_.TYPE * ( - iC );
2005  fVec[li_BaseP] -= vBBp * gX - model_.TYPE * ( iB );
2006  fVec[li_EmitP] -= vEEp * gEpr + model_.TYPE * ( - iE );
2007 
2008  // excess phase ERK-dcop.
2009  double i_fx = 0.0;
2010  double di_fx = 0.0;
2011 
2013  {
2014  i_fx = solVec[li_Ifx];
2015  di_fx = solVec[li_dIfx];
2016 
2017  if (td != 0)
2018  {
2019  if (!(getSolverState().dcopFlag) )
2020  {
2021  // omega0 = 1/td;
2022  fVec[li_Ifx] += - di_fx;
2023  fVec[li_dIfx] += 3 * di_fx*td + 3*i_fx -3 * iBE / qB;
2024  }
2025  else
2026  {
2027  fVec[li_Ifx] += i_fx -iBE/qB;
2028  fVec[li_dIfx] = 0.0;
2029  }
2030  }
2031  else
2032  {
2033  fVec[li_Ifx] += i_fx;
2034  fVec[li_dIfx] += di_fx;
2035  }
2036  }
2037 
2038  double Cp_Jdxp_f=0.0;
2039  double Bp_Jdxp_f=0.0;
2040  double Ep_Jdxp_f=0.0;
2041  double dIfx_Jdxp_f=0.0 ;
2042  double Ifx_Jdxp_f=0.0 ;
2043 
2044  // Now for the jdxp terms
2046  {
2047  if (!origFlag)
2048  {
2049  Cp_Jdxp_f = + diCEdvBp * vbe_diff
2050  + diCEdvCp * vce_diff
2051  - gBCtot * vbc_diff;
2052 
2053  Cp_Jdxp_f *= model_.TYPE;
2054 
2055  Bp_Jdxp_f = gBEtot * vbe_diff + gBCtot * vbc_diff;
2056  Bp_Jdxp_f *= model_.TYPE;
2057 
2058  Ep_Jdxp_f = - diCEdvCp * vce_diff - (diCEdvBp + gBEtot) * vbe_diff;
2059  Ep_Jdxp_f *= model_.TYPE;
2060 
2061  // ERK-dcop.
2062  if ( td != 0 && getDeviceOptions().newExcessPhase )
2063  {
2064  if ( !(getSolverState().dcopFlag) )
2065  {
2066  dIfx_Jdxp_f = -3 *( diBEdvBp*vbe_diff + diBEdvCp * vce_diff);
2067  dIfx_Jdxp_f *= model_.TYPE;
2068  }
2069  else
2070  {
2071  Ifx_Jdxp_f = ( diBEdvBp*vbe_diff + diBEdvCp * vce_diff);
2072  Ifx_Jdxp_f *= model_.TYPE;
2073  }
2074  }
2075  }
2076 
2077  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
2078  dFdxdVp[li_CollP] += Cp_Jdxp_f;
2079  dFdxdVp[li_BaseP] += Bp_Jdxp_f;
2080  dFdxdVp[li_EmitP] += Ep_Jdxp_f;
2081 
2082  // ERK-dcop.
2083  if ( td != 0 && getDeviceOptions().newExcessPhase )
2084  {
2085  if ( !(getSolverState().dcopFlag) )
2086  {
2087  dFdxdVp[li_dIfx] += dIfx_Jdxp_f;
2088  }
2089  else
2090  {
2091  dFdxdVp[li_Ifx] += Ifx_Jdxp_f;
2092  }
2093  }
2094  }
2095 
2096  if( loadLeadCurrent )
2097  {
2098  double * storeLeadF = extData.nextStoVectorRawPtr;
2099 
2100  storeLeadF[li_store_dev_ic] = model_.TYPE * ( iC );
2101  storeLeadF[li_store_dev_is] = 0;
2102  storeLeadF[li_store_dev_ie] = model_.TYPE * ( iE );
2103  storeLeadF[li_store_dev_ib] = model_.TYPE * ( iB );
2104  }
2105  return true;
2106 }
2107 
2108 //-----------------------------------------------------------------------------
2109 // Function : Instance::loadDAEdQdx
2110 //
2111 // Purpose : Loads the Q-vector contributions for a single
2112 // BJT instance.
2113 //
2114 // Special Notes : The "Q" vector is part of a standard DAE formalism in
2115 // which the system of equations is represented as:
2116 //
2117 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
2118 //
2119 // The "Q" vector contains charges and fluxes. So, this
2120 // matrix will contain only the capacitance terms.
2121 //
2122 // Scope : public
2123 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2124 // Creation Date : 03/05/04
2125 //-----------------------------------------------------------------------------
2127 {
2128  double td = model_.excessPhaseFac;
2129 
2130  N_LAS_Matrix & dQdx = *(extData.dQdxMatrixPtr);
2131 
2133 
2137 
2141  += capCS + capBX + capBCdep + capBCdiff;
2142 
2144  += -capBCdep - capBCdiff;
2145 
2147  += -capBCdiff - capBCdep - capeqCB;
2148 
2150  += capBEdiff + capBEdep + capBCdiff + capBCdep + capeqCB;
2151 
2153  += -capBEdiff - capBEdep;
2156  += -capBEdiff - capBEdep - capeqCB;
2158  += capBEdiff + capBEdep;
2159 
2160  // excess phase terms. ERK-dcop
2161  if ( td != 0 && getDeviceOptions().newExcessPhase )
2162  {
2163  if (!(getSolverState().dcopFlag) )
2164  {
2165  dQdx[li_Ifx][AIfxEquIfxNodeOffset] += 1;
2166  dQdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1*td*td;
2167  }
2168  }
2169 
2170  return true;
2171 }
2172 
2173 //-----------------------------------------------------------------------------
2174 // Function : Instance::loadDAEdFdx ()
2175 //
2176 // Purpose : Loads the F-vector contributions for a single
2177 // BJT instance.
2178 //
2179 // Special Notes : See the special notes for loadDAEFVector.
2180 //
2181 // This is an algebraic constaint.
2182 //
2183 // Scope : public
2184 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2185 // Creation Date : 03/05/04
2186 //-----------------------------------------------------------------------------
2188 {
2189  double td = model_.excessPhaseFac;
2190 
2191  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
2192 
2199 
2201 
2203 
2204 
2208  += diCEdvBp - gBCtot;
2210 
2211  // excess phase terms. ERK-dcop
2212  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
2213  dFdx[li_CollP][ACollPEquIfxNodeOffset] += 1.0 * model_.TYPE;
2214 
2217  += -diBrdvCp - gBCtot;
2218 
2220  += -diBrdvBp + gBEtot + gBCtot;
2221 
2223  += -diBrdvEp - gBEtot;
2224 
2228  += - diCEdvBp - gBEtot;
2229 
2230  // ERK Note: -diCEdvEp should equal + diCEdvBp + diCEdvCp. In the
2231  // original old-DAE form, + diCEdvBp + diCEdvCp is used. In
2232  // the more recent new-DAE form, we've used diCEdvEp, but it sometimes
2233  // results in subtle differences between old- and new-DAE jacobians.
2234  // This should matter, but .....
2236  //+= gBEtot + gEpr - diCEdvEp;
2237  += gBEtot + gEpr + diCEdvBp + diCEdvCp; // this is a test.
2238 
2239  // excess phase terms. ERK-dcop
2240  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
2241  dFdx[li_EmitP][AEmitPEquIfxNodeOffset] += -1.0 * model_.TYPE;
2242 
2243  // excess phase terms. ERK-dcop
2245  {
2246  if ( td != 0 )
2247  {
2248  if ( !(getSolverState().dcopFlag) )
2249  {
2250  dFdx[li_Ifx][AIfxEqudIfxNodeOffset]+= -1;
2254  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 3* td;
2255  dFdx[li_dIfx][AdIfxEquIfxNodeOffset] += 3;
2256  }
2257  else
2258  {
2262  dFdx[li_Ifx][AIfxEquIfxNodeOffset]+= 1;
2263  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1;
2264  }
2265  }
2266  else
2267  {
2268  dFdx[li_Ifx][AIfxEquIfxNodeOffset]+= 1;
2269  dFdx[li_dIfx][AdIfxEqudIfxNodeOffset] += 1;
2270  }
2271  }
2272 
2273  return true;
2274 }
2275 
2276 //-----------------------------------------------------------------------------
2277 // Function : Instance::updatePrimaryState
2278 // Purpose :
2279 // Special Notes :
2280 // Scope : public
2281 // Creator : Robert J. Hoekstra
2282 // Creation Date : 1/13/00
2283 //-----------------------------------------------------------------------------
2285 {
2286  // Do the bulk of the work in updateIntermediateVars:
2287  bool bsuccess = updateIntermediateVars();
2288 
2289  double * staVec = extData.nextStaVectorRawPtr;
2290  double * currStaVec = extData.currStaVectorRawPtr;
2291 
2292  // save voltage drops
2293 
2294  double * stoVec = extData.nextStoVectorRawPtr;
2295  stoVec[li_storevBE] = vBE;
2296  stoVec[li_storevBC] = vBC;
2297  stoVec[li_store_capeqCB] = capeqCB;
2298 
2299  staVec[li_qstateBEdiff] = qBEdiff;
2300  staVec[li_qstateBEdep] = qBEdep;
2301  staVec[li_qstateBCdiff] = qBCdiff;
2302  staVec[li_qstateBCdep] = qBCdep;
2303  staVec[li_qstateBX] = qBX;
2304  staVec[li_qstateCS] = qCS;
2305 
2306 
2307  // if this is the first newton step of the first time step
2308  // of the transient simulation, we need to enforce that the
2309  // time derivatives w.r.t. charge are zero. This is to maintain 3f5
2310  // compatibility. ERK.
2311 
2312  if (!(getSolverState().dcopFlag) && (getSolverState().initTranFlag) && getSolverState().newtonIter==0)
2313  {
2314  currStaVec[li_qstateBEdiff] = qBEdiff;
2315  currStaVec[li_qstateBEdep] = qBEdep;
2316  currStaVec[li_qstateBCdiff] = qBCdiff;
2317  currStaVec[li_qstateBCdep] = qBCdep;
2318  currStaVec[li_qstateBX] = qBX;
2319  currStaVec[li_qstateCS] = qCS;
2320  }
2321 
2322  return bsuccess;
2323 }
2324 
2325 //-----------------------------------------------------------------------------
2326 // Function : Instance::updateSecondaryState
2327 // Purpose :
2328 // Special Notes :
2329 // Scope : public
2330 // Creator : Robert J. Hoekstra
2331 // Creation Date : 1/13/00
2332 //-----------------------------------------------------------------------------
2334 {
2335  double * staDerivVec = extData.nextStaDerivVectorRawPtr;
2336 
2337  // Now that the state vector for time=0 is up-to-date, get the derivative
2338  // with respect to time of the charge, to obtain the best estimate for
2339  // the current in the capacitor.
2340 
2341  iBEdiff = staDerivVec[li_qstateBEdiff];
2342  iBEdep = staDerivVec[li_qstateBEdep ];
2343  iCS = staDerivVec[li_qstateCS ];
2344  iBCdiff = staDerivVec[li_qstateBCdiff];
2345  iBCdep = staDerivVec[li_qstateBCdep ];
2346  iBX = staDerivVec[li_qstateBX ];
2347 
2348  return true;
2349 }
2350 
2351 //-----------------------------------------------------------------------------
2352 // Function : Instance::oldDAEExcessPhaseCalculation1
2353 //
2354 // Purpose : This handles the parts of the calculation of excess phase
2355 // terms that need to be done in the
2356 // updatePrimaryState function.
2357 //
2358 // Special Notes : The excess phase calculation is based on a second-order
2359 // time derivative.
2360 //
2361 // Most of the excess phase work is done in the companion
2362 // function, oldDAEExcessPhaseCalculation2.
2363 //
2364 // This function mainly enforces a constant history.
2365 //
2366 // Scope : public
2367 // Creator : Eric Keiter, 9233, Computational Sciences.
2368 // Creation Date : 04/11/04
2369 //-----------------------------------------------------------------------------
2371 {
2372  // do excess phase stuff if we are in transient mode and td is nonzero.
2373  double td = model_.excessPhaseFac;
2374 
2375  currCexbc = lastCexbc = 0.0;
2376 
2377  if (!(getSolverState().dcopFlag) && td != 0)
2378  {
2379  // If there is no cexbc history, create one and use it.
2380  if (getSolverState().beginIntegrationFlag)
2381  {
2382  currCexbc = lastCexbc = iBE/qB;
2385  }
2386  }
2387 
2388  return;
2389 }
2390 
2391 //-----------------------------------------------------------------------------
2392 // Function : Instance::oldDAEExcessPhaseCalculation2
2393 //
2394 // Purpose : This handles the parts of the calculation of excess phase
2395 // terms that need to be done in the
2396 // updateSecondaryState function.
2397 //
2398 // Special Notes : This function has a companion function,
2399 // oldDAEExcessPhaseCalculation1. Most of the work is done
2400 // in this one.
2401 //
2402 // Scope : public
2403 // Creator : Eric Keiter, 9233, Computational Sciences.
2404 // Creation Date : 04/11/04
2405 //-----------------------------------------------------------------------------
2407  (double & iEX, double & gEX, double & iC_local)
2408 {
2409  ////////////////////////////////////////////////////////////////
2410  double td = model_.excessPhaseFac;
2411 
2412 #ifdef Xyce_DEBUG_DEVICE
2413  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2414  {
2415  Xyce::dout() << std::endl;
2416  Xyce::dout() << " Excess Phase stuff:" <<std::endl;
2417  Xyce::dout() << " name = " << getName() <<std::endl;
2418  Xyce::dout() << " td = " << td <<std::endl;
2419  }
2420 #endif
2421 
2422  ////////////////////////////////////////////////////////////////
2423  // ERK: 07/13/01
2424  //
2425  // weil's approx. for excess phase applied with backward-
2426  // euler integration
2427  // (copied over from chilespice).
2428  //
2429  ////////////////////////////////////////////////////////////////
2430 
2431  iEX=iBE;
2432  gEX=gBE;
2433 
2434  dt0 = getSolverState().currTimeStep;
2435  dt1 = getSolverState().lastTimeStep;
2436 
2437  iC_local = 0.0;
2438 
2439  // do excess phase stuff if we are in transient mode and td is nonzero.
2440  if (!(getSolverState().dcopFlag) && td != 0)
2441  {
2442  double arg1, arg2, denom;
2443 
2444  arg1 = dt0 / td;
2445  arg2 = 3.0 * arg1;
2446  arg1 = arg2 * arg1;
2447  denom = 1.0 + arg1 + arg2;
2448  phaseScalar = arg1 / denom;
2449 
2450  // Secondary state stuff:
2451  if (!getSolverState().beginIntegrationFlag)
2452  {
2453  currCexbc = (*extData.currStaVectorPtr)[li_istateCEXBC];
2454  lastCexbc = (*extData.lastStaVectorPtr)[li_istateCEXBC];
2455  }
2456 
2457  iC_local = ((currCexbc) * (1 + dt0 / dt1 + arg2) - (lastCexbc) * dt0 / dt1) / denom;
2458  iEX = iBE * phaseScalar;
2459  gEX = gBE * phaseScalar;
2460 
2461  nextCexbc = iC_local + iEX / qB;
2462  (*extData.nextStaVectorPtr)[li_istateCEXBC] = nextCexbc;
2463  }
2464 
2465  return;
2466 }
2467 
2468 //-----------------------------------------------------------------------------
2469 // Function : Instance::updateIntermediateVars
2470 // Purpose :
2471 // Special Notes :
2472 // Scope : public
2473 // Creator : Robert J. Hoekstra
2474 // Creation Date : 1/13/00
2475 //-----------------------------------------------------------------------------
2477 {
2478 
2479  bool bsuccess = true;
2480 
2481  double v_emit, v_emitP;
2482  double v_base, v_baseP;
2483  double v_coll, v_collP;
2484  double v_subst;
2485 
2486  double q1, q2;
2487  double * solVec = extData.nextSolVectorRawPtr;
2488 
2489 #ifdef Xyce_DEBUG_DEVICE
2490  if (getDeviceOptions().debugLevel>0 && getSolverState().debugTimeFlag)
2491  {
2492  Xyce::dout() << Xyce::section_divider << std::endl;
2493  Xyce::dout() << "Instance::updateIntermediateVars " << getName() <<std::endl;
2494  }
2495 #endif
2496 
2497  // obtain voltages:
2498  v_emit = solVec[li_Emit];
2499  v_emitP = solVec[li_EmitP];
2500  v_base = solVec[li_Base];
2501  v_baseP = solVec[li_BaseP];
2502  v_coll = solVec[li_Coll];
2503  v_collP = solVec[li_CollP];
2504  v_subst = solVec[li_Subst];
2505 
2506  vEEp = (v_emit - v_emitP);
2507  vBBp = (v_base - v_baseP);
2508  vCCp = (v_coll - v_collP);
2509 
2510  vBE = model_.TYPE * (v_baseP - v_emitP);
2511  vBC = model_.TYPE * (v_baseP - v_collP);
2512  vBX = model_.TYPE * (v_base - v_collP);
2513  //vCS = model_.TYPE * (v_collP - v_subst);
2514  vCS = model_.TYPE * (v_subst - v_collP);
2515 
2516  vBE_orig = vBE;
2517  vBC_orig = vBC;
2518 
2519  // Reset this to show we're starting from the originals
2520  origFlag = true;
2521  offFlag = false;
2522 
2524  {
2525  if( IC_GIVEN )
2526  {
2527  vBE = model_.TYPE * icVBE;
2528  double vCE = model_.TYPE * icVCE;
2529  vBC = vBE - vCE;
2530  vBX = vBC;
2531  origFlag = false;
2532  }
2533  else
2534  {
2536  {
2537  N_LAS_Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
2538  if ((*flagSolVectorPtr)[li_Emit] == 0 || (*flagSolVectorPtr)[li_EmitP] == 0 ||
2539  (*flagSolVectorPtr)[li_Base] == 0 || (*flagSolVectorPtr)[li_BaseP] == 0 ||
2540  (*flagSolVectorPtr)[li_Coll] == 0 || (*flagSolVectorPtr)[li_CollP] == 0 ||
2541  (*flagSolVectorPtr)[li_Subst] == 0 )
2542  {
2543  vBC = 0;
2544  vBE = tVCrit;
2545  vBX = vBC;
2546  origFlag = false;
2547  }
2548  }
2549  else
2550  {
2551  vBE=tVCrit;
2552  vBX = vBC;
2553  origFlag = false;
2554 #ifdef Xyce_DEBUG_DEVICE
2556  {
2557  Xyce::dout() << " Setting device initial condition to Base-Emitter drop=tVCrit (" << tVCrit << ")"<<std::endl;
2558  }
2559 #endif
2560  }
2561  }
2562 
2563 
2564 #ifdef Xyce_DEBUG_DEVICE
2565  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2566  {
2567  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2568  Xyce::dout() << " " <<std::endl;
2569  Xyce::dout() << " using UIC.\n";
2570  Xyce::dout() << " vBE = " << vBE << std::endl;
2571  Xyce::dout() << " vBC = " << vBC << std::endl;
2572  Xyce::dout() << " vBX = " << vBX << std::endl;
2573  Xyce::dout() << " vCS = " << vCS << std::endl;
2574  }
2575 #endif
2576  }
2577  else if ((getSolverState().initFixFlag || getSolverState().initJctFlag) && OFF)
2578  {
2579  vBX = vBC = vBE = 0.0 ;
2580  // NOTE: Must not set "origFlag" here, because that flags "non-converged"
2581  // which causes initFixFlag always to be set, which causes this section
2582  // always to be executed. Bad!
2583  // instead, flag with "offFlag" that will not be used in convergence
2584  // testing, but WILL be used in the voltage limiting machinery to make
2585  // this work properly.
2586  offFlag = true;
2587 
2588 #ifdef Xyce_DEBUG_DEVICE
2589  if (getDeviceOptions().debugLevel > 0 && getSolverState().debugTimeFlag)
2590  {
2591  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2592  Xyce::dout() << " " <<std::endl;
2593  Xyce::dout() << " BJT explicitly set OFF, zeroing all junction drops.\n";
2594  }
2595 #endif
2596  }
2597 
2598 
2599  if (getSolverState().newtonIter == 0)
2600  {
2601  if (!(getSolverState().dcopFlag)||(getSolverState().locaEnabledFlag && getSolverState().dcopFlag))
2602  {
2606  }
2607  else
2608  {
2609  vBE_old = vBE; // otherwise we have no history
2610  vBC_old = vBC;
2611  capeqCB = 0.0;
2612  }
2613  }
2614  else
2615  {
2619  }
2620 
2621 #ifdef Xyce_DEBUG_DEVICE
2623  {
2624  Xyce::dout() << " tVCrit = " << tVCrit << std::endl;
2625  Xyce::dout().width(3);
2626  Xyce::dout() << getSolverState().newtonIter;
2627  Xyce::dout().width(5); Xyce::dout() << getName();
2628  Xyce::dout() << " Blim: ";
2629  Xyce::dout() << " vBE=";
2630  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2631  Xyce::dout() << vBE;
2632  Xyce::dout() << " vBC=";
2633  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2634  Xyce::dout() << vBC << std::endl;
2635  }
2636 #endif
2637 
2638  // if we had bypass implemented, most of it would be here.
2639  // don't bother limiting voltages if we've already forced OFF.
2640 
2641  if (getDeviceOptions().voltageLimiterFlag && !(getSolverState().initFixFlag&&OFF))
2642  {
2643  // "reset" the junction voltages to keep them from changing too much.
2644  // only do this if this is not the first newton iteration, and not
2645  // a by pass step.
2646  int ichk1, icheck;
2647 
2648  if (getSolverState().newtonIter >= 0)
2649  {
2650  ichk1=1; // don't know what this is for...
2651 
2652  vBE = devSupport.pnjlim(vBE, vBE_old, vt, tVCrit, &icheck);
2653  vBC = devSupport.pnjlim(vBC, vBC_old, vt, tVCrit, &ichk1);
2654 
2655  if (ichk1 == 1) icheck=1;
2656 
2657  // set the origFlag to zero if things have changed.
2658  if (icheck==1) origFlag = false;
2659  }
2660 
2661 #ifdef Xyce_DEBUG_DEVICE
2662  if (getDeviceOptions().debugLevel > -2 && getSolverState().debugTimeFlag)
2663  {
2664  Xyce::dout().width(3);
2665  Xyce::dout() << getSolverState().newtonIter;
2666  Xyce::dout().width(5); Xyce::dout() << getName() ;
2667  Xyce::dout() << " Alim: ";
2668  Xyce::dout() << " vBE=";
2669  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2670  Xyce::dout() << vBE;
2671  Xyce::dout() << " vBC=";
2672  Xyce::dout().width(21); Xyce::dout().precision(13); Xyce::dout().setf(std::ios::scientific);
2673  Xyce::dout() << vBC;
2674 
2675  //cout << " vBE_orig = " << vBE_orig << std::endl;
2676  //cout << " vBC_orig = " << vBC_orig << std::endl <<std::endl;
2677  //cout << " origFlag = " << origFlag << std::endl;
2678 
2679  if (origFlag) Xyce::dout() << " SAME";
2680  else Xyce::dout() << " DIFF";
2681  Xyce::dout() << std::endl;
2682  }
2683 #endif
2684  }
2685 
2686  //Junction Current Calculations
2687 
2688  double csat = tSatCur * AREA;
2689  double vtF = vt * model_.emissionCoeffF;
2690  double vtR = vt * model_.emissionCoeffR;
2691  double vtE = vt * tleakBEEmissionCoeff;
2692  double vtC = vt * tleakBCEmissionCoeff;
2693  double iLeakBE = tBELeakCur * AREA;
2694  double iLeakBC = tBCLeakCur * AREA;
2695 
2696  // determine currents using LambertW
2697  if (lambertWFlag)
2698  {
2699  if( vBE > -5.0 * vtF )
2700  {
2701  lambertWCurrent(iBE, gBE, vBE, vtF, csat);
2702 
2703  if( iLeakBE == 0.0 )
2704  iBEleak = gBEleak = 0.0;
2705  else
2706  {
2707  lambertWCurrent(iBEleak, gBEleak, vBE, vtE, iLeakBE);
2708  }
2709  }
2710  else
2711  {
2712  gBE = -csat / vBE + getDeviceOptions().gmin;
2713  iBE = gBE * vBE;
2714  gBEleak = -iLeakBE / vBE;
2715  iBEleak = gBEleak * vBE;
2716  }
2717 
2718  if( vBC > -5.0 * vtR )
2719  {
2720  lambertWCurrent(iBC, gBC, vBC, vtR, csat);
2721 
2722  if( iLeakBC == 0.0 )
2723  iBCleak = gBCleak = 0.0;
2724  else
2725  {
2726  lambertWCurrent(iBCleak, gBCleak, vBC, vtC, iLeakBC);
2727  }
2728  }
2729  else
2730  {
2731  gBC = -csat / vBC + getDeviceOptions().gmin;
2732  iBC = gBC * vBC;
2733  gBCleak = -iLeakBC / vBC;
2734  iBCleak = gBCleak * vBC;
2735  }
2736  }
2737 
2738  // determine currents using normal exponential
2739  else
2740  {
2741  if (vBE > -5.0 * vtF)
2742  {
2743  double arg1 = vBE / vtF ;
2744  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2745  double devBE;
2746  double evBE;
2747  if (getSolverState().bjtArtParameterFlag)
2748  {
2749  evBE = devSupport.Xexp( arg1 , devBE, getDeviceOptions().exp_order );
2750  }
2751  else
2752  {
2753  evBE = exp( arg1 );
2754  devBE=evBE;
2755  }
2756  iBE = csat * ( evBE - 1.0 ) + getDeviceOptions().gmin * vBE;
2757  gBE = csat * devBE / vtF + getDeviceOptions().gmin;
2758 
2759  if (iLeakBE == 0.0)
2760  iBEleak = gBEleak = 0.0;
2761  else
2762  {
2763  double arg1 = vBE / vtE ;
2764  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2765  double devBEleak;
2766  double evBEleak;
2767  if (getSolverState().bjtArtParameterFlag)
2768  {
2769  evBEleak =devSupport.Xexp(arg1,devBEleak,getDeviceOptions().exp_order );
2770  }
2771  else
2772  {
2773  evBEleak = exp(arg1);
2774  devBEleak=evBEleak;
2775  }
2776  iBEleak = iLeakBE * (evBEleak - 1.0);
2777  gBEleak = iLeakBE * devBEleak / vtE;
2778  }
2779  }
2780  else
2781  {
2782  gBE = -csat / vBE + getDeviceOptions().gmin;
2783  iBE = gBE * vBE;
2784  gBEleak = -iLeakBE / vBE;
2785  iBEleak = gBEleak * vBE;
2786  }
2787 
2788  if( vBC > -5.0 * vtR )
2789  {
2790  double arg1 = vBC / vtR ;
2791  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2792  double devBC;
2793  double evBC;
2794  if (getSolverState().bjtArtParameterFlag)
2795  {
2796  evBC = devSupport.Xexp( arg1 , devBC, getDeviceOptions().exp_order );
2797  }
2798  else
2799  {
2800  evBC = exp( arg1 );
2801  devBC=evBC;
2802  }
2803  iBC = csat * ( evBC - 1.0 ) + getDeviceOptions().gmin * vBC;
2804  gBC = csat * devBC / vtR + getDeviceOptions().gmin;
2805 
2806  if (iLeakBC == 0.0)
2807  iBCleak = gBCleak = 0.0;
2808  else
2809  {
2810  double arg1 = vBC / vtC ;
2811  arg1 = Xycemin(CONSTMAX_EXP_ARG, arg1);
2812  double devBCleak;
2813  double evBCleak;
2814  if (getSolverState().bjtArtParameterFlag)
2815  {
2816  evBCleak= devSupport.Xexp(arg1,devBCleak,getDeviceOptions().exp_order);
2817  }
2818  else
2819  {
2820  evBCleak = exp(arg1);
2821  devBCleak=evBCleak;
2822  }
2823  iBCleak = iLeakBC * (evBCleak - 1.0);
2824  gBCleak = iLeakBC * devBCleak / vtC;
2825  }
2826  }
2827  else
2828  {
2829  gBC = -csat / vBC + getDeviceOptions().gmin;
2830  iBC = gBC * vBC;
2831  gBCleak = -iLeakBC / vBC;
2832  iBCleak = gBCleak * vBC;
2833  }
2834  }
2835 
2836  // base charge calculations:
2837  double rofF = tInvRollOffF / AREA;
2838  double rofR = tInvRollOffR / AREA;
2839 
2840  q1 = 1.0 / ( 1.0 - tInvEarlyVoltF * vBC - tInvEarlyVoltR * vBE );
2841 
2842  if (rofF == 0.0 && rofR == 0.0)
2843  {
2844  qB = q1;
2845  double q1_qB = q1 * qB;
2846 
2847  dqBdvEp = q1_qB * tInvEarlyVoltR;
2848  dqBdvCp = q1_qB * tInvEarlyVoltF;
2849 /* replaced with simpler expression after if block
2850  dqBdvBp = -q1_qB * (model_.invEarlyVoltR + model_.invEarlyVoltF);
2851 */
2852  }
2853  else
2854  {
2855  q2 = rofF * iBE + rofR * iBC;
2856 
2857  // Difference from SPICE: spice puts a max(0,) around the arg definition,
2858  // which means we use the square root expression all the way down to
2859  // q2= -1/4. This is not really good, because it means that the derivative
2860  // of the square root term goes to negative infinity at the break point
2861  // between the expressions, and qB will be very discontinuous.
2862  // This doesn't have a huge effect on the solutions, but can possibly
2863  // lead to convergence issues (see bug 1214). This fix hasn't yet
2864  // been shown to help anything, but it has not hurt anything either.
2865  if (q2 >= 0)
2866  {
2867 
2868  double arg = 1.0 + 4.0 * q2;
2869  double sqarg = 1.0;
2870 
2871  // if (fabs(arg) > 0.0) sqarg = sqrt(arg);
2872  // double rofF_gBE_invSqarg = rofF * gBE / sqarg;
2873  // double rofR_gBC_invSqarg = rofR * gBC / sqarg;
2874  // add Pspice compatible rolloff parameter NK = tRollOffExp
2875 
2876  if (fabs(arg) > 0.0) sqarg = pow(arg,tRollOffExp);
2877  double rofF_gBE_invSqarg = 0.0;
2878  double rofR_gBC_invSqarg = 0.0;
2879  if(arg != 0) rofF_gBE_invSqarg = rofF*gBE*2*tRollOffExp*sqarg/arg;
2880  if(arg != 0) rofR_gBC_invSqarg = rofR*gBC*2*tRollOffExp*sqarg/arg;
2881 
2882  qB = 0.5 * q1 * (1.0 + sqarg);
2883 
2884  dqBdvEp = q1 * (qB * tInvEarlyVoltR + rofF_gBE_invSqarg);
2885  dqBdvCp = q1 * (qB * tInvEarlyVoltF + rofR_gBC_invSqarg);
2886 
2887  /* replaced with simpler expression after if block
2888  dqBdvBp = -q1 * (qB * ( model_.invEarlyVoltF + model_.invEarlyVoltR) +
2889  rofF_gBE_invSqarg + rofR_gBC_invSqarg);
2890  */
2891  }
2892  else
2893  {
2894  qB = q1;
2895  dqBdvEp = q1*qB*tInvEarlyVoltR;
2896  dqBdvCp = q1*qB*tInvEarlyVoltF;
2897  }
2898  }
2899  dqBdvBp = - (dqBdvEp + dqBdvCp);
2900 
2901  invqB = 1.0 / qB;
2902 
2903 
2904  // NOTE: this is a block that (for some reason) was originally in the
2905  // updatePrimaryState function. It got moved as in general, the "state"
2906  // functions are only for manipulating the state vector.
2907  // NOTE: brackets are around this block of code to preserve variable scope.
2908 
2909  double arg, sarg;
2910  double ctot;
2911  double czBC;
2912  double czBX;
2913  double czBE;
2914  double czCS;
2915  double fcpc;
2916  double fcpe;
2917 
2918  // capacitance calculations and "current" charge value calculations:
2919  ctot = tBCCap * AREA;
2920  czBC = ctot * model_.baseFracBCCap;
2921  czBX = ctot - czBC;
2922  czBE = tBECap * AREA;
2923  czCS = model_.CJS * AREA;
2924  fcpc = model_.depCapCoeff * model_.potBC;
2925  fcpe = tDepCap;
2926 
2927  // High current perturbation to BE current
2928  // The high current perturbation to the BE current is only
2929  // used in determining capacitance values. It does not enter
2930  // directly into the RHS KCL equations, or the Jacobian.
2931  iBEhighCurr = iBE;
2932  gBEhighCurr = gBE;
2933 
2934  // geqCB is only calculated sometimes (based on the if-statement).
2935  // If it is not calculated, then the value used will be the one from
2936  // the state vector, that was pulled out already.
2937  bool geqCB_recalc(false);
2938  if (model_.transTimeF != 0.0 && vBE > 0.0 &&
2939  ((!getSolverState().dcopFlag)||getSolverState().tranopFlag||getSolverState().acopFlag))
2940  {
2941  double argtf = 0.0;
2942  double arg2 = 0.0;
2943  double arg3 = 0.0;
2944 
2945  if ( model_.transTimeBiasCoeffF != 0.0)
2946  {
2947  argtf = model_.transTimeBiasCoeffF;
2948 
2949  if (model_.transTimeVBCFac != 0.0)
2950  argtf *= exp(vBC * model_.transTimeVBCFac);
2951 
2952  arg2 = argtf;
2953 
2954  if (model_.transTimeHighCurrF != 0.0)
2955  {
2956  double tmp = iBEhighCurr /
2958 
2959  argtf *= tmp * tmp;
2960  arg2 = argtf * (3.0 - 2.0 * tmp);
2961  }
2962  arg3 = iBEhighCurr * argtf * model_.transTimeVBCFac;
2963  }
2964 
2965  iBEhighCurr *= (1.0 + argtf) / qB;
2966  gBEhighCurr = (gBEhighCurr * (1.0 + arg2) - iBEhighCurr * dqBdvEp) / qB;
2967 
2968  capeqCB = model_.transTimeF * (arg3 - iBEhighCurr * dqBdvCp) / qB;
2970  geqCB_recalc = true;
2971  }
2972 
2973  // baseP-emitP depletion capacitance
2974  if( czBE == 0.0 )
2975  {
2976  qBEdep = 0.0;
2977  capBEdep = 0.0;
2978  }
2979  else
2980  {
2981  if ( vBE < fcpe )
2982  {
2983  arg = 1.0 - vBE / tBEPot;
2984  sarg = exp( -model_.juncExpBE * log( arg ) );
2985 
2986  qBEdep = tBEPot * czBE * ( 1.0 - arg * sarg ) /
2987  ( 1.0 - model_.juncExpBE );
2988  capBEdep = czBE * sarg;
2989  }
2990  else
2991  {
2992  double czBEf2 = czBE / model_.f2;
2993 
2994  qBEdep = czBE * tF1 + czBEf2 * ( model_.f3 * ( vBE -
2995  fcpe ) + ( model_.juncExpBE / ( 2.0 *
2996  tBEPot ) ) * ( vBE * vBE - fcpe * fcpe ) );
2997  capBEdep = czBEf2 * ( model_.f3 + model_.juncExpBE * vBE /
2998  tBEPot );
2999  }
3000  }
3001 
3002  // baseP-emitP diffusion capacitance
3003  if (model_.transTimeF == 0.0)
3004  {
3005  qBEdiff = capBEdiff = 0.0;
3006  }
3007  else
3008  {
3011  }
3012 
3013  // baseP-collP depletion capacitance
3014  if( czBC == 0.0 )
3015  {
3016  qBCdep = 0.0;
3017  capBCdep = 0.0;
3018  }
3019  else
3020  {
3021  if ( vBC < fcpc )
3022  {
3023  arg = 1.0 - vBC / tBCPot;
3024  sarg = exp( -model_.juncExpBC * log( arg ) );
3025 
3026  qBCdep = tBCPot * czBC * ( 1.0 - arg * sarg ) /
3027  ( 1.0 - model_.juncExpBC );
3028  capBCdep = czBC * sarg;
3029  }
3030  else
3031  {
3032  double czBCf2 = czBC / model_.f6;
3033 
3034  qBCdep = czBC * tF5 + czBCf2 * ( model_.f7 * ( vBC -
3035  fcpc ) + ( model_.juncExpBC / ( 2.0 *
3036  tBCPot ) ) * ( vBC * vBC - fcpc * fcpc ) );
3037  capBCdep = czBCf2 * ( model_.f7 + model_.juncExpBC * vBC / tBCPot );
3038  }
3039  }
3040 
3041  // baseP-collP diffusion capacitance
3042  if (model_.transTimeR == 0.0)
3043  {
3044  qBCdiff = capBCdiff = 0.0;
3045  }
3046  else
3047  {
3050  }
3051 
3052  // base-collP depletion capacitance
3053  if( czBX == 0.0 )
3054  {
3055  qBX = 0.0;
3056  capBX = 0.0;
3057  }
3058  else
3059  {
3060  if (vBX < fcpc)
3061  {
3062  arg = 1.0 - vBX / tBCPot;
3063  sarg = exp( -model_.juncExpBC * log( arg ) );
3064 
3065  qBX = tBCPot * czBX * ( 1.0 - arg * sarg ) /
3066  ( 1.0 - model_.juncExpBC );
3067  capBX = czBX * sarg;
3068  }
3069  else
3070  {
3071  double czBXf2 = czBX / model_.f6;
3072 
3073  qBX = czBX * tF5 + czBXf2 * ( model_.f7 * ( vBX -
3074  fcpc ) + ( model_.juncExpBC / ( 2.0 *
3075  tBCPot ) ) * ( vBX * vBX - fcpc * fcpc ) );
3076  capBX = czBXf2 * ( model_.f7 + model_.juncExpBC * vBX /
3077  tBCPot );
3078  }
3079  }
3080 
3081  // collP-subst depletion capacitance
3082  if( czCS == 0.0 )
3083  {
3084  qCS = 0.0;
3085  capCS = 0.0;
3086  }
3087  else
3088  {
3089  if ( vCS < 0.0 )
3090  {
3091  arg = 1.0 - vCS / model_.potSubst;
3092  sarg = exp( -model_.expSubst * log( arg ) );
3093 
3094  qCS = model_.potSubst * czCS * ( 1.0 - arg * sarg ) /
3095  ( 1.0 - model_.expSubst );
3096  capCS = czCS * sarg;
3097  }
3098  else
3099  {
3100  qCS = vCS * czCS * ( 1.0 + model_.expSubst * vCS / ( 2.0 *
3101  model_.potSubst ) );
3102  capCS = czCS * ( 1.0 + model_.expSubst * vCS / model_.potSubst );
3103  }
3104  }
3105 
3106  // Here things get a little confusing. Generally, this is a logical place
3107  // to calculate iB, iC, and iE. iC and iE include the excess phase current.
3108 
3109  // Doing the old excess phase calculation, for both new and old-DAE, out
3110  // of curiousity to see that they match. However, if running new-DAE, these
3111  // calculations will only be used in diagnostics, not the actual loads.
3112  double iEX_tmp = 0.0; double gEX_tmp = 0.0; double iC_tmp = 0.0;
3114  oldDAEExcessPhaseCalculation2 (iEX_tmp,gEX_tmp,iC_tmp);
3115 
3116  if (getDeviceOptions().newExcessPhase)
3117  {
3118  auxDAECalculations (); // iB, iC and iE calculated here.
3119 
3120  }
3121  else
3122  {
3123  if (!(getSolverState().dcopFlag))
3124  {
3125  double pdt = getSolverState().pdt;
3126 
3127  // ERK. 12/17/2006.
3128  // It is necessary to set pdt=0.0, because for the first time step out of
3129  // the DCOP, all the time derivatives are forced to be zero. Thus, all
3130  // their derivatives should also be zero. If it wasn't for that, then pdt
3131  // could always be pdt. (it used to be, before the -jacobian_test capability).
3132  if (getSolverState().initTranFlag && getSolverState().newtonIter==0)
3133  {
3134  pdt = 0.0;
3135  }
3136 
3137  gCapBEdiff = capBEdiff * pdt;
3138  gCapBEdep = capBEdep * pdt;
3139  gCapBCdiff = capBCdiff * pdt;
3140  gCapBCdep = capBCdep * pdt;
3141  gCapBX = capBX * pdt;
3142  gCapCS = capCS * pdt;
3143  }
3144  else
3145  {
3146  gCapBEdiff = 0.0;
3147  gCapBEdep = 0.0;
3148  gCapBCdiff = 0.0;
3149  gCapBCdep = 0.0;
3150  gCapBX = 0.0;
3151  gCapCS = 0.0;
3152  }
3153 
3154  // Do the iB, iC, and iE calculations for the old-DAE case here.
3155  double iEX = 0.0;
3156  double gEX = 0.0;
3157 
3158  iC = iC_tmp;
3159  iEX = iEX_tmp;
3160  gEX = gEX_tmp;
3161 
3162  iCE = ( iEX - iBC ) / qB;
3163  iC += iCE - iBC / tBetaR - iBCleak;
3164 
3165  iB = iBE / tBetaF + iBEleak + iBC / tBetaR + iBCleak;
3166  iE = -iC-iB;
3167 
3168  // These 3 derivatives depend upon excess phase terms, old-DAE version, so
3169  // they have to be set up here.
3170  diCEdvEp = invqB * (iCE * dqBdvEp - gEX);
3171  diCEdvCp = invqB * (iCE * dqBdvCp + gBC);
3172  diCEdvBp = invqB * (iCE * dqBdvBp + gEX - gBC);
3173 
3174  }
3175 
3176  // Some derivatives setup:
3177  // Emitter and Conductor conductances
3180 
3181  // Generation of gX for b-b' resistance
3182  double rBpr = model_.minBaseResist / AREA;
3183  double rBpi = model_.baseResist / AREA - rBpr;
3184  double xjrB = model_.baseCurrHalfResist * AREA;
3185 
3186  gX = rBpr + rBpi / qB;
3187 
3188  if (fabs(xjrB) > 0.0)
3189  {
3190  double arg1 = Xycemax(iB / xjrB, 1.0e-09);
3191  double arg2 = (-1.0 + sqrt( 1.0 + 14.59025 * arg1)) / 2.4317 / sqrt(arg1);
3192  arg1 = tan(arg2);
3193  gX = rBpr + 3.0 * rBpi * (arg1 - arg2) / arg2 / arg1 / arg1;
3194  }
3195 
3196  if (fabs(gX) > 0.0) gX = 1.0 / gX;
3197 
3198  diBrdvB = gX;
3199  diBrdvCp = 0.0;
3200  diBrdvEp = 0.0;
3201  diBrdvBp = -gX;
3202 
3203  gBEtot = gBE / tBetaF + gBEleak;
3204  gBCtot = gBC / tBetaR + gBCleak;
3205 
3206  return bsuccess;
3207 }
3208 
3209 //-----------------------------------------------------------------------------
3210 // Function : Instance::outputPlotFiles
3211 // Purpose :
3212 // Special Notes :
3213 // Scope : public
3214 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3215 // Creation Date : 9/01/06
3216 //-----------------------------------------------------------------------------
3218 {
3219  bool bsuccess = true;
3220 
3221  int i;
3222  std::ostringstream oss;
3223  oss << "Q_" << getName() << ".dat";
3224  std::string filename = oss.str();
3225 
3226  double time = getSolverState().currTime;
3227  FILE *fp1;
3228 
3229  if (callsOutputPlot <= 0)
3230  {
3231  fp1 = fopen(filename.c_str(),"w");
3232  }
3233  else
3234  {
3235  fp1 = fopen(filename.c_str(),"a");
3236  }
3237 
3238  if (callsOutputPlot <= 0)
3239  {
3240  fprintf(fp1,
3241  " TITLE = \"Debug Excess Phase data: %s \"\n", getName().getEncodedName().c_str());
3242  }
3243 
3244  if (callsOutputPlot <= 0)
3245  {
3246  fprintf(fp1,"%s","\tVARIABLES = \"TIME (S)\",\n");
3247 
3248  fprintf(fp1,"%s","\t \"iBE/qB \",\n");
3249  fprintf(fp1,"%s","\t \"currCexbc \",\n");
3250  fprintf(fp1,"%s","\t \"lastCexbc \",\n");
3251  if (getDeviceOptions().newExcessPhase)
3252  {
3253  fprintf(fp1,"%s","\t \"i_fx \",\n");
3254  fprintf(fp1,"%s","\t \"di_fx \",\n");
3255  }
3256 
3257  fprintf(fp1,"%s","\tZONE F=POINT T=\"Excess Phase Data\"\n");
3258  }
3259 
3260  fprintf(fp1," %12.4e",time);
3261  fprintf(fp1," %12.4e",(iBE/qB));
3262  fprintf(fp1," %12.4e",currCexbc);
3263  fprintf(fp1," %12.4e",nextCexbc);
3264 
3265  if (getDeviceOptions().newExcessPhase)
3266  {
3267  double * solVec = extData.nextSolVectorRawPtr;
3268  double i_fx = solVec[li_Ifx];
3269  double di_fx = solVec[li_dIfx];
3270  fprintf(fp1," %12.4e",i_fx);
3271  fprintf(fp1," %12.4e",di_fx);
3272  }
3273 
3274  fprintf(fp1,"%s","\n");
3275 
3276  ++callsOutputPlot;
3277  fclose(fp1);
3278 
3279  return bsuccess;
3280 }
3281 
3282 //-----------------------------------------------------------------------------
3283 // Function : Model::processParams
3284 // Purpose :
3285 // Special Notes :
3286 // Scope : public
3287 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3288 // Creation Date : 6/03/02
3289 //-----------------------------------------------------------------------------
3291 {
3292 
3293  if (!leakBECurrentGiven && c2Given)
3294  leakBECurrent = c2 * satCur;
3295 
3296  if (!leakBCCurrentGiven && c4Given)
3297  leakBCCurrent = c4 * satCur;
3298 
3299  if (!minBaseResistGiven)
3301 
3302  if (VAFgiven && ( earlyVoltF != 0.0 ) )
3303  invEarlyVoltF = 1.0 / earlyVoltF;
3304  else
3305  invEarlyVoltF = 0.0;
3306 
3307  if( IKFgiven && ( rollOffF != 0.0 ) )
3308  invRollOffF = 1.0 / rollOffF;
3309  else
3310  invRollOffF = 0.0;
3311 
3312  if( VARgiven && ( earlyVoltR != 0.0 ) )
3313  invEarlyVoltR = 1.0 / earlyVoltR;
3314  else
3315  invEarlyVoltR = 0.0;
3316 
3317  if( IKRgiven && ( rollOffR != 0.0 ) )
3318  invRollOffR = 1.0 / rollOffR;
3319  else
3320  invRollOffR = 0.0;
3321 
3322  if( collectorResist != 0.0 )
3324  else
3325  collectorConduct = 0;
3326 
3327  if( emitterResist != 0.0 )
3328  emitterConduct = 1.0 / emitterResist;
3329  else
3330  emitterConduct = 0;
3331 
3332  if( given("VTF") && ( transTimeFVBC != 0.0 ) )
3333  transTimeVBCFac = 1.0 / ( transTimeFVBC * 1.44 );
3334  else
3335  transTimeVBCFac = 0.0;
3336 
3337  double mpi = M_PI;
3338  excessPhaseFac = ( excessPhase / ( 180.0 / mpi ) ) * transTimeF;
3339 
3340  if( given("FC") )
3341  {
3342  if( depCapCoeff > 0.9999 )
3343  {
3344  depCapCoeff = 0.9999;
3345  Xyce::dout() << "Bad Depletion Capacitance Coefficient" << std::endl;
3346  }
3347  }
3348  else
3349  {
3350  depCapCoeff = 0.5;
3351  }
3352 
3353  double xfc = log( 1.0 - depCapCoeff );
3354 
3355  f2 = exp( ( 1.0 + juncExpBE ) * xfc );
3356  f3 = 1.0 - depCapCoeff * ( 1.0 + juncExpBE );
3357  f6 = exp( ( 1.0 + juncExpBC ) * xfc );
3358  f7 = 1.0 - depCapCoeff * ( 1.0 + juncExpBC );
3359 
3360  return true;
3361 }
3362 
3363 //----------------------------------------------------------------------------
3364 // Function : Model::processInstanceParams
3365 // Purpose :
3366 // Special Notes :
3367 // Scope : public
3368 // Creator : Dave Shirely, PSSI
3369 // Creation Date : 03/23/06
3370 //----------------------------------------------------------------------------
3372 {
3373 
3374  std::vector<Instance*>::iterator iter;
3375  std::vector<Instance*>::iterator first = instanceContainer.begin();
3376  std::vector<Instance*>::iterator last = instanceContainer.end();
3377 
3378  for (iter=first; iter!=last; ++iter)
3379  {
3380  (*iter)->processParams();
3381  }
3382 
3383  return true;
3384 }
3385 
3386 //-----------------------------------------------------------------------------
3387 // Function : Model::Model
3388 // Purpose : modelblock constructor
3389 // Special Notes :
3390 // Scope : public
3391 // Creator : Laura Boucheron
3392 // Creation Date : 7/12/00
3393 //-----------------------------------------------------------------------------
3395  const Configuration & configuration,
3396  const ModelBlock & MB,
3397  const FactoryBlock & factory_block)
3398  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
3399  TYPE(1),
3400  TNOM(300.0),
3401  satCur(1.0e-16),
3402  betaF(100.0),
3403  BFgiven(false),
3404  BFMgiven(false),
3405  emissionCoeffF(1.0),
3406  earlyVoltF(1e99),
3407  VAgiven(false),
3408  VAFgiven(false),
3409  VBFgiven(false),
3410  rollOffF(1e99),
3411  IKFgiven(false),
3412  IKgiven(false),
3413  JBFgiven(false),
3414  leakBECurrent(0.0),
3415  leakBEEmissionCoeff(1.5),
3416  NEgiven(false),
3417  NLEgiven(false),
3418  betaR(1.0),
3419  BRgiven(false),
3420  BRMgiven(false),
3421  emissionCoeffR(1.0),
3422  earlyVoltR(1e99),
3423  VARgiven(false),
3424  VBgiven(false),
3425  VRBgiven(false),
3426  BVgiven(false),
3427  rollOffR(1e99),
3428  IKRgiven(false),
3429  JBRgiven(false),
3430 
3431  leakBCCurrent(0.0),
3432  leakBCEmissionCoeff(2.0),
3433  baseResist(0.0),
3434  baseCurrHalfResist(0.0),
3435  IRBgiven(false),
3436  JRBgiven(false),
3437  IOBgiven(false),
3438  minBaseResist(baseResist),
3439  emitterResist(0.0),
3440  collectorResist(0.0),
3441  depCapBE(0.0),
3442  potBE(0.75),
3443  VJEgiven(false),
3444  PEgiven(false),
3445 
3446  juncExpBE(0.33),
3447  MJEgiven(false),
3448  MEgiven(false),
3449 
3450  transTimeF(0.0),
3451  transTimeBiasCoeffF(0.0),
3452  transTimeFVBC(1.e99),
3453  transTimeHighCurrF(0.0),
3454  ITFgiven(false),
3455  JTFgiven(false),
3456 
3457  excessPhase(0.0),
3458  depCapBC(0.0),
3459  potBC(0.75),
3460  VJCgiven(false),
3461  PCgiven(false),
3462 
3463  juncExpBC(0.33),
3464  MJCgiven(false),
3465  MCgiven(false),
3466 
3467  baseFracBCCap(1.0),
3468  XCJCgiven(false),
3469  CDISgiven(false),
3470  transTimeR(0.0),
3471  CJS(0.0),
3472  CJSgiven(false),
3473  CCSgiven(false),
3474  CSUBgiven(false),
3475  potSubst(0.75),
3476  VJSgiven(false),
3477  PSgiven(false),
3478  PSUBgiven(false),
3479 
3480  expSubst(0.0),
3481  MJSgiven(false),
3482  MSgiven(false),
3483  ESUBgiven(false),
3484 
3485  betaExp(0.0),
3486  XTBgiven(false),
3487  TBgiven(false),
3488  TCBgiven(false),
3489 
3490  energyGap(1.11),
3491  tempExpIS(3.0),
3492  XTIgiven(false),
3493  PTgiven(false),
3494 
3495  depCapCoeff(0.5),
3496  fNCoeff(0.0),
3497  fNExp(1.0),
3498  c2(0.0),
3499  c4(0.0),
3500  rollOffExp(0.5),
3501  NKgiven(false),
3502  NKFgiven(false),
3503 
3504  leakBCCurrentGiven(false),
3505  JLCgiven(false),
3506  leakBECurrentGiven(false),
3507  JLEgiven(false),
3508  minBaseResistGiven(false),
3509  c2Given(false),
3510  c4Given(false)
3511 {
3512  // Default value is type=1 (NPN) so only check for pnp
3513  if (getType() == "pnp" || getType() == "PNP")
3514  {
3515  TYPE = -1;
3516  }
3517 
3518  ////////////////////////////////////////////////////////////////////////////////
3519  // trap for redunantly specified parameters (some can be specified by several different names)
3520  // forward beta (BF/BFM)
3521  if (BFgiven && BFMgiven)
3522  {
3523  UserError0(*this) << "Both BF and BFM are set, which is redundant.";
3524  }
3525  if (BFgiven || BFMgiven)
3526  {
3527  BFgiven = true; // this is the given flag that is actually used later.
3528  }
3529 
3530  // reverse beta (Re/BRM)
3531  if (BRgiven && BRMgiven)
3532  {
3533  UserError0(*this) << "Both BR and BRM are set, which is redundant.";
3534  }
3535  if (BRgiven || BRMgiven)
3536  {
3537  BRgiven = true; // this is the given flag that is actually used later.
3538  }
3539 
3540  // forward early voltage (VA/VAF/VBF)
3541  int VAFgivenCount = 0;
3542  VAFgivenCount += VAgiven?1:0;
3543  VAFgivenCount += VAFgiven?1:0;
3544  VAFgivenCount += VBFgiven?1:0;
3545  if (VAFgivenCount > 1)
3546  {
3547  UserError0(*this) << "The forward early voltage is set more than once. VA, VAF and VBF are aliases.";
3548  }
3549  if (VAFgivenCount > 0)
3550  {
3551  VAFgiven = true; // this is the given flag that is actually used later.
3552  }
3553 
3554  // reverse early voltage (VAR/VB/VRB/BV)
3555  int VARgivenCount = 0;
3556  VARgivenCount += VARgiven?1:0;
3557  VARgivenCount += VRBgiven?1:0;
3558  VARgivenCount += VBgiven?1:0;
3559  VARgivenCount += BVgiven?1:0;
3560  if (VARgivenCount > 1)
3561  {
3562  UserError0(*this) << "The reverse early voltage is set more than once. VAR,VB,VRB and BV are aliases.";
3563  }
3564  if (VARgivenCount > 0)
3565  {
3566  VARgiven = true; // this is the given flag that is actually used later.
3567  }
3568 
3569  // high current roll-off (IKF/IK/JBF)
3570  int IKFgivenCount = 0;
3571  IKFgivenCount += IKgiven?1:0;
3572  IKFgivenCount += IKFgiven?1:0;
3573  IKFgivenCount += JBFgiven?1:0;
3574  if (IKFgivenCount > 1)
3575  {
3576  UserError0(*this) << "High current roll-off is set more than once (IKF, JBF or IK).";
3577  }
3578  if (IKFgivenCount > 0)
3579  {
3580  IKFgiven = true; // this is the given flag that is actually used later.
3581  }
3582 
3583  // reverse high current roll-off (IKR/JBR)
3584  if (IKRgiven && JBRgiven)
3585  {
3586  UserError0(*this) << "Both IKR and JBRgiven are set, which is redundant.";
3587  }
3588  if (IKRgiven || JBRgiven)
3589  {
3590  IKRgiven = true; // this is the flag actually used later.
3591  }
3592 
3593  // BE leakage saturation current (ISE/JLE). C2 is sometimes thougt of as equivalent,
3594  // but it is not.
3596  {
3597  UserError0(*this) << "Both JLE and ISE are set, which is redundant.";
3598  }
3600  {
3601  leakBECurrentGiven = true; // this is the flag actually used later.
3602  }
3603 
3604  // BC leakage saturation current (ISC/JLC). C4 is sometimes thougt of as equivalent,
3605  // but it is not.
3607  {
3608  UserError0(*this) << "Both JLC and ISC are set, which is redundant.";
3609  }
3611  {
3612  leakBCCurrentGiven = true; // this is the flag actually used later.
3613  }
3614 
3615  // leakage emission coefficient (NE/NLE)
3616  if (NLEgiven && NEgiven)
3617  {
3618  UserError0(*this) << "Both NLE and NE are set, which is redundant.";
3619  }
3620  if (NLEgiven || NEgiven)
3621  {
3622  NEgiven = true; // this is the flag actually used later.
3623  }
3624 
3625  // BE exponential factor (MJE/ME)
3626  if (MJEgiven && MEgiven)
3627  {
3628  UserError0(*this) << " Both MJE and ME are set, which is redundant.";
3629  }
3630  if (MJEgiven || MEgiven)
3631  {
3632  MJEgiven = true; // this is the flag actually used later.
3633  }
3634 
3635  // BC exponential factor (MJC/MC)
3636  if (MJCgiven && MCgiven)
3637  {
3638  UserError0(*this) << "Both MJC and MC are set, which is redundant.";
3639  }
3640  if (MJCgiven || MCgiven)
3641  {
3642  MJCgiven = true; // this is the flag actually used later.
3643  }
3644 
3645  // zero-bias coll-subst capacitance (CJS/CCS/CSUB)
3646  int CJSgivenCount = 0;
3647  CJSgivenCount += CJSgiven?1:0;
3648  CJSgivenCount += CCSgiven?1:0;
3649  CJSgivenCount += CSUBgiven?1:0;
3650  if (CJSgivenCount > 1)
3651  {
3652  UserError0(*this) << "The zero-bias collector-substrate capacitance (CJS, CCS or CSUB) is set more than once.";
3653  }
3654  if (CJSgivenCount > 0)
3655  {
3656  CJSgiven = true; // this is the given flag that is actually used later.
3657  }
3658 
3659  // current for 1/2 base resist. (IRB/JRB/IOB)
3660  int IRBgivenCount = 0;
3661  IRBgivenCount += IRBgiven?1:0;
3662  IRBgivenCount += JRBgiven?1:0;
3663  IRBgivenCount += IOBgiven?1:0;
3664  if (IRBgivenCount > 1)
3665  {
3666  UserError0(*this) << "The current for 1/2 base resistance (IRB, JRB or IOB) is set more than once.";
3667  }
3668  if (IRBgivenCount > 0)
3669  {
3670  IRBgiven = true; // this is the given flag that is actually used later.
3671  }
3672 
3673  // BE built-in potential (VJE/PE)
3674  if (VJEgiven && PEgiven)
3675  {
3676  UserError0(*this) << "The BE built-in potential (VJE or PE) is set more than once.";
3677  }
3678  if (VJEgiven && PEgiven)
3679  {
3680  VJEgiven = true; // this is the given flag that is actually used later.
3681  }
3682 
3683  // BC built-in potential (VJC/PC)
3684  if (VJCgiven && PCgiven)
3685  {
3686  UserError0(*this) << "The BC built-in potential (VJC or PC) is set more than once.";
3687  }
3688  if (VJCgiven && PCgiven)
3689  {
3690  VJCgiven = true; // this is the given flag that is actually used later.
3691  }
3692 
3693  // fraction of BC capacitance to int. base node (XCJC/CDIS)
3694  if (XCJCgiven && CDISgiven)
3695  {
3696  UserError0(*this) << "XCJC and CDIS are both set (they are aliases).";
3697  }
3698  if (XCJCgiven && CDISgiven)
3699  {
3700  XCJCgiven = true; // this is the given flag that is actually used later.
3701  }
3702 
3703  // substrate junction built-in potential (VJS/PS/PSUB)
3704  int VJSgivenCount = 0;
3705  VJSgivenCount += PSgiven?1:0;
3706  VJSgivenCount += VJSgiven?1:0;
3707  VJSgivenCount += PSUBgiven?1:0;
3708  if (VJSgivenCount > 1)
3709  {
3710  UserError0(*this) << "The forward early voltage is set more than once. PS, VJS and PSUB are aliases.";
3711  }
3712  if (VJSgivenCount > 0)
3713  {
3714  VJSgiven = true; // this is the given flag that is actually used later.
3715  }
3716 
3717  // substrate junction built-in potential (MJS/MS/ESUB)
3718  int MJSgivenCount = 0;
3719  MJSgivenCount += MSgiven?1:0;
3720  MJSgivenCount += MJSgiven?1:0;
3721  MJSgivenCount += ESUBgiven?1:0;
3722  if (MJSgivenCount > 1)
3723  {
3724  UserError0(*this) << "The forward early voltage is set more than once. MS, MJS and ESUB are aliases.";
3725  }
3726  if (MJSgivenCount > 0)
3727  {
3728  MJSgiven = true; // this is the given flag that is actually used later.
3729  }
3730 
3731  // (ITF/JTF)
3732  if (ITFgiven && JTFgiven)
3733  {
3734  UserError0(*this) << "ITF and JTF are both set (they are aliases).";
3735  }
3736  if (ITFgiven && JTFgiven)
3737  {
3738  ITFgiven = true; // this is the given flag that is actually used later.
3739  }
3740 
3741  // (NK/NKF)
3742  if (NKgiven && NKFgiven)
3743  {
3744  UserError0(*this) << "NK and NKF are both set (they are aliases).";
3745  }
3746  if (NKgiven && NKFgiven)
3747  {
3748  NKgiven = true; // this is the given flag that is actually used later.
3749  }
3750 
3751  // beta temperature exponent (XTB/TB/TCB)
3752  int XTBgivenCount = 0;
3753  XTBgivenCount += TBgiven?1:0;
3754  XTBgivenCount += XTBgiven?1:0;
3755  XTBgivenCount += TCBgiven?1:0;
3756  if (XTBgivenCount > 1)
3757  {
3758  UserError0(*this) << "The forward early voltage is set more than once. TB, XTB and TCB are aliases.";
3759  }
3760  if (XTBgivenCount > 0)
3761  {
3762  XTBgiven = true; // this is the given flag that is actually used later.
3763  }
3764 
3765 
3766  // (PT/XTI)
3767  if (PTgiven && XTIgiven)
3768  {
3769  UserError0(*this) << "PT and XTI are both set (they are aliases).";
3770  }
3771  if (PTgiven && XTIgiven)
3772  {
3773  XTIgiven = true; // this is the given flag that is actually used later.
3774  }
3775 
3776  // end of redundant parameter traps
3777  ////////////////////////////////////////////////////////////////////////////////
3778 
3779 
3780  // Set params to constant default values:
3781  setDefaultParams ();
3782 
3783  // Set params according to .model line and constant defaults from metadata:
3784  setModParams (MB.params);
3785 
3786  // Set any non-constant parameter defaults:
3787  if (!given("TNOM"))
3789 
3790  if( !NKgiven)
3791  rollOffExp = 0.5;
3792 
3793  // Calculate any parameters specified as expressions:
3795 
3796  // calculate dependent (ie computed) params and check for errors:
3797  processParams ();
3798 }
3799 
3800 //-----------------------------------------------------------------------------
3801 // Function : Model::~Model
3802 // Purpose : destructor
3803 // Special Notes :
3804 // Scope : public
3805 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3806 // Creation Date : 3/16/00
3807 //-----------------------------------------------------------------------------
3809 {
3810  std::vector<Instance*>::iterator iterI;
3811  std::vector<Instance*>::iterator firstI = instanceContainer.begin ();
3812  std::vector<Instance*>::iterator lastI = instanceContainer.end ();
3813 
3814  // loop over instances:
3815  for (iterI = firstI; iterI != lastI; ++iterI)
3816  {
3817  delete (*iterI);
3818  }
3819 
3820 }
3821 
3822 //-----------------------------------------------------------------------------
3823 // Function : Model::printOutInstances
3824 // Purpose : debugging tool.
3825 // Special Notes :
3826 // Scope : public
3827 // Creator : Laura Boucheron
3828 // Creation Date : 7/11/00
3829 //-----------------------------------------------------------------------------
3830 std::ostream &Model::printOutInstances(std::ostream &os) const
3831 {
3832  std::vector<Instance*>::const_iterator iter;
3833  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
3834  std::vector<Instance*>::const_iterator last = instanceContainer.end();
3835 
3836  int i;
3837  os << " name modelName Parameters" << std::endl;
3838  for (i = 0, iter = first; iter != last; ++iter, ++i)
3839  {
3840  os << " " << i << ": " << (*iter)->getName() << " ";
3841  os << getName();
3842 
3843  os << std::endl;
3844  os << " AREA = " << (*iter)->AREA << std::endl;
3845  os << " icVBE = " << (*iter)->icVBE << std::endl;
3846  os << " icVCE = " << (*iter)->icVCE << std::endl;
3847  os << " TEMP = " << (*iter)->TEMP << std::endl;
3848  os << " OFF = " << (*iter)->OFF << std::endl;
3849 
3850  os << std::endl;
3851  }
3852 
3853  os << std::endl;
3854 
3855  return os;
3856 }
3857 
3858 //-----------------------------------------------------------------------------
3859 // Function : Model::forEachInstance
3860 // Purpose :
3861 // Special Notes :
3862 // Scope : public
3863 // Creator : David Baur
3864 // Creation Date : 2/4/2014
3865 //-----------------------------------------------------------------------------
3866 /// Apply a device instance "op" to all instances associated with this
3867 /// model
3868 ///
3869 /// @param[in] op Operator to apply to all instances.
3870 ///
3871 ///
3872 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
3873 {
3874  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
3875  op(*it);
3876 }
3877 
3878 
3879 //-----------------------------------------------------------------------------
3880 // BJT Master functions:
3881 //-----------------------------------------------------------------------------
3882 
3883 //-----------------------------------------------------------------------------
3884 // Function : Master::updateState
3885 // Purpose :
3886 // Special Notes :
3887 // Scope : public
3888 // Creator : Eric Keiter, SNL
3889 // Creation Date : 11/26/08
3890 //-----------------------------------------------------------------------------
3891 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
3892 {
3893  bool bsuccess = true;
3894 
3895  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3896  {
3897  Instance & bi = *(*it);
3898 
3899  double * stoVec = bi.extData.nextStoVectorRawPtr;
3900 
3901  // Do the bulk of the work in updateIntermediateVars:
3902  bool btmp = bi.updateIntermediateVars ();
3903  bsuccess = bsuccess && btmp;
3904 
3905  // save voltage drops
3906  stoVec[bi.li_storevBE] = bi.vBE;
3907  stoVec[bi.li_storevBC] = bi.vBC;
3908  stoVec[bi.li_store_capeqCB] = bi.capeqCB;
3909 
3910  staVec[bi.li_qstateBEdiff] = bi.qBEdiff;
3911  staVec[bi.li_qstateBEdep] = bi.qBEdep;
3912  staVec[bi.li_qstateBCdiff] = bi.qBCdiff;
3913  staVec[bi.li_qstateBCdep] = bi.qBCdep;
3914  staVec[bi.li_qstateBX] = bi.qBX;
3915  staVec[bi.li_qstateCS] = bi.qCS;
3916 
3917 
3918  // if this is the first newton step of the first time step
3919  // of the transient simulation, we need to enforce that the
3920  // time derivatives w.r.t. charge are zero. This is to maintain 3f5
3921  // compatibility. ERK.
3922 
3923  if (!(getSolverState().dcopFlag) && (getSolverState().initTranFlag) && getSolverState().newtonIter==0)
3924  {
3925  double * currStaVec = (bi.extData.currStaVectorRawPtr);
3926 
3927  currStaVec[bi.li_qstateBEdiff] = bi.qBEdiff;
3928  currStaVec[bi.li_qstateBEdep] = bi.qBEdep;
3929  currStaVec[bi.li_qstateBCdiff] = bi.qBCdiff;
3930  currStaVec[bi.li_qstateBCdep] = bi.qBCdep;
3931  currStaVec[bi.li_qstateBX] = bi.qBX;
3932  currStaVec[bi.li_qstateCS] = bi.qCS;
3933  }
3934  }
3935 
3936  return bsuccess;
3937 }
3938 
3939 //-----------------------------------------------------------------------------
3940 // Function : Master::updateSecondaryState
3941 // Purpose :
3942 // Special Notes :
3943 // Scope : public
3944 // Creator : Eric Keiter, SNL
3945 // Creation Date : 11/26/08
3946 //-----------------------------------------------------------------------------
3947 bool Master::updateSecondaryState ( double * staDerivVec, double * stoVec )
3948 {
3949  bool bsuccess = true;
3950 
3951  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3952  {
3953  Instance & bi = *(*it);
3954 
3955  // Now that the state vector for time=0 is up-to-date, get the derivative
3956  // with respect to time of the charge, to obtain the best estimate for
3957  // the current in the capacitor.
3958 
3959  bi.iBEdiff = staDerivVec[bi.li_qstateBEdiff];
3960  bi.iBEdep = staDerivVec[bi.li_qstateBEdep ];
3961  bi.iCS = staDerivVec[bi.li_qstateCS ];
3962  bi.iBCdiff = staDerivVec[bi.li_qstateBCdiff];
3963  bi.iBCdep = staDerivVec[bi.li_qstateBCdep ];
3964  bi.iBX = staDerivVec[bi.li_qstateBX ];
3965  }
3966 
3967  return bsuccess;
3968 }
3969 
3970 //-----------------------------------------------------------------------------
3971 // Function : Master::loadDAEVectors
3972 // Purpose :
3973 // Special Notes :
3974 // Scope : public
3975 // Creator : Eric Keiter, SNL
3976 // Creation Date : 11/26/08
3977 //-----------------------------------------------------------------------------
3978 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ)
3979 {
3980  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
3981  {
3982  Instance & bi = *(*it);
3983 
3984  double td = bi.model_.excessPhaseFac;
3985  double vbe_diff = bi.vBE - bi.vBE_orig;
3986  double vbc_diff = bi.vBC - bi.vBC_orig;
3987  double vce_diff = vbe_diff - vbc_diff;
3988 
3989  // F-vector:
3990  fVec[bi.li_Coll] -= -bi.vCCp * bi.gCpr;
3991  fVec[bi.li_Base] -= -bi.vBBp * bi.gX;
3992  fVec[bi.li_Emit] -= -bi.vEEp * bi.gEpr;
3993  fVec[bi.li_CollP] -= bi.vCCp * bi.gCpr + bi.model_.TYPE * ( - bi.iC );
3994  fVec[bi.li_BaseP] -= bi.vBBp * bi.gX - bi.model_.TYPE * ( bi.iB );
3995  fVec[bi.li_EmitP] -= bi.vEEp * bi.gEpr + bi.model_.TYPE * ( - bi.iE );
3996 
3997  // excess phase ERK-dcop.
3998  double i_fx = 0.0;
3999  double di_fx = 0.0;
4000 
4002  {
4003  i_fx = solVec[bi.li_Ifx];
4004  di_fx = solVec[bi.li_dIfx];
4005 
4006  if (td != 0)
4007  {
4008  if (!(getSolverState().dcopFlag) )
4009  {
4010  // omega0 = 1/td;
4011  fVec[bi.li_Ifx] += - di_fx;
4012  fVec[bi.li_dIfx] += 3 * di_fx*td + 3*i_fx -3 * bi.iBE / bi.qB;
4013  }
4014  else
4015  {
4016  fVec[bi.li_Ifx] += i_fx -bi.iBE/bi.qB;
4017  fVec[bi.li_dIfx] = 0.0;
4018  }
4019  }
4020  else
4021  {
4022  fVec[bi.li_Ifx] += i_fx;
4023  fVec[bi.li_dIfx] += di_fx;
4024  }
4025  }
4026 
4027  // Q-vector:
4028  qVec[bi.li_Base] -= - bi.model_.TYPE * bi.qBX;
4029  qVec[bi.li_Subst] -= -bi.model_.TYPE * bi.qCS;
4030  qVec[bi.li_CollP] -= bi.model_.TYPE * ( bi.qCS + bi.qBX + bi.qBCdep + bi.qBCdiff );
4031  qVec[bi.li_BaseP] -= -bi.model_.TYPE * ( bi.qBEdep + bi.qBEdiff + bi.qBCdep + bi.qBCdiff );
4032  qVec[bi.li_EmitP] -= bi.model_.TYPE*( bi.qBEdep + bi.qBEdiff );
4033 
4034  // excess phase ERK-dcop
4035  if (td != 0 && getDeviceOptions().newExcessPhase)
4036  {
4037  qVec[bi.li_Ifx] += solVec[bi.li_Ifx];
4038 
4039  if (!(getSolverState().dcopFlag) )
4040  {
4041  qVec[bi.li_dIfx] += solVec[bi.li_dIfx]*td*td;
4042  }
4043  else
4044  {
4045  qVec[bi.li_dIfx] = 0.0;
4046  }
4047  }
4048 
4049  // voltage limiter terms:
4051  {
4052  double Cp_Jdxp_f(0.0), Bp_Jdxp_f(0.0), Ep_Jdxp_f(0.0),
4053  dIfx_Jdxp_f(0.0 ), Ifx_Jdxp_f(0.0 ),
4054  Cp_Jdxp_q ( 0.0), Ep_Jdxp_q ( 0.0), Bp_Jdxp_q ( 0.0);
4055 
4056  // F-limiters:
4057  if (!bi.origFlag || bi.offFlag)
4058  {
4059  Cp_Jdxp_f = + bi.diCEdvBp * vbe_diff
4060  + bi.diCEdvCp * vce_diff
4061  - bi.gBCtot * vbc_diff;
4062 
4063  Cp_Jdxp_f *= bi.model_.TYPE;
4064 
4065  Bp_Jdxp_f = bi.gBEtot * vbe_diff + bi.gBCtot * vbc_diff;
4066  Bp_Jdxp_f *= bi.model_.TYPE;
4067 
4068  Ep_Jdxp_f = - bi.diCEdvCp * vce_diff - (bi.diCEdvBp + bi.gBEtot) * vbe_diff;
4069  Ep_Jdxp_f *= bi.model_.TYPE;
4070 
4071  // ERK-dcop.
4072  if ( td != 0 && getDeviceOptions().newExcessPhase )
4073  {
4074  if ( !(getSolverState().dcopFlag) )
4075  {
4076  dIfx_Jdxp_f = -3 *( bi.diBEdvBp*vbe_diff + bi.diBEdvCp * vce_diff);
4077  dIfx_Jdxp_f *= bi.model_.TYPE;
4078  }
4079  else
4080  {
4081  Ifx_Jdxp_f = ( bi.diBEdvBp*vbe_diff + bi.diBEdvCp * vce_diff);
4082  Ifx_Jdxp_f *= bi.model_.TYPE;
4083  }
4084  }
4085  }
4086 
4087  double * dFdxdVp = bi.extData.dFdxdVpVectorRawPtr;
4088  dFdxdVp[bi.li_CollP] += Cp_Jdxp_f;
4089  dFdxdVp[bi.li_BaseP] += Bp_Jdxp_f;
4090  dFdxdVp[bi.li_EmitP] += Ep_Jdxp_f;
4091 
4092  // ERK-dcop.
4093  if ( td != 0 && getDeviceOptions().newExcessPhase )
4094  {
4095  if ( !(getSolverState().dcopFlag) )
4096  {
4097  dFdxdVp[bi.li_dIfx] += dIfx_Jdxp_f;
4098  }
4099  else
4100  {
4101  dFdxdVp[bi.li_Ifx] += Ifx_Jdxp_f;
4102  }
4103  }
4104 
4105  // Q-limiters:
4106  if (!bi.origFlag || bi.offFlag)
4107  {
4108  Cp_Jdxp_q = -(bi.capBCdep + bi.capBCdiff)*vbc_diff;
4109  Cp_Jdxp_q *= bi.model_.TYPE;
4110 
4111  Bp_Jdxp_q = (bi.capBEdep + bi.capBEdiff)*vbe_diff
4112  + (bi.capBCdiff + bi.capBCdep + bi.capeqCB) *vbc_diff;
4113  Bp_Jdxp_q *= bi.model_.TYPE;
4114 
4115  Ep_Jdxp_q = - bi.capeqCB * vbc_diff - (bi.capBEdiff + bi.capBEdep)* vbe_diff;
4116  Ep_Jdxp_q *= bi.model_.TYPE;
4117  }
4118 
4119  double * dQdxdVp = bi.extData.dQdxdVpVectorRawPtr;
4120  dQdxdVp[bi.li_CollP] += Cp_Jdxp_q;
4121  dQdxdVp[bi.li_BaseP] += Bp_Jdxp_q;
4122  dQdxdVp[bi.li_EmitP] += Ep_Jdxp_q;
4123  }
4124 
4125  if( bi.loadLeadCurrent )
4126  {
4127  storeLeadQ[bi.li_store_dev_ic] = -bi.model_.TYPE * ( bi.qCS + bi.qBX + bi.qBCdep + bi.qBCdiff );
4128  storeLeadQ[bi.li_store_dev_ib] = bi.model_.TYPE * ( bi.qBX + bi.qBEdep + bi.qBEdiff + bi.qBCdep + bi.qBCdiff );
4129  storeLeadQ[bi.li_store_dev_ie] = -bi.model_.TYPE*( bi.qBEdep + bi.qBEdiff );
4130  storeLeadQ[bi.li_store_dev_is] = bi.model_.TYPE * bi.qCS;
4131 
4132  storeLeadF[bi.li_store_dev_ic] = bi.model_.TYPE * ( bi.iC );
4133  storeLeadF[bi.li_store_dev_is] = 0;
4134  storeLeadF[bi.li_store_dev_ie] = bi.model_.TYPE * ( bi.iE );
4135  storeLeadF[bi.li_store_dev_ib] = bi.model_.TYPE * ( bi.iB );
4136 
4137  }
4138 
4139  }
4140 
4141  return true;
4142 }
4143 
4144 //-----------------------------------------------------------------------------
4145 // Function : Master::loadDAEMatrices
4146 // Purpose :
4147 // Special Notes :
4148 // Scope : public
4149 // Creator : Eric Keiter, SNL
4150 // Creation Date : 11/26/08
4151 //-----------------------------------------------------------------------------
4152 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
4153 {
4154  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
4155  {
4156  Instance & bi = *(*it);
4157 
4158  double td = bi.model_.excessPhaseFac;
4159 
4160 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
4161  // F-matrix:
4162 
4163  *bi.f_CollEquCollNodePtr += bi.gCpr;
4164  *bi.f_CollEquCollPNodePtr -= bi.gCpr;
4165  *bi.f_BaseEquBaseNodePtr += bi.diBrdvB;
4166  *bi.f_BaseEquCollPNodePtr += bi.diBrdvCp;
4167  *bi.f_BaseEquBasePNodePtr += bi.diBrdvBp;
4168  *bi.f_BaseEquEmitPNodePtr += bi.diBrdvEp;
4169  *bi.f_EmitEquEmitNodePtr += bi.gEpr;
4170  *bi.f_EmitEquEmitPNodePtr -= bi.gEpr;
4171  *bi.f_CollPEquCollNodePtr -= bi.gCpr;
4172  *bi.f_CollPEquCollPNodePtr +=bi.diCEdvCp + bi.gBCtot + bi.gCpr;
4173  *bi.f_CollPEquBasePNodePtr += bi.diCEdvBp - bi.gBCtot;
4174  *bi.f_CollPEquEmitPNodePtr += bi.diCEdvEp;
4175 
4176  // excess phase terms. ERK-dcop
4177  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4178  {
4179  *bi.f_CollPEquIfxNodePtr += 1.0 * bi.model_.TYPE;
4180  }
4181  *bi.f_BasePEquBaseNodePtr -= bi.diBrdvB;
4182  *bi.f_BasePEquCollPNodePtr += -bi.diBrdvCp - bi.gBCtot;
4183  *bi.f_BasePEquBasePNodePtr += -bi.diBrdvBp + bi.gBEtot + bi.gBCtot;
4184  *bi.f_BasePEquEmitPNodePtr += -bi.diBrdvEp - bi.gBEtot;
4185  *bi.f_EmitPEquEmitNodePtr -= bi.gEpr;
4186  *bi.f_EmitPEquCollPNodePtr += -bi.diCEdvCp;
4187  *bi.f_EmitPEquBasePNodePtr += - bi.diCEdvBp - bi.gBEtot;
4188 
4189  // ERK Note: -bi.diCEdvEp should equal + bi.diCEdvBp + bi.diCEdvCp. In the
4190  // original old-DAE form, + bi.diCEdvBp + bi.diCEdvCp is used. In
4191  // the more recent new-DAE form, we've used bi.diCEdvEp, but it sometimes
4192  // results in subtle differences between old- and new-DAE jacobians.
4193  // This should matter, but .....
4194  *bi.f_EmitPEquEmitPNodePtr += bi.gBEtot + bi.gEpr + bi.diCEdvBp + bi.diCEdvCp; // this is a test.
4195  //+= bi.gBEtot + bi.gEpr - bi.diCEdvEp;
4196 
4197  // excess phase terms. ERK-dcop
4198  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4199  {
4200  *bi.f_EmitPEquIfxNodePtr += -1.0 * bi.model_.TYPE;
4201  }
4202 
4203  // excess phase terms. ERK-dcop
4205  {
4206  if ( td != 0 )
4207  {
4208  if ( !(getSolverState().dcopFlag) )
4209  {
4210  *bi.f_IfxEqudIfxNodePtr += -1;
4211 
4212  *bi.f_dIfxEquCollPNodePtr += -3*bi.diBEdvCp * bi.model_.TYPE;
4213  *bi.f_dIfxEquBasePNodePtr += -3*bi.diBEdvBp * bi.model_.TYPE;
4214  *bi.f_dIfxEquEmitPNodePtr += -3*bi.diBEdvEp * bi.model_.TYPE;
4215  *bi.f_dIfxEqudIfxNodePtr += 3* td;
4216  *bi.f_dIfxEquIfxNodePtr += 3;
4217  }
4218  else
4219  {
4220  *bi.f_IfxEquCollPNodePtr += -bi.diBEdvCp * bi.model_.TYPE;
4221  *bi.f_IfxEquBasePNodePtr += -bi.diBEdvBp * bi.model_.TYPE;
4222  *bi.f_IfxEquEmitPNodePtr += -bi.diBEdvEp * bi.model_.TYPE;
4223 
4224  *bi.f_IfxEquIfxNodePtr+= 1;
4225  *bi.f_dIfxEqudIfxNodePtr += 1;
4226  }
4227  }
4228  else
4229  {
4230  *bi.f_IfxEquIfxNodePtr += 1;
4231  *bi.f_dIfxEqudIfxNodePtr += 1;
4232  }
4233  }
4234 
4235  // Q-matrix:
4236 
4237  *bi.q_BaseEquBaseNodePtr += bi.capBX;
4238  *bi.q_BaseEquCollPNodePtr += -bi.capBX;
4239  *bi.q_SubstEquSubstNodePtr += bi.capCS;
4240  *bi.q_SubstEquCollPNodePtr -= bi.capCS;
4241  *bi.q_CollPEquBaseNodePtr -= bi.capBX;
4242  *bi.q_CollPEquSubstNodePtr -= bi.capCS;
4243  *bi.q_CollPEquCollPNodePtr += bi.capCS + bi.capBX + bi.capBCdep + bi.capBCdiff;
4244  *bi.q_CollPEquBasePNodePtr += -bi.capBCdep - bi.capBCdiff;
4245  *bi.q_BasePEquCollPNodePtr += -bi.capBCdiff - bi.capBCdep - bi.capeqCB;
4246  *bi.q_BasePEquBasePNodePtr += bi.capBEdiff + bi.capBEdep + bi.capBCdiff + bi.capBCdep + bi.capeqCB;
4247  *bi.q_BasePEquEmitPNodePtr += -bi.capBEdiff - bi.capBEdep;
4248  *bi.q_EmitPEquCollPNodePtr += bi.capeqCB;
4249  *bi.q_EmitPEquBasePNodePtr += -bi.capBEdiff - bi.capBEdep - bi.capeqCB;
4250  *bi.q_EmitPEquEmitPNodePtr += bi.capBEdiff + bi.capBEdep;
4251 
4252  // excess phase terms. ERK-dcop
4253  if ( td != 0 && getDeviceOptions().newExcessPhase )
4254  {
4255  if (!(getSolverState().dcopFlag) )
4256  {
4257  *bi.q_IfxEquIfxNodePtr += 1;
4258  *bi.q_dIfxEqudIfxNodePtr += 1*td*td;
4259  }
4260  }
4261 
4262 #else
4263  // F-matrix:
4264 
4265  dFdx[bi.li_Coll][bi.ACollEquCollNodeOffset] += bi.gCpr;
4266  dFdx[bi.li_Coll][bi.ACollEquCollPNodeOffset] -= bi.gCpr;
4267  dFdx[bi.li_Base][bi.ABaseEquBaseNodeOffset] += bi.diBrdvB;
4268  dFdx[bi.li_Base][bi.ABaseEquCollPNodeOffset] += bi.diBrdvCp;
4269  dFdx[bi.li_Base][bi.ABaseEquBasePNodeOffset] += bi.diBrdvBp;
4270  dFdx[bi.li_Base][bi.ABaseEquEmitPNodeOffset] += bi.diBrdvEp;
4271  dFdx[bi.li_Emit][bi.AEmitEquEmitNodeOffset] += bi.gEpr;
4272  dFdx[bi.li_Emit][bi.AEmitEquEmitPNodeOffset] -= bi.gEpr;
4273  dFdx[bi.li_CollP][bi.ACollPEquCollNodeOffset] -= bi.gCpr;
4274  dFdx[bi.li_CollP][bi.ACollPEquCollPNodeOffset] +=bi.diCEdvCp + bi.gBCtot + bi.gCpr;
4275  dFdx[bi.li_CollP][bi.ACollPEquBasePNodeOffset] += bi.diCEdvBp - bi.gBCtot;
4276  dFdx[bi.li_CollP][bi.ACollPEquEmitPNodeOffset] += bi.diCEdvEp;
4277 
4278  // excess phase terms. ERK-dcop
4279  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4280  {
4281  dFdx[bi.li_CollP][bi.ACollPEquIfxNodeOffset] += 1.0 * bi.model_.TYPE;
4282  }
4283 
4284  dFdx[bi.li_BaseP][bi.ABasePEquBaseNodeOffset] -= bi.diBrdvB;
4285  dFdx[bi.li_BaseP][bi.ABasePEquCollPNodeOffset] += -bi.diBrdvCp - bi.gBCtot;
4286  dFdx[bi.li_BaseP][bi.ABasePEquBasePNodeOffset] += -bi.diBrdvBp + bi.gBEtot + bi.gBCtot;
4287  dFdx[bi.li_BaseP][bi.ABasePEquEmitPNodeOffset] += -bi.diBrdvEp - bi.gBEtot;
4288  dFdx[bi.li_EmitP][bi.AEmitPEquEmitNodeOffset] -= bi.gEpr;
4289  dFdx[bi.li_EmitP][bi.AEmitPEquCollPNodeOffset] += -bi.diCEdvCp;
4290  dFdx[bi.li_EmitP][bi.AEmitPEquBasePNodeOffset] += - bi.diCEdvBp - bi.gBEtot;
4291 
4292  // ERK Note: -bi.diCEdvEp should equal + bi.diCEdvBp + bi.diCEdvCp. In the
4293  // original old-DAE form, + bi.diCEdvBp + bi.diCEdvCp is used. In
4294  // the more recent new-DAE form, we've used bi.diCEdvEp, but it sometimes
4295  // results in subtle differences between old- and new-DAE jacobians.
4296  // This should matter, but .....
4297 
4298  dFdx[bi.li_EmitP][bi.AEmitPEquEmitPNodeOffset] += bi.gBEtot + bi.gEpr + bi.diCEdvBp + bi.diCEdvCp; // this is a test.
4299  //+= bi.gBEtot + bi.gEpr - bi.diCEdvEp;
4300 
4301  // excess phase terms. ERK-dcop
4302  if ( td != 0 && getDeviceOptions().newExcessPhase && !(getSolverState().dcopFlag) )
4303  {
4304  dFdx[bi.li_EmitP][bi.AEmitPEquIfxNodeOffset] += -1.0 * bi.model_.TYPE;
4305  }
4306 
4307  // excess phase terms. ERK-dcop
4309  {
4310  if ( td != 0 )
4311  {
4312  if ( !(getSolverState().dcopFlag) )
4313  {
4314  dFdx[bi.li_Ifx][bi.AIfxEqudIfxNodeOffset]+= -1;
4315  dFdx[bi.li_dIfx][bi.AdIfxEquCollPNodeOffset] += -3*bi.diBEdvCp * bi.model_.TYPE;
4316  dFdx[bi.li_dIfx][bi.AdIfxEquBasePNodeOffset] += -3*bi.diBEdvBp * bi.model_.TYPE;
4317  dFdx[bi.li_dIfx][bi.AdIfxEquEmitPNodeOffset] += -3*bi.diBEdvEp * bi.model_.TYPE;
4318  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 3* td;
4319  dFdx[bi.li_dIfx][bi.AdIfxEquIfxNodeOffset] += 3;
4320  }
4321  else
4322  {
4323  dFdx[bi.li_Ifx][bi.AIfxEquCollPNodeOffset] += -bi.diBEdvCp * bi.model_.TYPE;
4324  dFdx[bi.li_Ifx][bi.AIfxEquBasePNodeOffset] += -bi.diBEdvBp * bi.model_.TYPE;
4325  dFdx[bi.li_Ifx][bi.AIfxEquEmitPNodeOffset] += -bi.diBEdvEp * bi.model_.TYPE;
4326  dFdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset]+= 1;
4327  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1;
4328  }
4329  }
4330  else
4331  {
4332  dFdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset]+= 1;
4333  dFdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1;
4334  }
4335  }
4336 
4337  // Q-matrix:
4338 
4339  dQdx[bi.li_Base][bi.ABaseEquBaseNodeOffset] += bi.capBX;
4340  dQdx[bi.li_Base][bi.ABaseEquCollPNodeOffset] += -bi.capBX;
4341  dQdx[bi.li_Subst][bi.ASubstEquSubstNodeOffset] += bi.capCS;
4342  dQdx[bi.li_Subst][bi.ASubstEquCollPNodeOffset] -= bi.capCS;
4343  dQdx[bi.li_CollP][bi.ACollPEquBaseNodeOffset] -= bi.capBX;
4344  dQdx[bi.li_CollP][bi.ACollPEquSubstNodeOffset] -= bi.capCS;
4345  dQdx[bi.li_CollP][bi.ACollPEquCollPNodeOffset] += bi.capCS + bi.capBX + bi.capBCdep + bi.capBCdiff;
4346  dQdx[bi.li_CollP][bi.ACollPEquBasePNodeOffset] += -bi.capBCdep - bi.capBCdiff;
4347  dQdx[bi.li_BaseP][bi.ABasePEquCollPNodeOffset] += -bi.capBCdiff - bi.capBCdep - bi.capeqCB;
4348  dQdx[bi.li_BaseP][bi.ABasePEquBasePNodeOffset] += bi.capBEdiff + bi.capBEdep + bi.capBCdiff + bi.capBCdep + bi.capeqCB;
4349  dQdx[bi.li_BaseP][bi.ABasePEquEmitPNodeOffset] += -bi.capBEdiff - bi.capBEdep;
4350  dQdx[bi.li_EmitP][bi.AEmitPEquCollPNodeOffset] += bi.capeqCB;
4351  dQdx[bi.li_EmitP][bi.AEmitPEquBasePNodeOffset] += -bi.capBEdiff - bi.capBEdep - bi.capeqCB;
4352  dQdx[bi.li_EmitP][bi.AEmitPEquEmitPNodeOffset] += bi.capBEdiff + bi.capBEdep;
4353 
4354  // excess phase terms. ERK-dcop
4355  if ( td != 0 && getDeviceOptions().newExcessPhase )
4356  {
4357  if (!(getSolverState().dcopFlag) )
4358  {
4359  dQdx[bi.li_Ifx][bi.AIfxEquIfxNodeOffset] += 1;
4360  dQdx[bi.li_dIfx][bi.AdIfxEqudIfxNodeOffset] += 1*td*td;
4361  }
4362  }
4363  #endif
4364  }
4365  return true;
4366 }
4367 
4368 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
4369 {
4370 
4371  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
4372 }
4373 
4375 {
4377  .registerDevice("q", 1)
4378  .registerModelType("pnp", 1)
4379  .registerModelType("npn", 1);
4380 }
4381 
4382 } // namespace BJT
4383 } // namespace Device
4384 } // namespace Xyce