Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-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_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.57.2.1 $
40 //
41 // Revision Date : $Date: 2014/08/28 16:40:51 $
42 //
43 // Current Owner : $Author: tvrusso $
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 
66 namespace Xyce {
67 namespace Device {
68 
69 
70 namespace ThermalResistor {
71 
72 
74 {
75  // Set up double precision variables:
76  p.addPar ("R", 1000.0, false, ParameterType::TIME_DEP,
78  NULL, U_OHM, CAT_NONE, "Resistance");
79 
80  p.addPar ("L", 0.0, false, ParameterType::NO_DEP,
82  NULL, U_METER, CAT_NONE, "Length of conductor");
83 
84  p.addPar ("W", 0.0, false, ParameterType::NO_DEP,
86  NULL, U_METER, CAT_NONE, "Width of conductor");
87 
88  p.addPar ("A", 0.0, false, ParameterType::NO_DEP,
90  NULL, U_METER2, CAT_NONE, "Area of conductor");
91 
92  p.addPar ("THERMAL_L", 0.0, false, ParameterType::NO_DEP,
94  NULL, U_METER, CAT_NONE, "Length of material thermally coupled to conductor");
95 
96  p.addPar ("THERMAL_A", 0.0, false, ParameterType::NO_DEP,
98  NULL, U_METER2, CAT_NONE, "Area of material thermally coupled to conductor");
99 
100 
101  // This stuff is copied from the model:
102  p.addPar ("RESISTIVITY", 0.0, false, ParameterType::TIME_DEP,
104  NULL, U_OHMM, CAT_NONE, "Resistor material resistivity");
105 
106  p.addPar ("DENSITY", 0.0, false, ParameterType::TIME_DEP,
108  NULL, U_KGMM3, CAT_NONE, "Resistor material density (unused)");
109 
110  p.addPar ("HEATCAPACITY", 0.0, false, ParameterType::TIME_DEP,
112  NULL, U_JMM3KM1, CAT_NONE, "Resistor material volumetric heat capacity");
113 
114  p.addPar ("THERMAL_HEATCAPACITY", 0.0, false, ParameterType::TIME_DEP,
116  NULL, U_JMM3KM1, CAT_NONE, "Volumetric heat capacity of material thermally coupled to conductor");
117 
118 
119  p.addPar ("TEMP", 0.0, false, ParameterType::TIME_DEP,
121  NULL, U_DEGC, CAT_NONE, "Device temperature");
122 
123  // Set up non-double precision variables:
124  p.addPar ("OUTPUTINTVARS", false, false, ParameterType::NO_DEP,
126  U_NONE, CAT_CONTROL, "Debug Output switch");
127 }
128 
130 {
131  p.addPar ("TC1", 0.0, false, ParameterType::NO_DEP,
133  U_DEGCM1, CAT_NONE, "Linear Temperature Coefficient");
134 
135  p.addPar ("TC2", 0.0, false, ParameterType::NO_DEP,
137  U_DEGCM2, CAT_NONE, "Quadratic Temperature Coefficient");
138 
139  p.addPar ("RSH", 0.0, false, ParameterType::NO_DEP,
141  U_OHM, CAT_NONE, "Sheet Resistance");
142 
144  .setUnit(U_NONE)
145  .setDescription("Resistance Multiplier");
146 
147  p.addPar ("RESISTIVITY", 0.0, false, ParameterType::TIME_DEP,
149  U_OHMM, CAT_NONE, "Resistor material resistivity");
150 
151  p.addPar ("DENSITY", 0.0, false, ParameterType::TIME_DEP,
153  U_KGMM3, CAT_NONE, "Resistor material density (unused)");
154 
155  p.addPar ("HEATCAPACITY", 0.0, false, ParameterType::TIME_DEP,
157  U_JMM3KM1, CAT_NONE, "Resistor material volumetric heat capacity");
158 
159  p.addPar ("THERMAL_HEATCAPACITY", 0.0, false, ParameterType::TIME_DEP,
161  U_JMM3KM1, CAT_NONE, "Volumetric heat capacity of material thermally coupled to conductor");
162 
163  p.addPar ("DEFW", 1.e-5, false, ParameterType::NO_DEP,
165  U_METER, CAT_NONE, "Default Instance Width");
166 
167  p.addPar ("NARROW", 0.0, false, ParameterType::NO_DEP,
169  U_METER, CAT_NONE, "Narrowing due to side etching");
170 
171  p.addPar ("TNOM", 0.0, false, ParameterType::NO_DEP,
173  U_DEGC, CAT_NONE, "Parameter Measurement Temperature");
174 }
175 
176 
177 std::vector< std::vector<int> > Instance::jacStamp;
178 
179 
180 // Class Instance
181 //-----------------------------------------------------------------------------
182 // Function : Instance::processParams
183 // Purpose :
184 // Special Notes :
185 // Scope : public
186 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
187 // Creation Date : 6/03/02
188 //-----------------------------------------------------------------------------
190 {
191 
192  // now set the temperature related stuff.
194 
195  return true;
196 }
197 
198 //-----------------------------------------------------------------------------
199 // Function : Instance::Instance
200 // Purpose : instance block constructor
201 // Special Notes :
202 // Scope : public
203 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
204 // Creation Date : 3/16/00
205 //-----------------------------------------------------------------------------
207  const Configuration & configuration,
208  const InstanceBlock & IB,
209  Model & Riter,
210  const FactoryBlock & factory_block)
211  : DeviceInstance(IB, configuration.getInstanceParameters(), factory_block),
212  model_(Riter),
213  R(0.0), G(0.0),
214  i0(0.0),
215  length(0.0),
216  width(0.0),
217  temp(getDeviceOptions().temp.getImmutableValue<double>()),
218  li_Pos(-1),
219  li_Neg(-1),
220  APosEquPosNodeOffset(-1),
221  APosEquNegNodeOffset(-1),
222  ANegEquPosNodeOffset(-1),
223  ANegEquNegNodeOffset(-1),
224  f_PosEquPosNodePtr(0),
225  f_PosEquNegNodePtr(0),
226  f_NegEquPosNodePtr(0),
227  f_NegEquNegNodePtr(0),
228  tempModelEnabled(false),
229  outputInternalVarsFlag(false),
230  li_TempState(-1),
231  li_store_dev_i(-1)
232 {
233  numIntVars = 0;
234  numExtVars = 2;
235  numStateVars = 0;
236  numLeadCurrentStoreVars = 1; // one potential lead current
237 
238  if( jacStamp.empty() )
239  {
240  jacStamp.resize(2);
241  jacStamp[0].resize(2);
242  jacStamp[1].resize(2);
243  jacStamp[0][0] = 0;
244  jacStamp[0][1] = 1;
245  jacStamp[1][0] = 0;
246  jacStamp[1][1] = 1;
247  }
248 
249 
250  // Set params to constant default values:
251  setDefaultParams ();
252 
253  // Set params according to instance line and constant defaults from metadata:
254  setParams (IB.params);
255 
256  // Set any non-constant parameter defaults:
257  if (!given("TEMP"))
258  temp = getDeviceOptions().temp.getImmutableValue<double>();
259  if (!given("W"))
260  width = model_.defWidth;;
261 
262  // Nonzero value for numStateVars indicates that the self-consistent thermal
263  // resistor model is being used.
264  if (given("A") && given("L") &&
265  ( (model_.given("HEATCAPACITY") && model_.given("RESISTIVITY"))
266  || (given("HEATCAPACITY") && given("RESISTIVITY")) )
267  )
268  {
269  numStateVars++;
270  tempModelEnabled = true;
271  }
272 
273  // If the instance parameters are NOT given, but the model parameters
274  // ARE given, then copy the model params into the instance. All the
275  // work is actually done in the instance anyway,
276  // but this stuff can be specified on the model level.
277  if ( !(given("HEATCAPACITY")) && !(given("RESISTIVITY")) &&
278  model_.given("HEATCAPACITY") && model_.given("RESISTIVITY") )
279  {
283 
284  // copy over the dependent parameters. For now, it only appears necessary
285  // to copy the dependentParams vector, and not anything else like
286  // the expVarLIDs vector.
287 
288  if (!(model_.getDependentParams().empty()))
289  {
290  const std::vector<Depend> & model_dp = model_.getDependentParams();
291  int dpSize = model_dp.size();
292 
293  for (int i=0;i<dpSize;++i)
294  {
295  Depend dpTmp;
296  dpTmp.name = model_dp[i].name;
297  dpTmp.vals = model_dp[i].vals;
298  dpTmp.global_params = model_dp[i].global_params;
299  dpTmp.n_vars = model_dp[i].n_vars;
300  dpTmp.lo_var = model_dp[i].lo_var;
301  dpTmp.vectorIndex = -1;
302 
303  // dpTmp needs to point to a copy of the original expression.
304  dpTmp.expr = new Util::Expression( *(model_dp[i].expr) );
305 
306  double *Dval;
307  if (dpTmp.name=="RESISTIVITY")
308  {
309  //Dval = &Instance::resistivity;
310  Dval = &resistivity;
311  dpTmp.resultU.result = Dval;
312 
313  }
314 
315  if (dpTmp.name=="HEATCAPACITY")
316  {
317  Dval = &heatCapacity;
318  dpTmp.resultU.result = Dval;
319  }
320 
321  addDependentParameter(dpTmp);
322  }
323  }
324  }
325 
326  // Calculate any parameters specified as expressions:
328 
329  // calculate dependent (ie computed) params and check for errors:
330 
331  if (!given("R") && numStateVars == 0)
332  {
333  if (model_.given("RSH") && given("L") && (model_.sheetRes!=0) &&
334  (length != 0))
335  {
337  / (width - model_.narrow);
338  }
339  else
340  {
341  UserWarning(*this) << "Resistance is0, set to default of 1000 ohms " << getName();
342 
343  R = 1000;
344  }
345  }
346 
347  processParams ();
348 }
349 
350 //-----------------------------------------------------------------------------
351 // Function : Instance::~Instance
352 // Purpose : destructor
353 // Special Notes :
354 // Scope : public
355 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
356 // Creation Date : 3/16/00
357 //-----------------------------------------------------------------------------
359 {}
360 
361 //-----------------------------------------------------------------------------
362 // Function : Instance::registerLIDs
363 // Purpose :
364 // Special Notes :
365 // Scope : public
366 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
367 // Creation Date : 6/12/02
368 //-----------------------------------------------------------------------------
369 void Instance::registerLIDs( const std::vector<int> & intLIDVecRef,
370  const std::vector<int> & extLIDVecRef )
371 {
372  AssertLIDs(intLIDVecRef.size() == numIntVars);
373  AssertLIDs(extLIDVecRef.size() == numExtVars);
374 
375 #ifdef Xyce_DEBUG_DEVICE
376  if (getDeviceOptions().debugLevel > 0)
377  {
378  Xyce::dout() << std::endl << section_divider << std::endl;
379  Xyce::dout() << " ResistorInstance::registerLIDs" << std::endl;
380  Xyce::dout() << " name = " << getName() << std::endl;
381  }
382 #endif
383 
384  // copy over the global ID lists.
385  intLIDVec = intLIDVecRef;
386  extLIDVec = extLIDVecRef;
387 
388  li_Pos = extLIDVec[0];
389  li_Neg = extLIDVec[1];
390 
391 #ifdef Xyce_DEBUG_DEVICE
392  if (getDeviceOptions().debugLevel > 0 )
393  {
394  Xyce::dout() << " li_Pos = " << li_Pos << std::endl;
395  Xyce::dout() << " li_Neg = " << li_Neg << std::endl;
396  }
397 #endif
398 
399 #ifdef Xyce_DEBUG_DEVICE
400  if (getDeviceOptions().debugLevel > 0 )
401  {
402  Xyce::dout() << section_divider << std::endl;
403  }
404 #endif
405 }
406 
407 //-----------------------------------------------------------------------------
408 // Function : Instance::registerStateLIDs
409 // Purpose : Note that the resistor does not have any state vars.
410 // Special Notes :
411 // Scope : public
412 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
413 // Creation Date : 06/12/02
414 //-----------------------------------------------------------------------------
415 void Instance::registerStateLIDs(const std::vector<int> & staLIDVecRef )
416 {
417  AssertLIDs(staLIDVecRef.size() == numStateVars);
418 
419  // Copy over the global ID lists:
420  staLIDVec = staLIDVecRef;
421 
422  if (numStateVars > 0)
423  li_TempState = staLIDVec[0];
424 
425 }
426 
427 // ----------------------------------------------------------------------------
428 // Function : Instance::registerStoreLIDs
429 // Purpose : One store var for device current.
430 // Special Notes :
431 // Scope : public
432 // Creator : Richard Schiek, Electrical Systems Modeling
433 // Creation Date : 04/24/2013
434 // ----------------------------------------------------------------------------
435 void Instance::registerStoreLIDs(const std::vector<int> & stoLIDVecRef)
436 {
437  AssertLIDs(stoLIDVecRef.size() == getNumStoreVars());
438 
439  if( loadLeadCurrent )
440  {
441  li_store_dev_i = stoLIDVecRef[0];
442  }
443 }
444 
445 // ----------------------------------------------------------------------------
446 // Function : Instance::getStoreNameMap
447 // Purpose :
448 // Special Notes :
449 // Scope : public
450 // Creator : Richard Schiek, Electrical Systems Modeling
451 // Creation Date : 04/24/2013
452 // ----------------------------------------------------------------------------
453 std::map<int,std::string> & Instance::getStoreNameMap()
454 {
455  // set up the internal name map, if it hasn't been already.
456  if( loadLeadCurrent && storeNameMap.empty ())
457  {
459  }
460 
461  return storeNameMap;
462 }
463 
464 //-----------------------------------------------------------------------------
465 // Function : Instance::jacobianStamp
466 // Purpose :
467 // Special Notes :
468 // Scope : public
469 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
470 // Creation Date : 08/20/01
471 //-----------------------------------------------------------------------------
472 const std::vector< std::vector<int> > & Instance::jacobianStamp() const
473 {
474  return jacStamp;
475 }
476 
477 //-----------------------------------------------------------------------------
478 // Function : Instance::registerJacLIDs
479 // Purpose :
480 // Special Notes :
481 // Scope : public
482 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
483 // Creation Date : 08/27/01
484 //-----------------------------------------------------------------------------
485 void Instance::registerJacLIDs( const std::vector< std::vector<int> > & jacLIDVec )
486 {
487  DeviceInstance::registerJacLIDs( jacLIDVec );
488 
489  APosEquPosNodeOffset = jacLIDVec[0][0];
490  APosEquNegNodeOffset = jacLIDVec[0][1];
491  ANegEquPosNodeOffset = jacLIDVec[1][0];
492  ANegEquNegNodeOffset = jacLIDVec[1][1];
493 }
494 
495 //-----------------------------------------------------------------------------
496 // Function : Instance::setupPointers
497 // Purpose :
498 // Special Notes :
499 // Scope : public
500 // Creator : Eric Keiter, SNL
501 // Creation Date : 12/12/08
502 //-----------------------------------------------------------------------------
504 {
505 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
506  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
511 #endif
512 }
513 
514 //-----------------------------------------------------------------------------
515 // Function : Instance::updateIntermediateVars
516 // Purpose : update intermediate variables for one diode instance
517 // Special Notes :
518 // Scope : public
519 // Creator : Eric R. Keiter, Dept. 9233.
520 // Creation Date : 3/05/04
521 //-----------------------------------------------------------------------------
523 {
524  double * solVec = extData.nextSolVectorRawPtr;
525 
526  if (tempModelEnabled)
527  {
528  N_LAS_Vector * staVectorPtr = extData.currStaVectorPtr;
529 
530  if (!getSolverState().dcopFlag)
531  {
532  if (li_TempState >= 0)
533  {
534  temp = (*staVectorPtr)[li_TempState];
536  }
537  }
538  }
539 
540  double v_pos = solVec[li_Pos];
541  double v_neg = solVec[li_Neg];
542 
543  // Load RHS vector element for the positive circuit node KCL equ.
544  i0 = (v_pos-v_neg)*G;
545 
546  return true;
547 }
548 
549 //-----------------------------------------------------------------------------
550 // Function : Instance::updatePrimaryState
551 // Purpose :
552 // Special Notes :
553 // Scope : public
554 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
555 // Creation Date : 01/29/01
556 //-----------------------------------------------------------------------------
558 {
559  bool bsuccess = updateIntermediateVars ();
560 
561  if (tempModelEnabled)
562  {
563  double * staVec = extData.nextStaVectorRawPtr;
564  if (li_TempState >= 0)
565  {
566  double dissipation = i0*i0*R;
569  staVec[li_TempState] = temp;
570  }
571  }
572 
573  return bsuccess;
574 }
575 
576 //-----------------------------------------------------------------------------
577 // Function : Instance::outputPlotFiles
578 // Purpose :
579 // Special Notes :
580 // Scope : public
581 // Creator :
582 // Creation Date :
583 //-----------------------------------------------------------------------------
585 {
586  bool bsuccess = true;
587 
589  {
590  Xyce::dout().width(28); Xyce::dout().precision(20); Xyce::dout().setf(std::ios::scientific);
591  N_LAS_Vector * sta1VectorPtr = extData.nextStaVectorPtr;
592  N_LAS_Vector * sta2VectorPtr = extData.currStaVectorPtr;
593  Xyce::dout() << "TEMP("<<getName()<<"): " << getSolverState().currTime << " "
594  << ((*sta1VectorPtr)[li_TempState]-CONSTCtoK) << " "
595  << ((*sta2VectorPtr)[li_TempState]-CONSTCtoK)
596  << std::endl;
597  }
598 
599  return bsuccess;
600 }
601 
602 //-----------------------------------------------------------------------------
603 // Function : Instance::loadDAEFVector
604 //
605 // Purpose : Loads the F-vector contributions for a single
606 // resistor instance.
607 //
608 // Special Notes :
609 //
610 // Scope : public
611 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
612 // Creation Date : 01/24/03
613 //-----------------------------------------------------------------------------
615 {
616  double * fVec = extData.daeFVectorRawPtr;
617  fVec[li_Pos] += i0;
618  fVec[li_Neg] += -i0;
619 
620  if( loadLeadCurrent )
621  {
622  double * stoVec = extData.nextStoVectorRawPtr;
623  stoVec[li_store_dev_i] = i0;
624  }
625  return true;
626 }
627 
628 //-----------------------------------------------------------------------------
629 // Function : Instance::loadDAEdFdx ()
630 //
631 // Purpose : Loads the F-vector contributions for a single
632 // resistor instance.
633 //
634 // Special Notes :
635 //
636 // Scope : public
637 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
638 // Creation Date : 03/05/04
639 //-----------------------------------------------------------------------------
641 {
642  N_LAS_Matrix & dFdx = *(extData.dFdxMatrixPtr);
643 
644  dFdx[li_Pos][APosEquPosNodeOffset] += G;
645  dFdx[li_Pos][APosEquNegNodeOffset] -= G;
646  dFdx[li_Neg][ANegEquPosNodeOffset] -= G;
647  dFdx[li_Neg][ANegEquNegNodeOffset] += G;
648 
649  return true;
650 }
651 
652 //-----------------------------------------------------------------------------
653 // Function : Instance::updateTemperature
654 // Purpose :
655 // Special Notes :
656 // Scope : public
657 // Creator : Tom Russo, Component Information and Models
658 // Creation Date : 02/27/01
659 //-----------------------------------------------------------------------------
660 bool Instance::updateTemperature ( const double & temp_tmp)
661 {
662  double difference, factor;
663 
664  if (tempModelEnabled)
665  {
666  updateDependentParameters(temp_tmp);
667  R = resistivity * length / area;
668  factor = 1;
669  }
670  else
671  {
672  difference = temp_tmp - model_.tnom;
673  factor = model_.resistanceMultiplier*(1.0 + (model_.tempCoeff1)*difference +
674  (model_.tempCoeff2)*difference*difference);
675  }
676 
677  if (R*factor != 0.0)
678  G = 1.0/(R * factor);
679  else
680  G = 0.0;
681 
682 
683  return true;
684 }
685 
686 //-----------------------------------------------------------------------------
687 // Function : Model::processParams
688 // Purpose :
689 // Special Notes :
690 // Scope : public
691 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
692 // Creation Date : 6/03/02
693 //-----------------------------------------------------------------------------
695 {
696  return true;
697 }
698 
699 //----------------------------------------------------------------------------
700 // Function : Model::processInstanceParams
701 // Purpose :
702 // Special Notes :
703 // Scope : public
704 // Creator : Dave Shirely, PSSI
705 // Creation Date : 03/23/06
706 //----------------------------------------------------------------------------
708 {
709  std::vector<Instance*>::iterator iter;
710  std::vector<Instance*>::iterator first = instanceContainer.begin();
711  std::vector<Instance*>::iterator last = instanceContainer.end();
712 
713  for (iter=first; iter!=last; ++iter)
714  {
715  (*iter)->processParams();
716  }
717 
718  return true;
719 }
720 
721 //-----------------------------------------------------------------------------
722 // Function : Model::Model
723 // Purpose : model block constructor
724 // Special Notes :
725 // Scope : public
726 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
727 // Creation Date : 5/16/00
728 //-----------------------------------------------------------------------------
730  const Configuration & configuration,
731  const ModelBlock & MB,
732  const FactoryBlock & factory_block)
733  : DeviceModel(MB, configuration.getModelParameters(), factory_block),
734  tempCoeff1(0.0),
735  tempCoeff2(0.0),
736  sheetRes(0.0),
737  resistanceMultiplier(1.0),
738  defWidth(10e-6),
739  narrow(0.0),
740  tnom(getDeviceOptions().tnom)
741 {
742 
743  // Set params to constant default values:
744  setDefaultParams ();
745 
746  // Set params according to .model line and constant defaults from metadata:
747  setModParams (MB.params);
748 
749  // Set any non-constant parameter defaults:
750  if (!given("TNOM"))
752 
753  // Calculate any parameters specified as expressions:
755 
756  if (!given("THERMAL_HEATCAPACITY"))
758 
759  // calculate dependent (ie computed) params and check for errors:
760  processParams();
761 }
762 
763 //-----------------------------------------------------------------------------
764 // Function : Model::~Model
765 // Purpose : destructor
766 // Special Notes :
767 // Scope : public
768 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
769 // Creation Date : 3/16/00
770 //-----------------------------------------------------------------------------
772 {
773  std::vector<Instance*>::iterator iter;
774  std::vector<Instance*>::iterator first = instanceContainer.begin();
775  std::vector<Instance*>::iterator last = instanceContainer.end();
776 
777  for (iter=first; iter!=last; ++iter)
778  {
779  delete (*iter);
780  }
781 }
782 
783 //-----------------------------------------------------------------------------
784 // Function : Model::printOutInstances
785 // Purpose : debugging tool.
786 // Special Notes :
787 // Scope : public
788 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
789 // Creation Date : 4/03/00
790 //-----------------------------------------------------------------------------
791 std::ostream &Model::printOutInstances(std::ostream &os) const
792 {
793  std::vector<Instance*>::const_iterator iter;
794  std::vector<Instance*>::const_iterator first = instanceContainer.begin();
795  std::vector<Instance*>::const_iterator last = instanceContainer.end();
796 
797  int i,isize;
798  isize = instanceContainer.size();
799  os << std::endl;
800  os << "Number of Resistor Instances: " << isize << std::endl;
801  os << " name model name Parameters" << std::endl;
802  for (i=0, iter=first; iter!=last; ++iter, ++i)
803  {
804  os << " " << i << ": " << (*iter)->getName() << "\t";
805  os << getName();
806  os << "\t\tR(Tnom) = " << (*iter)->R;
807  os << "\tG(T) = " << (*iter)->G;
808  os << std::endl;
809  }
810 
811  os << std::endl;
812 
813  return os;
814 }
815 
816 //-----------------------------------------------------------------------------
817 // Function : Model::forEachInstance
818 // Purpose :
819 // Special Notes :
820 // Scope : public
821 // Creator : David Baur
822 // Creation Date : 2/4/2014
823 //-----------------------------------------------------------------------------
824 /// Apply a device instance "op" to all instances associated with this
825 /// model
826 ///
827 /// @param[in] op Operator to apply to all instances.
828 ///
829 ///
830 void Model::forEachInstance(DeviceInstanceOp &op) const /* override */
831 {
832  for (std::vector<Instance *>::const_iterator it = instanceContainer.begin(); it != instanceContainer.end(); ++it)
833  op(*it);
834 }
835 
836 
837 // ThermalResistor Master functions:
838 
839 //-----------------------------------------------------------------------------
840 // Function : Master::updateState
841 // Purpose :
842 // Special Notes :
843 // Scope : public
844 // Creator : Eric Keiter, SNL
845 // Creation Date : 11/26/08
846 //-----------------------------------------------------------------------------
847 bool Master::updateState (double * solVec, double * staVec, double * stoVec)
848 {
849  bool bsuccess = true;
850  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
851  {
852  Instance & ri = *(*it);
853 
854  bool btmp = ri.updateIntermediateVars ();
855  bsuccess = bsuccess && btmp;
856 
857  if (ri.tempModelEnabled)
858  {
859  if (ri.li_TempState >= 0)
860  {
861  double dissipation = ri.i0*ri.i0*ri.R;
862  double dt = ri.getSolverState().currTimeStep;
863  ri.temp += dissipation*dt/(ri.area*ri.length*ri.heatCapacity +
865  staVec[ri.li_TempState] = ri.temp;
866  }
867  }
868  }
869 // }
870 
871  return bsuccess;
872 }
873 
874 //-----------------------------------------------------------------------------
875 // Function : Master::loadDAEVectors
876 // Purpose :
877 // Special Notes :
878 // Scope : public
879 // Creator : Eric Keiter, SNL
880 // Creation Date : 11/26/08
881 //-----------------------------------------------------------------------------
882 bool Master::loadDAEVectors (double * solVec, double * fVec, double *qVec, double * bVec, double * storeLeadF, double * storeLeadQ)
883 {
884  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
885  {
886  Instance & ri = *(*it);
887  fVec[ri.li_Pos] += ri.i0;
888  fVec[ri.li_Neg] += -ri.i0;
889  if( ri.loadLeadCurrent )
890  {
891  storeLeadF[ri.li_store_dev_i] = ri.i0;
892  }
893  }
894 
895  return true;
896 }
897 
898 //-----------------------------------------------------------------------------
899 // Function : Master::loadDAEMatrices
900 // Purpose :
901 // Special Notes :
902 // Scope : public
903 // Creator : Eric Keiter, SNL
904 // Creation Date : 11/26/08
905 //-----------------------------------------------------------------------------
906 bool Master::loadDAEMatrices (N_LAS_Matrix & dFdx, N_LAS_Matrix & dQdx)
907 {
908 #ifdef _OMP
909 #pragma omp parallel for
910 #endif
911  for (InstanceVector::const_iterator it = getInstanceBegin(); it != getInstanceEnd(); ++it)
912  {
913  Instance & ri = *(*it);
914 #ifndef Xyce_NONPOINTER_MATRIX_LOAD
915 
916  *(ri.f_PosEquPosNodePtr) += ri.G;
917 
918  *(ri.f_PosEquNegNodePtr) -= ri.G;
919 
920  *(ri.f_NegEquPosNodePtr) -= ri.G;
921 
922  *(ri.f_NegEquNegNodePtr) += ri.G;
923 #else
924 
925  dFdx[ri.li_Pos][ri.APosEquPosNodeOffset] += ri.G;
926 
927  dFdx[ri.li_Pos][ri.APosEquNegNodeOffset] -= ri.G;
928 
929  dFdx[ri.li_Neg][ri.ANegEquPosNodeOffset] -= ri.G;
930 
931  dFdx[ri.li_Neg][ri.ANegEquNegNodeOffset] += ri.G;
932 #endif
933  }
934 
935  return true;
936 }
937 
938 Device *
939 Traits::factory(const Configuration &configuration, const FactoryBlock &factory_block)
940 {
941 
942  return new Master(configuration, factory_block, factory_block.solverState_, factory_block.deviceOptions_);
943 }
944 
945 void
947 {
949  .registerDevice("r", 2)
950  .registerModelType("r", 2);
951 }
952 
953 } // namespace ThermalResistor
954 } // namespace Device
955 } // namespace Xyce