Xyce  6.1
N_DEV_ThermalResistor.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_DEV_ThermalResistor.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.69 $
40 //
41 // Revision Date : $Date: 2015/04/24 20:25:45 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //----------------------------------------------------------------------------
45 #include <Xyce_config.h>
46 
47 // ---------- Standard Includes ----------
48 
49 // ---------- Xyce Includes ----------
50 #include <N_DEV_Const.h>
51 #include <N_DEV_DeviceOptions.h>
52 #include <N_DEV_ExternData.h>
53 #include <N_DEV_MatrixLoadData.h>
54 #include <N_DEV_SolverState.h>
55 #include <N_DEV_ThermalResistor.h>
56 #include <N_DEV_Message.h>
57 #include <N_ERH_ErrorMgr.h>
58 
59 #include <N_DEV_Resistor.h>
60 
61 #include <N_LAS_Matrix.h>
62 #include <N_LAS_Vector.h>
63 
64 #include <N_UTL_Expression.h>
65 #include <N_UTL_FeatureTest.h>
66 
67 namespace Xyce {
68 namespace Device {
69 
70 namespace ThermalResistor {
71 
73 {
74  // Set up double precision variables:
75  p.addPar ("R",1000.0,&ThermalResistor::Instance::R)
76  .setUnit(U_OHM)
77  .setCategory(CAT_NONE)
78  .setDescription("Resistance");
79 
81  .setUnit(U_METER)
82  .setCategory(CAT_NONE)
83  .setDescription("Length of conductor");
84 
86  .setUnit(U_METER)
87  .setCategory(CAT_NONE)
88  .setDescription("Width of conductor");
89 
91  .setUnit(U_METER2)
92  .setCategory(CAT_NONE)
93  .setDescription("Area of conductor");
94 
96  .setUnit(U_METER)
97  .setCategory(CAT_NONE)
98  .setDescription("Length of material thermally coupled to conductor");
99 
101  .setUnit(U_METER2)
102  .setCategory(CAT_NONE)
103  .setDescription("Area of material thermally coupled to conductor");
104 
105  // This stuff is copied from the model:
106  p.addPar ("RESISTIVITY",0.0,&ThermalResistor::Instance::resistivity)
107  .setUnit(U_OHMM)
108  .setCategory(CAT_NONE)
109  .setDescription("Resistor material resistivity");
110 
111  p.addPar ("DENSITY",0.0,&ThermalResistor::Instance::density)
112  .setUnit(U_KGMM3)
113  .setCategory(CAT_NONE)
114  .setDescription("Resistor material density (unused)");
115 
116  p.addPar ("HEATCAPACITY",0.0,&ThermalResistor::Instance::heatCapacity)
117  .setUnit(U_JMM3KM1)
118  .setCategory(CAT_NONE)
119  .setDescription("Resistor material volumetric heat capacity");
120 
121  p.addPar ("THERMAL_HEATCAPACITY",0.0,&ThermalResistor::Instance::thermalHeatCapacity)
122  .setUnit(U_JMM3KM1)
123  .setCategory(CAT_NONE)
124  .setDescription("Volumetric heat capacity of material thermally coupled to conductor");
125 
127  .setUnit(U_DEGC)
128  .setCategory(CAT_NONE)
129  .setDescription("Device temperature");
130 
131  // Set up non-double precision variables:
133  .setUnit(U_NONE)
134  .setCategory(CAT_CONTROL)
135  .setDescription("Debug Output switch");
136 }
137 
139 {
141  .setUnit(U_DEGCM1)
142  .setCategory(CAT_NONE)
143  .setDescription("Linear Temperature Coefficient");
144 
146  .setUnit(U_DEGCM2)
147  .setCategory(CAT_NONE)
148  .setDescription("Quadratic Temperature Coefficient");
149 
151  .setUnit(U_OHM)
152  .setCategory(CAT_NONE)
153  .setDescription("Sheet Resistance");
154 
156  .setUnit(U_NONE)
157  .setDescription("Resistance Multiplier");
158 
159  p.addPar ("RESISTIVITY",0.0,&ThermalResistor::Model::resistivity)
160  .setUnit(U_OHMM)
161  .setCategory(CAT_NONE)
162  .setDescription("Resistor material resistivity");
163 
164  p.addPar ("DENSITY",0.0,&ThermalResistor::Model::density)
165  .setUnit(U_KGMM3)
166  .setCategory(CAT_NONE)
167  .setDescription("Resistor material density (unused)");
168 
169  p.addPar ("HEATCAPACITY",0.0,&ThermalResistor::Model::heatCapacity)
170  .setUnit(U_JMM3KM1)
171  .setCategory(CAT_NONE)
172  .setDescription("Resistor material volumetric heat capacity");
173 
174  p.addPar ("THERMAL_HEATCAPACITY",0.0,&ThermalResistor::Model::thermalHeatCapacity)
175  .setUnit(U_JMM3KM1)
176  .setCategory(CAT_NONE)
177  .setDescription("Volumetric heat capacity of material thermally coupled to conductor");
178 
179  p.addPar ("DEFW",1.e-5,&ThermalResistor::Model::defWidth)
180  .setUnit(U_METER)
181  .setCategory(CAT_NONE)
182  .setDescription("Default Instance Width");
183 
184  p.addPar ("NARROW",0.0,&ThermalResistor::Model::narrow)
185  .setUnit(U_METER)
186  .setCategory(CAT_NONE)
187  .setDescription("Narrowing due to side etching");
188 
189  p.addPar ("TNOM",0.0,&ThermalResistor::Model::tnom)
190  .setUnit(STANDARD)
191  .setCategory(CAT_NONE)
192  .setDescription("Parameter Measurement Temperature");
193 }
194 
195 std::vector< std::vector<int> > Instance::jacStamp;
196 
197 
198 // Class Instance
199 //-----------------------------------------------------------------------------
200 // Function : Instance::processParams
201 // Purpose :
202 // Special Notes :
203 // Scope : public
204 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
205 // Creation Date : 6/03/02
206 //-----------------------------------------------------------------------------
208 {
209 
210  // now set the temperature related stuff.
212 
213  return true;
214 }
215 
216 //-----------------------------------------------------------------------------
217 // Function : Instance::Instance
218 // Purpose : instance block constructor
219 // Special Notes :
220 // Scope : public
221 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
222 // Creation Date : 3/16/00
223 //-----------------------------------------------------------------------------
225  const Configuration & configuration,
226  const InstanceBlock & IB,
227  Model & Riter,
228  const FactoryBlock & factory_block)
229  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
230  model_(Riter),
231  R(0.0), G(0.0),
232  i0(0.0),
233  length(0.0),
234  width(0.0),
235  temp(getDeviceOptions().temp.getImmutableValue<double>()),
236  li_Pos(-1),
237  li_Neg(-1),
238  APosEquPosNodeOffset(-1),
239  APosEquNegNodeOffset(-1),
240  ANegEquPosNodeOffset(-1),
241  ANegEquNegNodeOffset(-1),
242  f_PosEquPosNodePtr(0),
243  f_PosEquNegNodePtr(0),
244  f_NegEquPosNodePtr(0),
245  f_NegEquNegNodePtr(0),
246  tempModelEnabled(false),
247  outputInternalVarsFlag(false),
248  li_TempState(-1),
249  li_store_dev_i(-1)
250 {
251  numIntVars = 0;
252  numExtVars = 2;
253  numStateVars = 0;
254  numLeadCurrentStoreVars = 1; // one potential lead current
255 
256  setNumBranchDataVars(0); // by default don't allocate space in branch vectors
257  numBranchDataVarsIfAllocated = 1; // this is the space to allocate if lead current or power is needed.
258 
259  if( jacStamp.empty() )
260  {
261  jacStamp.resize(2);
262  jacStamp[0].resize(2);
263  jacStamp[1].resize(2);
264  jacStamp[0][0] = 0;
265  jacStamp[0][1] = 1;
266  jacStamp[1][0] = 0;
267  jacStamp[1][1] = 1;
268  }
269 
270 
271  // Set params to constant default values:
272  setDefaultParams ();
273 
274  // Set params according to instance line and constant defaults from metadata:
275  setParams (IB.params);
276 
277  // Set any non-constant parameter defaults:
278  if (!given("TEMP"))
279  temp = getDeviceOptions().temp.getImmutableValue<double>();
280  if (!given("W"))
281  width = model_.defWidth;;
282 
283  // Nonzero value for numStateVars indicates that the self-consistent thermal
284  // resistor model is being used.
285  if (given("A") && given("L") &&
286  ( (model_.given("HEATCAPACITY") && model_.given("RESISTIVITY"))
287  || (given("HEATCAPACITY") && given("RESISTIVITY")) )
288  )
289  {
290  numStateVars++;
291  tempModelEnabled = true;
292  }
293 
294  // If the instance parameters are NOT given, but the model parameters
295  // ARE given, then copy the model params into the instance. All the
296  // work is actually done in the instance anyway,
297  // but this stuff can be specified on the model level.
298  if ( !(given("HEATCAPACITY")) && !(given("RESISTIVITY")) &&
299  model_.given("HEATCAPACITY") && model_.given("RESISTIVITY") )
300  {
304 
305  // copy over the dependent parameters. For now, it only appears necessary
306  // to copy the dependentParams vector, and not anything else like
307  // the expVarLIDs vector.
308 
309  if (!(model_.getDependentParams().empty()))
310  {
311  const std::vector<Depend> & model_dp = model_.getDependentParams();
312  int dpSize = model_dp.size();
313 
314  for (int i=0;i<dpSize;++i)
315  {
316  Depend dpTmp;
317  dpTmp.name = model_dp[i].name;
318  dpTmp.vals = model_dp[i].vals;
319  dpTmp.global_params = model_dp[i].global_params;
320  dpTmp.n_vars = model_dp[i].n_vars;
321  dpTmp.lo_var = model_dp[i].lo_var;
322  dpTmp.vectorIndex = -1;
323 
324  // dpTmp needs to point to a copy of the original expression.
325  dpTmp.expr = new Util::Expression( *(model_dp[i].expr) );
326 
327  double *Dval;
328  if (dpTmp.name=="RESISTIVITY")
329  {
330  //Dval = &Instance::resistivity;
331  Dval = &resistivity;
332  dpTmp.resultU.result = Dval;
333 
334  }
335 
336  if (dpTmp.name=="HEATCAPACITY")
337  {
338  Dval = &heatCapacity;
339  dpTmp.resultU.result = Dval;
340  }
341 
342  addDependentParameter(dpTmp);
343  }
344  }
345  }
346 
347  // Calculate any parameters specified as expressions:
349 
350  // calculate dependent (ie computed) params and check for errors:
351 
352  if (!given("R") && numStateVars == 0)
353  {
354  if (model_.given("RSH") && given("L") && (model_.sheetRes!=0) &&
355  (length != 0))
356  {
358  / (width - model_.narrow);
359  }
360  else
361  {
362  UserWarning(*this) << "Resistance is0, set to default of 1000 ohms " << getName();
363 
364  R = 1000;
365  }
366  }
367 
368  processParams ();
369 }
370 
371 //-----------------------------------------------------------------------------
372 // Function : Instance::~Instance
373 // Purpose : destructor
374 // Special Notes :
375 // Scope : public
376 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
377 // Creation Date : 3/16/00
378 //-----------------------------------------------------------------------------
380 {}
381 
382 //-----------------------------------------------------------------------------
383 // Function : Instance::registerLIDs
384 // Purpose :
385 // Special Notes :
386 // Scope : public
387 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
388 // Creation Date : 6/12/02
389 //-----------------------------------------------------------------------------
390 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
391  const std::vector<int> & extLIDVecRef )
392 {
393  AssertLIDs(intLIDVecRef.size() == numIntVars);
394  AssertLIDs(extLIDVecRef.size() == numExtVars);
395 
396  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS))
397  {
398  Xyce::dout() << std::endl << section_divider << std::endl;
399  Xyce::dout() << " ResistorInstance::registerLIDs" << std::endl;
400  Xyce::dout() << " name = " << getName() << std::endl;
401  }
402 
403  // copy over the global ID lists.
404  intLIDVec = intLIDVecRef;
405  extLIDVec = extLIDVecRef;
406 
407  li_Pos = extLIDVec[0];
408  li_Neg = extLIDVec[1];
409 
410  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
411  {
412  Xyce::dout() << " li_Pos = " << li_Pos << std::endl;
413  Xyce::dout() << " li_Neg = " << li_Neg << std::endl;
414  }
415 
416  if (DEBUG_DEVICE && isActive(Diag::DEVICE_PARAMETERS) )
417  {
418  Xyce::dout() << section_divider << std::endl;
419  }
420 }
421 
422 //-----------------------------------------------------------------------------
423 // Function : Instance::registerStateLIDs
424 // Purpose : Note that the resistor does not have any state vars.
425 // Special Notes :
426 // Scope : public
427 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
428 // Creation Date : 06/12/02
429 //-----------------------------------------------------------------------------
430 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef )
431 {
432  AssertLIDs(staLIDVecRef.size() == numStateVars);
433 
434  // Copy over the global ID lists:
435  staLIDVec = staLIDVecRef;
436 
437  if (numStateVars > 0)
438  li_TempState = staLIDVec[0];
439 
440 }
441 
442 // ----------------------------------------------------------------------------
443 // Function : Instance::registerStoreLIDs
444 // Purpose : One store var for device current.
445 // Special Notes :
446 // Scope : public
447 // Creator : Richard Schiek, Electrical Systems Modeling
448 // Creation Date : 04/24/2013
449 // ----------------------------------------------------------------------------
450 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef)
451 {
452  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
453 
454  if( loadLeadCurrent )
455  {
456  li_store_dev_i = stoLIDVecRef[0];
457  }
458 }
459 
460 //-----------------------------------------------------------------------------
461 // Function : Xyce::Device::Resistor::Instance::registerBranchDataLIDs
462 // Purpose :
463 // Special Notes :
464 // Scope : public
465 // Creator : Richard Schiek, Electrical Systems Modeling
466 // Creation Date : 12/18/2012
467 //-----------------------------------------------------------------------------
468 /// Register the local store IDs
469 ///
470 /// In addition to state vector, Xyce maintains a separate datastructure
471 /// called a "branch data" vector. As with other such vectors, the device
472 /// declares at construction time how many branch vector entries it needs,
473 /// and later Topology assigns locations for devices, returning LIDs.
474 ///
475 /// These LIDs are stored in this method for later use.
476 ///
477 /// The Resistor device uses exactly one "branch data vector" element, where
478 /// it keeps the "lead current" that may be used on .PRINT lines as
479 /// "I(R1)" for the current through resistor R1. and a junction voltage.
480 ///
481 /// @param stoLIDVecRef Store variable local IDs
482 ///
483 /// @author Richard Schiek, Electrical Systems Modeling
484 /// @date 12/18/2012
485 
486 void Instance::registerBranchDataLIDs(const std::vector<int> & branchLIDVecRef)
487 {
488  AssertLIDs(branchLIDVecRef.size() == getNumBranchDataVars());
489 
490  if (loadLeadCurrent)
491  {
492  li_branch_data= branchLIDVecRef[0];
493  }
494 }
495 
496 //-----------------------------------------------------------------------------
497 // Function : Instance::jacobianStamp
498 // Purpose :
499 // Special Notes :
500 // Scope : public
501 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
502 // Creation Date : 08/20/01
503 //-----------------------------------------------------------------------------
504 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
505 {
506  return jacStamp;
507 }
508 
509 //-----------------------------------------------------------------------------
510 // Function : Instance::registerJacLIDs
511 // Purpose :
512 // Special Notes :
513 // Scope : public
514 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
515 // Creation Date : 08/27/01
516 //-----------------------------------------------------------------------------
517 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
518 {
519  DeviceInstance::registerJacLIDs( jacLIDVec );
520 
521  APosEquPosNodeOffset = jacLIDVec[0][0];
522  APosEquNegNodeOffset = jacLIDVec[0][1];
523  ANegEquPosNodeOffset = jacLIDVec[1][0];
524  ANegEquNegNodeOffset = jacLIDVec[1][1];
525 }
526 
527 //-----------------------------------------------------------------------------
528 // Function : Instance::setupPointers
529 // Purpose :
530 // Special Notes :
531 // Scope : public
532 // Creator : Eric Keiter, SNL
533 // Creation Date : 12/12/08
534 //-----------------------------------------------------------------------------
536 {
537 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
538  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
543 #endif
544 }
545 
546 //-----------------------------------------------------------------------------
547 // Function : Instance::loadNodeSymbols
548 // Purpose :
549 // Special Notes :
550 // Scope : public
551 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
552 // Creation Date : 05/13/05
553 //-----------------------------------------------------------------------------
554 void Instance::loadNodeSymbols(Util::SymbolTable &symbol_table) const
555 {
556  if (loadLeadCurrent)
557  //addStoreNode(symbol_table, li_store_dev_i, getName(), "DEV_I");
558  addBranchDataNode( symbol_table, li_branch_data, getName(), "BRANCH_D");
559 }
560 
561 
562 //-----------------------------------------------------------------------------
563 // Function : Instance::updateIntermediateVars
564 // Purpose : update intermediate variables for one diode instance
565 // Special Notes :
566 // Scope : public
567 // Creator : Eric R. Keiter, Dept. 9233.
568 // Creation Date : 3/05/04
569 //-----------------------------------------------------------------------------
571 {
572  double * solVec = extData.nextSolVectorRawPtr;
573 
574  if (tempModelEnabled)
575  {
576  Linear::Vector * staVectorPtr = extData.currStaVectorPtr;
577 
578  if (!getSolverState().dcopFlag)
579  {
580  if (li_TempState >= 0)
581  {
582  temp = (*staVectorPtr)[li_TempState];
584  }
585  }
586  }
587 
588  double v_pos = solVec[li_Pos];
589  double v_neg = solVec[li_Neg];
590 
591  // Load RHS vector element for the positive circuit node KCL equ.
592  i0 = (v_pos-v_neg)*G;
593 
594  return true;
595 }
596 
597 //-----------------------------------------------------------------------------
598 // Function : Instance::updatePrimaryState
599 // Purpose :
600 // Special Notes :
601 // Scope : public
602 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
603 // Creation Date : 01/29/01
604 //-----------------------------------------------------------------------------
606 {
607  bool bsuccess = updateIntermediateVars ();
608 
609  if (tempModelEnabled)
610  {
611  double * staVec = extData.nextStaVectorRawPtr;
612  if (li_TempState >= 0)
613  {
614  double dissipation = i0*i0*R;
617  staVec[li_TempState] = temp;
618  }
619  }
620 
621  return bsuccess;
622 }
623 
624 //-----------------------------------------------------------------------------
625 // Function : Instance::outputPlotFiles
626 // Purpose :
627 // Special Notes :
628 // Scope : public
629 // Creator :
630 // Creation Date :
631 //-----------------------------------------------------------------------------
632 bool Instance::outputPlotFiles(bool force_final_output)
633 {
634  bool bsuccess = true;
635 
637  {
638  Xyce::dout().width(28); Xyce::dout().precision(20); Xyce::dout().setf(std::ios::scientific);
639  Linear::Vector * sta1VectorPtr = extData.nextStaVectorPtr;
640  Linear::Vector * sta2VectorPtr = extData.currStaVectorPtr;
641  Xyce::dout() << "TEMP("<<getName()<<"): " << getSolverState().currTime_ << " "
642  << ((*sta1VectorPtr)[li_TempState]-CONSTCtoK) << " "
643  << ((*sta2VectorPtr)[li_TempState]-CONSTCtoK)
644  << std::endl;
645  }
646 
647  return bsuccess;
648 }
649 
650 //-----------------------------------------------------------------------------
651 // Function : Instance::loadDAEFVector
652 //
653 // Purpose : Loads the F-vector contributions for a single
654 // resistor instance.
655 //
656 // Special Notes :
657 //
658 // Scope : public
659 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
660 // Creation Date : 01/24/03
661 //-----------------------------------------------------------------------------
663 {
664  double * fVec = extData.daeFVectorRawPtr;
665  fVec[li_Pos] += i0;
666  fVec[li_Neg] += -i0;
667 
668  if( loadLeadCurrent )
669  {
670  double * stoVec = extData.nextStoVectorRawPtr;
671  double * leadF = extData.nextLeadCurrFCompRawPtr;
672  double * junctionV = extData.nextJunctionVCompRawPtr;
673  double * solVec = extData.nextSolVectorRawPtr;
674  stoVec[li_store_dev_i] = i0;
675  leadF[li_branch_data] = i0;
676  junctionV[li_branch_data] = solVec[li_Pos] - solVec[li_Neg];
677  }
678  return true;
679 }
680 
681 //-----------------------------------------------------------------------------
682 // Function : Instance::loadDAEdFdx ()
683 //
684 // Purpose : Loads the F-vector contributions for a single
685 // resistor instance.
686 //
687 // Special Notes :
688 //
689 // Scope : public
690 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
691 // Creation Date : 03/05/04
692 //-----------------------------------------------------------------------------
694 {
695  Linear::Matrix & dFdx = *(extData.dFdxMatrixPtr);
696 
697  dFdx[li_Pos][APosEquPosNodeOffset] += G;
698  dFdx[li_Pos][APosEquNegNodeOffset] -= G;
699  dFdx[li_Neg][ANegEquPosNodeOffset] -= G;
700  dFdx[li_Neg][ANegEquNegNodeOffset] += G;
701 
702  return true;
703 }
704 
705 //-----------------------------------------------------------------------------
706 // Function : Instance::updateTemperature
707 // Purpose :
708 // Special Notes :
709 // Scope : public
710 // Creator : Tom Russo, Component Information and Models
711 // Creation Date : 02/27/01
712 //-----------------------------------------------------------------------------
713 bool Instance::updateTemperature ( const double & temp_tmp)
714 {
715  double difference, factor;
716 
717  if (tempModelEnabled)
718  {
719  updateDependentParameters(temp_tmp);
720  R = resistivity * length / area;
721  factor = 1;
722  }
723  else
724  {
725  difference = temp_tmp - model_.tnom;
726  factor = model_.resistanceMultiplier*(1.0 + (model_.tempCoeff1)*difference +
727  (model_.tempCoeff2)*difference*difference);
728  }
729 
730  if (R*factor != 0.0)
731  G = 1.0/(R * factor);
732  else
733  G = 0.0;
734 
735 
736  return true;
737 }
738 
739 //-----------------------------------------------------------------------------
740 // Function : Model::processParams
741 // Purpose :
742 // Special Notes :
743 // Scope : public
744 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
745 // Creation Date : 6/03/02
746 //-----------------------------------------------------------------------------
748 {
749  return true;
750 }
751 
752 //----------------------------------------------------------------------------
753 // Function : Model::processInstanceParams
754 // Purpose :
755 // Special Notes :
756 // Scope : public
757 // Creator : Dave Shirely, PSSI
758 // Creation Date : 03/23/06
759 //----------------------------------------------------------------------------
761 {
762  std::vector<Instance*>::iterator iter;
763  std::vector<Instance*>::iterator first = instanceContainer.begin();
764  std::vector<Instance*>::iterator last = instanceContainer.end();
765 
766  for (iter=first; iter!=last; ++iter)
767  {
768  (*iter)->processParams();
769  }
770 
771  return true;
772 }
773 
774 //-----------------------------------------------------------------------------
775 // Function : Model::Model
776 // Purpose : model block constructor
777 // Special Notes :
778 // Scope : public
779 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
780 // Creation Date : 5/16/00
781 //-----------------------------------------------------------------------------
783  const Configuration & configuration,
784  const ModelBlock & MB,
785  const FactoryBlock & factory_block)
786  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
787  tempCoeff1(0.0),
788  tempCoeff2(0.0),
789  sheetRes(0.0),
790  resistanceMultiplier(1.0),
791  defWidth(10e-6),
792  narrow(0.0),
793  tnom(getDeviceOptions().tnom)
794 {
795 
796  // Set params to constant default values:
797  setDefaultParams ();
798 
799  // Set params according to .model line and constant defaults from metadata:
800  setModParams (MB.params);
801 
802  // Set any non-constant parameter defaults:
803  if (!given("TNOM"))
805 
806  // Calculate any parameters specified as expressions:
808 
809  if (!given("THERMAL_HEATCAPACITY"))
811 
812  // calculate dependent (ie computed) params and check for errors:
813  processParams();
814 }
815 
816 //-----------------------------------------------------------------------------
817 // Function : Model::~Model
818 // Purpose : destructor
819 // Special Notes :
820 // Scope : public
821 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
822 // Creation Date : 3/16/00
823 //-----------------------------------------------------------------------------
825 {
826  std::vector<Instance*>::iterator iter;
827  std::vector<Instance*>::iterator first = instanceContainer.begin();
828  std::vector<Instance*>::iterator last = instanceContainer.end();
829 
830  for (iter=first; iter!=last; ++iter)
831  {
832  delete (*iter);
833  }
834 }
835 
836 //-----------------------------------------------------------------------------
837 // Function : Model::printOutInstances
838 // Purpose : debugging tool.
839 // Special Notes :
840 // Scope : public
841 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
842 // Creation Date : 4/03/00
843 //-----------------------------------------------------------------------------
844 std::ostream &Model::printOutInstances(std::ostream &os) const
845 {
846  std::vector<Instance*>::const_iterator iter;
847  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
848  std::vector<Instance*>::const_iterator last = instanceContainer.end();
849 
850  int i,isize;
851  isize = instanceContainer.size();
852  os << std::endl;
853  os << "Number of Resistor Instances: " << isize << std::endl;
854  os << " name model name Parameters" << std::endl;
855  for (i=0, iter=first; iter!=last; ++iter, ++i)
856  {
857  os << " " << i << ": " << (*iter)->getName() << "\t";
858  os << getName();
859  os << "\t\tR(Tnom) = " << (*iter)->R;
860  os << "\tG(T) = " << (*iter)->G;
861  os << std::endl;
862  }
863 
864  os << std::endl;
865 
866  return os;
867 }
868 
869 //-----------------------------------------------------------------------------
870 // Function : Model::forEachInstance
871 // Purpose :
872 // Special Notes :
873 // Scope : public
874 // Creator : David Baur
875 // Creation Date : 2/4/2014
876 //-----------------------------------------------------------------------------
877 /// Apply a device instance "op" to all instances associated with this
878 /// model
879 ///
880 /// @param[in] op Operator to apply to all instances.
881 ///
882 ///
883 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
884 {
885  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
886  op(*it);
887 }
888 
889 
890 // ThermalResistor Master functions:
891 
892 //-----------------------------------------------------------------------------
893 // Function : Master::updateState
894 // Purpose :
895 // Special Notes :
896 // Scope : public
897 // Creator : Eric Keiter, SNL
898 // Creation Date : 11/26/08
899 //-----------------------------------------------------------------------------
900 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
901 {
902  bool bsuccess = true;
903  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
904  {
905  Instance & ri = *(*it);
906 
907  bool btmp = ri.updateIntermediateVars ();
908  bsuccess = bsuccess && btmp;
909 
910  if (ri.tempModelEnabled)
911  {
912  if (ri.li_TempState >= 0)
913  {
914  double dissipation = ri.i0*ri.i0*ri.R;
915  double dt = ri.getSolverState().currTimeStep_;
916  ri.temp += dissipation*dt/(ri.area*ri.length*ri.heatCapacity +
918  staVec[ri.li_TempState] = ri.temp;
919  }
920  }
921  }
922 // }
923 
924  return bsuccess;
925 }
926 
927 //-----------------------------------------------------------------------------
928 // Function : Master::loadDAEVectors
929 // Purpose :
930 // Special Notes :
931 // Scope : public
932 // Creator : Eric Keiter, SNL
933 // Creation Date : 11/26/08
934 //-----------------------------------------------------------------------------
935 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ, double * leadF, double * leadQ, double * junctionV)
936 {
937  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
938  {
939  Instance & ri = *(*it);
940  fVec[ri.li_Pos] += ri.i0;
941  fVec[ri.li_Neg] += -ri.i0;
942  if( ri.loadLeadCurrent )
943  {
944  storeLeadF[ri.li_store_dev_i] = ri.i0;
945  leadF[ri.li_branch_data] = ri.i0;
946  junctionV[ri.li_branch_data] = solVec[ri.li_Pos] - solVec[ri.li_Neg];
947  }
948  }
949 
950  return true;
951 }
952 
953 //-----------------------------------------------------------------------------
954 // Function : Master::loadDAEMatrices
955 // Purpose :
956 // Special Notes :
957 // Scope : public
958 // Creator : Eric Keiter, SNL
959 // Creation Date : 11/26/08
960 //-----------------------------------------------------------------------------
961 bool Master::loadDAEMatrices (Linear::Matrix & dFdx, Linear::Matrix & dQdx)
962 {
963 #ifdef _OMP
964 #pragma omp parallel for
965 #endif
966  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
967  {
968  Instance & ri = *(*it);
969 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
970 
971  *(ri.f_PosEquPosNodePtr) += ri.G;
972 
973  *(ri.f_PosEquNegNodePtr) -= ri.G;
974 
975  *(ri.f_NegEquPosNodePtr) -= ri.G;
976 
977  *(ri.f_NegEquNegNodePtr) += ri.G;
978 #else
979 
980  dFdx[ri.li_Pos][ri.APosEquPosNodeOffset] += ri.G;
981 
982  dFdx[ri.li_Pos][ri.APosEquNegNodeOffset] -= ri.G;
983 
984  dFdx[ri.li_Neg][ri.ANegEquPosNodeOffset] -= ri.G;
985 
986  dFdx[ri.li_Neg][ri.ANegEquNegNodeOffset] += ri.G;
987 #endif
988  }
989 
990  return true;
991 }
992 
993 Device *
994 Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
995 {
996 
997  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
998 }
999 
1000 void
1002 {
1004  .registerDevice("r", 2)
1005  .registerModelType("r", 2);
1006 }
1007 
1008 } // namespace ThermalResistor
1009 } // namespace Device
1010 } // namespace Xyce
const InstanceName & getName() const
int li_branch_data
Index for Lead Current and junction voltage (for power calculations)
virtual void registerBranchDataLIDs(const std::vector< int > &branchLIDVecRef)
Register the local store IDs.
virtual void loadNodeSymbols(Util::SymbolTable &symbol_table) const
Populates and returns the store name map.
const DeviceOptions & deviceOptions_
Descriptor & addPar(const char *parName, T default_value, T U::*varPtr)
Adds the parameter description to the parameter map.
Definition: N_DEV_Pars.h:1429
#define CONSTCtoK
Definition: N_DEV_Const.h:52
void registerStoreLIDs(const std::vector< int > &stoLIDVecRef)
double currTimeStep_
Region, BJT, Digital, ThermalResistor, ROM, Charon, Others.
bool given(const std::string &parameter_name) const
void G(const ScalarT &V1, const ScalarT &V2, const ScalarT &Ap, const ScalarT &An, ScalarT &Vp, ScalarT &Vn, ScalarT &fval)
virtual void forEachInstance(DeviceInstanceOp &op) const
Apply a device instance "op" to all instances associated with this model.
Pure virtual class to augment a linear system.
void registerStateLIDs(const std::vector< int > &staLIDVecRef)
void addBranchDataNode(Util::SymbolTable &symbol_table, int index, const InstanceName &instance_name, const std::string &lead_name)
static std::vector< std::vector< int > > jacStamp
void registerLIDs(const std::vector< int > &intLIDVecRef, const std::vector< int > &extLIDVecRef)
InstanceVector::const_iterator getInstanceEnd() const
Returns an iterator to the ending of the vector of all instances created for this device...
const std::vector< Depend > & getDependentParams()
#define AssertLIDs(cmp)
virtual void registerJacLIDs(const JacobianStamp &jacLIDVec)
bool processInstanceParams()
processInstanceParams
double tnom
nominal temperature for device params.
InstanceVector::const_iterator getInstanceBegin() const
Returns an iterator to the beginning of the vector of all instances created for this device...
std::vector< Param > params
Parameters from the line.
void setParams(const std::vector< Param > &params)
const std::string & getName() const
std::vector< double > vals
The FactoryBlock contains parameters needed by the device, instance and model creation functions...
static void loadModelParameters(ParametricData< Model > &model_parameters)
Instance(const Configuration &configuration, const InstanceBlock &IB, Model &Riter, const FactoryBlock &factory_block)
const DeviceOptions & getDeviceOptions() const
virtual std::ostream & printOutInstances(std::ostream &os) const
union Xyce::Device::Depend::resUnion resultU
Linear::Vector * nextStaVectorPtr
std::vector< std::string > global_params
static Config< T > & addConfiguration()
Adds the device to the Xyce device configuration.
Linear::Matrix * dFdxMatrixPtr
The Device class is an interface for device implementations.
Definition: N_DEV_Device.h:101
virtual bool loadDAEVectors(double *solVec, double *fVec, double *qVec, double *bVec, double *storeLeadF, double *storeLeadQ, double *leadF, double *leadQ, double *junctionV)
Populates the device's ExternData object with these pointers.
static void loadInstanceParameters(ParametricData< Instance > &instance_parameters)
const SolverState & solverState_
Class Configuration contains device configuration data.
virtual bool updateState(double *solVec, double *staVec, double *stoVec)
Updates the devices state information.
virtual bool loadDAEMatrices(Linear::Matrix &dFdx, Linear::Matrix &dQdx)
Populates the device's Jacobian object with these pointers.
const SolverState & getSolverState() const
void addDependentParameter(const Depend &param)
bool updateTemperature(const double &temp_tmp)
void setNumBranchDataVars(int num_branch_data_vars)
Linear::Vector * currStaVectorPtr
Util::Expression * expr
static Device * factory(const Configuration &configuration, const FactoryBlock &factory_block)
ModelBlock represents a .MODEL line from the netlist.
Manages parameter binding for class C.
Definition: N_DEV_Pars.h:214
InstanceBlock represent a device instance line from the netlist.
double currTime_
DeviceEntity for expression time, breakpoints DeviceMgr for dependent parameters, breakpoints...
Util::Param temp
operating temperature of ckt.
std::vector< Param > params
void registerJacLIDs(const std::vector< std::vector< int > > &jacLIDVec)
std::vector< Instance * > instanceContainer
const std::vector< std::vector< int > > & jacobianStamp() const
bool outputPlotFiles(bool force_final_output)
void setModParams(const std::vector< Param > &params)