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