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.162.2.1 $
40 //
41 // Revision Date : $Date: 2015/04/02 18:20:11 $
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  // Set any non-constant parameter defaults:
594  if (!given("TEMP"))
595  temp = getDeviceOptions().temp.getImmutableValue<double>();
596 
597  // Calculate any parameters specified as expressions:
599 
600  // calculate dependent (ie computed) params and check for errors:
601  processParams ();
602 
603  drainCond = 0;
604  if (model_.RD != 0)
606  sourceCond = 0;
607  if (model_.RS != 0)
609 
610  numIntVars = (((sourceCond == 0.0)?0:1)+((drainCond == 0.0)?0:1));
611 }
612 
613 //-----------------------------------------------------------------------------
614 // Function : Instance::Instance
615 // Purpose : destructor
616 // Special Notes :
617 // Scope : public
618 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
619 // Creation Date : 3/16/00
620 //-----------------------------------------------------------------------------
622 {
623 }
624 
625 //----------------------------------------------------------------------------
626 // Function : Instance::registerLIDs
627 // Purpose :
628 // Special Notes :
629 // Scope : public
630 // Creator : pmc
631 // Creation Date : 11/16/2003
632 //----------------------------------------------------------------------------
633 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
634  const std::vector<int> & extLIDVecRef )
635 {
636  numIntVars = (((sourceCond == 0.0)?0:1)+((drainCond == 0.0)?0:1));
637 
638  AssertLIDs(intLIDVecRef.size() == numIntVars);
639  AssertLIDs(extLIDVecRef.size() == numExtVars);
640 
641  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
642  {
643  Xyce::dout() << std::endl << section_divider << std::endl;
644  Xyce::dout() << " Instance::registerLIDs. name = " << getName() << std::endl;
645  Xyce::dout() << " number of internal variables: " << numIntVars << std::endl;
646  Xyce::dout() << " number of external variables: " << numExtVars << std::endl;
647  }
648 
649  // copy over the global ID lists.
650  intLIDVec = intLIDVecRef;
651  extLIDVec = extLIDVecRef;
652 
653  // now use these lists to obtain the indices into the
654  // linear algebra entities. This assumes an order.
655  // For the matrix indices, first do the rows.
656 
657  li_Drain = extLIDVec[0];
658  li_Gate = extLIDVec[1];
659  li_Source = extLIDVec[2];
660 
661  int intLoc = 0;
662 
663  if( drainCond )
664  li_DrainPrime = intLIDVec[intLoc++];
665  else
667 
668  if( sourceCond )
669  li_SourcePrime = intLIDVec[intLoc];
670  else
672 
673  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
674  {
675  Xyce::dout() << "\n variable local indices:\n";
676  Xyce::dout() << " li_Drain = " << li_Drain << std::endl;
677  Xyce::dout() << " li_DrainPrime = " << li_DrainPrime << std::endl;
678  Xyce::dout() << " li_Source = " << li_Source << std::endl;
679  Xyce::dout() << " li_SourcePrime = " << li_SourcePrime << std::endl;
680  Xyce::dout() << " li_Gate = " << li_Gate << std::endl;
681 
682  Xyce::dout() << section_divider << std::endl;
683  }
684 
685 }
686 
687 //-----------------------------------------------------------------------------
688 // Function : Instance::loadNodeSymbols
689 // Purpose :
690 // Special Notes :
691 // Scope : public
692 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
693 // Creation Date : 05/13/05
694 //-----------------------------------------------------------------------------
695 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
696 {
697  if (drainCond != 0.0)
698  addInternalNode(symbol_table, li_DrainPrime, getName(), "drainprime");
699 
700  if (sourceCond != 0.0)
701  addInternalNode(symbol_table, li_SourcePrime, getName(), "sourceprime");
702 
703  if (loadLeadCurrent)
704  {
705  addStoreNode(symbol_table, li_store_dev_id, getName(), "DEV_ID");
706  addStoreNode(symbol_table, li_store_dev_is, getName(), "DEV_IS");
707  addStoreNode(symbol_table, li_store_dev_ig, getName(), "DEV_IG");
708  }
709 }
710 
711 //----------------------------------------------------------------------------
712 // Function : Instance::registerStateLIDs
713 // Purpose :
714 // Special Notes :
715 // Scope : public
716 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
717 // Creation Date : 3/16/00
718 //----------------------------------------------------------------------------
719 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef)
720 {
721  AssertLIDs(staLIDVecRef.size() == numStateVars);
722 
723  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
724  {
725  Xyce::dout() << std::endl;
726  Xyce::dout() << section_divider << std::endl;
727  Xyce::dout() << " In Instance::registerStateLIDs. name = " << getName() << std::endl;
728  Xyce::dout() << " Number of State LIDs: " << numStateVars << std::endl;
729  }
730 
731  // Copy over the global ID lists:
732  staLIDVec = staLIDVecRef;
733 
734  int lid = 0;
735 
736  li_state_qgs = staLIDVec[lid++];
737  li_state_gcgs = staLIDVec[lid++];
738 
739  li_state_qgd = staLIDVec[lid++];
740  li_state_gcgd = staLIDVec[lid++];
741 
742 
743  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
744  {
745  Xyce::dout() << " State local indices:" << std::endl;
746  Xyce::dout() << std::endl;
747 
748  Xyce::dout() << " li_state_qgs = " << li_state_qgs << std::endl;
749  Xyce::dout() << " li_state_gcgs = " << li_state_gcgs;
750  Xyce::dout() << " li_state_qgd = " << li_state_qgd;
751  Xyce::dout() << " li_state_gcgd = " << li_state_gcgd << std::endl;;
752 
753  Xyce::dout() << section_divider << std::endl;
754  }
755 
756 }
757 
758 //----------------------------------------------------------------------------
759 // Function : Instance::registerStoreLIDs
760 // Purpose :
761 // Special Notes :
762 // Scope : public
763 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
764 // Creation Date : 3/16/11
765 //----------------------------------------------------------------------------
766 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef)
767 {
768  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
769 
770 // Copy over the global ID lists:
771  stoLIDVec = stoLIDVecRef;
772 
773  int lid = 0;
774  li_store_vgs = stoLIDVec[lid++];
775  li_store_vgd = stoLIDVec[lid++];
776  if( loadLeadCurrent )
777  {
778  li_store_dev_id = stoLIDVec[lid++];
779  li_store_dev_is = stoLIDVec[lid++];
780  li_store_dev_ig = stoLIDVec[lid++];
781  }
782 }
783 
784 //----------------------------------------------------------------------------
785 // Function : Instance::jacobianStamp
786 // Purpose :
787 // Special Notes :
788 // Scope : public
789 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
790 // Creation Date : 3/16/00
791 //----------------------------------------------------------------------------
792 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
793 {
794  if( drainCond != 0.0 && sourceCond != 0.0 )
795  return jacStamp_DC_SC;
796  else if( drainCond != 0.0 && sourceCond == 0.0 )
797  return jacStamp_DC;
798  else if( drainCond == 0.0 && sourceCond != 0.0 )
799  return jacStamp_SC;
800  else if( drainCond == 0.0 && sourceCond == 0.0 )
801  return jacStamp;
802  else
803  return jacStamp;
804 }
805 
806 //----------------------------------------------------------------------------
807 // Function : Instance::registerJacLIDs
808 // Special Notes :
809 // Scope : public
810 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
811 // Creation Date : 3/16/00
812 //----------------------------------------------------------------------------
813 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
814 {
815  DeviceInstance::registerJacLIDs( jacLIDVec );
816  std::vector<int> map;
817  std::vector< std::vector<int> > map2;
818 
819  if (drainCond != 0.0)
820  {
821  if (sourceCond != 0.0)
822  {
823  map = jacMap_DC_SC;
824  map2 = jacMap2_DC_SC;
825  }
826  else
827  {
828  map = jacMap_DC;
829  map2 = jacMap2_DC;
830  }
831  }
832  else
833  {
834  if (sourceCond != 0.0)
835  {
836  map = jacMap_SC;
837  map2 = jacMap2_SC;
838  }
839  else
840  {
841  map = jacMap;
842  map2 = jacMap2;
843  }
844  }
845 
846  ADrainEquDrainNodeOffset = jacLIDVec[map[0]][map2[0][0]];
847  ADrainEquDrainPrimeNodeOffset = jacLIDVec[map[0]][map2[0][1]];
848 
849  AGateEquGateNodeOffset = jacLIDVec[map[1]][map2[1][0]];
850  AGateEquDrainPrimeNodeOffset = jacLIDVec[map[1]][map2[1][1]];
851  AGateEquSourcePrimeNodeOffset = jacLIDVec[map[1]][map2[1][2]];
852 
853  ASourceEquSourceNodeOffset = jacLIDVec[map[2]][map2[2][0]];
854  ASourceEquSourcePrimeNodeOffset = jacLIDVec[map[2]][map2[2][1]];
855 
856  ADrainPrimeEquDrainNodeOffset = jacLIDVec[map[3]][map2[3][0]];
857  ADrainPrimeEquGateNodeOffset = jacLIDVec[map[3]][map2[3][1]];
858  ADrainPrimeEquDrainPrimeNodeOffset = jacLIDVec[map[3]][map2[3][2]];
859  ADrainPrimeEquSourcePrimeNodeOffset = jacLIDVec[map[3]][map2[3][3]];
860 
861  ASourcePrimeEquGateNodeOffset = jacLIDVec[map[4]][map2[4][0]];
862  ASourcePrimeEquSourceNodeOffset = jacLIDVec[map[4]][map2[4][1]];
863  ASourcePrimeEquDrainPrimeNodeOffset = jacLIDVec[map[4]][map2[4][2]];
864  ASourcePrimeEquSourcePrimeNodeOffset = jacLIDVec[map[4]][map2[4][3]];
865 }
866 
867 //-----------------------------------------------------------------------------
868 // Function : Instance::setupPointers
869 // Purpose :
870 // Special Notes :
871 // Scope : public
872 // Creator : Eric Keiter, SNL
873 // Creation Date : 11/30/08
874 //-----------------------------------------------------------------------------
876 {
877 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
878  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
879  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
880 
881  // F-matrix:
884 
888 
891 
896 
901 
902  // Q-matrix:
905 
909 
912 
917 
922 
923 #endif
924 }
925 
926 //----------------------------------------------------------------------------
927 // Function : Instance::updatePrimaryState
928 // Purpose :
929 // Special Notes :
930 // Scope : public
931 // Creator : pmc
932 // Creation Date : 11/16/2003
933 //----------------------------------------------------------------------------
935 {
936  double * staVec = extData.nextStaVectorRawPtr;
937  bool bsuccess = updateIntermediateVars ();
938 
939  double * stoVec = extData.nextStoVectorRawPtr;
940  stoVec[li_store_vgs] = vgs;
941  stoVec[li_store_vgd] = vgd;
942  staVec[li_state_qgs] = qgs;
943  staVec[li_state_qgd] = qgd;
944 
945  return bsuccess;
946 }
947 
948 //-----------------------------------------------------------------------------
949 // Function : Instance::updateIntermediateVars
950 // Purpose :
951 // Special Notes :
952 // Scope : public
953 // Creator : pmc
954 // Creation Date : 11/16/2003
955 //-----------------------------------------------------------------------------
957 {
958  double * solVec = extData.nextSolVectorRawPtr;
959 
960  int dtype;
961  double csat, betap;
962  double vgst, vgdt;
963  double evgs, evgd;
964  double apart, cpart;
965  double sarg, vtf;;
966 
967 // from the spice jfet
968  double czgd, czgs;
969  double czgdf2, czgsf2;
970  double fcpb2;
971  double twop;
972  int icheck, ichk1;
973 
974 // for the Shockley version
975  double A, B, C, B12, C12, D;
976  double Idsat, Vdsat;
977  int level;
978 
979  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
980  {
981  Xyce::dout() << subsection_divider << std::endl;
982  Xyce::dout() <<" Instance::updateIntermediateVars. name = " << getName() << std::endl;
983  Xyce::dout() <<" Model name = " << model_.getName() << std::endl;
984  Xyce::dout() << std::endl;
985  Xyce::dout().width(25); Xyce::dout().precision(17); Xyce::dout().setf(std::ios::scientific);
986  }
987 
988  icheck = 1;
989  dtype = model_.dtype;
990 
991  // we need our solution variables for any of this stuff
992  Vd = 0.0;
993  Vs = 0.0;
994  Vg = 0.0;
995  Vdp = 0.0;
996  Vsp = 0.0;
997 
998  Vd = solVec[li_Drain];
999  Vg = solVec[li_Gate];
1000  Vs = solVec[li_Source];
1001  Vsp = solVec[li_SourcePrime];
1002  Vdp = solVec[li_DrainPrime];
1003 
1004  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1005  {
1006  Xyce::dout() << " " << std::endl;
1007  Xyce::dout() << " Vg = " << Vg << std::endl;
1008  Xyce::dout() << " Vd = " << Vd << std::endl;
1009  Xyce::dout() << " Vs = " << Vs << std::endl;
1010  Xyce::dout() << " Vdp = " << Vdp << std::endl;
1011  Xyce::dout() << " Vsp = " << Vsp << std::endl;
1012  }
1013 
1014  // now we need voltage drops
1015  Vddp = Vd - Vdp;
1016  Vssp = Vs - Vsp;
1017  Vgsp = Vg - Vsp;
1018  Vgdp = Vg - Vdp;
1019  Vdpsp = Vdp - Vsp;
1020 
1021  // Now the things that the 3f5 code really uses
1022  vgs = dtype * Vgsp;
1023  vgd = dtype * Vgdp;
1024  vds = vgs-vgd;
1025 
1026  origFlag = 1;
1027  limitedFlag = false;
1028  vgs_orig = vgs;
1029  vgd_orig = vgd;
1030  vds_orig = vds;
1031 
1032  if (getSolverState().newtonIter == 0)
1033  {
1034  if (getSolverState().initJctFlag && getDeviceOptions().voltageLimiterFlag)
1035  {
1036  if (getSolverState().inputOPFlag)
1037  {
1038  Linear::Vector * flagSolVectorPtr = extData.flagSolVectorPtr;
1039  if ((*flagSolVectorPtr)[li_Drain] == 0 || (*flagSolVectorPtr)[li_Gate] == 0 ||
1040  (*flagSolVectorPtr)[li_Source] == 0 || (*flagSolVectorPtr)[li_SourcePrime] ||
1041  (*flagSolVectorPtr)[li_DrainPrime] )
1042  {
1043  vgs = 0;
1044  vgd = 0;
1045  vds = vgs-vgd;
1046  }
1047  }
1048  else
1049  {
1050  vgs = 0;
1051  vgd = 0;
1052  vds = vgs-vgd;
1053  }
1054  }
1055  if (!(getSolverState().dcopFlag)||(getSolverState().locaEnabledFlag && getSolverState().dcopFlag))
1056  {
1057  double * currStoVec = extData.currStoVectorRawPtr;
1058  vgs_old = currStoVec[li_store_vgs];
1059  vgd_old = currStoVec[li_store_vgd];
1060  vds_old = vgs_old - vgd_old;
1061  }
1062  else
1063  { // there is no history
1064  vgs_old = vgs;
1065  vgd_old = vgd;
1066  vds_old = vds;
1067  }
1068  }
1069  else
1070  {
1071  double *stoVec = extData.nextStoVectorRawPtr;
1072  vgs_old = stoVec[li_store_vgs];
1073  vgd_old = stoVec[li_store_vgd];
1074  vds_old = vgs_old - vgd_old;
1075  }
1076 
1077  // SPICE-type Voltage Limiting
1078  ////////////////////////////////////////////
1079 
1080  if (getDeviceOptions().voltageLimiterFlag)
1081  {
1082  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1083  {
1084  Xyce::dout() << " before limiting: " << std::endl;
1085  Xyce::dout() << " vgs = " << vgs << " vgs_old = " << vgs_old << std::endl;
1086  Xyce::dout() << " vgd = " << vgd << " vgd_old = " << vgd_old << std::endl;
1087  }
1088 
1089  ichk1=1;
1090  vgs = devSupport.pnjlim(vgs, vgs_old, vt, vcrit, &icheck);
1091  vgd = devSupport.pnjlim(vgd, vgd_old, vt, vcrit, &ichk1);
1092 
1093  if (ichk1 == 1) {icheck=1;}
1094  if (icheck == 1) limitedFlag=true;
1095 
1097  vgd = devSupport.fetlim(vgd, vgd_old, tvt0);
1098  vds = vgs-vgd;
1099 
1100  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1101  {
1102  Xyce::dout() << " After limiting: " << std::endl;
1103  Xyce::dout() << " vgs = " << vgs << std::endl;
1104  Xyce::dout() << " vgd = " << vgd << std::endl;
1105  Xyce::dout() << " " << std::endl;
1106  }
1107  }
1108 
1109  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1110  {
1111  Xyce::dout() << "vgs = " << vgs << std::endl;
1112  Xyce::dout() << "vgd = " << vgd << std::endl;
1113  Xyce::dout() << "vds = " << vds << std::endl;
1114  Xyce::dout() << "Vddp = " << Vddp << std::endl;
1115  Xyce::dout() << "Vssp = " << Vssp << std::endl;
1116  Xyce::dout() << "Vgsp = " << Vgsp << std::endl;
1117  Xyce::dout() << "Vgdp = " << Vgdp << std::endl;
1118  Xyce::dout() << "Vdpsp = " << Vdpsp << std::endl;
1119  Xyce::dout() << " " << std::endl;
1120  }
1121  // Now set the origFlag
1122  if (vgs_orig != vgs || vds_orig != vds || vgd_orig != vgd) origFlag = 0;
1123 
1124  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1125  {
1126  if (origFlag == 0)
1127  {
1128  Xyce::dout() << getName() << " Something modified the voltages. " << std::endl;
1129  }
1130  else
1131  {
1132  Xyce::dout() << getName() << " No voltages were limited. " << std::endl;
1133  }
1134  Xyce::dout() << " Voltage before after diff " << std::endl;
1135  Xyce::dout() << getName() <<" vgs " <<vgs_orig <<" " << vgs <<" " << vgs-vgs_orig << std::endl;
1136  Xyce::dout() << getName() <<" vgd " <<vgd_orig <<" " << vgd <<" " << vgd-vgd_orig << std::endl;
1137  Xyce::dout() << getName() <<" vds " <<vds_orig <<" " << vds <<" " << vds-vds_orig << std::endl;
1138  Xyce::dout() << " " << std::endl;
1139  }
1140 
1141  //
1142  // the following block of code evaluates the dc current and its
1143  // derivatives and the charges associated with the gate and
1144  // channel
1145  //
1146 
1147  // vt set in updateTemperature
1148  vtf = 5.0*vt;
1149  csat = tIS;
1150  if (vgs <= -vtf)
1151  {
1152  ggs = -csat/vgs + getDeviceOptions().gmin;
1153  cg = ggs*vgs;
1154  }
1155  else
1156  {
1157  evgs = exp(vgs/vt);
1158  ggs = csat*evgs/vt + getDeviceOptions().gmin;
1159  cg = csat*(evgs-1) + getDeviceOptions().gmin*vgs;
1160  }
1161  if (vgd <= -vtf)
1162  {
1163  ggd = -csat/vgd + getDeviceOptions().gmin;
1164  cgd = ggd*vgd;
1165  }
1166  else
1167  {
1168  evgd = exp(vgd/vt);
1169  ggd = csat*evgd/vt + getDeviceOptions().gmin;
1170  cgd = csat*(evgd-1) + getDeviceOptions().gmin*vgd;
1171  }
1172  cg = cg + cgd;
1173 
1174  // 3f5 does this simple stuff
1175  if (vds >= 0)
1176  mode = 1;
1177  else
1178  mode = -1;
1179 
1180  level = model_.getLevel();
1181  if(level == 1)
1182  {
1183  //
1184  // Sydney University JFET model
1185  //
1186  if(vds >= 0) // normal mode
1187  {
1188  vgst=vgs-tvt0;
1189  if (vgst <= 0)
1190  {
1191  //
1192  // cutoff region
1193  //
1194  cdrain=0;
1195  gm=0;
1196  gds=0;
1197  // Xyce::dout() << " cutoff region - normal mode " << std::endl;
1198  }
1199  else
1200  {
1201  betap=tBeta*(1+tLambda*vds);
1202  Bfac = (1.0-tJFETb)/(tPB-tvt0);
1203  if( vgst >= vds )
1204  {
1205  //
1206  // linear region
1207  //
1208  apart=2.0*tJFETb+3.0*Bfac*(vgst-vds);
1209  cpart=vds*(vds*(Bfac*vds - tJFETb)+vgst*apart);
1210  cdrain=betap*cpart;
1211  gm=betap*vds*(apart+3.0*Bfac*vgst);;
1212  gds=betap*(vgst-vds)*apart+tLambda*tBeta*cpart;
1213  // Xyce::dout() << " linear region - normal mode" << std::endl;
1214  }
1215  else
1216  {
1217  //
1218  // saturation region
1219  //
1220  Bfac=vgst*Bfac;
1221  gm=betap*vgst*(2.0*tJFETb+3.0*Bfac);
1222  cpart=vgst*vgst*(tJFETb+Bfac);
1223  cdrain=betap*cpart;
1224  gds=tLambda*tBeta*cpart;
1225  // Xyce::dout() << " saturation region - normal mode " << std::endl;
1226  }
1227  }
1228  }
1229  else // inverse mode
1230 // Inverse mode is where you switch the drain and source
1231 // and run the device in reverse. The equations for inverse
1232 // mode are obtained by the following substitutions:
1233 // vgst -> vgdt, vds -> -vds, cdrain -> -cdrain
1234  {
1235  vgdt=vgd-tvt0;
1236  if (vgdt <= 0)
1237  {
1238  //
1239  // inverse mode cutoff region
1240  //
1241  cdrain=0;
1242  gm=0;
1243  gds=0;
1244  // Xyce::dout() << " cutoff region - inverse mode" << std::endl;
1245  }
1246  else
1247  {
1248  betap=tBeta*(1-tLambda*vds);
1249  Bfac=(1.0-tJFETb)/(tPB-tvt0);
1250  if (vgdt+vds >= 0)
1251  {
1252  //
1253  // linear region
1254  //
1255  apart=2.0*tJFETb+3.0*Bfac*(vgdt+vds);
1256  cpart=vds*(-vds*(-Bfac*vds - tJFETb)+vgdt*apart);
1257  cdrain=betap*cpart;
1258  gm=betap*vds*(apart+3.0*Bfac*vgdt);;
1259  gds=betap*(vgdt+vds)*apart-tLambda*tBeta*cpart - gm;
1260  // Xyce::dout() << " linear region - inverse mode" << std::endl;
1261  }
1262  else
1263  {
1264  //
1265  // saturation region
1266  //
1267  Bfac=vgdt*Bfac;
1268  gm=-betap*vgdt*(2.0*tJFETb+3.0*Bfac);
1269  cpart=vgdt*vgdt*(tJFETb+Bfac);
1270  cdrain=-betap*cpart;
1271  gds=tLambda*tBeta*cpart - gm;
1272  // Xyce::dout() << " saturation region - inverse mode " << std::endl;
1273  }
1274  }
1275  }
1276  }
1277  else if(level == 2)
1278  {
1279  //
1280  // Shockley JFET model with modified Vdsat
1281  //
1282  if(vds >= 0) // normal mode
1283  {
1284  vgst=vgs-tvt0;
1285  if (vgst <= 0)
1286  {
1287  //
1288  // cutoff region
1289  //
1290  cdrain=0;
1291  gm=0;
1292  gds=0;
1293  // Xyce::dout() << " cutoff region - Shockley normal mode " << std::endl;
1294  }
1295  else
1296  {
1297  A = tPB-tvt0;
1298  if(A != 0) B = (A-vgst)/A;
1299  else B = 0;
1300  if(B >= 0) B12 = sqrt(B);
1301  else B12 = 0;
1302 
1303  betap=tBeta*(1+tLambda*vds)/(1+tTheta*vgst);
1304  Vdsat = vgst + tDelta;
1305  // Idsat = dtype*betap*(vgst-(2*A/3)*(1-B*B12));
1306 
1307  if(A != 0) C = (vds - tDelta*vds/Vdsat + A-vgst)/A;
1308  else C = 0;
1309  if(C >= 0) C12 = sqrt(C);
1310  else C12 = 0;
1311  D = C*C12 - B*B12;
1312 
1313  if( dtype*Vd <= Vdsat )
1314  {
1315  //
1316  // linear region
1317  //
1318  cdrain = betap*(vds - tDelta*vds/Vdsat - (2*A/3)*D);
1319  gm = -cdrain*tTheta/(1+tTheta*vgst) + betap*(C12 - B12)
1320  + betap*tDelta*(1-C12)*vds/(Vdsat*Vdsat);
1321  gds = tLambda*cdrain/(1+tLambda*vds)
1322  + betap*(1-(1-C12)*tDelta/Vdsat-C12);
1323  // Xyce::dout() << " linear region - Shockley normal mode" << std::endl;
1324  }
1325  else
1326  {
1327  //
1328  // saturation region
1329  //
1330  cdrain = betap*(vgst - (2*A/3)*(1 - B*B12));
1331  gm = betap*(1-B12) - tTheta*cdrain/(1+tTheta*vgst);
1332  gds = tLambda*cdrain/(1+tLambda*vds);
1333  // Xyce::dout() << " saturation region - Shockley normal mode" << std::endl;
1334  }
1335  }
1336  }
1337  else // inverse mode
1338 // Inverse mode is where you switch the drain and source
1339 // and run the device in reverse. The equations for inverse
1340 // mode are obtained by the following substitutions:
1341 // vgst -> vgdt, vds -> -vds, cdrain -> -cdrain
1342  {
1343  vgdt=vgd-tvt0;
1344  if (vgdt <= 0)
1345  {
1346  //
1347  // cutoff region
1348  //
1349  cdrain=0;
1350  gm=0;
1351  gds=0;
1352  // Xyce::dout() << " cutoff region - Shockley inverse mode " << std::endl;
1353  }
1354  else
1355  {
1356  A = tPB-tvt0;
1357  if(A != 0) B = (A-vgdt)/A;
1358  else B = 0;
1359  if(B >= 0) B12 = sqrt(B);
1360  else B12 = 0;
1361 
1362  betap = tBeta*(1-tLambda*vds)/(1+tTheta*vgdt);
1363  Vdsat = vgdt + tDelta;
1364  // Idsat = -dtype*betap*(vgdt-(2*A/3)*(1-B*B12));
1365 
1366  if(A != 0) C = (-vds + tDelta*vds/Vdsat + A-vgdt)/A;
1367  else C = 0;
1368  if(C >= 0) C12 = sqrt(C);
1369  else C12 = 0;
1370  D = C*C12 - B*B12;
1371 
1372  if( dtype*Vs <= Vdsat )
1373  {
1374  //
1375  // linear region
1376  //
1377  cdrain = -betap*(-vds + tDelta*vds/Vdsat - (2*A/3)*D);
1378  gm = -betap*(C12 - B12) - tTheta*cdrain/(1+tTheta*vgdt);
1379  gm += betap*(1-C12)*tDelta*vds/(Vdsat*Vdsat);
1380  gds = betap*(1 - (1-C12)*tDelta/Vdsat - C12)
1381  - tLambda*cdrain/(1-tLambda*vds);
1382 
1383  // Xyce::dout() << " linear region - Shockley inverse mode" << std::endl;
1384  }
1385  else
1386  {
1387  //
1388  // saturation region
1389  //
1390  cdrain = -betap*(vgdt - (2*A/3)*(1 - B*B12));
1391  gm = -betap*(1-B12) - tTheta*cdrain/(1+tTheta*vgdt);
1392  gds = tLambda*cdrain/(1-tLambda*vds);
1393  // Xyce::dout() << " saturation region - Shockley inverse mode" << std::endl;
1394  }
1395  }
1396  }
1397  }
1398  cd = cdrain-cgd;
1399 
1400  //
1401  // charge storage elements
1402  //
1403  twop = 2.0*tPB;
1404  fcpb2 = corDepCap*corDepCap;
1405  czgs = tCGS;
1406  czgd = tCGD;
1407  if(czgs != 0)
1408  {
1409  czgsf2=czgs/f2;
1410  if (vgs < corDepCap)
1411  {
1412  sarg=sqrt(1-vgs/tPB);
1413  qgs = twop*czgs*(1-sarg);
1414  capgs=czgs/sarg;
1415  }
1416  else
1417  {
1418  qgs = czgs*f1 + czgsf2*(f3 *(vgs - corDepCap)
1419  +(vgs*vgs - fcpb2)/(2*twop));
1420  capgs=czgsf2*(f3 + vgs/twop);
1421  }
1422  }
1423  else
1424  {
1425  qgs=0.0;
1426  capgs=0.0;
1427  }
1428 
1429  if(czgd != 0)
1430  {
1431  czgdf2=czgd/f2;
1432  if (vgd < corDepCap)
1433  {
1434  sarg=sqrt(1-vgd/tPB);
1435  qgd = twop*czgd*(1-sarg);
1436  capgd=czgd/sarg;
1437  }
1438  else
1439  {
1440  qgd = czgd*f1 + czgdf2*( f3*(vgd - corDepCap)
1441  +(vgd*vgd - fcpb2)/(2*twop) );
1442  capgd=czgdf2*(f3 + vgd/twop);
1443  }
1444  }
1445  else
1446  {
1447  qgd=0.0;
1448  capgd=0.0;
1449  }
1450 
1451  Idrain = drainCond * Vddp;
1452  Isource = sourceCond * Vssp;
1453 
1454  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1455  {
1456  Xyce::dout() << " Done with Instance::updateIntermediateVars. name = " << getName() << std::endl;
1457  Xyce::dout() << " mode = " << mode << std::endl;
1458  Xyce::dout() << " tBeta = " << tBeta << std::endl;
1459  Xyce::dout() << " Idrain = " << Idrain << std::endl;
1460  Xyce::dout() << " Isource = " << Isource << std::endl;
1461  Xyce::dout() << " gds = " << gds << std::endl;
1462  Xyce::dout() << " gm = " << gm << std::endl;
1463  }
1464 
1465  /// CURRENTS to load into RHS:
1466 
1467  // so at this point:
1468 
1469  // current out of drain is
1470  // Idrain
1471 
1472  // current out of gate:
1473  // dtype*( d/dt(qgs) + d/dt(qgd) )
1474 
1475  // the current *out of* the source should be simply
1476  // Isource
1477 
1478  // current out of drain' is
1479  // -Idrain - dtype*( d/dt(qgd) - cdrain )
1480 
1481  // the current out of the source' is
1482  // -Isource - dtype*( d/dt(qgs) + cdrain )
1483 
1484  return true;
1485 }
1486 
1487 //-----------------------------------------------------------------------------
1488 // Function : Instance::loadDAEQVector
1489 //
1490 // Purpose : Loads the Q-vector contributions for a single
1491 // voltage source instance.
1492 //
1493 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1494 // which the system of equations is represented as:
1495 //
1496 // f(x) = dQ(x)/dt + F(x) + B(t) = 0
1497 //
1498 // The "Q" vector contains charges and fluxes, mostly.
1499 // The voltage source will not make any contributions to Q,
1500 // so this function does nothing.
1501 //
1502 // from updateSecondaryState:
1503 //
1504 // ggd = ggd + capgd*(getSolverState().pdt);
1505 // ggs = ggs + capgs*(getSolverState().pdt);
1506 //
1507 // // Sum the capacitor currents into the DC currents.
1508 // cg = cg + cqgs + cqgd;
1509 // cd = cd - cqgd;
1510 // cgd = cgd + cqgd;
1511 //
1512 // So:
1513 //
1514 // replace ggd with capgd.
1515 // replace ggs with capgs
1516 //
1517 // replace cg with qgs+qgd
1518 // replace cd with -qgd
1519 // replace cgd with qgd.
1520 //
1521 //
1522 // Scope : public
1523 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1524 // Creation Date : 02/19/05
1525 //-----------------------------------------------------------------------------
1527 {
1528  double * qVec = extData.daeQVectorRawPtr;
1529  double * dQdxdVp = extData.dQdxdVpVectorRawPtr;
1530 
1531  // set up the final load variables:
1532  int Dtype = model_.dtype;
1533  double ceqgd = Dtype*(qgd);
1534  double ceqgs = Dtype*(((qgs+qgd)-qgd));
1535  double cdreq = Dtype*(((-qgd)+qgd));
1536 
1537  double ceqgd_Jdxp = -Dtype*(capgd*(vgd-vgd_orig));
1538  double ceqgs_Jdxp = -Dtype*(capgs*(vgs-vgs_orig));
1539  double cdreq_Jdxp = 0.0;
1540 
1541  qVec[li_Gate ] += ( ceqgs+ceqgd);
1542  qVec[li_DrainPrime ] -= (-cdreq+ceqgd);
1543  qVec[li_SourcePrime] -= ( cdreq+ceqgs);
1544 
1545  if (!origFlag)
1546  {
1547  dQdxdVp[li_Gate ] -= ( ceqgs_Jdxp+ceqgd_Jdxp);
1548  dQdxdVp[li_DrainPrime ] += (-cdreq_Jdxp+ceqgd_Jdxp);
1549  dQdxdVp[li_SourcePrime] += ( cdreq_Jdxp+ceqgs_Jdxp);
1550  }
1551 
1552  if( loadLeadCurrent )
1553  {
1554  double * stoVec = extData.storeLeadCurrQCompRawPtr;
1555  stoVec[li_store_dev_id] = -(-cdreq+ceqgd);
1556  stoVec[li_store_dev_is] = -(cdreq+ceqgs);
1557  stoVec[li_store_dev_ig] = ceqgs+ceqgd;
1558  }
1559 
1560  if( loadLeadCurrent )
1561  {
1562  double * stoVec = extData.storeLeadCurrQCompRawPtr;
1563  stoVec[li_store_dev_id] = -(-cdreq+ceqgd);
1564  stoVec[li_store_dev_is] = -(cdreq+ceqgs);
1565  stoVec[li_store_dev_ig] = ceqgs+ceqgd;
1566  }
1567 
1568  return true;
1569 }
1570 
1571 //-----------------------------------------------------------------------------
1572 // Function : Instance::loadDAEFVector
1573 //
1574 // Purpose : Loads the F-vector contributions for a single
1575 // JFET instance.
1576 //
1577 // Special Notes :
1578 //
1579 // Scope : public
1580 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1581 // Creation Date : 02/19/05
1582 //-----------------------------------------------------------------------------
1584 {
1585  double * fVec = extData.daeFVectorRawPtr;
1586  double * dFdxdVp = extData.dFdxdVpVectorRawPtr;
1587 
1588  // set up the final load variables:
1589  int Dtype = model_.dtype;
1590  double ceqgd = Dtype*(cgd);
1591  double ceqgs = Dtype*((cg-cgd));
1592  double cdreq = Dtype*((cd+cgd));
1593 
1594  double ceqgd_Jdxp = -Dtype*(ggd*(vgd-vgd_orig));
1595  double ceqgs_Jdxp = -Dtype*(ggs*(vgs-vgs_orig));
1596  double cdreq_Jdxp = -Dtype*(gds*(vds-vds_orig)+gm*(vgs-vgs_orig));
1597 
1598  // optional load JFETs:
1599  if (drainCond != 0.0)
1600  {
1601  fVec[li_Drain ] += Idrain;
1602  }
1603 
1604  if (sourceCond != 0.0)
1605  {
1606  fVec[li_Source] += Isource;
1607  }
1608 
1609  fVec[li_Gate ] += (ceqgs+ceqgd);
1610  fVec[li_DrainPrime ] -= (Idrain +(-cdreq+ceqgd));
1611  fVec[li_SourcePrime] -= (Isource+(cdreq+ceqgs));
1612 
1613  if (!origFlag)
1614  {
1615  dFdxdVp[li_Gate ] -= ( ceqgs_Jdxp+ceqgd_Jdxp);
1616  dFdxdVp[li_DrainPrime ] += (-cdreq_Jdxp+ceqgd_Jdxp);
1617  dFdxdVp[li_SourcePrime] += ( cdreq_Jdxp+ceqgs_Jdxp);
1618  }
1619 
1620  if( loadLeadCurrent )
1621  {
1622  double * stoVec = extData.nextStoVectorRawPtr;
1623  if (drainCond != 0.0)
1624  {
1625  stoVec[li_store_dev_id] = Idrain;
1626  }
1627  else
1628  {
1629  stoVec[li_store_dev_id] = -(Idrain +(-cdreq+ceqgd));
1630  }
1631  if (sourceCond != 0.0)
1632  {
1633  stoVec[li_store_dev_is] = Isource;
1634  }
1635  else
1636  {
1637  stoVec[li_store_dev_is] = -(Isource+(cdreq+ceqgs));
1638  }
1639  stoVec[li_store_dev_ig] = (ceqgs+ceqgd);
1640  }
1641 
1642  if( loadLeadCurrent )
1643  {
1644  double * stoVec = extData.nextStoVectorRawPtr;
1645  if (drainCond != 0.0)
1646  {
1647  stoVec[li_store_dev_id] = Idrain;
1648  }
1649  else
1650  {
1651  stoVec[li_store_dev_id] = -(Idrain +(-cdreq+ceqgd));
1652  }
1653  if (sourceCond != 0.0)
1654  {
1655  stoVec[li_store_dev_is] = Isource;
1656  }
1657  else
1658  {
1659  stoVec[li_store_dev_is] = -(Isource+(cdreq+ceqgs));
1660  }
1661  stoVec[li_store_dev_ig] = (ceqgs+ceqgd);
1662  }
1663 
1664  return true;
1665 }
1666 
1667 //-----------------------------------------------------------------------------
1668 // Function : Instance::loadDAEdQdx
1669 //
1670 // Purpose : Loads the Q-vector contributions for a single
1671 // JFET instance.
1672 //
1673 // Special Notes : The "Q" vector is part of a standard DAE formalism in
1674 // which the system of equations is represented as:
1675 //
1676 // f(x) = dQ(x)/dt + F(x) - B(t) = 0
1677 //
1678 // Scope : public
1679 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1680 // Creation Date : 02/19/05
1681 //-----------------------------------------------------------------------------
1683 {
1684  Linear::Matrix & dQdx = *(extData.dQdxMatrixPtr);
1685 
1693 
1694  return true;
1695 }
1696 
1697 //-----------------------------------------------------------------------------
1698 // Function : Instance::loadDAEdFdx ()
1699 //
1700 // Purpose : Loads the F-vector contributions for a single
1701 // JFET instance.
1702 //
1703 // Special Notes : The F-vector is an algebraic constaint.
1704 //
1705 // Scope : public
1706 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
1707 // Creation Date : 02/19/05
1708 //-----------------------------------------------------------------------------
1710 {
1711  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
1712 
1715 
1719 
1722 
1726  drainCond+gds+ggd;
1728 
1733  += sourceCond+gds+gm+ggs;
1734 
1735  return true;
1736 }
1737 
1738 //-----------------------------------------------------------------------------
1739 // Function : Instance::updateTemperature
1740 // Purpose :
1741 // Special Notes :
1742 // Scope : public
1743 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1744 // Creation Date : 3/16/00
1745 //-----------------------------------------------------------------------------
1746 bool Instance::updateTemperature ( const double & temp_tmp)
1747 {
1748  bool bsuccess = true;
1749  double tnom, ratio;
1750  double arg, arg1;
1751  double ratio1;
1752  double fact1, fact2;
1753  double kt, kt1;
1754  double vtnom;
1755  double egfet, egfet1;
1756  double pbfact;
1757  double cjfact, cjfact1;
1758  double gmanew, gmaold;
1759  double pbo;
1760  double xfc;
1761  double Pb;
1762 
1763  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1764  {
1765 // Xyce::dout() << subsection_divider << std::endl;
1766  Xyce::dout() << " Instance::Begin of updateTemperature. name = " << getName() << std::endl;
1767  Xyce::dout() << std::endl;
1768  }
1769 
1770  // first set the instance temperature to the new temperature:
1771  if (temp_tmp != -999.0) temp = temp_tmp;
1773  {
1774  // make sure interpolation doesn't take any resistance negative
1775  if(model_.RD < 0) model_.RD = 0;
1776  if(model_.RS < 0) model_.RS = 0;
1777 
1778  // some params may have changed during interpolation
1779  // model_.processParams();
1780  }
1781 
1782  Pb = model_.PB;
1783  tnom = model_.TNOM;
1784  ratio = temp/tnom;
1785 
1786  // first do the model stuff
1787 
1788  if (model_.RD != 0)
1789  drainCond = area/model_.RD;
1790  if (model_.RS != 0)
1792  vtnom = tnom*CONSTKoverQ;
1793  fact1 = tnom/CONSTREFTEMP;
1794  kt1 = CONSTboltz*tnom;
1795  egfet1 = 1.16 - (7.02e-4*tnom*tnom)/(tnom + 1108);
1796  arg1 = -egfet1/(2.0*kt1) + 1.1150877/(CONSTboltz*2.0*CONSTREFTEMP);
1797  pbfact = -2.0*vtnom*(1.5*log(fact1) + CONSTQ*arg1);
1798  pbo = (Pb - pbfact)/fact1;
1799  gmaold = (Pb - pbo)/pbo;
1800  cjfact = 1.0/(1.0 + 0.5*(4e-4*(tnom - CONSTREFTEMP) - gmaold));
1801 
1802  if(model_.FC >.95) {
1803  Xyce::dout() << "Depletion cap. coeff. FC too large, limited to .95" <<
1804  Xyce::dout() << std::endl;
1805  model_.FC = .95;
1806  }
1807  xfc = log(1.0 - model_.FC);
1808  f2 = exp(1.5*xfc);
1809  f3 = 1.0 - 1.5*model_.FC;
1810  // skip bFac
1811 
1812  // now do the instance stuff
1813 
1814  vt = temp*CONSTKoverQ;
1815  kt = temp*CONSTboltz;
1816  fact2 = temp/CONSTREFTEMP;
1817  ratio1 = ratio - 1.0;
1818  tIS = model_.IS*exp(ratio1*1.11/vt)*area;
1819 
1820  tCGS = model_.CGS*cjfact*area;
1821  tCGD = model_.CGD*cjfact*area;
1822  egfet = 1.16 - (7.02e-4*temp*temp)/(temp + 1108);
1823  arg = -egfet/(2.0*kt) + 1.1150877/(CONSTboltz*2.0*CONSTREFTEMP);
1824  pbfact = -2.0*vt*(1.5*log(fact2) + CONSTQ*arg);
1825  tPB = fact2*pbo + pbfact;
1826  gmanew = (tPB - pbo)/pbo;
1827  cjfact1 = 1.0 + 0.5*(4e-4*(temp - CONSTREFTEMP) - gmanew);
1828  tCGS *= cjfact1;
1829  tCGD *= cjfact1;
1830 
1831  corDepCap = model_.FC*tPB;
1832  f1 = tPB*(1.0 - exp((0.5)*xfc))/(0.5);
1833  vcrit = vt * log(vt/(CONSTroot2 * tIS));
1834 
1835  // the following parameters have no temperature dependence in Spice 3f5
1836  //
1837  tBeta = model_.BETA*area; // transconductance parameter
1838  tvt0 = model_.VTO; // threshold voltage
1839  tLambda = model_.LAMBDA; // channel-length modulation
1840  tDelta = model_.DELTA; // parameter to shift Shockley Vdsat
1841  tTheta = model_.THETA; // gate voltage mobility parameter
1842  tRD = model_.RD/area; // drain ohmic resistance
1843  tRS = model_.RS/area; // source ohmic resistance
1844  tJFETb = model_.B; // dopinng tail parameter
1845 
1846  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) && getSolverState().debugTimeFlag)
1847  {
1848  Xyce::dout() << std::endl;
1849  Xyce::dout() << "temp = "<< temp << std::endl;
1850  Xyce::dout() << "tnom = " << tnom << std::endl;
1851  Xyce::dout() << "ratio = " << ratio << std::endl;
1852  Xyce::dout() << "vt = " << vt << std::endl;
1853  Xyce::dout() << "kt = " << kt << std::endl;
1854  Xyce::dout() << "fact2 = " << fact2 << std::endl;
1855  Xyce::dout() << "egfet = " << egfet << std::endl;
1856  Xyce::dout() << "arg = " << arg << std::endl;
1857  Xyce::dout() << "pbfact = " << pbfact << std::endl;
1858  Xyce::dout() << "pbo = " << pbo << std::endl;
1859  Xyce::dout() << "f2 = " << f2 << std::endl;
1860  Xyce::dout() << "f3 = " << f3 << std::endl;
1861  Xyce::dout() << "corDepCap = " << corDepCap << std::endl;
1862  Xyce::dout() << "tBeta = " << tBeta << std::endl;
1863  Xyce::dout() << "tvt0 = " << tvt0 << std::endl;
1864  Xyce::dout() << "tPB = " << tPB << std::endl;
1865  Xyce::dout() << "tJFETb = " << tJFETb << std::endl;
1866  Xyce::dout() << "tLambda = " << tLambda << std::endl;
1867  Xyce::dout() << "tDelta = " << tDelta << std::endl;
1868  Xyce::dout() << "tTheta = " << tTheta << std::endl;
1869  Xyce::dout() << "tRD = " << tRD << std::endl;
1870  Xyce::dout() << "tRS = " << tRS << std::endl;
1871  Xyce::dout() << " " << std::endl;
1872  }
1873 
1874  return bsuccess;
1875 }
1876 
1877 //-----------------------------------------------------------------------------
1878 // Function : Instance::processParams
1879 // Purpose :
1880 // Special Notes :
1881 // Scope : public
1882 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1883 // Creation Date : 3/16/00
1884 //-----------------------------------------------------------------------------
1886 {
1888 
1889  return true;
1890 }
1891 
1892 
1893 // JFET Master functions:
1894 
1895 //-----------------------------------------------------------------------------
1896 // Function : Master::updateState
1897 // Purpose :
1898 // Special Notes :
1899 // Scope : public
1900 // Creator : Eric Keiter, SNL
1901 // Creation Date : 11/26/08
1902 //-----------------------------------------------------------------------------
1903 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
1904 {
1905  bool bsuccess = true;
1906 
1907  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1908  {
1909  Instance & ji = *(*it);
1910  bool btmp = ji.updateIntermediateVars ();
1911  bsuccess = bsuccess && btmp;
1912 
1913  double * stoVec = ji.extData.nextStoVectorRawPtr;
1914  stoVec[ji.li_store_vgs] = ji.vgs;
1915  stoVec[ji.li_store_vgd] = ji.vgd;
1916  staVec[ji.li_state_qgs] = ji.qgs;
1917  staVec[ji.li_state_qgd] = ji.qgd;
1918  }
1919 
1920  return bsuccess;
1921 }
1922 
1923 //-----------------------------------------------------------------------------
1924 // Function : Master::loadDAEVectors
1925 // Purpose :
1926 // Special Notes :
1927 // Scope : public
1928 // Creator : Eric Keiter, SNL
1929 // Creation Date : 11/26/08
1930 //-----------------------------------------------------------------------------
1931 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
1932 {
1933  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
1934  {
1935  Instance & ji = *(*it);
1936 
1937  // F-vector:
1938  double * dFdxdVp = ji.extData.dFdxdVpVectorRawPtr;
1939 
1940  // set up the final load variables:
1941  int Dtype = ji.getModel().dtype;
1942  double f_ceqgd = Dtype*(ji.cgd);
1943  double f_ceqgs = Dtype*((ji.cg-ji.cgd));
1944  double f_cdreq = Dtype*((ji.cd+ji.cgd));
1945 
1946  double f_ceqgd_Jdxp = -Dtype*(ji.ggd*(ji.vgd-ji.vgd_orig));
1947  double f_ceqgs_Jdxp = -Dtype*(ji.ggs*(ji.vgs-ji.vgs_orig));
1948  double f_cdreq_Jdxp = -Dtype*(ji.gds*(ji.vds-ji.vds_orig)+ji.gm*(ji.vgs-ji.vgs_orig));
1949 
1950  // optional load JFETs:
1951  if (ji.drainCond != 0.0)
1952  {
1953  fVec[ji.li_Drain ] += ji.Idrain;
1954  }
1955 
1956  if (ji.sourceCond != 0.0)
1957  {
1958  fVec[ji.li_Source] += ji.Isource;
1959  }
1960 
1961  fVec[ji.li_Gate ] += (f_ceqgs+f_ceqgd);
1962  fVec[ji.li_DrainPrime ] -= (ji.Idrain +(-f_cdreq+f_ceqgd));
1963  fVec[ji.li_SourcePrime] -= (ji.Isource+(f_cdreq+f_ceqgs));
1964 
1965  if (!ji.origFlag)
1966  {
1967  dFdxdVp[ji.li_Gate ] -= ( f_ceqgs_Jdxp+f_ceqgd_Jdxp);
1968  dFdxdVp[ji.li_DrainPrime ] += (-f_cdreq_Jdxp+f_ceqgd_Jdxp);
1969  dFdxdVp[ji.li_SourcePrime] += ( f_cdreq_Jdxp+f_ceqgs_Jdxp);
1970  }
1971 
1972  // Q-vector:
1973  double * dQdxdVp = ji.extData.dQdxdVpVectorRawPtr;
1974  // set up the final load variables:
1975  double q_ceqgd = Dtype*(ji.qgd);
1976  double q_ceqgs = Dtype*(((ji.qgs+ji.qgd)-ji.qgd));
1977  double q_cdreq = Dtype*(((-ji.qgd)+ji.qgd));
1978 
1979  double q_ceqgd_Jdxp = -Dtype*(ji.capgd*(ji.vgd-ji.vgd_orig));
1980  double q_ceqgs_Jdxp = -Dtype*(ji.capgs*(ji.vgs-ji.vgs_orig));
1981  double q_cdreq_Jdxp = 0.0;
1982 
1983  qVec[ji.li_Gate ] += ( q_ceqgs+q_ceqgd);
1984  qVec[ji.li_DrainPrime ] -= (-q_cdreq+q_ceqgd);
1985  qVec[ji.li_SourcePrime] -= ( q_cdreq+q_ceqgs);
1986 
1987  if (!ji.origFlag)
1988  {
1989  dQdxdVp[ji.li_Gate ] -= ( q_ceqgs_Jdxp+q_ceqgd_Jdxp);
1990  dQdxdVp[ji.li_DrainPrime ] += (-q_cdreq_Jdxp+q_ceqgd_Jdxp);
1991  dQdxdVp[ji.li_SourcePrime] += ( q_cdreq_Jdxp+q_ceqgs_Jdxp);
1992  }
1993  if( ji.loadLeadCurrent )
1994  {
1995  if (ji.drainCond != 0.0)
1996  {
1997  storeLeadF[ji.li_store_dev_id] = ji.Idrain;
1998  }
1999  else
2000  {
2001  storeLeadF[ji.li_store_dev_id] = -(ji.Idrain +(-f_cdreq+f_ceqgd));
2002  storeLeadQ[ji.li_store_dev_id] = -(-q_cdreq+q_ceqgd);
2003  }
2004  if (ji.sourceCond != 0.0)
2005  {
2006  storeLeadF[ji.li_store_dev_is] = ji.Isource;
2007  }
2008  else
2009  {
2010  storeLeadF[ji.li_store_dev_is] = -(ji.Isource+(f_cdreq+f_ceqgs));
2011  storeLeadQ[ji.li_store_dev_is] = -(q_cdreq+q_ceqgs);
2012  }
2013  storeLeadF[ji.li_store_dev_ig] = (f_ceqgs+f_ceqgd);
2014  storeLeadQ[ji.li_store_dev_ig] = q_ceqgs+q_ceqgd;
2015  }
2016  }
2017 
2018  return true;
2019 }
2020 
2021 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
2022 //-----------------------------------------------------------------------------
2023 // Function : Master::loadDAEMatrices
2024 // Purpose :
2025 // Special Notes :
2026 // Scope : public
2027 // Creator : Eric Keiter, SNL
2028 // Creation Date : 12/12/08
2029 //-----------------------------------------------------------------------------
2030 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
2031 {
2032  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
2033  {
2034  Instance & ji = *(*it);
2035 
2036  // F-matrix:
2037 
2039 
2041 
2042 
2043  *ji.f_GateEquGateNodePtr += ji.ggd+ji.ggs;
2044 
2045  *ji.f_GateEquDrainPrimeNodePtr -= ji.ggd;
2046 
2047  *ji.f_GateEquSourcePrimeNodePtr -= ji.ggs;
2048 
2049 
2051 
2053 
2054 
2056 
2057  *ji.f_DrainPrimeEquGateNodePtr += ji.gm-ji.ggd;
2058 
2060 
2062 
2063 
2064  *ji.f_SourcePrimeEquGateNodePtr -= ji.gm+ji.ggs;
2065 
2067 
2069 
2071 
2072  // Q-matrix:
2073 
2074  *ji.q_GateEquGateNodePtr += ji.capgd+ji.capgs;
2075 
2077 
2079 
2081 
2083 
2085 
2087  }
2088 
2089  return true;
2090 }
2091 
2092 #else
2093 //-----------------------------------------------------------------------------
2094 // Function : Master::loadDAEMatrices
2095 // Purpose :
2096 // Special Notes :
2097 // Scope : public
2098 // Creator : Eric Keiter, SNL
2099 // Creation Date : 12/12/08
2100 //-----------------------------------------------------------------------------
2101 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
2102 {
2103  int sizeInstances = instanceContainer_.size();
2104 
2105  for (int i=0; i<sizeInstances; ++i)
2106  {
2107  Instance & ji = *(instanceContainer_.at(i));
2108 
2109  // dFdx matrix:
2110 
2111  dFdx[ji.li_Drain][ji.ADrainEquDrainNodeOffset] += ji.drainCond;
2112 
2114 
2115 
2116  dFdx[ji.li_Gate][ji.AGateEquGateNodeOffset] += ji.ggd+ji.ggs;
2117 
2118  dFdx[ji.li_Gate][ji.AGateEquDrainPrimeNodeOffset] -= ji.ggd;
2119 
2120  dFdx[ji.li_Gate][ji.AGateEquSourcePrimeNodeOffset] -= ji.ggs;
2121 
2122 
2123  dFdx[ji.li_Source][ji.ASourceEquSourceNodeOffset] += ji.sourceCond;
2124 
2126 
2127 
2129 
2130  dFdx[ji.li_DrainPrime][ji.ADrainPrimeEquGateNodeOffset] += ji.gm-ji.ggd;
2131 
2133  ji.drainCond+ji.gds+ji.ggd;
2134 
2136 
2137 
2138  dFdx[ji.li_SourcePrime][ji.ASourcePrimeEquGateNodeOffset] -= ji.gm+ji.ggs;
2139 
2141 
2143 
2145  += ji.sourceCond+ji.gds+ji.gm+ji.ggs;
2146 
2147  // dQdx matrix:
2148 
2149  dQdx[ji.li_Gate ][ji.AGateEquGateNodeOffset ] += ji.capgd+ji.capgs;
2150 
2151  dQdx[ji.li_Gate ][ji.AGateEquDrainPrimeNodeOffset ] -= ji.capgd;
2152 
2153  dQdx[ji.li_Gate ][ji.AGateEquSourcePrimeNodeOffset ] -= ji.capgs;
2154 
2155  dQdx[ji.li_DrainPrime ][ji.ADrainPrimeEquGateNodeOffset ] -= ji.capgd;
2156 
2158 
2160 
2162  }
2163 
2164  return true;
2165 }
2166 #endif
2167 
2168 Device *Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
2169 {
2170 
2171  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
2172 }
2173 
2175 {
2177  .registerDevice("j", 1)
2178  .registerDevice("j", 2)
2179  .registerModelType("pjf", 1)
2180  .registerModelType("njf", 1)
2181  .registerModelType("pjf", 2)
2182  .registerModelType("njf", 2);
2183 }
2184 
2185 } // namespace JFET
2186 } // namespace Device
2187 } // namespace Xyce
const InstanceName & getName() const
double * q_SourcePrimeEquSourceNodePtr
Definition: N_DEV_JFET.h:330
#define CONSTPMOS
Definition: N_DEV_Const.h:77
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:1746
#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:76
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)
#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:766
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:1931
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:792
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:2030
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:719
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
Definition: N_DEV_JFET.C:633
bool processInstanceParams()
processInstanceParams
Definition: N_DEV_JFET.C:347
#define Xyce_NONPOINTER_MATRIX_LOAD
Definition: N_DEV_Bsrc.C:92
double * f_SourcePrimeEquSourcePrimeNodePtr
Definition: N_DEV_JFET.h:304
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
Definition: N_DEV_JFET.C:2168
const std::string & getType() const
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
Definition: N_DEV_JFET.C:1903
#define RS
#define CONSTKoverQ
Definition: N_DEV_Const.h:58
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
Definition: N_DEV_JFET.C:813
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:695
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