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