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