Xyce  6.1
N_DEV_JFET.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_JFET.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.166 $
40 //
41 // Revision Date : $Date: 2015/09/15 19:53:49 $
42 //
43 // Current Owner : $Author: tvrusso $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 
49 // ---------- Standard Includes ----------
50 #include <N_UTL_Math.h>
51 
52 // ---------- Xyce Includes ----------
53 #include <N_DEV_Const.h>
54 #include <N_DEV_DeviceOptions.h>
55 #include <N_DEV_ExternData.h>
56 #include <N_DEV_JFET.h>
57 #include <N_DEV_MatrixLoadData.h>
58 #include <N_DEV_SolverState.h>
59 #include <N_DEV_Message.h>
60 #include <N_ERH_ErrorMgr.h>
61 
62 #include <N_LAS_Matrix.h>
63 #include <N_LAS_Vector.h>
64 #include <N_UTL_FeatureTest.h>
65 
66 namespace Xyce {
67 namespace Device {
68 namespace JFET {
69 
71 {
72  p.addPar("TEMP", 0.0, &JFET::Instance::temp)
73  .setExpressionAccess(ParameterType::TIME_DEP)
74  .setDescription("Device temperature");
75 
76  p.addPar("AREA", 1.0, &JFET::Instance::area)
77  .setUnit(U_METER2)
78  .setCategory(CAT_GEOMETRY)
79  .setDescription("Device area");
80 }
81 
83 {
84  p.addPar("AF", 1.0, &JFET::Model::AF)
85  .setCategory(CAT_FLICKER)
86  .setDescription("Flicker noise exponent");
87 
88  p.addPar("B", 1.0, &JFET::Model::B)
89  .setUnit(U_VOLTM1)
90  .setCategory(CAT_PROCESS)
91  .setDescription("Doping tail parameter (level 1)");
92 
93  p.addPar("BETA", 1.0e-4, &JFET::Model::BETA)
94  .setUnit(U_AMPVM2)
95  .setCategory(CAT_PROCESS)
96  .setDescription("Transconductance parameter");
97 
98  p.addPar("CGS", 0.0, &JFET::Model::CGS)
99  .setExpressionAccess(ParameterType::MIN_CAP)
100  .setUnit(U_FARAD)
101  .setCategory(CAT_CAP)
102  .setDescription("Zero-bias gate-source junction capacitance");
103 
104  p.addPar("CGD", 0.0, &JFET::Model::CGD)
105  .setExpressionAccess(ParameterType::MIN_CAP)
106  .setUnit(U_FARAD)
107  .setCategory(CAT_CAP)
108  .setDescription("Zero-bias gate-drain junction capacitance");
109 
110  p.addPar("FC", 0.5, &JFET::Model::FC)
111  .setUnit(U_FARAD)
112  .setCategory(CAT_CAP)
113  .setDescription("Coefficient for forward-bias depletion capacitance");
114 
115  p.addPar("IS", 1.0E-14, &JFET::Model::IS)
116  .setUnit(U_AMP)
117  .setCategory(CAT_CURRENT)
118  .setDescription("Gate junction saturation current");
119 
120  p.addPar("KF", 0.05, &JFET::Model::KF)
121  .setCategory(CAT_FLICKER)
122  .setDescription("Flicker noise coefficient");
123 
124  p.addPar("LAMBDA", 0.0, &JFET::Model::LAMBDA)
125  .setUnit(U_VOLTM1)
126  .setCategory(CAT_VOLT)
127  .setDescription("Channel length modulation");
128 
129  p.addPar("PB", 1.0, &JFET::Model::PB)
130  .setUnit(U_VOLT)
131  .setCategory(CAT_VOLT)
132  .setDescription("Gate junction potential");
133 
134  p.addPar("RD", 0.0, &JFET::Model::RD)
135  .setExpressionAccess(ParameterType::MIN_RES)
136  .setUnit(U_OHM)
137  .setCategory(CAT_RES)
138  .setDescription("Drain ohmic resistance");
139 
140  p.addPar("RS", 0.0, &JFET::Model::RS)
141  .setExpressionAccess(ParameterType::MIN_RES)
142  .setUnit(U_OHM)
143  .setCategory(CAT_RES)
144  .setDescription("Source ohmic resistance");
145 
146  p.addPar("TNOM", 0.0, &JFET::Model::TNOM)
147  .setUnit(STANDARD)
148  .setCategory(CAT_NONE)
149  .setDescription("Parameter measurement temperature");
150 
151  p.addPar("VTO", -2.0, &JFET::Model::VTO)
152  .setUnit(U_VOLT)
153  .setCategory(CAT_VOLT)
154  .setDescription("Threshold voltage");
155 
156  p.addPar("DELTA", 0.0, &JFET::Model::DELTA)
157  .setUnit(U_VOLT)
158  .setCategory(CAT_VOLT)
159  .setDescription("Saturation voltage parrameter (level 2)");
160 
161  p.addPar("THETA", 0.0, &JFET::Model::THETA)
162  .setUnit(U_VOLTM1)
163  .setCategory(CAT_VOLT)
164  .setDescription("Mobility modulation parameter (level 2)");
165 
167 }
168 
169 std::vector< std::vector<int> > Instance::jacStamp_DC_SC;
170 std::vector< std::vector<int> > Instance::jacStamp_DC;
171 std::vector< std::vector<int> > Instance::jacStamp_SC;
172 std::vector< std::vector<int> > Instance::jacStamp;
173 
174 std::vector<int> Instance::jacMap_DC_SC;
175 std::vector<int> Instance::jacMap_DC;
176 std::vector<int> Instance::jacMap_SC;
177 std::vector<int> Instance::jacMap;
178 
179 std::vector< std::vector<int> > Instance::jacMap2_DC_SC;
180 std::vector< std::vector<int> > Instance::jacMap2_DC;
181 std::vector< std::vector<int> > Instance::jacMap2_SC;
182 std::vector< std::vector<int> > Instance::jacMap2;
183 
184 //--------------------- Class Model ---------------------------------
185 
186 //-----------------------------------------------------------------------------
187 // Function : Model::Model
188 // Purpose : model block constructor
189 // Special Notes :
190 // Scope : public
191 // Creator : pmc
192 // Creation Date : 11/16/2003
193 //-----------------------------------------------------------------------------
195  const Configuration & configuration,
196  const ModelBlock & MB,
197  const FactoryBlock & factory_block)
198  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
199  AF(1.0),
200  B(1.0),
201  BETA(1.0e-4),
202  CGS(0.0),
203  CGD(0.0),
204  FC(0.5),
205  IS(1.0e-14),
206  KF(0.0),
207  LAMBDA(0.0),
208  DELTA(0.0),
209  THETA(0.0),
210  PB(1.0),
211  RD(0.0),
212  RS(0.0),
213  TNOM(CONSTREFTEMP),
214  VTO(-2.0),
215  fNcoef(0.0),
216  fNexp(1.0),
217  dtype(CONSTNMOS)
218 {
219  if (getType() != "")
220  {
221  if (getType() == "NJF") {
222  dtype = CONSTNMOS;
223  }
224  else if (getType() == "PJF") {
225  dtype = CONSTPMOS;
226  }
227  else
228  {
229  UserError0(*this) << "Could not recognize the type for model " << getName();
230  }
231  }
232 
233  // Set params to constant default values:
234  setDefaultParams ();
235 
236  // Set params according to .model line and constant defaults from metadata:
237  setModParams (MB.params);
238 
239  // Set any non-constant parameter defaults:
240  if (!given("TNOM"))
242 
243  // Calculate any parameters specified as expressions:
245 
246  // calculate dependent (ie computed) params and check for errors:
247  processParams ();
248 }
249 
250 //-----------------------------------------------------------------------------
251 // Function : Model::~Model
252 // Purpose : destructor
253 // Special Notes :
254 // Scope : public
255 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
256 // Creation Date : 3/16/00
257 //-----------------------------------------------------------------------------
259 {
260  std::vector<Instance*>::iterator iter;
261  std::vector<Instance*>::iterator first = instanceContainer.begin();
262  std::vector<Instance*>::iterator last = instanceContainer.end();
263 
264  for (iter=first; iter!=last; ++iter)
265  {
266  delete (*iter);
267  }
268 
269 }
270 
271 
272 //-----------------------------------------------------------------------------
273 // Function : Model::printOutInstances
274 // Purpose : debugging tool.
275 // Special Notes :
276 // Scope : public
277 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
278 // Creation Date : 3/16/00
279 //-----------------------------------------------------------------------------
280 std::ostream &Model::printOutInstances(std::ostream &os) const
281 {
282  std::vector<Instance*>::const_iterator iter;
283  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
284  std::vector<Instance*>::const_iterator last = instanceContainer.end();
285 
286  int i,isize;
287  isize = instanceContainer.size();
288  os << std::endl;
289  os << "Number of JFET Instances: " << isize << std::endl;
290  os << " name model name Parameters" << std::endl;
291 
292  for (i=0, iter=first; iter!=last; ++iter, ++i)
293  {
294  os << " " << i << ": " << (*iter)->getName() << "\t";
295  os << getName();
296  os << std::endl;
297  }
298 
299  os << std::endl;
300 
301  return os;
302 }
303 
304 //-----------------------------------------------------------------------------
305 // Function : Model::forEachInstance
306 // Purpose :
307 // Special Notes :
308 // Scope : public
309 // Creator : David Baur
310 // Creation Date : 2/4/2014
311 //-----------------------------------------------------------------------------
312 /// Apply a device instance "op" to all instances associated with this
313 /// model
314 ///
315 /// @param[in] op Operator to apply to all instances.
316 ///
317 ///
318 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
319 {
320  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
321  op(*it);
322 }
323 
324 
325 //-----------------------------------------------------------------------------
326 // Function : Model::processParams
327 // Purpose :
328 // Special Notes :
329 // Scope : public
330 // Creator : pmc
331 // Creation Date : 11/16/2003
332 //-----------------------------------------------------------------------------
334 {
335 
336  return true;
337 }
338 
339 //----------------------------------------------------------------------------
340 // Function : Model::processInstanceParams
341 // Purpose :
342 // Special Notes :
343 // Scope : public
344 // Creator : Dave Shirely, PSSI
345 // Creation Date : 03/23/06
346 //----------------------------------------------------------------------------
348 {
349 
350  std::vector<Instance*>::iterator iter;
351  std::vector<Instance*>::iterator first = instanceContainer.begin();
352  std::vector<Instance*>::iterator last = instanceContainer.end();
353 
354  for (iter=first; iter!=last; ++iter)
355  {
356  (*iter)->processParams();
357  }
358 
359  return true;
360 }
361 
362 //-------------------------- Class Instance -------------------------
363 
364 //-----------------------------------------------------------------------------
365 // Function : Instance::Instance
366 // Purpose : instance block constructor
367 // Special Notes :
368 // Scope : public
369 // Creator : pmc
370 // Creation Date : 11/16/2003
371 //-----------------------------------------------------------------------------
373  const Configuration & configuration,
374  const InstanceBlock & instance_block,
375  Model & model,
376  const FactoryBlock & factory_block)
377  : DeviceInstance(instance_block, configuration.getInstanceParameters(), factory_block),
378  model_(model),
379  limitedFlag(false),
380  off(0),
381  ic(0),
382  area(1.0),
383  ic_vds(0.0),
384  ic_vgs(0.0),
385  temp(getDeviceOptions().temp.getImmutableValue<double>()),
386  sourceCond(0.0),
387  drainCond(0.0),
388  tCGS(0.0),
389  tCGD(0.0),
390  tIS(0.0),
391  tPB(0.0),
392  tJFETb(0.0),
393 
394  tBeta(0.0),
395  tvt0(0.0),
396  tLambda(0.0),
397  tDelta(0.0),
398  tTheta(0.0),
399  tRD(0.0),
400  tRS(0.0),
401  vt(0.0),
402 
403  dNode(0),
404  gNode(0),
405  sNode(0),
406  dpNode(0),
407  spNode(0),
408  Vgs(0.0),
409  Vgd(0.0),
410  gm(0.0),
411  gds(0.0),
412  ggs(0.0),
413  ggd(0.0),
414 
415  cdrain(0.0),
416  cdTRAN(0.0),
417  cgTRAN(0.0),
418  cgdTRAN(0.0),
419  cd(0.0),
420  cg(0.0),
421  cgd(0.0),
422  corDepCap(0.0),
423  vcrit(0.0),
424  f1(0.0),
425  f2(0.0),
426  f3(0.0),
427  Bfac(0.0),
428 
429  p(0.0),
430  // Solution variables and intermediate quantities
431  // drain,source,gate, drainprime and sourceprime voltages
432  Vd(0.0),
433  Vs(0.0),
434  Vg(0.0),
435  Vdp(0.0),
436  Vsp(0.0),
437  // vector local indices
438  li_Drain(-1),
439  li_DrainPrime(-1),
440  li_Source(-1),
441  li_SourcePrime(-1),
442  li_Gate(-1),
443  // Jacobian Matrix
444  // Jacobian Matrix Offset:
445  // V_d Row:
446  ADrainEquDrainNodeOffset(-1),
447  ADrainEquDrainPrimeNodeOffset(-1),
448  // V_g Row:
449  AGateEquGateNodeOffset(-1),
450  AGateEquDrainPrimeNodeOffset(-1),
451  AGateEquSourcePrimeNodeOffset(-1),
452  // V_s Row:
453  ASourceEquSourceNodeOffset(-1),
454  ASourceEquSourcePrimeNodeOffset(-1),
455  // V_d' Row:
456  ADrainPrimeEquDrainNodeOffset(-1),
457  ADrainPrimeEquGateNodeOffset(-1),
458  ADrainPrimeEquDrainPrimeNodeOffset(-1),
459  ADrainPrimeEquSourcePrimeNodeOffset(-1),
460  // V_s' Row:
461  ASourcePrimeEquGateNodeOffset(-1),
462  ASourcePrimeEquSourceNodeOffset(-1),
463  ASourcePrimeEquDrainPrimeNodeOffset(-1),
464  ASourcePrimeEquSourcePrimeNodeOffset(-1),
465 
467  // dFdx Matrix Ptr:
468  // V_d Row:
469  f_DrainEquDrainNodePtr(0),
470  f_DrainEquDrainPrimeNodePtr(0),
471  // V_g Row:
472  f_GateEquGateNodePtr(0),
473  f_GateEquDrainPrimeNodePtr(0),
474  f_GateEquSourcePrimeNodePtr(0),
475  // V_s Row:
476  f_SourceEquSourceNodePtr(0),
477  f_SourceEquSourcePrimeNodePtr(0),
478  // V_d' Row:
479  f_DrainPrimeEquDrainNodePtr(0),
480  f_DrainPrimeEquGateNodePtr(0),
481  f_DrainPrimeEquDrainPrimeNodePtr(0),
482  f_DrainPrimeEquSourcePrimeNodePtr(0),
483  // V_s' Row:
484  f_SourcePrimeEquGateNodePtr(0),
485  f_SourcePrimeEquSourceNodePtr(0),
486  f_SourcePrimeEquDrainPrimeNodePtr(0),
487  f_SourcePrimeEquSourcePrimeNodePtr(0),
488 
489  // dQdx Matrix Ptr:
490  // V_d Row:
491  q_DrainEquDrainNodePtr(0),
492  q_DrainEquDrainPrimeNodePtr(0),
493  // V_g Row:
494  q_GateEquGateNodePtr(0),
495  q_GateEquDrainPrimeNodePtr(0),
496  q_GateEquSourcePrimeNodePtr(0),
497  // V_s Row:
498  q_SourceEquSourceNodePtr(0),
499  q_SourceEquSourcePrimeNodePtr(0),
500  // V_d' Row:
501  q_DrainPrimeEquDrainNodePtr(0),
502  q_DrainPrimeEquGateNodePtr(0),
503  q_DrainPrimeEquDrainPrimeNodePtr(0),
504  q_DrainPrimeEquSourcePrimeNodePtr(0),
505  // V_s' Row:
506  q_SourcePrimeEquGateNodePtr(0),
507  q_SourcePrimeEquSourceNodePtr(0),
508  q_SourcePrimeEquDrainPrimeNodePtr(0),
509  q_SourcePrimeEquSourcePrimeNodePtr(0),
510 #endif
511  vgs(0.0),
512  vgd(0.0),
513  vgs_old(0.0),
514  vgd_old(0.0),
515  vds_old(0.0),
516  vgs_orig(0.0),
517  vgd_orig(0.0),
518 
519  gCAPgs(0.0),
520  capgs(0.0),
521  qgs(0.0),
522  cqgs(0.0),
523  gCAPgd(0.0),
524  capgd(0.0),
525  qgd(0.0),
526  cqgd(0.0),
527  mode(1),
528  // local indices
529  li_store_vgs(-1),
530  li_store_vgd(-1),
531  li_store_dev_id(-1),
532  li_store_dev_is(-1),
533  li_store_dev_ig(-1),
534  li_state_qgs(-1),
535  li_state_gcgs(-1),
536  li_state_qgd(-1),
537  li_state_gcgd(-1)
538 {
539  numIntVars = 2; // may be reset in processParams
540  numExtVars = 3;
541  numStateVars = 4;
542  setNumStoreVars(2);
543  numLeadCurrentStoreVars = 3; // drain, source, gate lead currents
544 
545  devConMap.resize(3);
546  devConMap[0] = 1;
547  devConMap[1] = 2;
548  devConMap[2] = 1;
549 
550  if( jacStamp.empty() )
551  {
552  // stamp for RS!=0, RD!=0
553  jacStamp_DC_SC.resize(5);
554  jacStamp_DC_SC[0].resize(2); // Drain row
555  jacStamp_DC_SC[0][0]=0; // d-d
556  jacStamp_DC_SC[0][1]=3; // d-d'
557  jacStamp_DC_SC[1].resize(3); // Gate row
558  jacStamp_DC_SC[1][0]=1; // g-g
559  jacStamp_DC_SC[1][1]=3; // g-d'
560  jacStamp_DC_SC[1][2]=4; // g-s'
561  jacStamp_DC_SC[2].resize(2); // Source row
562  jacStamp_DC_SC[2][0]=2; // s-s
563  jacStamp_DC_SC[2][1]=4; // s-s'
564  jacStamp_DC_SC[3].resize(4); // Drain' row
565  jacStamp_DC_SC[3][0]=0; // d'-d
566  jacStamp_DC_SC[3][1]=1; // d'-g
567  jacStamp_DC_SC[3][2]=3; // d'-d'
568  jacStamp_DC_SC[3][3]=4; // d'-s'
569  jacStamp_DC_SC[4].resize(4); // Source' row
570  jacStamp_DC_SC[4][0]=1; // s'-g
571  jacStamp_DC_SC[4][1]=2; // s'-s
572  jacStamp_DC_SC[4][2]=3; // s'-d'
573  jacStamp_DC_SC[4][3]=4; // s'-s'
574 
575  jacMap_DC_SC.clear();
577  jacStamp_DC, jacMap_DC, jacMap2_DC, 4, 2, 5);
578 
580  jacStamp_SC, jacMap_SC, jacMap2_SC, 3, 0, 5);
581 
583  jacStamp, jacMap, jacMap2, 3, 0, 5);
584 
585  }
586 
587  // Set params to constant default values:
588  setDefaultParams ();
589 
590  // Set params according to instance line and constant defaults from metadata:
591  setParams (instance_block.params);
592 
593  // Calculate any parameters specified as expressions:
595 
596  // calculate dependent (ie computed) params and check for errors:
597  processParams ();
598 
599  numIntVars = (((sourceCond == 0.0)?0:1)+((drainCond == 0.0)?0:1));
600 }
601 
602 //-----------------------------------------------------------------------------
603 // Function : Instance::Instance
604 // Purpose : destructor
605 // Special Notes :
606 // Scope : public
607 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
608 // Creation Date : 3/16/00
609 //-----------------------------------------------------------------------------
611 {
612 }
613 
614 //----------------------------------------------------------------------------
615 // Function : Instance::registerLIDs
616 // Purpose :
617 // Special Notes :
618 // Scope : public
619 // Creator : pmc
620 // Creation Date : 11/16/2003
621 //----------------------------------------------------------------------------
622 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
623  const std::vector<int> & extLIDVecRef )
624 {
625  numIntVars = (((sourceCond == 0.0)?0:1)+((drainCond == 0.0)?0:1));
626 
627  AssertLIDs(intLIDVecRef.size() == numIntVars);
628  AssertLIDs(extLIDVecRef.size() == numExtVars);
629 
630  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
631  {
632  Xyce::dout() << std::endl << section_divider << std::endl;
633  Xyce::dout() << " Instance::registerLIDs. name = " << getName() << std::endl;
634  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
635  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
636  }
637 
638  // copy over the global ID lists.
639  intLIDVec = intLIDVecRef;
640  extLIDVec = extLIDVecRef;
641 
642  // now use these lists to obtain the indices into the
643  // linear algebra entities. This assumes an order.
644  // For the matrix indices, first do the rows.
645 
646  li_Drain = extLIDVec[0];
647  li_Gate = extLIDVec[1];
648  li_Source = extLIDVec[2];
649 
650  int intLoc = 0;
651 
652  if( drainCond )
653  li_DrainPrime = intLIDVec[intLoc++];
654  else
656 
657  if( sourceCond )
658  li_SourcePrime = intLIDVec[intLoc];
659  else
661 
662  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
663  {
664  Xyce::dout() << "\n variable local indices:\n";
665  Xyce::dout() << " li_Drain = " << li_Drain << std::endl;
666  Xyce::dout() << " li_DrainPrime = " << li_DrainPrime << std::endl;
667  Xyce::dout() << " li_Source = " << li_Source << std::endl;
668  Xyce::dout() << " li_SourcePrime = " << li_SourcePrime << std::endl;
669  Xyce::dout() << " li_Gate = " << li_Gate << std::endl;
670 
671  Xyce::dout() << section_divider << std::endl;
672  }
673 
674 }
675 
676 //-----------------------------------------------------------------------------
677 // Function : Instance::loadNodeSymbols
678 // Purpose :
679 // Special Notes :
680 // Scope : public
681 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
682 // Creation Date : 05/13/05
683 //-----------------------------------------------------------------------------
684 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
685 {
686  if (drainCond != 0.0)
687  addInternalNode(symbol_table, li_DrainPrime, getName(), "drainprime");
688 
689  if (sourceCond != 0.0)
690  addInternalNode(symbol_table, li_SourcePrime, getName(), "sourceprime");
691 
692  if (loadLeadCurrent)
693  {
694  addStoreNode(symbol_table, li_store_dev_id, getName(), "DEV_ID");
695  addStoreNode(symbol_table, li_store_dev_is, getName(), "DEV_IS");
696  addStoreNode(symbol_table, li_store_dev_ig, getName(), "DEV_IG");
697  }
698 }
699 
700 //----------------------------------------------------------------------------
701 // Function : Instance::registerStateLIDs
702 // Purpose :
703 // Special Notes :
704 // Scope : public
705 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
706 // Creation Date : 3/16/00
707 //----------------------------------------------------------------------------
708 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef)
709 {
710  AssertLIDs(staLIDVecRef.size() == numStateVars);
711 
712  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
713  {
714  Xyce::dout() << std::endl;
715  Xyce::dout() << section_divider << std::endl;
716  Xyce::dout() << " In Instance::registerStateLIDs. name = " << getName() << std::endl;
717  Xyce::dout() << " Number of State LIDs: " << numStateVars << std::endl;
718  }
719 
720  // Copy over the global ID lists:
721  staLIDVec = staLIDVecRef;
722 
723  int lid = 0;
724 
725  li_state_qgs = staLIDVec[lid++];
726  li_state_gcgs = staLIDVec[lid++];
727 
728  li_state_qgd = staLIDVec[lid++];
729  li_state_gcgd = staLIDVec[lid++];
730 
731 
732  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
733  {
734  Xyce::dout() << " State local indices:" << std::endl;
735  Xyce::dout() << std::endl;
736 
737  Xyce::dout() << " li_state_qgs = " << li_state_qgs << std::endl;
738  Xyce::dout() << " li_state_gcgs = " << li_state_gcgs;
739  Xyce::dout() << " li_state_qgd = " << li_state_qgd;
740  Xyce::dout() << " li_state_gcgd = " << li_state_gcgd << std::endl;;
741 
742  Xyce::dout() << section_divider << std::endl;
743  }
744 
745 }
746 
747 //----------------------------------------------------------------------------
748 // Function : Instance::registerStoreLIDs
749 // Purpose :
750 // Special Notes :
751 // Scope : public
752 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
753 // Creation Date : 3/16/11
754 //----------------------------------------------------------------------------
755 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef)
756 {
757  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
758 
759 // Copy over the global ID lists:
760  stoLIDVec = stoLIDVecRef;
761 
762  int lid = 0;
763  li_store_vgs = stoLIDVec[lid++];
764  li_store_vgd = stoLIDVec[lid++];
765  if( loadLeadCurrent )
766  {
767  li_store_dev_id = stoLIDVec[lid++];
768  li_store_dev_is = stoLIDVec[lid++];
769  li_store_dev_ig = stoLIDVec[lid++];
770  }
771 }
772 
773 //----------------------------------------------------------------------------
774 // Function : Instance::jacobianStamp
775 // Purpose :
776 // Special Notes :
777 // Scope : public
778 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
779 // Creation Date : 3/16/00
780 //----------------------------------------------------------------------------
781 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
782 {
783  if( drainCond != 0.0 && sourceCond != 0.0 )
784  return jacStamp_DC_SC;
785  else if( drainCond != 0.0 && sourceCond == 0.0 )
786  return jacStamp_DC;
787  else if( drainCond == 0.0 && sourceCond != 0.0 )
788  return jacStamp_SC;
789  else if( drainCond == 0.0 && sourceCond == 0.0 )
790  return jacStamp;
791  else
792  return jacStamp;
793 }
794 
795 //----------------------------------------------------------------------------
796 // Function : Instance::registerJacLIDs
797 // Special Notes :
798 // Scope : public
799 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
800 // Creation Date : 3/16/00
801 //----------------------------------------------------------------------------
802 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
803 {
804  DeviceInstance::registerJacLIDs( jacLIDVec );
805  std::vector<int> map;
806  std::vector< std::vector<int> > map2;
807 
808  if (drainCond != 0.0)
809  {
810  if (sourceCond != 0.0)
811  {
812  map = jacMap_DC_SC;
813  map2 = jacMap2_DC_SC;
814  }
815  else
816  {
817  map = jacMap_DC;
818  map2 = jacMap2_DC;
819  }
820  }
821  else
822  {
823  if (sourceCond != 0.0)
824  {
825  map = jacMap_SC;
826  map2 = jacMap2_SC;
827  }
828  else
829  {
830  map = jacMap;
831  map2 = jacMap2;
832  }
833  }
834 
835  ADrainEquDrainNodeOffset = jacLIDVec[map[0]][map2[0][0]];
836  ADrainEquDrainPrimeNodeOffset = jacLIDVec[map[0]][map2[0][1]];
837 
838  AGateEquGateNodeOffset = jacLIDVec[map[1]][map2[1][0]];
839  AGateEquDrainPrimeNodeOffset = jacLIDVec[map[1]][map2[1][1]];
840  AGateEquSourcePrimeNodeOffset = jacLIDVec[map[1]][map2[1][2]];
841 
842  ASourceEquSourceNodeOffset = jacLIDVec[map[2]][map2[2][0]];
843  ASourceEquSourcePrimeNodeOffset = jacLIDVec[map[2]][map2[2][1]];
844 
845  ADrainPrimeEquDrainNodeOffset = jacLIDVec[map[3]][map2[3][0]];
846  ADrainPrimeEquGateNodeOffset = jacLIDVec[map[3]][map2[3][1]];
847  ADrainPrimeEquDrainPrimeNodeOffset = jacLIDVec[map[3]][map2[3][2]];
848  ADrainPrimeEquSourcePrimeNodeOffset = jacLIDVec[map[3]][map2[3][3]];
849 
850  ASourcePrimeEquGateNodeOffset = jacLIDVec[map[4]][map2[4][0]];
851  ASourcePrimeEquSourceNodeOffset = jacLIDVec[map[4]][map2[4][1]];
852  ASourcePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[4]][map2[4][2]];
853  ASourcePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[4]][map2[4][3]];
854 }
855 
856 //-----------------------------------------------------------------------------
857 // Function : Instance::setupPointers
858 // Purpose :
859 // Special Notes :
860 // Scope : public
861 // Creator : Eric Keiter, SNL
862 // Creation Date : 11/30/08
863 //-----------------------------------------------------------------------------
865 {
866 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
867  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
868  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
869 
870  // F-matrix:
873 
877 
880 
885 
890 
891  // Q-matrix:
894 
898 
901 
906 
911 
912 #endif
913 }
914 
915 //----------------------------------------------------------------------------
916 // Function : Instance::updatePrimaryState
917 // Purpose :
918 // Special Notes :
919 // Scope : public
920 // Creator : pmc
921 // Creation Date : 11/16/2003
922 //----------------------------------------------------------------------------
924 {
925  double * staVec = extData.nextStaVectorRawPtr;
926  bool bsuccess = updateIntermediateVars ();
927 
928  double * stoVec = extData.nextStoVectorRawPtr;
929  stoVec[li_store_vgs] = vgs;
930  stoVec[li_store_vgd] = vgd;
931  staVec[li_state_qgs] = qgs;
932  staVec[li_state_qgd] = qgd;
933 
934  return bsuccess;
935 }
936 
937 //-----------------------------------------------------------------------------
938 // Function : Instance::updateIntermediateVars
939 // Purpose :
940 // Special Notes :
941 // Scope : public
942 // Creator : pmc
943 // Creation Date : 11/16/2003
944 //-----------------------------------------------------------------------------
946 {
947  double * solVec = extData.nextSolVectorRawPtr;
948 
949  int dtype;
950  double csat, betap;
951  double vgst, vgdt;
952  double evgs, evgd;
953  double apart, cpart;
954  double sarg, vtf;;
955 
956 // from the spice jfet
957  double czgd, czgs;
958  double czgdf2, czgsf2;
959  double fcpb2;
960  double twop;
961  int icheck, ichk1;
962 
963 // for the Shockley version
964  double A, B, C, B12, C12, D;
965  double Idsat, Vdsat;
966  int level;
967 
968  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
969  {
970  Xyce::dout() << subsection_divider << std::endl;
971  Xyce::dout() <<" Instance::updateIntermediateVars. name = " << getName() << std::endl;
972  Xyce::dout() <<" Model name = " << model_.getName() << std::endl;
973  Xyce::dout() << std::endl;
974  Xyce::dout().width(25); Xyce::dout().precision(17); Xyce::dout().setf(std::ios::scientific);
975  }
976 
977  icheck = 1;
978  dtype = model_.dtype;
979 
980  // we need our solution variables for any of this stuff
981  Vd = 0.0;
982  Vs = 0.0;
983  Vg = 0.0;
984  Vdp = 0.0;
985  Vsp = 0.0;
986 
987  Vd = solVec[li_Drain];
988  Vg = solVec[li_Gate];
989  Vs = solVec[li_Source];
990  Vsp = solVec[li_SourcePrime];
991  Vdp = solVec[li_DrainPrime];
992 
993  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
994  {
995  Xyce::dout() << " " << std::endl;
996  Xyce::dout() << " Vg = " << Vg << std::endl;
997  Xyce::dout() << " Vd = " << Vd << std::endl;
998  Xyce::dout() << " Vs = " << Vs << std::endl;
999  Xyce::dout() << " Vdp = " << Vdp << std::endl;
1000  Xyce::dout() << " Vsp = " << Vsp << std::endl;
1001  }
1002 
1003  // now we need voltage drops
1004  Vddp = Vd - Vdp;
1005  Vssp = Vs - Vsp;
1006  Vgsp = Vg - Vsp;
1007  Vgdp = Vg - Vdp;
1008  Vdpsp = Vdp - Vsp;
1009 
1010  // Now the things that the 3f5 code really uses
1011  vgs = dtype * Vgsp;
1012  vgd = dtype * Vgdp;
1013  vds = vgs-vgd;
1014 
1015  origFlag = 1;
1016  limitedFlag = false;
1017  vgs_orig = vgs;
1018  vgd_orig = vgd;
1019  vds_orig = vds;
1020 
1021  if (getSolverState().newtonIter == 0)
1022  {
1023  if (getSolverState().initJctFlag_ && getDeviceOptions().voltageLimiterFlag)
1024  {
1025  if (getSolverState().inputOPFlag)
1026  {
1027  Linear::Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
1028  if ((*flagSolVectorPtr)[li_Drain] == 0 || (*flagSolVectorPtr)[li_Gate] == 0 ||
1029  (*flagSolVectorPtr)[li_Source] == 0 || (*flagSolVectorPtr)[li_SourcePrime] ||
1030  (*flagSolVectorPtr)[li_DrainPrime] )
1031  {
1032  vgs = 0;
1033  vgd = 0;
1034  vds = vgs-vgd;
1035  }
1036  }
1037  else
1038  {
1039  vgs = 0;
1040  vgd = 0;
1041  vds = vgs-vgd;
1042  }
1043  }
1044  if (!(getSolverState().dcopFlag)||(getSolverState().locaEnabledFlag && getSolverState().dcopFlag))
1045  {
1046  double * currStoVec = extData.currStoVectorRawPtr;
1047  vgs_old = currStoVec[li_store_vgs];
1048  vgd_old = currStoVec[li_store_vgd];
1049  vds_old = vgs_old - vgd_old;
1050  }
1051  else
1052  { // there is no history
1053  vgs_old = vgs;
1054  vgd_old = vgd;
1055  vds_old = vds;
1056  }
1057  }
1058  else
1059  {
1060  double *stoVec = extData.nextStoVectorRawPtr;
1061  vgs_old = stoVec[li_store_vgs];
1062  vgd_old = stoVec[li_store_vgd];
1063  vds_old = vgs_old - vgd_old;
1064  }
1065 
1066  // SPICE-type Voltage Limiting
1067  ////////////////////////////////////////////
1068 
1069  if (getDeviceOptions().voltageLimiterFlag)
1070  {
1071  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1072  {
1073  Xyce::dout() << " before limiting: " << std::endl;
1074  Xyce::dout() << " vgs = " << vgs << " vgs_old = " << vgs_old << std::endl;
1075  Xyce::dout() << " vgd = " << vgd << " vgd_old = " << vgd_old << std::endl;
1076  }
1077 
1078  ichk1=1;
1079  vgs = devSupport.pnjlim(vgs, vgs_old, vt, vcrit, &icheck);
1080  vgd = devSupport.pnjlim(vgd, vgd_old, vt, vcrit, &ichk1);
1081 
1082  if (ichk1 == 1) {icheck=1;}
1083  if (icheck == 1) limitedFlag=true;
1084 
1086  vgd = devSupport.fetlim(vgd, vgd_old, tvt0);
1087  vds = vgs-vgd;
1088 
1089  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1090  {
1091  Xyce::dout() << " After limiting: " << std::endl;
1092  Xyce::dout() << " vgs = " << vgs << std::endl;
1093  Xyce::dout() << " vgd = " << vgd << std::endl;
1094  Xyce::dout() << " " << std::endl;
1095  }
1096  }
1097 
1098  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1099  {
1100  Xyce::dout() << "vgs = " << vgs << std::endl;
1101  Xyce::dout() << "vgd = " << vgd << std::endl;
1102  Xyce::dout() << "vds = " << vds << std::endl;
1103  Xyce::dout() << "Vddp = " << Vddp << std::endl;
1104  Xyce::dout() << "Vssp = " << Vssp << std::endl;
1105  Xyce::dout() << "Vgsp = " << Vgsp << std::endl;
1106  Xyce::dout() << "Vgdp = " << Vgdp << std::endl;
1107  Xyce::dout() << "Vdpsp = " << Vdpsp << std::endl;
1108  Xyce::dout() << " " << std::endl;
1109  }
1110  // Now set the origFlag
1111  if (vgs_orig != vgs || vds_orig != vds || vgd_orig != vgd) origFlag = 0;
1112 
1113  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1114  {
1115  if (origFlag == 0)
1116  {
1117  Xyce::dout() << getName() << " Something modified the voltages. " << std::endl;
1118  }
1119  else
1120  {
1121  Xyce::dout() << getName() << " No voltages were limited. " << std::endl;
1122  }
1123  Xyce::dout() << " Voltage before after diff " << std::endl;
1124  Xyce::dout() << getName() <<" vgs " <<vgs_orig <<" " << vgs <<" " << vgs-vgs_orig << std::endl;
1125  Xyce::dout() << getName() <<" vgd " <<vgd_orig <<" " << vgd <<" " << vgd-vgd_orig << std::endl;
1126  Xyce::dout() << getName() <<" vds " <<vds_orig <<" " << vds <<" " << vds-vds_orig << std::endl;
1127  Xyce::dout() << " " << std::endl;
1128  }
1129 
1130  //
1131  // the following block of code evaluates the dc current and its
1132  // derivatives and the charges associated with the gate and
1133  // channel
1134  //
1135 
1136  // vt set in updateTemperature
1137  vtf = 5.0*vt;
1138  csat = tIS;
1139  if (vgs <= -vtf)
1140  {
1141  ggs = -csat/vgs + getDeviceOptions().gmin;
1142  cg = ggs*vgs;
1143  }
1144  else
1145  {
1146  evgs = exp(vgs/vt);
1147  ggs = csat*evgs/vt + getDeviceOptions().gmin;
1148  cg = csat*(evgs-1) + getDeviceOptions().gmin*vgs;
1149  }
1150  if (vgd <= -vtf)
1151  {
1152  ggd = -csat/vgd + getDeviceOptions().gmin;
1153  cgd = ggd*vgd;
1154  }
1155  else
1156  {
1157  evgd = exp(vgd/vt);
1158  ggd = csat*evgd/vt + getDeviceOptions().gmin;
1159  cgd = csat*(evgd-1) + getDeviceOptions().gmin*vgd;
1160  }
1161  cg = cg + cgd;
1162 
1163  // 3f5 does this simple stuff
1164  if (vds >= 0)
1165  mode = 1;
1166  else
1167  mode = -1;
1168 
1169  level = model_.getLevel();
1170  if(level == 1)
1171  {
1172  //
1173  // Sydney University JFET model
1174  //
1175  if(vds >= 0) // normal mode
1176  {
1177  vgst=vgs-tvt0;
1178  if (vgst <= 0)
1179  {
1180  //
1181  // cutoff region
1182  //
1183  cdrain=0;
1184  gm=0;
1185  gds=0;
1186  // Xyce::dout() << " cutoff region - normal mode " << std::endl;
1187  }
1188  else
1189  {
1190  betap=tBeta*(1+tLambda*vds);
1191  Bfac = (1.0-tJFETb)/(tPB-tvt0);
1192  if( vgst >= vds )
1193  {
1194  //
1195  // linear region
1196  //
1197  apart=2.0*tJFETb+3.0*Bfac*(vgst-vds);
1198  cpart=vds*(vds*(Bfac*vds - tJFETb)+vgst*apart);
1199  cdrain=betap*cpart;
1200  gm=betap*vds*(apart+3.0*Bfac*vgst);;
1201  gds=betap*(vgst-vds)*apart+tLambda*tBeta*cpart;
1202  // Xyce::dout() << " linear region - normal mode" << std::endl;
1203  }
1204  else
1205  {
1206  //
1207  // saturation region
1208  //
1209  Bfac=vgst*Bfac;
1210  gm=betap*vgst*(2.0*tJFETb+3.0*Bfac);
1211  cpart=vgst*vgst*(tJFETb+Bfac);
1212  cdrain=betap*cpart;
1213  gds=tLambda*tBeta*cpart;
1214  // Xyce::dout() << " saturation region - normal mode " << std::endl;
1215  }
1216  }
1217  }
1218  else // inverse mode
1219 // Inverse mode is where you switch the drain and source
1220 // and run the device in reverse. The equations for inverse
1221 // mode are obtained by the following substitutions:
1222 // vgst -> vgdt, vds -> -vds, cdrain -> -cdrain
1223  {
1224  vgdt=vgd-tvt0;
1225  if (vgdt <= 0)
1226  {
1227  //
1228  // inverse mode cutoff region
1229  //
1230  cdrain=0;
1231  gm=0;
1232  gds=0;
1233  // Xyce::dout() << " cutoff region - inverse mode" << std::endl;
1234  }
1235  else
1236  {
1237  betap=tBeta*(1-tLambda*vds);
1238  Bfac=(1.0-tJFETb)/(tPB-tvt0);
1239  if (vgdt+vds >= 0)
1240  {
1241  //
1242  // linear region
1243  //
1244  apart=2.0*tJFETb+3.0*Bfac*(vgdt+vds);
1245  cpart=vds*(-vds*(-Bfac*vds - tJFETb)+vgdt*apart);
1246  cdrain=betap*cpart;
1247  gm=betap*vds*(apart+3.0*Bfac*vgdt);;
1248  gds=betap*(vgdt+vds)*apart-tLambda*tBeta*cpart - gm;
1249  // Xyce::dout() << " linear region - inverse mode" << std::endl;
1250  }
1251  else
1252  {
1253  //
1254  // saturation region
1255  //
1256  Bfac=vgdt*Bfac;
1257  gm=-betap*vgdt*(2.0*tJFETb+3.0*Bfac);
1258  cpart=vgdt*vgdt*(tJFETb+Bfac);
1259  cdrain=-betap*cpart;
1260  gds=tLambda*tBeta*cpart - gm;
1261  // Xyce::dout() << " saturation region - inverse mode " << std::endl;
1262  }
1263  }
1264  }
1265  }
1266  else if(level == 2)
1267  {
1268  //
1269  // Shockley JFET model with modified Vdsat
1270  //
1271  if(vds >= 0) // normal mode
1272  {
1273  vgst=vgs-tvt0;
1274  if (vgst <= 0)
1275  {
1276  //
1277  // cutoff region
1278  //
1279  cdrain=0;
1280  gm=0;
1281  gds=0;
1282  // Xyce::dout() << " cutoff region - Shockley normal mode " << std::endl;
1283  }
1284  else
1285  {
1286  A = tPB-tvt0;
1287  if(A != 0) B = (A-vgst)/A;
1288  else B = 0;
1289  if(B >= 0) B12 = sqrt(B);
1290  else B12 = 0;
1291 
1292  betap=tBeta*(1+tLambda*vds)/(1+tTheta*vgst);
1293  Vdsat = vgst + tDelta;
1294  // Idsat = dtype*betap*(vgst-(2*A/3)*(1-B*B12));
1295 
1296  if(A != 0) C = (vds - tDelta*vds/Vdsat + A-vgst)/A;
1297  else C = 0;
1298  if(C >= 0) C12 = sqrt(C);
1299  else C12 = 0;
1300  D = C*C12 - B*B12;
1301 
1302  if( dtype*Vd <= Vdsat )
1303  {
1304  //
1305  // linear region
1306  //
1307  cdrain = betap*(vds - tDelta*vds/Vdsat - (2*A/3)*D);
1308  gm = -cdrain*tTheta/(1+tTheta*vgst) + betap*(C12 - B12)
1309  + betap*tDelta*(1-C12)*vds/(Vdsat*Vdsat);
1310  gds = tLambda*cdrain/(1+tLambda*vds)
1311  + betap*(1-(1-C12)*tDelta/Vdsat-C12);
1312  // Xyce::dout() << " linear region - Shockley normal mode" << std::endl;
1313  }
1314  else
1315  {
1316  //
1317  // saturation region
1318  //
1319  cdrain = betap*(vgst - (2*A/3)*(1 - B*B12));
1320  gm = betap*(1-B12) - tTheta*cdrain/(1+tTheta*vgst);
1321  gds = tLambda*cdrain/(1+tLambda*vds);
1322  // Xyce::dout() << " saturation region - Shockley normal mode" << std::endl;
1323  }
1324  }
1325  }
1326  else // inverse mode
1327 // Inverse mode is where you switch the drain and source
1328 // and run the device in reverse. The equations for inverse
1329 // mode are obtained by the following substitutions:
1330 // vgst -> vgdt, vds -> -vds, cdrain -> -cdrain
1331  {
1332  vgdt=vgd-tvt0;
1333  if (vgdt <= 0)
1334  {
1335  //
1336  // cutoff region
1337  //
1338  cdrain=0;
1339  gm=0;
1340  gds=0;
1341  // Xyce::dout() << " cutoff region - Shockley inverse mode " << std::endl;
1342  }
1343  else
1344  {
1345  A = tPB-tvt0;
1346  if(A != 0) B = (A-vgdt)/A;
1347  else B = 0;
1348  if(B >= 0) B12 = sqrt(B);
1349  else B12 = 0;
1350 
1351  betap = tBeta*(1-tLambda*vds)/(1+tTheta*vgdt);
1352  Vdsat = vgdt + tDelta;
1353  // Idsat = -dtype*betap*(vgdt-(2*A/3)*(1-B*B12));
1354 
1355  if(A != 0) C = (-vds + tDelta*vds/Vdsat + A-vgdt)/A;
1356  else C = 0;
1357  if(C >= 0) C12 = sqrt(C);
1358  else C12 = 0;
1359  D = C*C12 - B*B12;
1360 
1361  if( dtype*Vs <= Vdsat )
1362  {
1363  //
1364  // linear region
1365  //
1366  cdrain = -betap*(-vds + tDelta*vds/Vdsat - (2*A/3)*D);
1367  gm = -betap*(C12 - B12) - tTheta*cdrain/(1+tTheta*vgdt);
1368  gm += betap*(1-C12)*tDelta*vds/(Vdsat*Vdsat);
1369  gds = betap*(1 - (1-C12)*tDelta/Vdsat - C12)
1370  - tLambda*cdrain/(1-tLambda*vds);
1371 
1372  // Xyce::dout() << " linear region - Shockley inverse mode" << std::endl;
1373  }
1374  else
1375  {
1376  //
1377  // saturation region
1378  //
1379  cdrain = -betap*(vgdt - (2*A/3)*(1 - B*B12));
1380  gm = -betap*(1-B12) - tTheta*cdrain/(1+tTheta*vgdt);
1381  gds = tLambda*cdrain/(1-tLambda*vds);
1382  // Xyce::dout() << " saturation region - Shockley inverse mode" << std::endl;
1383  }
1384  }
1385  }
1386  }
1387  cd = cdrain-cgd;
1388 
1389  //
1390  // charge storage elements
1391  //
1392  twop = 2.0*tPB;
1393  fcpb2 = corDepCap*corDepCap;
1394  czgs = tCGS;
1395  czgd = tCGD;
1396  if(czgs != 0)
1397  {
1398  czgsf2=czgs/f2;
1399  if (vgs < corDepCap)
1400  {
1401  sarg=sqrt(1-vgs/tPB);
1402  qgs = twop*czgs*(1-sarg);
1403  capgs=czgs/sarg;
1404  }
1405  else
1406  {
1407  qgs = czgs*f1 + czgsf2*(f3 *(vgs - corDepCap)
1408  +(vgs*vgs - fcpb2)/(2*twop));
1409  capgs=czgsf2*(f3 + vgs/twop);
1410  }
1411  }
1412  else
1413  {
1414  qgs=0.0;
1415  capgs=0.0;
1416  }
1417 
1418  if(czgd != 0)
1419  {
1420  czgdf2=czgd/f2;
1421  if (vgd < corDepCap)
1422  {
1423  sarg=sqrt(1-vgd/tPB);
1424  qgd = twop*czgd*(1-sarg);
1425  capgd=czgd/sarg;
1426  }
1427  else
1428  {
1429  qgd = czgd*f1 + czgdf2*( f3*(vgd - corDepCap)
1430  +(vgd*vgd - fcpb2)/(2*twop) );
1431  capgd=czgdf2*(f3 + vgd/twop);
1432  }
1433  }
1434  else
1435  {
1436  qgd=0.0;
1437  capgd=0.0;
1438  }
1439 
1440  Idrain = drainCond * Vddp;
1441  Isource = sourceCond * Vssp;
1442 
1443  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1444  {
1445  Xyce::dout() << " Done with Instance::updateIntermediateVars. name = " << getName() << std::endl;
1446  Xyce::dout() << " mode = " << mode << std::endl;
1447  Xyce::dout() << " tBeta = " << tBeta << std::endl;
1448  Xyce::dout() << " Idrain = " << Idrain << std::endl;
1449  Xyce::dout() << " Isource = " << Isource << std::endl;
1450  Xyce::dout() << " gds = " << gds << std::endl;
1451  Xyce::dout() << " gm = " << gm << std::endl;
1452  }
1453 
1454  /// CURRENTS to load into RHS:
1455 
1456  // so at this point:
1457 
1458  // current out of drain is
1459  // Idrain
1460 
1461  // current out of gate:
1462  // dtype*( d/dt(qgs) + d/dt(qgd) )
1463 
1464  // the current *out of* the source should be simply
1465  // Isource
1466 
1467  // current out of drain' is
1468  // -Idrain - dtype*( d/dt(qgd) - cdrain )
1469 
1470  // the current out of the source' is
1471  // -Isource - dtype*( d/dt(qgs) + cdrain )
1472 
1473  return true;
1474 }
1475 
1476 //-----------------------------------------------------------------------------
1477 // Function : Instance::loadDAEQVector
1478 //
1479 // Purpose : Loads the Q-vector contributions for a single
1480 // voltage source instance.
1481 //
1482 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1483 // which the system of equations is represented as:
1484 //
1485 // f(x) = dQ(x)/dt + F(x) + B(t) = 0
1486 //
1487 // The "Q" vector contains charges and fluxes, mostly.
1488 // The voltage source will not make any contributions to Q,
1489 // so this function does nothing.
1490 //
1491 // from updateSecondaryState:
1492 //
1493 // ggd = ggd + capgd*(getSolverState().pdt);
1494 // ggs = ggs + capgs*(getSolverState().pdt);
1495 //
1496 // // Sum the capacitor currents into the DC currents.
1497 // cg = cg + cqgs + cqgd;
1498 // cd = cd - cqgd;
1499 // cgd = cgd + cqgd;
1500 //
1501 // So:
1502 //
1503 // replace ggd with capgd.
1504 // replace ggs with capgs
1505 //
1506 // replace cg with qgs+qgd
1507 // replace cd with -qgd
1508 // replace cgd with qgd.
1509 //
1510 //
1511 // Scope : public
1512 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1513 // Creation Date : 02/19/05
1514 //-----------------------------------------------------------------------------
1516 {
1517  double * qVec = extData.daeQVectorRawPtr;
1518  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
1519 
1520  // set up the final load variables:
1521  int Dtype = model_.dtype;
1522  double ceqgd = Dtype*(qgd);
1523  double ceqgs = Dtype*(((qgs+qgd)-qgd));
1524  double cdreq = Dtype*(((-qgd)+qgd));
1525 
1526  double ceqgd_Jdxp = -Dtype*(capgd*(vgd-vgd_orig));
1527  double ceqgs_Jdxp = -Dtype*(capgs*(vgs-vgs_orig));
1528  double cdreq_Jdxp = 0.0;
1529 
1530  qVec[li_Gate ] += ( ceqgs+ceqgd);
1531  qVec[li_DrainPrime ] -= (-cdreq+ceqgd);
1532  qVec[li_SourcePrime] -= ( cdreq+ceqgs);
1533 
1534  if (!origFlag)
1535  {
1536  dQdxdVp[li_Gate ] -= ( ceqgs_Jdxp+ceqgd_Jdxp);
1537  dQdxdVp[li_DrainPrime ] += (-cdreq_Jdxp+ceqgd_Jdxp);
1538  dQdxdVp[li_SourcePrime] += ( cdreq_Jdxp+ceqgs_Jdxp);
1539  }
1540 
1541  if( loadLeadCurrent )
1542  {
1543  double * stoVec = extData.storeLeadCurrQCompRawPtr;
1544  stoVec[li_store_dev_id] = -(-cdreq+ceqgd);
1545  stoVec[li_store_dev_is] = -(cdreq+ceqgs);
1546  stoVec[li_store_dev_ig] = ceqgs+ceqgd;
1547  }
1548 
1549  if( loadLeadCurrent )
1550  {
1551  double * stoVec = extData.storeLeadCurrQCompRawPtr;
1552  stoVec[li_store_dev_id] = -(-cdreq+ceqgd);
1553  stoVec[li_store_dev_is] = -(cdreq+ceqgs);
1554  stoVec[li_store_dev_ig] = ceqgs+ceqgd;
1555  }
1556 
1557  return true;
1558 }
1559 
1560 //-----------------------------------------------------------------------------
1561 // Function : Instance::loadDAEFVector
1562 //
1563 // Purpose : Loads the F-vector contributions for a single
1564 // JFET instance.
1565 //
1566 // Special Notes :
1567 //
1568 // Scope : public
1569 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1570 // Creation Date : 02/19/05
1571 //-----------------------------------------------------------------------------
1573 {
1574  double * fVec = extData.daeFVectorRawPtr;
1575  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
1576 
1577  // set up the final load variables:
1578  int Dtype = model_.dtype;
1579  double ceqgd = Dtype*(cgd);
1580  double ceqgs = Dtype*((cg-cgd));
1581  double cdreq = Dtype*((cd+cgd));
1582 
1583  double ceqgd_Jdxp = -Dtype*(ggd*(vgd-vgd_orig));
1584  double ceqgs_Jdxp = -Dtype*(ggs*(vgs-vgs_orig));
1585  double cdreq_Jdxp = -Dtype*(gds*(vds-vds_orig)+gm*(vgs-vgs_orig));
1586 
1587  // optional load JFETs:
1588  if (drainCond != 0.0)
1589  {
1590  fVec[li_Drain ] += Idrain;
1591  }
1592 
1593  if (sourceCond != 0.0)
1594  {
1595  fVec[li_Source] += Isource;
1596  }
1597 
1598  fVec[li_Gate ] += (ceqgs+ceqgd);
1599  fVec[li_DrainPrime ] -= (Idrain +(-cdreq+ceqgd));
1600  fVec[li_SourcePrime] -= (Isource+(cdreq+ceqgs));
1601 
1602  if (!origFlag)
1603  {
1604  dFdxdVp[li_Gate ] -= ( ceqgs_Jdxp+ceqgd_Jdxp);
1605  dFdxdVp[li_DrainPrime ] += (-cdreq_Jdxp+ceqgd_Jdxp);
1606  dFdxdVp[li_SourcePrime] += ( cdreq_Jdxp+ceqgs_Jdxp);
1607  }
1608 
1609  if( loadLeadCurrent )
1610  {
1611  double * stoVec = extData.nextStoVectorRawPtr;
1612  if (drainCond != 0.0)
1613  {
1614  stoVec[li_store_dev_id] = Idrain;
1615  }
1616  else
1617  {
1618  stoVec[li_store_dev_id] = -(Idrain +(-cdreq+ceqgd));
1619  }
1620  if (sourceCond != 0.0)
1621  {
1622  stoVec[li_store_dev_is] = Isource;
1623  }
1624  else
1625  {
1626  stoVec[li_store_dev_is] = -(Isource+(cdreq+ceqgs));
1627  }
1628  stoVec[li_store_dev_ig] = (ceqgs+ceqgd);
1629  }
1630 
1631  if( loadLeadCurrent )
1632  {
1633  double * stoVec = extData.nextStoVectorRawPtr;
1634  if (drainCond != 0.0)
1635  {
1636  stoVec[li_store_dev_id] = Idrain;
1637  }
1638  else
1639  {
1640  stoVec[li_store_dev_id] = -(Idrain +(-cdreq+ceqgd));
1641  }
1642  if (sourceCond != 0.0)
1643  {
1644  stoVec[li_store_dev_is] = Isource;
1645  }
1646  else
1647  {
1648  stoVec[li_store_dev_is] = -(Isource+(cdreq+ceqgs));
1649  }
1650  stoVec[li_store_dev_ig] = (ceqgs+ceqgd);
1651  }
1652 
1653  return true;
1654 }
1655 
1656 //-----------------------------------------------------------------------------
1657 // Function : Instance::loadDAEdQdx
1658 //
1659 // Purpose : Loads the Q-vector contributions for a single
1660 // JFET instance.
1661 //
1662 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1663 // which the system of equations is represented as:
1664 //
1665 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1666 //
1667 // Scope : public
1668 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1669 // Creation Date : 02/19/05
1670 //-----------------------------------------------------------------------------
1672 {
1673  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
1674 
1682 
1683  return true;
1684 }
1685 
1686 //-----------------------------------------------------------------------------
1687 // Function : Instance::loadDAEdFdx ()
1688 //
1689 // Purpose : Loads the F-vector contributions for a single
1690 // JFET instance.
1691 //
1692 // Special Notes : The F-vector is an algebraic constaint.
1693 //
1694 // Scope : public
1695 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1696 // Creation Date : 02/19/05
1697 //-----------------------------------------------------------------------------
1699 {
1700  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
1701 
1704 
1708 
1711 
1715  drainCond+gds+ggd;
1717 
1722  += sourceCond+gds+gm+ggs;
1723 
1724  return true;
1725 }
1726 
1727 //-----------------------------------------------------------------------------
1728 // Function : Instance::updateTemperature
1729 // Purpose :
1730 // Special Notes :
1731 // Scope : public
1732 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1733 // Creation Date : 3/16/00
1734 //-----------------------------------------------------------------------------
1735 bool Instance::updateTemperature ( const double & temp_tmp)
1736 {
1737  bool bsuccess = true;
1738  double tnom, ratio;
1739  double arg, arg1;
1740  double ratio1;
1741  double fact1, fact2;
1742  double kt, kt1;
1743  double vtnom;
1744  double egfet, egfet1;
1745  double pbfact;
1746  double cjfact, cjfact1;
1747  double gmanew, gmaold;
1748  double pbo;
1749  double xfc;
1750  double Pb;
1751 
1752  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1753  {
1754 // Xyce::dout() << subsection_divider << std::endl;
1755  Xyce::dout() << " Instance::Begin of updateTemperature. name = " << getName() << std::endl;
1756  Xyce::dout() << std::endl;
1757  }
1758 
1759  // first set the instance temperature to the new temperature:
1760  if (temp_tmp != -999.0) temp = temp_tmp;
1762  {
1763  // make sure interpolation doesn't take any resistance negative
1764  if(model_.RD < 0) model_.RD = 0;
1765  if(model_.RS < 0) model_.RS = 0;
1766 
1767  // some params may have changed during interpolation
1768  // model_.processParams();
1769  }
1770 
1771  Pb = model_.PB;
1772  tnom = model_.TNOM;
1773  ratio = temp/tnom;
1774 
1775  // first do the model stuff
1776 
1777  if (model_.RD != 0)
1778  drainCond = area/model_.RD;
1779  if (model_.RS != 0)
1781  vtnom = tnom*CONSTKoverQ;
1782  fact1 = tnom/CONSTREFTEMP;
1783  kt1 = CONSTboltz*tnom;
1784  egfet1 = 1.16 - (7.02e-4*tnom*tnom)/(tnom + 1108);
1785  arg1 = -egfet1/(2.0*kt1) + 1.1150877/(CONSTboltz*2.0*CONSTREFTEMP);
1786  pbfact = -2.0*vtnom*(1.5*log(fact1) + CONSTQ*arg1);
1787  pbo = (Pb - pbfact)/fact1;
1788  gmaold = (Pb - pbo)/pbo;
1789  cjfact = 1.0/(1.0 + 0.5*(4e-4*(tnom - CONSTREFTEMP) - gmaold));
1790 
1791  if(model_.FC >.95) {
1792  Xyce::dout() << "Depletion cap. coeff. FC too large, limited to .95";
1793  Xyce::dout() << std::endl;
1794  model_.FC = .95;
1795  }
1796  xfc = log(1.0 - model_.FC);
1797  f2 = exp(1.5*xfc);
1798  f3 = 1.0 - 1.5*model_.FC;
1799  // skip bFac
1800 
1801  // now do the instance stuff
1802 
1803  vt = temp*CONSTKoverQ;
1804  kt = temp*CONSTboltz;
1805  fact2 = temp/CONSTREFTEMP;
1806  ratio1 = ratio - 1.0;
1807  tIS = model_.IS*exp(ratio1*1.11/vt)*area;
1808 
1809  tCGS = model_.CGS*cjfact*area;
1810  tCGD = model_.CGD*cjfact*area;
1811  egfet = 1.16 - (7.02e-4*temp*temp)/(temp + 1108);
1812  arg = -egfet/(2.0*kt) + 1.1150877/(CONSTboltz*2.0*CONSTREFTEMP);
1813  pbfact = -2.0*vt*(1.5*log(fact2) + CONSTQ*arg);
1814  tPB = fact2*pbo + pbfact;
1815  gmanew = (tPB - pbo)/pbo;
1816  cjfact1 = 1.0 + 0.5*(4e-4*(temp - CONSTREFTEMP) - gmanew);
1817  tCGS *= cjfact1;
1818  tCGD *= cjfact1;
1819 
1820  corDepCap = model_.FC*tPB;
1821  f1 = tPB*(1.0 - exp((0.5)*xfc))/(0.5);
1822  vcrit = vt * log(vt/(CONSTroot2 * tIS));
1823 
1824  // the following parameters have no temperature dependence in Spice 3f5
1825  //
1826  tBeta = model_.BETA*area; // transconductance parameter
1827  tvt0 = model_.VTO; // threshold voltage
1828  tLambda = model_.LAMBDA; // channel-length modulation
1829  tDelta = model_.DELTA; // parameter to shift Shockley Vdsat
1830  tTheta = model_.THETA; // gate voltage mobility parameter
1831  tRD = model_.RD/area; // drain ohmic resistance
1832  tRS = model_.RS/area; // source ohmic resistance
1833  tJFETb = model_.B; // dopinng tail parameter
1834 
1835  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1836  {
1837  Xyce::dout() << std::endl;
1838  Xyce::dout() << "temp = "<< temp << std::endl;
1839  Xyce::dout() << "tnom = " << tnom << std::endl;
1840  Xyce::dout() << "ratio = " << ratio << std::endl;
1841  Xyce::dout() << "vt = " << vt << std::endl;
1842  Xyce::dout() << "kt = " << kt << std::endl;
1843  Xyce::dout() << "fact2 = " << fact2 << std::endl;
1844  Xyce::dout() << "egfet = " << egfet << std::endl;
1845  Xyce::dout() << "arg = " << arg << std::endl;
1846  Xyce::dout() << "pbfact = " << pbfact << std::endl;
1847  Xyce::dout() << "pbo = " << pbo << std::endl;
1848  Xyce::dout() << "f2 = " << f2 << std::endl;
1849  Xyce::dout() << "f3 = " << f3 << std::endl;
1850  Xyce::dout() << "corDepCap = " << corDepCap << std::endl;
1851  Xyce::dout() << "tBeta = " << tBeta << std::endl;
1852  Xyce::dout() << "tvt0 = " << tvt0 << std::endl;
1853  Xyce::dout() << "tPB = " << tPB << std::endl;
1854  Xyce::dout() << "tJFETb = " << tJFETb << std::endl;
1855  Xyce::dout() << "tLambda = " << tLambda << std::endl;
1856  Xyce::dout() << "tDelta = " << tDelta << std::endl;
1857  Xyce::dout() << "tTheta = " << tTheta << std::endl;
1858  Xyce::dout() << "tRD = " << tRD << std::endl;
1859  Xyce::dout() << "tRS = " << tRS << std::endl;
1860  Xyce::dout() << " " << std::endl;
1861  }
1862 
1863  return bsuccess;
1864 }
1865 
1866 //-----------------------------------------------------------------------------
1867 // Function : Instance::processParams
1868 // Purpose :
1869 // Special Notes :
1870 // Scope : public
1871 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1872 // Creation Date : 3/16/00
1873 //-----------------------------------------------------------------------------
1875 {
1876  if (!given("TEMP"))
1877  temp = getDeviceOptions().temp.getImmutableValue<double>();
1878 
1880  return true;
1881 }
1882 
1883 
1884 // JFET Master functions:
1885 
1886 //-----------------------------------------------------------------------------
1887 // Function : Master::updateState
1888 // Purpose :
1889 // Special Notes :
1890 // Scope : public
1891 // Creator : Eric Keiter, SNL
1892 // Creation Date : 11/26/08
1893 //-----------------------------------------------------------------------------
1894 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
1895 {
1896  bool bsuccess = true;
1897 
1898  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1899  {
1900  Instance & ji = *(*it);
1901  bool btmp = ji.updateIntermediateVars ();
1902  bsuccess = bsuccess && btmp;
1903 
1904  double * stoVec = ji.extData.nextStoVectorRawPtr;
1905  stoVec[ji.li_store_vgs] = ji.vgs;
1906  stoVec[ji.li_store_vgd] = ji.vgd;
1907  staVec[ji.li_state_qgs] = ji.qgs;
1908  staVec[ji.li_state_qgd] = ji.qgd;
1909  }
1910 
1911  return bsuccess;
1912 }
1913 
1914 //-----------------------------------------------------------------------------
1915 // Function : Master::loadDAEVectors
1916 // Purpose :
1917 // Special Notes :
1918 // Scope : public
1919 // Creator : Eric Keiter, SNL
1920 // Creation Date : 11/26/08
1921 //-----------------------------------------------------------------------------
1922 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
1923 {
1924  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1925  {
1926  Instance & ji = *(*it);
1927 
1928  // F-vector:
1929  double * dFdxdVp = ji.extData.dFdxdVpVectorRawPtr;
1930 
1931  // set up the final load variables:
1932  int Dtype = ji.getModel().dtype;
1933  double f_ceqgd = Dtype*(ji.cgd);
1934  double f_ceqgs = Dtype*((ji.cg-ji.cgd));
1935  double f_cdreq = Dtype*((ji.cd+ji.cgd));
1936 
1937  double f_ceqgd_Jdxp = -Dtype*(ji.ggd*(ji.vgd-ji.vgd_orig));
1938  double f_ceqgs_Jdxp = -Dtype*(ji.ggs*(ji.vgs-ji.vgs_orig));
1939  double f_cdreq_Jdxp = -Dtype*(ji.gds*(ji.vds-ji.vds_orig)+ji.gm*(ji.vgs-ji.vgs_orig));
1940 
1941  // optional load JFETs:
1942  if (ji.drainCond != 0.0)
1943  {
1944  fVec[ji.li_Drain ] += ji.Idrain;
1945  }
1946 
1947  if (ji.sourceCond != 0.0)
1948  {
1949  fVec[ji.li_Source] += ji.Isource;
1950  }
1951 
1952  fVec[ji.li_Gate ] += (f_ceqgs+f_ceqgd);
1953  fVec[ji.li_DrainPrime ] -= (ji.Idrain +(-f_cdreq+f_ceqgd));
1954  fVec[ji.li_SourcePrime] -= (ji.Isource+(f_cdreq+f_ceqgs));
1955 
1956  if (!ji.origFlag)
1957  {
1958  dFdxdVp[ji.li_Gate ] -= ( f_ceqgs_Jdxp+f_ceqgd_Jdxp);
1959  dFdxdVp[ji.li_DrainPrime ] += (-f_cdreq_Jdxp+f_ceqgd_Jdxp);
1960  dFdxdVp[ji.li_SourcePrime] += ( f_cdreq_Jdxp+f_ceqgs_Jdxp);
1961  }
1962 
1963  // Q-vector:
1964  double * dQdxdVp = ji.extData.dQdxdVpVectorRawPtr;
1965  // set up the final load variables:
1966  double q_ceqgd = Dtype*(ji.qgd);
1967  double q_ceqgs = Dtype*(((ji.qgs+ji.qgd)-ji.qgd));
1968  double q_cdreq = Dtype*(((-ji.qgd)+ji.qgd));
1969 
1970  double q_ceqgd_Jdxp = -Dtype*(ji.capgd*(ji.vgd-ji.vgd_orig));
1971  double q_ceqgs_Jdxp = -Dtype*(ji.capgs*(ji.vgs-ji.vgs_orig));
1972  double q_cdreq_Jdxp = 0.0;
1973 
1974  qVec[ji.li_Gate ] += ( q_ceqgs+q_ceqgd);
1975  qVec[ji.li_DrainPrime ] -= (-q_cdreq+q_ceqgd);
1976  qVec[ji.li_SourcePrime] -= ( q_cdreq+q_ceqgs);
1977 
1978  if (!ji.origFlag)
1979  {
1980  dQdxdVp[ji.li_Gate ] -= ( q_ceqgs_Jdxp+q_ceqgd_Jdxp);
1981  dQdxdVp[ji.li_DrainPrime ] += (-q_cdreq_Jdxp+q_ceqgd_Jdxp);
1982  dQdxdVp[ji.li_SourcePrime] += ( q_cdreq_Jdxp+q_ceqgs_Jdxp);
1983  }
1984  if( ji.loadLeadCurrent )
1985  {
1986  if (ji.drainCond != 0.0)
1987  {
1988  storeLeadF[ji.li_store_dev_id] = ji.Idrain;
1989  }
1990  else
1991  {
1992  storeLeadF[ji.li_store_dev_id] = -(ji.Idrain +(-f_cdreq+f_ceqgd));
1993  storeLeadQ[ji.li_store_dev_id] = -(-q_cdreq+q_ceqgd);
1994  }
1995  if (ji.sourceCond != 0.0)
1996  {
1997  storeLeadF[ji.li_store_dev_is] = ji.Isource;
1998  }
1999  else
2000  {
2001  storeLeadF[ji.li_store_dev_is] = -(ji.Isource+(f_cdreq+f_ceqgs));
2002  storeLeadQ[ji.li_store_dev_is] = -(q_cdreq+q_ceqgs);
2003  }
2004  storeLeadF[ji.li_store_dev_ig] = (f_ceqgs+f_ceqgd);
2005  storeLeadQ[ji.li_store_dev_ig] = q_ceqgs+q_ceqgd;
2006  }
2007  }
2008 
2009  return true;
2010 }
2011 
2012 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2013 //-----------------------------------------------------------------------------
2014 // Function : Master::loadDAEMatrices
2015 // Purpose :
2016 // Special Notes :
2017 // Scope : public
2018 // Creator : Eric Keiter, SNL
2019 // Creation Date : 12/12/08
2020 //-----------------------------------------------------------------------------
2021 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
2022 {
2023  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
2024  {
2025  Instance & ji = *(*it);
2026 
2027  // F-matrix:
2028 
2030 
2032 
2033 
2034  *ji.f_GateEquGateNodePtr += ji.ggd+ji.ggs;
2035 
2036  *ji.f_GateEquDrainPrimeNodePtr -= ji.ggd;
2037 
2038  *ji.f_GateEquSourcePrimeNodePtr -= ji.ggs;
2039 
2040 
2042 
2044 
2045 
2047 
2048  *ji.f_DrainPrimeEquGateNodePtr += ji.gm-ji.ggd;
2049 
2051 
2053 
2054 
2055  *ji.f_SourcePrimeEquGateNodePtr -= ji.gm+ji.ggs;
2056 
2058 
2060 
2062 
2063  // Q-matrix:
2064 
2065  *ji.q_GateEquGateNodePtr += ji.capgd+ji.capgs;
2066 
2068 
2070 
2072 
2074 
2076 
2078  }
2079 
2080  return true;
2081 }
2082 
2083 #else
2084 //-----------------------------------------------------------------------------
2085 // Function : Master::loadDAEMatrices
2086 // Purpose :
2087 // Special Notes :
2088 // Scope : public
2089 // Creator : Eric Keiter, SNL
2090 // Creation Date : 12/12/08
2091 //-----------------------------------------------------------------------------
2092 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
2093 {
2094  int sizeInstances = instanceContainer_.size();
2095 
2096  for (int i=0; i<sizeInstances; ++i)
2097  {
2098  Instance & ji = *(instanceContainer_.at(i));
2099 
2100  // dFdx matrix:
2101 
2102  dFdx[ji.li_Drain][ji.ADrainEquDrainNodeOffset] += ji.drainCond;
2103 
2105 
2106 
2107  dFdx[ji.li_Gate][ji.AGateEquGateNodeOffset] += ji.ggd+ji.ggs;
2108 
2109  dFdx[ji.li_Gate][ji.AGateEquDrainPrimeNodeOffset] -= ji.ggd;
2110 
2111  dFdx[ji.li_Gate][ji.AGateEquSourcePrimeNodeOffset] -= ji.ggs;
2112 
2113 
2114  dFdx[ji.li_Source][ji.ASourceEquSourceNodeOffset] += ji.sourceCond;
2115 
2117 
2118 
2120 
2121  dFdx[ji.li_DrainPrime][ji.ADrainPrimeEquGateNodeOffset] += ji.gm-ji.ggd;
2122 
2124  ji.drainCond+ji.gds+ji.ggd;
2125 
2127 
2128 
2129  dFdx[ji.li_SourcePrime][ji.ASourcePrimeEquGateNodeOffset] -= ji.gm+ji.ggs;
2130 
2132 
2134 
2136  += ji.sourceCond+ji.gds+ji.gm+ji.ggs;
2137 
2138  // dQdx matrix:
2139 
2140  dQdx[ji.li_Gate ][ji.AGateEquGateNodeOffset ] += ji.capgd+ji.capgs;
2141 
2142  dQdx[ji.li_Gate ][ji.AGateEquDrainPrimeNodeOffset ] -= ji.capgd;
2143 
2144  dQdx[ji.li_Gate ][ji.AGateEquSourcePrimeNodeOffset ] -= ji.capgs;
2145 
2146  dQdx[ji.li_DrainPrime ][ji.ADrainPrimeEquGateNodeOffset ] -= ji.capgd;
2147 
2149 
2151 
2153  }
2154 
2155  return true;
2156 }
2157 #endif
2158 
2159 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
2160 {
2161 
2162  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
2163 }
2164 
2166 {
2168  .registerDevice("j", 1)
2169  .registerDevice("j", 2)
2170  .registerModelType("pjf", 1)
2171  .registerModelType("njf", 1)
2172  .registerModelType("pjf", 2)
2173  .registerModelType("njf", 2);
2174 }
2175 
2176 } // namespace JFET
2177 } // namespace Device
2178 } // namespace Xyce
const InstanceName & getName() const
double * q_SourcePrimeEquSourceNodePtr
Definition: N_DEV_JFET.h:330
#define CONSTPMOS
Definition: N_DEV_Const.h:80
static void initThermalModel(ParametricData< T > &parametric_data)
Add the parameter "TEMPMODEL" to the parametric_data.
const DeviceOptions & deviceOptions_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
Instance(const Configuration &configuration, const InstanceBlock &instance_block, Model &model, const FactoryBlock &factory_block)
Definition: N_DEV_JFET.C:372
#define CONSTQ
Definition: N_DEV_Const.h:51
#define CONSTREFTEMP
Definition: N_DEV_Const.h:56
static std::vector< int > jacMap_SC
Definition: N_DEV_JFET.h:147
bool updateTemperature(const double &temp_tmp)
Definition: N_DEV_JFET.C:1735
#define RD
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.
virtual std::ostream & printOutInstances(std::ostream &os) const
Definition: N_DEV_JFET.C:280
Parameter may be specified as time dependent expression from netlist.
Definition: N_DEV_Pars.h:67
void addInternalNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Definition: N_DEV_JFET.C:318
static std::vector< std::vector< int > > jacStamp
Definition: N_DEV_JFET.h:143
double * f_SourceEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:292
void setNumStoreVars(int num_store_vars)
double * f_DrainPrimeEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:298
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
static std::vector< int > jacMap_DC
Definition: N_DEV_JFET.h:146
#define AssertLIDs(cmp)
#define CONSTNMOS
Definition: N_DEV_Const.h:79
Parameter is subject to being set to minimum junction capacitance.
Definition: N_DEV_Pars.h:71
static std::vector< std::vector< int > > jacStamp_SC
Definition: N_DEV_JFET.h:142
static std::vector< std::vector< int > > jacStamp_DC
Definition: N_DEV_JFET.h:141
double * q_SourcePrimeEquDrainPrimeNodePtr
Definition: N_DEV_JFET.h:331
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
Parameter is subject to being set to minimum lead resistance.
Definition: N_DEV_Pars.h:70
double fetlim(double vnew, double vold, double vto)
double tnom
nominal temperature for device params.
#define DELTA
double * q_SourceEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:320
double * f_DrainPrimeEquDrainPrimeNodePtr
Definition: N_DEV_JFET.h:297
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
std::vector< Instance * > instanceContainer
Definition: N_DEV_JFET.h:427
std::vector< Param > params
Parameters from the line.
#define THETA
void setParams(const std::vector< Param > &params)
double * f_SourcePrimeEquSourceNodePtr
Definition: N_DEV_JFET.h:302
const std::string & getName() const
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
void registerStoreLIDs(const std::vector< int > &stoLIDVecRef)
Definition: N_DEV_JFET.C:755
double * q_SourcePrimeEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:332
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_JFET.C:1922
const DeviceOptions & getDeviceOptions() const
#define CONSTroot2
Definition: N_DEV_Const.h:50
static std::vector< std::vector< int > > jacMap2_DC
Definition: N_DEV_JFET.h:151
double * q_DrainPrimeEquDrainPrimeNodePtr
Definition: N_DEV_JFET.h:325
bool processParams()
processParams
Definition: N_DEV_JFET.C:333
static void loadModelParameters(ParametricData< Model > &model_parameters)
Definition: N_DEV_JFET.C:82
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
Linear::Matrix * dFdxMatrixPtr
static std::vector< std::vector< int > > jacMap2_DC_SC
Definition: N_DEV_JFET.h:150
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
void addStoreNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
const std::vector< std::vector< int > > & jacobianStamp() const
Definition: N_DEV_JFET.C:781
static std::vector< std::vector< int > > jacStamp_DC_SC
Definition: N_DEV_JFET.h:140
static std::vector< int > jacMap
Definition: N_DEV_JFET.h:148
const SolverState & solverState_
Class Configuration contains device configuration data.
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
Definition: N_DEV_JFET.C:2021
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
Definition: N_DEV_JFET.C:70
static std::vector< int > jacMap_DC_SC
Definition: N_DEV_JFET.h:145
void jacStampMap(const JacobianStamp &stamp_parent, IdVector &map_parent, JacobianStamp &map2_parent, JacobianStamp &stamp, IdVector &map, JacobianStamp &map2, int from, int to, int original_size)
const SolverState & getSolverState() const
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
Definition: N_DEV_JFET.C:708
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_JFET.C:622
bool processInstanceParams()
processInstanceParams
Definition: N_DEV_JFET.C:347
#define Xyce_NONPOINTER_MATRIX_LOAD
Definition: N_DEV_Bsrc.C:97
double * f_SourcePrimeEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:304
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Definition: N_DEV_JFET.C:2159
const std::string & getType() const
double gmin
minimum allowed conductance.
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_JFET.C:1894
#define RS
#define CONSTKoverQ
Definition: N_DEV_Const.h:58
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_JFET.C:802
ModelBlock represents a .MODEL line from the netlist.
double * f_SourcePrimeEquDrainPrimeNodePtr
Definition: N_DEV_JFET.h:303
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
Definition: N_DEV_JFET.C:684
Util::Param temp
operating temperature of ckt.
std::vector< Param > params
Linear::Matrix * dQdxMatrixPtr
double * q_DrainPrimeEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:326
static std::vector< std::vector< int > > jacMap2
Definition: N_DEV_JFET.h:153
Linear::Vector * flagSolVectorPtr
#define LAMBDA
void setModParams(const std::vector< Param > &params)
#define CONSTboltz
Definition: N_DEV_Const.h:53
static std::vector< std::vector< int > > jacMap2_SC
Definition: N_DEV_JFET.h:152