Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_DeviceEntity.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_DeviceEntity.C,v $
27 //
28 // Purpose :
29 //
30 // Special Notes :
31 //
32 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
33 //
34 // Creation Date : 04/03/00
35 //
36 // Revision Information:
37 // ---------------------
38 //
39 // Revision Number: $Revision: 1.234.2.1 $
40 //
41 // Revision Date : $Date: 2014/08/13 20:36:35 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 #include <string>
49 #include <iostream>
50 #include <map>
51 
52 #include <N_DEV_fwd.h>
53 #include <N_DEV_CompositeParam.h>
54 #include <N_DEV_Const.h>
55 #include <N_DEV_DeviceEntity.h>
56 #include <N_DEV_DeviceOptions.h>
57 #include <N_DEV_Message.h>
58 #include <N_DEV_Param.h>
59 #include <N_DEV_SolverState.h>
60 #include <N_LAS_Vector.h>
61 #include <N_UTL_BreakPoint.h>
62 #include <N_UTL_Expression.h>
63 
64 
65 namespace Xyce {
66 namespace Device {
67 
68 //-----------------------------------------------------------------------------
69 // Function : DeviceEntity::DeviceEntity
70 // Purpose : constructor
71 // Special Notes :
72 // Scope : public
73 // Creator : Dave Shirley, PSSI
74 // Creation Date : 12/13/04
75 //-----------------------------------------------------------------------------
77  ParametricData<void> & parametric_data,
78  const SolverState & solver_state,
79  const DeviceOptions & device_options,
80  const std::string & netlist_path,
81  int netlist_line)
82  : parametricData_(parametric_data),
83  solState_(solver_state),
84  globals_(solver_state.getGlobals()),
85  devOptions_(device_options),
86  defaultParamName_(),
87  netlistLocation_(netlist_path, netlist_line)
88 {}
89 
90 //-----------------------------------------------------------------------------
91 // Function : DeviceEntity::~DeviceEntity
92 // Purpose : destructor
93 // Special Notes :
94 // Scope : public
95 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
96 // Creation Date : 3/30/00
97 //-----------------------------------------------------------------------------
99 {
100  for (std::vector<Depend>::iterator d = dependentParams_.begin(), end = dependentParams_.end(); d != end; ++d)
101  {
102  delete d->expr;
103  }
104 }
105 
106 //-----------------------------------------------------------------------------
107 // Function : DeviceEntity::scaleParam
108 //
109 // Purpose : Scales the original value of the specified parameter by the specified value.
110 // The parameter is never specified by the user so errors are developer caused.
111 //
112 // Special Notes :
113 //
114 // Scope : public
115 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
116 // Creation Date : 02/21/04
117 //-----------------------------------------------------------------------------
118 bool DeviceEntity::scaleParam( const std::string & paramName, double val, double val0)
119 {
120  ParameterMap::const_iterator p_i = getParameterMap().find(paramName);
121  if (p_i == getParameterMap().end())
122  {
123  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Unrecognized parameter " << paramName;
124  return false;
125  }
126 
127  const Descriptor &param = *(*p_i).second;
128  if (!param.hasOriginalValueStored())
129  {
130  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Original value not available for parameter " << paramName;
131  return false;
132  }
133 
134  if (!param.isType<double>())
135  {
136  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Can scale only double parameters, parameter " << paramName << " is not double";
137  return false;
138  }
139 
140  // Scale the parameter
141  setValue<double, DeviceEntity>(*this, param, Xyce::Device::getOriginalValue(*this, param.getSerialNumber())*val + val0*(1.0-val));
142 
143  if (param.hasGivenMember())
144  param.setGiven(*this, true);
145 
146  Xyce::Device::setValueGiven(*this, param.getSerialNumber(), true);
147 
148  return true;
149 }
150 
151 //-----------------------------------------------------------------------------
152 // Function : DeviceEntity::scaleParam
153 //
154 // Purpose : Scales the specified parameter by a specified value.
155 // The parameter is never specified by the user so errors are developer caused.
156 //
157 // Special Notes :
158 //
159 // Scope : public
160 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
161 // Creation Date : 02/21/04
162 //-----------------------------------------------------------------------------
163 bool DeviceEntity::scaleParam( const std::string & paramName, double val)
164 {
165  ParameterMap::const_iterator p_i = getParameterMap().find(paramName);
166  if (p_i == getParameterMap().end())
167  {
168  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Unrecognized parameter " << paramName;
169  return false;
170  }
171 
172  const Descriptor &param = *(*p_i).second;
173  if (!param.hasOriginalValueStored())
174  {
175  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Original value not available for parameter " << paramName;
176  return false;
177  }
178 
179  if (!param.isType<double>())
180  {
181  DevelFatal(*this).in("DeviceEntity::scaleParam") << "Can scale only double parameters, parameter " << paramName << " is not double";
182  return false;
183  }
184 
185  // Scale the parameter
186  param.value<double>(*this) = Xyce::Device::getOriginalValue(*this, param.getSerialNumber())*val;
187 
188  if (param.hasGivenMember())
189  param.setGiven(*this, true);
190 
191  Xyce::Device::setValueGiven(*this, param.getSerialNumber(), true);
192 
193  return true;
194 }
195 
196 //-----------------------------------------------------------------------------
197 // Function : DeviceEntity::scaleDefaultParam
198 // Purpose :
199 // The parameter is never specified by the user so errors are developer caused.
200 // Special Notes :
201 // Scope : public
202 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
203 // Creation Date : 5/19/05
204 //-----------------------------------------------------------------------------
206 {
207  if (defaultParamName_.empty())
208  {
209  DevelFatal(*this).in("DeviceEntity::scaleDefaultParam") << "Device does not have a default parameter";
210  return false;
211  }
212 
213  return scaleParam(defaultParamName_, val);
214 }
215 
216 //-----------------------------------------------------------------------------
217 // Function : DeviceEntity::analyticSensitivityAvailable
218 // Purpose :
219 // Special Notes :
220 // Scope : public
221 // Creator : Eric Keiter, SNL
222 // Creation Date : 7/17/2014
223 //-----------------------------------------------------------------------------
224 bool DeviceEntity::analyticSensitivityAvailable (const std::string & paramName)
225 {
226  ParameterMap::const_iterator p_i = getParameterMap().find(paramName);
227  if (p_i == getParameterMap().end())
228  {
229  DevelFatal(*this).in("DeviceEntity::analyticSensitivityAvailable") << "Unrecognized parameter " << paramName;
230  return false;
231  }
232 
233  const Descriptor &param = *(*p_i).second;
234  return param.getAnalyticSensitivityAvailable();
235 }
236 
237 //-----------------------------------------------------------------------------
238 // Function : DeviceEntity::getAnalyticSensitivity
239 // Purpose :
240 // Special Notes :
241 // Scope : public
242 // Creator : Eric Keiter, SNL
243 // Creation Date : 7/17/2014
244 //-----------------------------------------------------------------------------
245 bool DeviceEntity::getAnalyticSensitivity ( const std::string & paramName,
246  std::vector<double> & dfdpVec,
247  std::vector<double> & dqdpVec,
248  std::vector<double> & dbdpVec,
249  std::vector<int> & FindicesVec,
250  std::vector<int> & QindicesVec,
251  std::vector<int> & BindicesVec)
252 {
253  ParameterMap::const_iterator p_i = getParameterMap().find(paramName);
254  if (p_i == getParameterMap().end())
255  {
256  DevelFatal(*this).in("DeviceEntity::analyticSensitivityAvailable") << "Unrecognized parameter " << paramName;
257  return false;
258  }
259 
260  const Descriptor &param = *(*p_i).second;
261 
262  return param.getAnalyticSensitivity (*this, paramName, dfdpVec, dqdpVec, dbdpVec,
263  FindicesVec, QindicesVec, BindicesVec);
264 }
265 
266 //-----------------------------------------------------------------------------
267 // Function : DeviceEntity::setParam
268 //
269 // Purpose : This function loops over the vector of parameters, and
270 // sets the specified one (if found) to a specified value.
271 //
272 // Special Notes : This is kind of tricky, b/c some parameters are actually
273 // deep inside other classes (like a source class, for
274 // example)
275 //
276 // This function always returns a true, b/c there are many
277 // instances, (for example running in parallel), where one
278 // could set a param that didn't exist locally on
279 // processor.
280 //
281 // Scope : public
282 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
283 // Creation Date : 07/25/03
284 //-----------------------------------------------------------------------------
285 bool DeviceEntity::setParam(const std::string & paramName, double val)
286 {
287  ParameterMap::const_iterator p_i = getParameterMap().find(paramName);
288  if (p_i == getParameterMap().end())
289  return false;
290 
291  if (isTempParam(paramName))
292  val += CONSTCtoK;
293 
294  const Descriptor &param = *(*p_i).second;
295 
296  if (param.isType<double>())
297  param.value<double>(*this) = val;
298  else if (param.isType<int>())
299  param.value<int>(*this) = static_cast <int> (val);
300  else if (param.isType<long>())
301  param.value<long>(*this) = static_cast <long> (val);
302  else if (param.isType<bool>())
303  param.value<bool>(*this) = (val != 0);
304  else
305  DevelFatal0(*this) << "Illegal type for parameter " << paramName;
306 
307  if (param.hasGivenMember())
308  param.setGiven(*this, true);
309 
310  Xyce::Device::setValueGiven(*this, param.getSerialNumber(), true);
311 
312  return true;
313 }
314 
315 //-----------------------------------------------------------------------------
316 // Function : DeviceEntity::getParam
317 //
318 // Purpose : returns the value of the requested param.
319 //
320 // Special Notes : This function currently assumes that the requested
321 // param is a double-precision number.
322 //
323 // Parameters are not case-dependent.
324 //
325 // Scope : public
326 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
327 // Creation Date : 07/25/03
328 //-----------------------------------------------------------------------------
329 bool
331  const std::string & name,
332  double & result) const
333 {
334  double val = 0.0;
335  bool found = false;
336 
337  ParameterMap::const_iterator p_i = getParameterMap().find(name);
338  if (p_i != getParameterMap().end())
339  {
340  found = true;
341  const Descriptor &param = *(*p_i).second;
342  if (param.isType<double>())
343  val = param.value<double>(*this);
344  else if (param.isType<int>())
345  val = static_cast <double> (param.value<int>(*this));
346  else if (param.isType<long>())
347  val = static_cast <double> (param.value<long>(*this));
348  else if (param.isType<bool>())
349  {
350  if (param.value<bool>(*this))
351  val = 1;
352  else
353  val = 0;
354  }
355  else
356  {
357  DevelFatal(*this).in("DeviceEntity::getParam") << "Illegal type for parameter " << name;
358  }
359  if (isTempParam(name))
360  val -= CONSTCtoK;
361  }
362  else
363  {
364  // If not recognized, just do nothing
365  }
366  result = val;
367 
368  return found;
369 }
370 
371 //-----------------------------------------------------------------------------
372 // Function : DeviceEntity::setDefaultParam
373 // Purpose :
374 // Special Notes :
375 // Scope : public
376 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
377 // Creation Date : 11/06/03
378 //-----------------------------------------------------------------------------
380 {
381  if (defaultParamName_.empty())
382  {
383  DevelFatal(*this).in("DeviceEntity::setDefaultParam") << "Device does not have a default parameter";
384  }
385 
386  return setParam(defaultParamName_, val);
387 }
388 
389 //-----------------------------------------------------------------------------
390 // Function : DeviceEntity::getDefaultParam
391 // Purpose :
392 // Special Notes :
393 // Scope : public
394 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
395 // Creation Date : 11/06/03
396 //-----------------------------------------------------------------------------
398 {
399  if (defaultParamName_.empty())
400  {
401  return 0.0;
402  }
403 
404  double result = 0.0;
405 
406  getParam(defaultParamName_, result);
407 
408  return result;
409 }
410 
411 //-----------------------------------------------------------------------------
412 // Function : DeviceEntity::setDependentParameter
413 // Purpose : Add expression, param pairs for future updates
414 // Special Notes : This is an overloaded method, used instead of the old
415 // monolithic one.
416 // Scope : protected
417 // Creator : Tom Russo
418 // Creation Date : 6 Nov 07
419 //-----------------------------------------------------------------------------
420 double DeviceEntity::setDependentParameter (Util::Param & par,
421  double *res,
423 
424 {
425  Depend dependentParam;
426  setDependentParameter(par, dependentParam, depend);
427 
428  dependentParam.resultU.result = res;
429  dependentParam.vectorIndex = -1;
430  dependentParams_.push_back(dependentParam);
431 
432  double rval;
433  dependentParam.expr->evaluateFunction (rval);
434  dependentParam.expr->set_sim_time( getSolverState().currTime );
435 
436  return rval;
437 }
438 
439 //-----------------------------------------------------------------------------
440 // Function : DeviceEntity::setDependentParameter
441 // Purpose : Add expression, param pairs for future updates
442 // Special Notes : This is an overloaded method, used instead of the old
443 // monolithic one, and is specifically to set an element
444 // of a double vector.
445 // Scope : protected
446 // Creator : Tom Russo
447 // Creation Date : 6 Nov 07
448 //-----------------------------------------------------------------------------
449 double DeviceEntity::setDependentParameter (Util::Param & par,
450  std::vector<double> *res,
451  int ind,
453 
454 {
455  Depend dependentParam;
456  setDependentParameter(par,dependentParam, depend);
457 
458  dependentParam.resultU.resVec = res;
459  dependentParam.vectorIndex = ind;
460  dependentParams_.push_back(dependentParam);
461 
462  double rval;
463  dependentParam.expr->evaluateFunction (rval);
464  dependentParam.expr->set_sim_time(getSolverState().currTime);
465 
466  return rval;
467 }
468 
469 //-----------------------------------------------------------------------------
470 // Function : DeviceEntity::setDependentParameter
471 // Purpose : Add expression, param pairs for future updates
472 // Special Notes : This is a utility version, used by overloaded methods.
473 // Scope : protected
474 // Creator : Dave Shirley, PSSI
475 // Creation Date : 11/18/04
476 //-----------------------------------------------------------------------------
477 
478 void DeviceEntity::setDependentParameter (Util::Param & par,
479  Depend & dependentParam,
481 {
482  std::vector<std::string> instances, leads, names, variables;
483 
484  dependentParam.name = par.tag();
485  if (isTempParam(par.tag()))
486  {
487  dependentParam.expr = new Util::Expression ("(" + par.stringValue() + ")+CONSTCtoK");
488  dependentParam.expr->make_constant (std::string("CONSTCTOK"), CONSTCtoK);
489  }
490  else
491  {
492  dependentParam.expr = new Util::Expression (par.getValue<Util::Expression>());
493  }
494 
495  names.clear();
496  leads.clear();
497  instances.clear();
498  variables.clear();
499 
500  dependentParam.expr->get_names(XEXP_NODE, names);
501  dependentParam.expr->get_names(XEXP_LEAD, leads);
502  dependentParam.expr->get_names(XEXP_INSTANCE, instances);
503  dependentParam.expr->get_names(XEXP_VARIABLE, variables);
504 
505  //std::vector<std::string>::iterator s;
506  std::vector<std::string>::iterator iterS;
507 
508  if (!(depend & ParameterType::SOLN_DEP))
509  {
510  if (names.size() > 0 || instances.size() > 0)
511  {
512  UserError0(*this) << "Parameter " << par.tag() << " is not allowed to depend on voltage/current values";
513  return;
514  }
515  if (depend & ParameterType::NO_DEP)
516  {
517  if (dependentParam.expr->get_num(XEXP_SPECIAL) > 0)
518  {
519  UserError0(*this) << "Parameter " << par.tag() << " is not allowed to depend on time";
520  return;
521  }
522  }
523  }
524 
525  if (leads.size() > 0)
526  {
527  char type;
528  int index;
529  for (std::vector<std::string>::const_iterator n_i=leads.begin(); n_i != leads.end(); ++n_i)
530  {
531  index = n_i->find_last_of(":");
532  if (index == std::string::npos )
533  type = (*n_i)[0];
534  else
535  type = (*n_i)[index+1];
536 
537  if (type != 'B' && type != 'E' && type != 'H')
538  {
539  UserError(*this) << "Illegal use of lead current specification in expression '" << dependentParam.expr->get_expression()
540  << "' in parameter " << par.tag();
541  }
542  }
543  names.insert( names.end(), leads.begin(), leads.end() );
544  }
545 
546  names.insert( names.end(), instances.begin(), instances.end() );
547 
548  dependentParam.lo_var = expVarNames.size();
549  dependentParam.n_vars = names.size();
550  dependentParam.vals.resize(dependentParam.n_vars);
551  int expVarLen = dependentParam.lo_var+dependentParam.n_vars;
552  expVarGIDs.resize(expVarLen);
553  expVarLIDs.resize(expVarLen);
554  expVarVals.resize(expVarLen);
555 
556  if (!variables.empty())
557  names.insert( names.end(), variables.begin(), variables.end() );
558 
559  if ( !names.empty() )
560  {
561  // Order the names in the expression so that it agrees with the order
562  // in names.
563  dependentParam.expr->order_names( names );
564  }
565  for (int i=0 ; i<dependentParam.n_vars ; ++i)
566  expVarNames.push_back(names[i]);
567 
568  if (dependentParam.n_vars > 0)
569  {
570  std::vector<double> zeros;
571  zeros.resize(dependentParam.n_vars);
572  for (int i=0 ; i<dependentParam.n_vars ; ++i)
573  zeros[i] = 0;
574  dependentParam.expr->set_vars(zeros);
575  }
576 
577  dependentParam.global_params.clear();
578  if (!variables.empty())
579  {
580  for (iterS=variables.begin() ; iterS!=variables.end() ; ++iterS)
581  {
582  GlobalParameterMap::iterator global_param_it = globals_.global_params.find(*iterS);
583  if (global_param_it == globals_.global_params.end())
584  {
585  UserError0(*this) << "Global parameter " << *iterS << " not found";
586  }
587  else {
588  dependentParam.expr->set_var(*iterS, (*global_param_it).second);
589  dependentParam.global_params.push_back(*iterS);
590  }
591  }
592  }
593 }
594 
595 //-----------------------------------------------------------------------------
596 // Function : DeviceEntity::updateDependentParameters
597 // Purpose : Update values of parameters defined as expressions
598 // Special Notes :
599 // Scope : protected
600 // Creator : Dave Shirley, PSSI
601 // Creation Date : 03/15/05
602 //-----------------------------------------------------------------------------
604 {
605  std::vector<Depend>::iterator dpIter = dependentParams_.begin();
606  std::vector<Depend>::iterator end = dependentParams_.end();
607  double rval(0.0);
608  bool changed = false;
609 
610  for ( ; dpIter != end ; ++dpIter)
611  {
612  if (dpIter->expr->set_sim_time( getSolverState().currTime ))
613  changed = true;
614  eVarVals.resize(dpIter->n_vars);
615  if (dpIter->n_vars > 0)
616  {
617  int hi = dpIter->lo_var+dpIter->n_vars;
618  for (int i = dpIter->lo_var; i < hi; ++i)
619  {
620  expVarVals[i] = vars[expVarLIDs[i]];
621  eVarVals[i-dpIter->lo_var] = expVarVals[i];
622  }
623  if (dpIter->expr->set_vars(eVarVals))
624  changed = true;
625  }
626  dpIter->expr->evaluateFunction (rval);
627  if (dpIter->vectorIndex==-1)
628  *(dpIter->resultU.result) = rval;
629  else
630  (*(dpIter->resultU.resVec))[dpIter->vectorIndex] = rval;
631  }
632 
633  return changed;
634 }
635 
636 //-----------------------------------------------------------------------------
637 // Function : DeviceEntity::updateGlobalParameters
638 // Purpose : Update values of global parameters in expressions
639 // Special Notes :
640 // Scope : protected
641 // Creator : Dave Shirley, PSSI
642 // Creation Date : 11/17/05
643 //-----------------------------------------------------------------------------
645 {
646  std::vector<Depend>::iterator dpIter = dependentParams_.begin();
647  std::vector<Depend>::iterator end = dependentParams_.end();
648  double rval;
649  int i, hi;
650  bool changed = false;
651 
652  for ( ; dpIter != end ; ++dpIter)
653  {
654  if (!dpIter->global_params.empty())
655  {
656  std::vector<std::string>::iterator gp=dpIter->global_params.begin();
657  std::vector<std::string>::iterator gend=dpIter->global_params.end();
658  for ( ; gp != gend; ++gp)
659  {
660  if (global_map.find(*gp) == global_map.end())
661  {
662  DevelFatal(*this).in("DeviceEntity::updateGlobalParameters") << "Failed to find global parameter " << *gp;
663  }
664  if (dpIter->expr->set_var(*gp, global_map[*gp]))
665  changed = true;
666  }
667  }
668  }
669 
670  return changed;
671 }
672 
673 //-----------------------------------------------------------------------------
674 // Function : DeviceEntity::updateDependentParameters
675 // Purpose : Update values of parameters defined as expressions
676 // Special Notes :
677 // Scope : protected
678 // Creator : Dave Shirley, PSSI
679 // Creation Date : 11/18/04
680 //-----------------------------------------------------------------------------
682 {
683  double rval;
684  bool changed = false;
685 
686  std::vector<Depend>::iterator dpIter = dependentParams_.begin();
687  std::vector<Depend>::iterator end = dependentParams_.end();
688  for ( ; dpIter != end; ++dpIter)
689  {
690  if (dpIter->expr->set_sim_time( getSolverState().currTime ))
691  changed = true;
692  dpIter->expr->evaluateFunction (rval);
693  if (dpIter->vectorIndex == -1)
694  *(dpIter->resultU.result) = rval;
695  else
696  (*(dpIter->resultU.resVec))[dpIter->vectorIndex] = rval;
697  }
698 
699  return changed;
700 }
701 
702 //-----------------------------------------------------------------------------
703 // Function : DeviceEntity::updateDependentParameters
704 // Purpose : Update values of parameters defined as expressions with a
705 // specified temperature
706 // Special Notes :
707 // Scope : protected
708 // Creator : Dave Shirley, PSSI
709 // Creation Date : 01/11/06
710 //-----------------------------------------------------------------------------
712 {
713  double rval;
714  bool changed = false;
715 
716  std::vector<Depend>::iterator dpIter = dependentParams_.begin();
717  std::vector<Depend>::iterator end = dependentParams_.end();
718  for ( ; dpIter != end; ++dpIter)
719  {
720  if (dpIter->expr->set_sim_time( getSolverState().currTime ) || dpIter->expr->set_temp(tempIn))
721  changed = true;
722  dpIter->expr->evaluateFunction (rval);
723  if (dpIter->vectorIndex == -1)
724  *(dpIter->resultU.result) = rval;
725  else
726  (*(dpIter->resultU.resVec))[dpIter->vectorIndex] = rval;
727 
728  }
729 
730  return changed;
731 }
732 
733 //-----------------------------------------------------------------------------
734 // Function : DeviceEntity::getParamBreakpoints
735 // Purpose : Add breakpoints caused by discontinuities in computed params
736 // Special Notes :
737 // Scope : protected
738 // Creator : Dave Shirley, PSSI
739 // Creation Date : 11/18/04
740 //-----------------------------------------------------------------------------
741 bool DeviceEntity::getParamBreakpoints( std::vector<Util::BreakPoint> & breakPointTimes )
742 {
743  double bTime;
744 
745  std::vector<Depend>::iterator dpIter = dependentParams_.begin();
746  std::vector<Depend>::iterator end = dependentParams_.end();
747  for ( ; dpIter != end; ++dpIter)
748  {
749  bTime = dpIter->expr->get_break_time();
750  if (bTime > getSolverState().currTime)
751  breakPointTimes.push_back(bTime);
752  }
753 
754  return true;
755 }
756 
757 //-----------------------------------------------------------------------------
758 // Function : DeviceEntity::given
759 // Purpose : Return whether param was given
760 // Special Notes :
761 // Scope : protected
762 // Creator : Dave Shirley, PSSI
763 // Creation Date : 11/23/04
764 //-----------------------------------------------------------------------------
765 bool DeviceEntity::given( const std::string & parameter_name ) const
766 {
767  ParameterMap::const_iterator it = getParameterMap().find(parameter_name);
768  if (it == getParameterMap().end())
769  DevelFatal0(*this).in("DeviceEntity::given") << "Unrecognized parameter " << parameter_name;
770 
771  return Xyce::Device::wasValueGiven(*this, (*it).second->getSerialNumber());
772 }
773 
774 //-----------------------------------------------------------------------------
775 // Function : setParameters
776 // Purpose : Set parameters according to a vector of params. Used to
777 // set instance or model parameter sets to netlist values
778 // Special Notes :
779 // Scope : protected
780 // Creator : Dave Shirley, PSSI
781 // Creation Date : 11/20/04
782 //-----------------------------------------------------------------------------
783 void setParameters(DeviceEntity &entity, std::vector<Param>::const_iterator begin, std::vector<Param>::const_iterator end, const DeviceOptions &device_options)
784 {
785  std::vector<std::string> composite_name_list;
786  std::map<std::string, std::vector<CompositeParam *>, LessNoCase> composite_parameter_map;
787 
788  if (DEBUG_DEVICE && device_options.debugLevel > 0)
789  {
790  Xyce::dout() << std::endl << "In DeviceEntity::setParams, for ";
791  entity.printName(Xyce::dout());
792  Xyce::dout() << " parameters are:" << std::endl;
793  for (std::vector<Param>::const_iterator it = begin; it != end; ++it)
794  {
795  const Param &param = *it;
796  Xyce::dout() << "Param = " << param.tag() << ", Type = ";
797  int tmpType = param.getType();
798  switch (tmpType)
799  {
800  case Util::STR:
801  Xyce::dout() << "STR";
802  break;
803  case Util::DBLE:
804  Xyce::dout() << "DBLE";
805  break;
806  case Util::INT:
807  Xyce::dout() << "INT";
808  break;
809  case Util::LNG:
810  Xyce::dout() << "LNG";
811  break;
812  case Util::EXPR:
813  Xyce::dout() << "EXPR";
814  break;
815  case Util::BOOL:
816  Xyce::dout() << "BOOL";
817  break;
818  case Util::STR_VEC:
819  Xyce::dout() << "STR_VEC";
820  break;
821  case Util::INT_VEC:
822  Xyce::dout() << "INT_VEC";
823  break;
824  case Util::DBLE_VEC:
825  Xyce::dout() << "DBLE_VEC";
826  break;
827  case Util::DBLE_VEC_IND:
828  Xyce::dout() << "DBLE_VEC_IND";
829  break;
830  case Util::COMPOSITE:
831  Xyce::dout() << "COMPOSITE";
832  break;
833  default:
834  Xyce::dout() << "Unknown";
835  }
836  Xyce::dout() << ", Value = " << param.stringValue();
837 
838  if (param.given())
839  {
840  Xyce::dout() << " given=TRUE";
841  }
842  else
843  {
844  Xyce::dout() << " given=FALSE";
845  }
846 
847  if (param.default_val())
848  {
849  Xyce::dout() << " default=TRUE" << std::endl;
850  }
851  else
852  {
853  Xyce::dout() << " default=FALSE" << std::endl;
854  }
855  }
856  Xyce::dout() << std::endl;
857  }
858 
859  for (std::vector<Param>::const_iterator param_it = begin; param_it != end; ++param_it)
860  {
861  Param &param = const_cast<Param &>(*param_it);
862 
863  const std::string &tag = param.tag();
864 
865  // Is this parameter in the Entity?
866  ParameterMap::const_iterator entity_parameter_it = entity.getParameterMap().find(tag);
867  if (entity_parameter_it != entity.getParameterMap().end())
868  {
869  const Descriptor &descriptor = *(*entity_parameter_it).second;
870  if (descriptor.hasGivenMember())
871  {
872  if (param.given())
873  {
874  descriptor.setGiven(entity, true);
875  }
876  else if (descriptor.getGiven(entity))
877  {
878  continue;
879  }
880  }
881 
882  Xyce::Device::setValueGiven(entity, descriptor.getSerialNumber(), param.given());
883  if (param.given() || param.default_val())
884  {
885  if ( param.getType() == Util::EXPR )
886  {
887  if (descriptor.isType<double>())
888  {
889  double val = entity.setDependentParameter(param, &(descriptor.value<double>(entity)), descriptor.getExpressionAccess());
890  param.setVal(val);
891  }
892  else if (descriptor.isType<std::vector<double> >())
893  {
894  int ind = (descriptor.value<std::vector<double> >(entity)).size();
895  double val = entity.setDependentParameter (param, &(descriptor.value<std::vector<double> >(entity)), ind, descriptor.getExpressionAccess());
896  (descriptor.value<std::vector<double> >(entity)).push_back(val);
897  }
898  else
899  {
900  DevelFatal(entity).in("DeviceEntity::setParams") << "Non double param " << tag << " cannot be set to expression";
901  }
902  }
903  else
904  {
905  if (descriptor.isType<double>())
906  {
907  if (!param.isNumeric())
908  {
909  UserError(entity) << "Cannot convert parameter " << tag << " to a numeric value from " << param.stringValue();
910  continue;
911  }
912 
913  descriptor.value<double>(entity) = param.getImmutableValue<double>();
914  if (isTempParam(tag))
915  {
916  descriptor.value<double>(entity) += CONSTCtoK;
917  }
918  if (descriptor.hasOriginalValueStored())
919  {
920  Xyce::Device::setOriginalValue(entity, descriptor.getSerialNumber(), descriptor.value<double>(entity));
921  }
922  }
923  else if (descriptor.isType<std::string>())
924  {
925  descriptor.value<std::string>(entity) = param.stringValue();
926  }
927  else if (descriptor.isType<int>())
928  {
929  if (!param.isInteger())
930  {
931  UserError(entity) << "Cannot convert parameter " << tag << " to an integer value from " << param.stringValue();
932  continue;
933  }
934  descriptor.value<int>(entity) = param.getImmutableValue<int>();
935  if (descriptor.hasOriginalValueStored())
936  {
937  Xyce::Device::setOriginalValue(entity, descriptor.getSerialNumber(), static_cast<double> (descriptor.value<int>(entity)));
938  }
939  }
940  else if (descriptor.isType<long>())
941  {
942  if (!param.isInteger())
943  {
944  UserError(entity) << "Cannot convert parameter " << tag << " to an integer value from " << param.stringValue();
945  continue;
946  }
947  descriptor.value<long>(entity) = param.getImmutableValue<long>();
948  if (descriptor.hasOriginalValueStored())
949  {
950  Xyce::Device::setOriginalValue(entity, descriptor.getSerialNumber(), static_cast<double> (descriptor.value<long>(entity)));
951  }
952  }
953  else if (descriptor.isType<bool>())
954  {
955  if (!param.isBool())
956  {
957  UserError(entity) << "Cannot convert parameter " << tag << " to a logical value from " << param.stringValue();
958  continue;
959  }
960  descriptor.value<bool>(entity) = param.getImmutableValue<bool>();
961  if (descriptor.hasOriginalValueStored())
962  {
963  if (descriptor.value<bool>(entity))
964  {
965  Xyce::Device::setOriginalValue(entity, descriptor.getSerialNumber(), 1.0);
966  }
967  else
968  {
969  Xyce::Device::setOriginalValue(entity, descriptor.getSerialNumber(), 0.0);
970  }
971  }
972  }
973  else if (descriptor.isType<std::vector<int> >())
974  {
975  if (param.getType() == Util::INT_VEC)
976  {
977  (descriptor.value<std::vector<int> >(entity)) = param.getValue<std::vector<int> >();
978  }
979  else if (param.getType() == Util::INT)
980  {
981  (descriptor.value<std::vector<int> >(entity)).push_back(param.getImmutableValue<int>());
982  }
983  }
984  else if (descriptor.isType<std::vector<double> >())
985  {
986  if (param.getType() == Util::DBLE_VEC)
987  {
988  (descriptor.value<std::vector<double> >(entity)) = param.getValue<std::vector<double> >();
989  }
990  else if (param.getType() == Util::DBLE)
991  {
992  (descriptor.value<std::vector<double> >(entity)).push_back(param.getImmutableValue<double>());
993  }
994  }
995  else if (descriptor.isType<std::vector<std::string> >())
996  {
997  if (param.getType() == Util::STR_VEC)
998  {
999  (descriptor.value<std::vector<std::string> >(entity)) = param.getValue<std::vector<std::string> >();
1000  }
1001  else if (param.getType() == Util::STR)
1002  {
1003  (descriptor.value<std::vector<std::string> >(entity)).push_back(param.stringValue());
1004  }
1005  }
1006  else if (descriptor.hasCompositeData())
1007  {
1008  composite_parameter_map[tag].clear();
1009  composite_name_list.push_back(tag);
1010 
1011  // Note: ERK. This push-back is done to process the base-param tag of a vector composite.
1012  // For example, if the composite parameters are things like REGION0.XWIDTH, where REGION
1013  // is the base parameter tag, 0 is the index, and XWIDTH is the subcomponent, the
1014  // tag that should be pushed back is tagES=REGION.
1015  //
1016  // Note: ERK: This function seems to implicitly rely on the base parameter always preceeding
1017  // subcomponent parameters. So REGION (alone) should preceed REGION0.XWIDTH in the
1018  // STL vector params that is passed into this function. If it doesn't then vc_stat will
1019  // stay false and a fatal error will get thrown.
1020  if (DEBUG_DEVICE && device_options.debugLevel > 0)
1021  {
1022  Xyce::dout() << "pushing back composite " << tag << std::endl;
1023  }
1024  }
1025  else
1026  {
1027  DevelFatal(entity).in("DeviceEntity::setParams") << "Unknown type";
1028  }
1029  }
1030  }
1031  }
1032 
1033  // Is it a vector (why do nothing?)
1034  else if (param.stringValue() == "VECTOR")
1035  {
1036  }
1037 
1038  // Must be a composite
1039  else
1040  {
1041  bool vc_stat = false;
1042 
1043  std::string::size_type dot = tag.find_first_of('.');
1044  if (dot != std::string::npos)
1045  {
1046  for (std::vector<std::string>::const_iterator it = composite_name_list.begin(); it != composite_name_list.end(); ++it)
1047  {
1048  const std::string &composite_name = *it;
1049 
1050  if (tag.find(composite_name) == 0) // Tag starts with the composite parameter name
1051  {
1052  std::string param_name(tag.begin() + dot + 1, tag.end());
1053 
1054  vc_stat = true;
1055 
1056  int n = 0;
1057  {
1058  std::istringstream is(std::string(tag.begin() + composite_name.size(), tag.begin() + dot));
1059  is >> n;
1060  }
1061 
1062  if (param_name == "NAME")
1063  {
1064  if (n != composite_parameter_map[composite_name].size())
1065  {
1066  DevelFatal(entity).in("DeviceEntity::setParams") << "Error filling 'NAME' vector param " << composite_name;
1067  }
1068 
1069  std::string name = param.stringValue();
1070  CompositeParam *composite = entity.constructComposite(composite_name, name);
1071  composite_parameter_map[composite_name].push_back(composite);
1072  setDefaultParameters(*composite, composite->getParameterMap().begin(), composite->getParameterMap().end(), device_options);
1073  }
1074  else
1075  {
1076  if (n >= composite_parameter_map[composite_name].size())
1077  {
1078  DevelFatal(entity).in("DeviceEntity::setParams") << "Internal error in vector-composite, 'NAME' must come first " << composite_name;
1079  }
1080  }
1081  Xyce::Device::setParameters(*composite_parameter_map[composite_name][n], param_name, param);
1082  }
1083  }
1084  }
1085  if (!vc_stat)
1086  {
1087  DevelFatal(entity) << "Undefined parameter " << tag << ", this parameter is in metadata, but not recognized in constructor";
1088  }
1089  }
1090  }
1091 
1092  if (!composite_name_list.empty())
1093  {
1094  for (std::vector<std::string>::const_iterator name_it = composite_name_list.begin(); name_it != composite_name_list.end(); ++name_it)
1095  {
1096  const std::string &vcs = *name_it;
1097 
1098  for (std::vector<CompositeParam *>::iterator it = composite_parameter_map[vcs].begin(); it != composite_parameter_map[vcs].end(); ++it)
1099  {
1100  (*it)->processParams();
1101  }
1102  }
1103  }
1104 }
1105 
1106 
1107 //-----------------------------------------------------------------------------
1108 // Function : setParameters
1109 // Purpose : Set parameter according to input Param. Used to
1110 // set instance or model parameter sets to netlist values
1111 // Special Notes :
1112 // Scope : public
1113 // Creator : Dave Shirley, PSSI
1114 // Creation Date : 05/06/05
1115 //-----------------------------------------------------------------------------
1116 
1117 void setParameters(CompositeParam &composite_param, const std::string & pName, const Param & ndParam )
1118 {
1119  ParameterMap::const_iterator p_i = composite_param.getParameterMap().find(pName);
1120  if (p_i != composite_param.getParameterMap().end())
1121  {
1122  const Descriptor &p = *(*p_i).second;
1123  if (p.hasGivenMember())
1124  {
1125  if (ndParam.given())
1126  p.setGiven(composite_param, true);
1127  else if (p.getGiven(composite_param))
1128  return;
1129  }
1130  Xyce::Device::setValueGiven(composite_param, p.getSerialNumber(), ndParam.given());
1131  if (ndParam.given() || ndParam.default_val())
1132  {
1133  if (p.isType<double>())
1134  {
1135  p.value<double>(composite_param) = ndParam.getImmutableValue<double>();
1136  if (isTempParam(pName))
1137  p.value<double>(composite_param) += CONSTCtoK;
1138  if (p.hasOriginalValueStored())
1139  Xyce::Device::setOriginalValue(composite_param, p.getSerialNumber(), p.value<double>(composite_param));
1140  }
1141  else if (p.isType<std::string>())
1142  {
1143  p.value<std::string>(composite_param) = ndParam.stringValue();
1144  }
1145  else if (p.isType<int>())
1146  {
1147  p.value<int>(composite_param) = ndParam.getImmutableValue<int>();
1148  if (p.hasOriginalValueStored())
1149  Xyce::Device::setOriginalValue(composite_param, p.getSerialNumber(), static_cast<double>(p.value<int>(composite_param)));
1150  }
1151  else if (p.isType<long>())
1152  {
1153  p.value<long>(composite_param) = ndParam.getImmutableValue<long>();
1154  if (p.hasOriginalValueStored())
1155  Xyce::Device::setOriginalValue(composite_param, p.getSerialNumber(), static_cast<double>(p.value<long>(composite_param)));
1156  }
1157  else if (p.isType<bool>())
1158  {
1159  p.value<bool>(composite_param) = (ndParam.getImmutableValue<double>() != 0.0);
1160  if (p.hasOriginalValueStored())
1161  {
1162  if (p.value<bool>(composite_param))
1163  Xyce::Device::setOriginalValue(composite_param, p.getSerialNumber(), 1.0);
1164  else
1165  Xyce::Device::setOriginalValue(composite_param, p.getSerialNumber(), 0.0);
1166  }
1167  }
1168  else if (p.isType<std::vector<double> >())
1169  {
1170  (p.value<std::vector<double> >(composite_param)).push_back(ndParam.getImmutableValue<double>());
1171  }
1172  else if (p.isType<std::vector<std::string> >())
1173  {
1174  p.value<std::vector<std::string> >(composite_param).push_back(ndParam.stringValue());
1175  }
1176  else
1177  {
1178  Report::DevelFatal().in("CompositeParam::setParams") << "Unknown parameter type for " << pName;
1179  }
1180  }
1181  }
1182  else
1183  {
1184  Report::DevelFatal().in("CompositeParam::setParams") << "Undefined parameter " << pName << std::endl
1185  << "This parameter is in metadata, but not recognized in constructor";
1186  }
1187 }
1188 
1189 
1190 void populateParams(const ParameterMap &parameter_map, std::vector<Param> &param_list, CompositeParamMap &composite_param_map)
1191 {
1192  for (ParameterMap::const_iterator it = parameter_map.begin(); it != parameter_map.end(); ++it)
1193  {
1194  const Descriptor &param = *(*it).second;
1195 
1196  if (param.isType<double>())
1197  {
1198  if (param.getVec() == 0)
1199  {
1200  double val;
1201  if (isTempParam((*it).first))
1202  val = getDefaultValue<double>(param) - CONSTCtoK;
1203  else
1204  val = getDefaultValue<double>(param);
1205  param_list.push_back(Param((*it).first, val));
1206  }
1207  else if (param.getVec() > 0)
1208  {
1209  if (param.getVec() == 1)
1210  {
1211  // This converts parameters link IC1, IC2 to just IC and type vector
1212  std::string vPar((*it).first.substr(0, (*it).first.size()-1));
1213  param_list.push_back(Param(vPar, "VECTOR"));
1214  }
1215  // We will also output IC1, IC2 as type double so they can
1216  // be specified as individual elements
1217  // This allows TC=a, b to also be specified as TC1=a TC2=b
1218  double val = getDefaultValue<double>(param);
1219  param_list.push_back(Param((*it).first, val));
1220  }
1221  }
1222  else if (param.isType<bool>())
1223  {
1224  if (param.getVec() == 0)
1225  param_list.push_back(Param((*it).first, getDefaultValue<bool>(param)));
1226  else if (param.getVec() > 0)
1227  {
1228  if (param.getVec() == 1)
1229  {
1230  std::string vPar((*it).first.substr(0, (*it).first.size()-1));
1231  param_list.push_back(Param(vPar, "VECTOR"));
1232  }
1233  // We will also output IC1, IC2 as type double so they can
1234  // be specified as individual elements
1235  // This allows TC=a, b to also be specified as TC1=a TC2=b
1236  bool val = getDefaultValue<bool>(param);
1237  param_list.push_back(Param((*it).first, val));
1238  }
1239  }
1240  else if (param.isType<int>())
1241  {
1242  if (param.getVec() == 0)
1243  param_list.push_back(Param((*it).first, getDefaultValue<int>(param)));
1244  else if (param.getVec() > 0)
1245  {
1246  if (param.getVec() == 1)
1247  {
1248  std::string vPar((*it).first.substr(0, (*it).first.size()-1));
1249  param_list.push_back(Param(vPar, "VECTOR"));
1250  }
1251  int val = getDefaultValue<int>(param);
1252  param_list.push_back(Param((*it).first, val));
1253  }
1254  }
1255  else if (param.isType<std::string>())
1256  {
1257  if (param.getVec() == 0)
1258  param_list.push_back(Param((*it).first, getDefaultValue<std::string>(param)));
1259  else if (param.getVec() > 0)
1260  {
1261  if (param.getVec() == 1)
1262  {
1263  std::string vPar((*it).first.substr(0, (*it).first.size()-1));
1264  param_list.push_back(Param(vPar, "VECTOR"));
1265  }
1266  std::string val = getDefaultValue<std::string>(param);
1267  param_list.push_back(Param((*it).first, val));
1268  }
1269  }
1270  else if (param.isType<std::vector<std::string> >())
1271  {
1272  Param vc((*it).first, std::vector<std::string>()); // param.value<std::vector<std::string> >(entity));
1273  param_list.push_back(vc);
1274  }
1275  else if (param.isType<std::vector<double> >())
1276  {
1277  Param vc((*it).first, std::vector<double>()); // param.value<std::vector<double> >(entity));
1278  param_list.push_back(vc);
1279  }
1280  else if (param.hasCompositeData())
1281  {
1282  Param vc2((*it).first, "VECTOR-COMPOSITE");
1283  vc2.setDefault(true);
1284  param_list.push_back(vc2);
1285 
1286  std::vector<Param> compositeParams;
1288 
1289  if (c == 0)
1290  {
1291  Report::DevelFatal().in("populateParams") << "Vector-composite map for device type entity empty.";
1292  }
1293 
1294  // TODO: [DGB] I think when the Descriptor is refactored this will be clearer. But this basically adds the
1295  // type to the composite list with 'NAME' first.
1296  const ParametricData<CompositeParam> &d = *c;
1297  const ParameterMap &e = d.getMap();
1298 
1299  for (ParameterMap::const_iterator it4 = e.find("NAME"); it4 != e.end();) {
1300  const Descriptor &p = *(*it4).second;
1301  if (p.isType<double>())
1302  compositeParams.push_back(Param((*it4).first, getDefaultValue<double>(p)));
1303  else if (p.isType<bool>())
1304  compositeParams.push_back(Param((*it4).first, getDefaultValue<bool>(p)));
1305  else if (p.isType<int>())
1306  compositeParams.push_back(Param((*it4).first, getDefaultValue<int>(p)));
1307  else if (p.isType<std::string>())
1308  compositeParams.push_back(Param((*it4).first, getDefaultValue<std::string>(p)));
1309  if ((*it4).first == "NAME")
1310  it4 = e.begin();
1311  else
1312  it4++;
1313  if (it4 != e.end() && (*it4).first == "NAME")
1314  it4++;
1315  }
1316 
1317  composite_param_map[(*it).first] = compositeParams;
1318  }
1319  else
1320  {
1321 // Just skip these, like list of coupled inductors because not needed for metadata
1322 // std::string msg("DeviceEntity::getParams: Type not supported");
1323 // N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL, msg);
1324  Xyce::dout() << "In final else clause of DeviceEntity::getParams().";
1325  if( param.isType<std::vector<std::string> >() )
1326  Xyce::dout() << " type is STR_VEC ";
1327  if( param.isType<std::vector<double> >() )
1328  Xyce::dout() << " type is DBLE_VEC ";
1329  Xyce::dout() << it->first << " this item is NOT being added to default parameter list." << std::endl;
1330  }
1331  }
1332 }
1333 
1334 } // namespace Device
1335 } // namespace Xyce