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