Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
N_DEV_DeviceMgr.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_DeviceMgr.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.597.2.2 $
40 //
41 // Revision Date : $Date: 2014/03/11 18:50:03 $
42 //
43 // Current Owner : $Author: dgbaur $
44 //-------------------------------------------------------------------------
45 
46 #include <Xyce_config.h>
47 
48 #include <algorithm>
49 #include <sstream>
50 #include <stdexcept>
51 
52 #include <N_DEV_DeviceMgr.h>
53 
54 #include <N_UTL_Algorithm.h>
55 
56 #include <N_DEV_Const.h>
57 #include <N_DEV_Source.h>
58 #include <N_DEV_RegisterDevices.h>
60 #include <N_DEV_Algorithm.h>
61 #include <N_DEV_Print.h>
62 
63 #include <N_DEV_ADC.h>
64 #include <N_DEV_BJT.h>
65 #include <N_DEV_Bsrc.h>
66 #include <N_DEV_DAC.h>
67 #include <N_DEV_Diode.h>
68 #include <N_DEV_ISRC.h>
69 #include <N_DEV_MOSFET1.h>
70 #include <N_DEV_MOSFET_B3.h>
71 #include <N_DEV_MOSFET_B3SOI.h>
72 #include <N_DEV_MOSFET_B4.h>
73 #include <N_DEV_Resistor.h>
74 #include <N_DEV_Resistor3.h>
75 #include <N_DEV_Vsrc.h>
76 #include <N_DEV_Xygra.h>
77 
78 #include <N_LAS_System.h>
79 #include <N_LAS_Builder.h>
80 #include <N_LAS_Matrix.h>
81 
82 #include <N_PDS_Manager.h>
83 #include <N_PDS_Comm.h>
84 
85 #include <N_IO_CmdParse.h>
86 #include <N_IO_OutputMgr.h>
87 
88 #ifdef Xyce_EXTDEV
89 #include <N_DEV_ExternDevice.h>
90 #endif
91 
92 namespace Xyce {
93 namespace Device {
94 
95 //-----------------------------------------------------------------------------
96 // Function : DeviceMgr::factory
97 // Purpose : factory function
98 // Special Notes :
99 // Scope : public
100 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
101 // Creation Date : 3/16/00
102 //-----------------------------------------------------------------------------
103 DeviceMgr * DeviceMgr::factory(IO::CmdParse & cp)
104 {
105  DeviceMgr * DM_ptr = new DeviceMgr(cp);
106  DM_ptr->DevMgrPtr_ = DM_ptr;
107 
108  return DM_ptr;
109 }
110 
111 //-----------------------------------------------------------------------------
112 // Function : DeviceMgr::DeviceMgr
113 // Purpose : constructor
114 // Special Notes :
115 // Scope : private
116 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
117 // Creation Date : 3/16/00
118 //-----------------------------------------------------------------------------
119 DeviceMgr::DeviceMgr(IO::CmdParse &command_line)
120  : commandLine_(command_line),
121  devOptions_(),
122  icLoads_(NULL),
123  devSensPtr_(new DeviceSensitivities(*this, devOptions_)),
124  jacobianLoadCalledBefore_(false),
125  entityMapDone_ (false),
126  numPDEDevices_(0),
127  calledBeforeCSPI (false),
128  allDevsConverged_(false),
129  sensFlag_(false),
130  linearSystemFlag_(true),
131  firstDependent(true),
132  externalStateFlag_(false),
133  parameterChanged_(false),
134  breakPointInstancesInitialized(false),
135  timeParamsProcessed_(0.0),
136  numThreads_(0),
137  multiThreading_(false),
138  nonTrivialDeviceMaskFlag(false),
139  dotOpOutputFlag(false),
140  numJacStaVectorPtr_(0),
141  numJacSolVectorPtr_(0),
142  numJacStoVectorPtr_(0),
143  diagonalVectorPtr_(0)
144 {
145  devOptions_.setupDefaultOptions(command_line);
146  devOptions_.applyCmdLineOptions(command_line);
147 
148 #ifdef Xyce_EXTDEV
149  setUpPassThroughParamsMap_();
150 #endif
151 
152  solState_.debugTimeFlag = true;
153 }
154 
155 //-----------------------------------------------------------------------------
156 // Function : DeviceMgr::~DeviceMgr
157 // Purpose : destructor
158 // Special Notes :
159 // Scope : public
160 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
161 // Creation Date : 3/16/00
162 //-----------------------------------------------------------------------------
164 {
165  delete numJacStaVectorPtr_;
166  delete numJacSolVectorPtr_;
167  delete numJacStoVectorPtr_;
168  delete diagonalVectorPtr_;
169 
175 
176  delete externData_.tmpdIdXPtr;
177  delete externData_.tmpdQdXPtr;
178 
179  for (EntityTypeIdDeviceMap::iterator it = deviceMap_.begin(); it != deviceMap_.end(); ++it)
180  delete (*it).second;
181 
182 #ifdef Xyce_EXTDEV
183  for (int i = 0; i < extDevIBPtrVec_.size(); ++i)
184  {
185  if (extDevIBPtrVec_[i] != NULL)
186  {
187  delete extDevIBPtrVec_[i];
188  extDevIBPtrVec_[i] = 0;
189  }
190  }
191 #endif
192 
193  delete icLoads_;
194  delete devSensPtr_;
195 }
196 
197 //-----------------------------------------------------------------------------
198 // Function : DeviceMgr::registerPkgOptionsMgr
199 // Purpose :
200 // Special Notes :
201 // Scope : public
202 // Creator : Richard Schiek, Electrical and Mems Modeling
203 // Creation Date : 10/20/2008
204 //-----------------------------------------------------------------------------
205 bool DeviceMgr::registerPkgOptionsMgr(IO::PkgOptionsMgr *pkgOptPtr)
206 {
207  pkgOptMgrPtr_ = pkgOptPtr;
208  std::string netListFile("");
209  if (commandLine_.getArgumentValue(std::string("netlist")) != "")
210  {
211  netListFile = commandLine_.getArgumentValue(std::string("netlist"));
212  }
213  pkgOptMgrPtr_->submitRegistration(
214  "DEVICE", netListFile, new DeviceMgr_OptionsReg(this));
215 
216  pkgOptMgrPtr_->submitRegistration(
217  "SENS", netListFile, new DeviceMgr_SensOptionsReg(this));
218 
219  pkgOptMgrPtr_->submitRegistration(
220  "TIMEINT", netListFile, new DeviceMgr_TimeOptionsReg(this));
221 
222  // different analysis types.
223  pkgOptMgrPtr_->submitRegistration(
224  "TRAN", netListFile, new DeviceMgr_TransAnalysisReg(this));
225 
226  pkgOptMgrPtr_->submitRegistration(
227  "DC", netListFile, new DeviceMgr_DCAnalysisReg(this));
228 
229  pkgOptMgrPtr_->submitRegistration(
230  "OP", netListFile, new DeviceMgr_OPAnalysisReg(this));
231 
232  pkgOptMgrPtr_->submitRegistration(
233  "STEP", netListFile, new DeviceMgr_STEPAnalysisReg(this));
234 
235  // MPDE specific netlist lines
236  pkgOptMgrPtr_->submitRegistration(
237  "MPDE", netListFile, new DeviceMgr_MPDE_AnalysisReg(this));
238 
239  // HB Specific netlist lines
240  pkgOptMgrPtr_->submitRegistration(
241  "HB", netListFile, new DeviceMgr_HB_AnalysisReg(this));
242 
243  // AC Specific netlist lines
244  pkgOptMgrPtr_->submitRegistration(
245  "AC", netListFile, new DeviceMgr_AC_AnalysisReg(this));
246 
247  // MOR Specific netlist lines
248  pkgOptMgrPtr_->submitRegistration(
249  "MOR", netListFile, new DeviceMgr_MOR_AnalysisReg(this));
250 
251  return true;
252 }
253 
254 //-----------------------------------------------------------------------------
255 // Function : DeviceMgr::registerSensParams
256 // Purpose :
257 // Special Notes :
258 // Scope : public
259 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
260 // Creation Date : 6/03/02
261 //-----------------------------------------------------------------------------
262 bool DeviceMgr::registerSensParams (const Util::OptionBlock & OB)
263 {
264  sensFlag_ = true;
265 
266  if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
267  {
268  dout() << "DeviceMgr::registerSensParams called!" <<std::endl;
269  }
270 
271  return devSensPtr_->registerSensParams (OB);
272 }
273 
274 
275 //-----------------------------------------------------------------------------
276 // Function : DeviceMgr::registerLeadCurrentRequests
277 // Purpose : this function is called from the output manager (through the
278 // device interface) to inform the device package of the devices
279 // for which lead currents have been requested. The device
280 // manager will take care of doing isolated F and Q loads for
281 // these devices so the lead currents can be calculated
282 // Special Notes :
283 // Scope : public
284 // Creator : Richard Schiek, SNL, Electrical Systems Modeling
285 // Creation Date : 03/20/13
286 //-----------------------------------------------------------------------------
287 bool DeviceMgr::setLeadCurrentRequests(const std::set<std::string> & deviceNames)
288 {
289  // this is called prior to fully constructing the devices. So for now
290  // save the list
291  devicesNeedingLeadCurrentLoads_ = deviceNames;
292 
293  if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
294  {
295  if (! devicesNeedingLeadCurrentLoads_.empty())
296  {
297  std::set<std::string>::iterator currentDeviceNameItr = devicesNeedingLeadCurrentLoads_.begin();
298  std::set<std::string>::iterator endDeviceNameItr = devicesNeedingLeadCurrentLoads_.end();
299  dout() << "DeviceMgr::registerLeadCurrentRequests Devices for which lead currents were requested: ";
300  while (currentDeviceNameItr != endDeviceNameItr)
301  {
302  dout() << *currentDeviceNameItr << " ";
303  currentDeviceNameItr++;
304  }
305  dout() << std::endl;
306  }
307  }
308 
309  return true;
310 }
311 
312 //-----------------------------------------------------------------------------
313 // Function : DeviceMgr::setTranAnalysisParams
314 // Purpose :
315 // Special Notes :
316 // Scope : public
317 // Creator : Eric Keiter, SNL
318 // Creation Date : 10/14/11
319 //-----------------------------------------------------------------------------
320 bool DeviceMgr::setTranAnalysisParams (const Util::OptionBlock & OB)
321 {
322  solState_.TRANspecified = true;
323  return true;
324 }
325 
326 //-----------------------------------------------------------------------------
327 // Function : DeviceMgr::setDCAnalysisParams
328 // Purpose :
329 // Special Notes :
330 // Scope : public
331 // Creator : Eric Keiter, SNL
332 // Creation Date : 10/14/11
333 //-----------------------------------------------------------------------------
334 bool DeviceMgr::setDCAnalysisParams (const Util::OptionBlock & OB)
335 {
336  solState_.DCspecified = true;
337  return true;
338 }
339 
340 //-----------------------------------------------------------------------------
341 // Function : DeviceMgr::setOPAnalysisParams
342 // Purpose :
343 // Special Notes :
344 // Scope : public
345 // Creator : Eric Keiter, SNL
346 // Creation Date : 10/14/11
347 //-----------------------------------------------------------------------------
348 bool DeviceMgr::setOPAnalysisParams (const Util::OptionBlock & OB)
349 {
350  solState_.OPspecified = true;
351  return true;
352 }
353 
354 //-----------------------------------------------------------------------------
355 // Function : DeviceMgr::setSTEPAnalysisParams
356 // Purpose :
357 // Special Notes :
358 // Scope : public
359 // Creator : Eric Keiter, SNL
360 // Creation Date : 10/14/11
361 //-----------------------------------------------------------------------------
362 bool DeviceMgr::setSTEPAnalysisParams (const Util::OptionBlock & OB)
363 {
364  solState_.STEPspecified = true;
365  return true;
366 }
367 
368 //-----------------------------------------------------------------------------
369 // Function : DeviceMgr::setMPDEAnalysisParams
370 // Purpose :
371 // Special Notes :
372 // Scope : public
373 // Creator : Eric Keiter, SNL
374 // Creation Date : 10/14/11
375 //-----------------------------------------------------------------------------
376 bool DeviceMgr::setMPDEAnalysisParams (const Util::OptionBlock & OB)
377 {
378  solState_.MPDEspecified = true;
379  return true;
380 }
381 
382 //-----------------------------------------------------------------------------
383 // Function : DeviceMgr::setHBAnalysisParams
384 // Purpose :
385 // Special Notes :
386 // Scope : public
387 // Creator : Eric Keiter, SNL
388 // Creation Date : 10/14/11
389 //-----------------------------------------------------------------------------
390 bool DeviceMgr::setHBAnalysisParams (const Util::OptionBlock & OB)
391 {
392  solState_.HBspecified = true;
393  return true;
394 }
395 
396 //-----------------------------------------------------------------------------
397 // Function : DeviceMgr::setACAnalysisParams
398 // Purpose :
399 // Special Notes :
400 // Scope : public
401 // Creator : Eric Keiter, SNL
402 // Creation Date : 10/14/11
403 //-----------------------------------------------------------------------------
404 bool DeviceMgr::setACAnalysisParams (const Util::OptionBlock & OB)
405 {
406  solState_.ACspecified = true;
407  return true;
408 }
409 
410 //-----------------------------------------------------------------------------
411 // Function : DeviceMgr::setMORAnalysisParams
412 // Purpose :
413 // Special Notes :
414 // Scope : public
415 // Creator : Heidi Thornquist and Ting Mei, SNL
416 // Creation Date : 5/30/12
417 //-----------------------------------------------------------------------------
418 bool DeviceMgr::setMORAnalysisParams (const Util::OptionBlock & OB)
419 {
420  solState_.MORspecified = true;
421  return true;
422 }
423 
424 
425 //-----------------------------------------------------------------------------
426 // Function : DeviceMgr::getFastSourcePeriod
427 // Purpose :
428 // Special Notes :
429 // Scope : public
430 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
431 // Creation Date : 3/27/04
432 //-----------------------------------------------------------------------------
433 std::vector<double> DeviceMgr::getFastSourcePeriod (std::vector<std::string>& sourceNames)
434 {
435  int numFastSrcs = sourceNames.size();
436 
437  //Setup return of source periods
438  std::vector<double> srcPeriods(numFastSrcs);
439 
440  // Now loop over them, and mark them.
441  for(int i = 0; i < numFastSrcs; ++i)
442  {
443  ExtendedString tmpName(sourceNames[i]);
444  tmpName.toUpper();
445  std::map<std::string,SourceInstance*>::iterator iterFS = indepSourcePtrMap_.find(tmpName);
446  if (iterFS != indepSourcePtrMap_.end())
447  {
448  SourceInstance * SIPtr = iterFS->second;
449  srcPeriods[i] = SIPtr->period();
450  }
451  else
452  {
453 #ifndef Xyce_PARALLEL_MPI
454  Report::UserError message;
455  message << "Unable to find source: " << fastSourceNames_[i] << "\n"
456  << "Potential names are: ";
457  for (std::map<std::string,SourceInstance*>::const_iterator it = indepSourcePtrMap_.begin(); it != indepSourcePtrMap_.end(); ++it)
458  message << (*it).first << " ";
459 #endif
460  }
461  }
462 
463 #ifdef Xyce_PARALLEL_MPI
464  // Collect all the periods from all the processors, assuming periods are positive values.
465  std::vector<double> tmpSrcPeriods( srcPeriods );
466  pdsMgrPtr_->getPDSComm()->maxAll( &tmpSrcPeriods[0], &srcPeriods[0], numFastSrcs );
467 #endif
468 
469  return srcPeriods;
470 }
471 
472 
473 //-----------------------------------------------------------------------------
474 // Function : DeviceMgr::registerFastSources
475 // Purpose :
476 // Special Notes :
477 // Scope : public
478 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
479 // Creation Date : 3/27/04
480 //-----------------------------------------------------------------------------
481 std::vector<double> DeviceMgr::registerFastSources (std::vector<std::string>& sourceNames)
482 {
483  int numFastSrcs = sourceNames.size();
484  //Setup return of source periods
485  std::vector<double> srcPeriods;
486 
487  if (numFastSrcs > 0)
488  {
489  srcPeriods.resize(numFastSrcs, 0.0);
490 
491  // Default case, the sources are explicitely listed on the .option line
492  fastSourceNames_.resize(numFastSrcs);
493  copy(sourceNames.begin(), sourceNames.end(), fastSourceNames_.begin());
494 
495  // Now loop over them, and mark them.
496  for(int i = 0; i < numFastSrcs; ++i)
497  {
498  ExtendedString tmpName(fastSourceNames_[i]);
499  tmpName.toUpper();
500  std::map<std::string,SourceInstance*>::iterator iterFS = indepSourcePtrMap_.find(tmpName);
501  if (iterFS != indepSourcePtrMap_.end())
502  {
503  SourceInstance * SIPtr = iterFS->second;
504  SIPtr->setFastSourceFlag (true);
505  srcPeriods[i] = SIPtr->period();
506  }
507  else
508  {
509 #ifndef Xyce_PARALLEL_MPI
510  Report::UserError message;
511  message << "Unable to find source: " << fastSourceNames_[i] << "\n"
512  << "Potential names are: ";
513  for (std::map<std::string,SourceInstance*>::const_iterator it = indepSourcePtrMap_.begin(); it != indepSourcePtrMap_.end(); ++it)
514  message << (*it).first << " ";
515 #endif
516  }
517  }
518 
519  }
520  else
521  {
522  // tscoffe/tmei 09/16/08
523  // Special case: Use all sources
524  // Compute the total number of fast sources for all processors.
525  // NOTE: In parallel, this will not work correctly if more than one processor has fast sources.
526  int myNumFastSrcs = indepSourceInstancePtrVec_.size();
527  pdsMgrPtr_->getPDSComm()->sumAll( &myNumFastSrcs, &numFastSrcs, 1 );
528  srcPeriods.resize(numFastSrcs, -1.0);
529  for (int i=0 ; i<myNumFastSrcs ; ++i) {
530  indepSourceInstancePtrVec_[i]->setFastSourceFlag(true);
531  srcPeriods[i] = indepSourceInstancePtrVec_[i]->period();
532  }
533  }
534 
535 #ifdef Xyce_PARALLEL_MPI
536  // Collect all the periods from all the processors, assuming periods are positive values.
537  std::vector<double> tmpSrcPeriods( srcPeriods );
538  pdsMgrPtr_->getPDSComm()->maxAll( &tmpSrcPeriods[0], &srcPeriods[0], numFastSrcs );
539 #endif
540 
541  return srcPeriods;
542 }
543 
544 
545 //-----------------------------------------------------------------------------
546 // Function : DeviceMgr::deRegisterFastSources
547 // Purpose : reverses the effect of registerFastSources
548 // Special Notes :
549 // Scope : public
550 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
551 // Creation Date : 06/12/2013
552 //-----------------------------------------------------------------------------
553 void DeviceMgr::deRegisterFastSources (std::vector<std::string>& sourceNames)
554 {
555  int numFastSrcs = sourceNames.size();
556 
557  if (numFastSrcs > 0)
558  {
559  // Default case, the sources are explicitely listed on the .option line
560  fastSourceNames_.resize(numFastSrcs);
561  copy(sourceNames.begin(), sourceNames.end(), fastSourceNames_.begin());
562 
563  // Now loop over them, and mark them.
564  for(int i = 0; i < numFastSrcs; ++i)
565  {
566  ExtendedString tmpName(fastSourceNames_[i]);
567  tmpName.toUpper();
568  std::map<std::string,SourceInstance*>::iterator iterFS = indepSourcePtrMap_.find(tmpName);
569  if (iterFS != indepSourcePtrMap_.end())
570  {
571  SourceInstance * SIPtr = iterFS->second;
572  SIPtr->setFastSourceFlag (false);
573  }
574  else
575  {
576 #ifndef Xyce_PARALLEL_MPI
577  Report::DevelFatal message;
578  message << "DeviceMgr::deRegisterFastSources: Unable to find source: " << fastSourceNames_[i] << "\n"
579  << "Potential names are: ";
580  for (std::map<std::string,SourceInstance*>::const_iterator it = indepSourcePtrMap_.begin(); it != indepSourcePtrMap_.end(); ++it)
581  message << (*it).first << " ";
582 #endif
583  }
584  }
585  }
586  else
587  {
588  // Special case: Use all sources
589  numFastSrcs = indepSourceInstancePtrVec_.size();
590  for (int i=0 ; i<numFastSrcs ; ++i) {
591  indepSourceInstancePtrVec_[i]->setFastSourceFlag(false);
592  }
593  }
594  return;
595 }
596 
597 //-----------------------------------------------------------------------------
598 // Function : DeviceMgr::setFastSourceSetFlag
599 // Purpose : traverse fast source list and remove any slow sources from
600 // the deviceArray
601 // Special Notes :
602 // Scope : public
603 // Creator : Rich Schiek, SNL, Parallel Computational Sciences
604 // Creation Date : 3/22/07
605 //-----------------------------------------------------------------------------
607 {
608  // first back-up a copy of the deviceArray so we can edit out
609  // the slow sources
613 
614  // erase the existing list of sources
616 
617  // now copy back only those that are fast sources
618  std::vector<SourceInstance*>::iterator iter;
619  std::vector<SourceInstance*>::iterator begin =indepSourceInstanceBackupPtrVec_.begin();
620  std::vector<SourceInstance*>::iterator end =indepSourceInstanceBackupPtrVec_.end();
621  for (iter=begin; iter!=end;++iter)
622  {
623  if ((*iter)->getFastSourceFlag())
624  {
625  indepSourceInstancePtrVec_.push_back(*iter);
626  }
627  }
628 
629 }
630 
631 //-----------------------------------------------------------------------------
632 // Function : DeviceMgr::setFastSourceSetFlag
633 // Purpose : restore any slow sources to the device array.
634 // Special Notes :
635 // Scope : public
636 // Creator : Rich Schiek, SNL, Parallel Computational Sciences
637 // Creation Date : 3/22/07
638 //-----------------------------------------------------------------------------
640 {
641  // restore the independent source list from backup
646 }
647 
648 //-----------------------------------------------------------------------------
649 // Function : DeviceMgr::setMPDEFlag
650 // Purpose :
651 // Special Notes :
652 // Scope : public
653 // Creator : Richard Schiek, SNL, Parallel Computational Sciences
654 // Creation Date : 07/21/08
655 //-----------------------------------------------------------------------------
656 void DeviceMgr::setMPDEFlag(bool flagVal)
657 {
658  solState_.mpdeOnFlag = flagVal;
659 }
660 
661 //-----------------------------------------------------------------------------
662 // Function : DeviceMgr::setBlockAnalysisFlag
663 // Purpose :
664 // Special Notes :
665 // Scope : public
666 // Creator : Richard Schiek, SNL, Parallel Computational Sciences
667 // Creation Date : 07/21/08
668 //-----------------------------------------------------------------------------
670 {
671  solState_.blockAnalysisFlag = flagVal;
673 }
674 
675 //-----------------------------------------------------------------------------
676 // Function : DeviceMgr::setFastTime
677 // Purpose :
678 // Special Notes :
679 // Scope : public
680 // Creator : Richard Schiek, SNL, Parallel Computational Sciences
681 // Creation Date : 07/21/08
682 //-----------------------------------------------------------------------------
683 void DeviceMgr::setFastTime(double timeVal)
684 {
685  solState_.currFastTime = timeVal;
686 }
687 
688 //-----------------------------------------------------------------------------
689 // Function : DeviceMgr::initializeAll
690 // Purpose : This function, via the LAS system class, sets up
691 // the pointers to the various linear algebra entities.
692 // Special Notes :
693 // Scope : public
694 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
695 // Creation Date : 6/12/00
696 //-----------------------------------------------------------------------------
698 {
699  bool bsuccess = true;
700 
702 
703  // nullify ptrs that are passed in at each step (see the loadDAEVectors function args)
719 
720  if (DEBUG_DEVICE) {
721  // get f vector pointer:
722  externData_.fVectorPtr = lasSysPtr_->getFVector();
723  bsuccess = bsuccess && (externData_.fVectorPtr != 0);
724 
725  // create Jdxp vector pointer:
726  externData_.JdxpVectorPtr = lasSysPtr_->getJDXPVector();
727  bsuccess = bsuccess && (externData_.JdxpVectorPtr != 0);
728  }
729 
730 #ifdef Xyce_DEBUG_VOLTLIM
731  // get test matrix: (old DAE)
732  externData_.JTestMatrixPtr = lasSysPtr_->getJacTestMatrix();
733  bsuccess = bsuccess && (externData_.JTestMatrixPtr != 0);
734 
735  // get test matrix:
736  externData_.FTestMatrixPtr = lasSysPtr_->getdFdxTestMatrix();
737  bsuccess = bsuccess && (externData_.FTestMatrixPtr != 0);
738  externData_.QTestMatrixPtr = lasSysPtr_->getdQdxTestMatrix();
739  bsuccess = bsuccess && (externData_.QTestMatrixPtr != 0);
740 
741  // get dxVoltlim vector pointer:
742  externData_.dxVoltlimVectorPtr = lasSysPtr_->getDxVoltlimVector() ;
743  bsuccess = bsuccess && (externData_.dxVoltlimVectorPtr != 0);
744 
745  // create Jdx2 vector pointer: (old DAE)
746  externData_.Jdx2VectorPtr = lasSysPtr_->getJDX2Vector();
747  bsuccess = bsuccess && (externData_.Jdx2VectorPtr != 0);
748 
749  // create Jdx2 vector pointer:
750  externData_.Fdx2VectorPtr = lasSysPtr_->getFDX2Vector();
751  bsuccess = bsuccess && (externData_.Fdx2VectorPtr != 0);
752  externData_.Qdx2VectorPtr = lasSysPtr_->getQDX2Vector();
753  bsuccess = bsuccess && (externData_.Qdx2VectorPtr != 0);
754 #endif
755 
756  // get flag solution pointer-pointer:
757  externData_.flagSolVectorPtr = lasSysPtr_->getFlagSolVector();
758  bsuccess = bsuccess && (externData_.flagSolVectorPtr != 0);
759 
760  // get device mask pointer.
761  externData_.deviceMaskVectorPtr = lasSysPtr_->getDeviceMaskVector ();
762  bsuccess = bsuccess && (externData_.deviceMaskVectorPtr != 0);
763 
764  // create the temporary numerical jacobian vectors
766  {
767  numJacStaVectorPtr_ = lasSysPtr_->builder().createStateVector();
768  numJacSolVectorPtr_ = lasSysPtr_->builder().createVector();
769  numJacStoVectorPtr_ = lasSysPtr_->builder().createStoreVector();
770 
771  externData_.numJacRHSVectorPtr = lasSysPtr_->builder().createVector();
772  externData_.numJacFVectorPtr = lasSysPtr_->builder().createVector();
773  externData_.numJacQVectorPtr = lasSysPtr_->builder().createVector();
774  externData_.perturbVectorPtr = lasSysPtr_->builder().createVector();
775  externData_.numJacLoadFlagPtr = lasSysPtr_->builder().createVector();
776  }
777 
778  externData_.tmpdIdXPtr = lasSysPtr_->builder().createVector();
779  externData_.tmpdQdXPtr = lasSysPtr_->builder().createVector();
780 
781  // create a diagonal vector to be used for 2-level
782  diagonalVectorPtr_ = lasSysPtr_->builder().createVector();
783 
785 
786  // For Homotopy on block gainscale
788 
789 #ifdef Xyce_SIZEOF
790  int size = sizeof(*this);
791  dout() << "Size of device package after initializeAll = " << size << std::endl;
792 #endif
793 
794  return bsuccess;
795 }
796 
797 //-----------------------------------------------------------------------------
798 // Function : DeviceMgr::resetForStepAnalysis
799 // Purpose :
800 // Special Notes : Some "resetForStep" functions (only HB so far) will
801 // call dev->initializeAll. So, this must be called first.
802 // Scope : public
803 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
804 // Creation Date : 07/12/2013
805 //-----------------------------------------------------------------------------
807 {
808  delete numJacStaVectorPtr_;
809  delete numJacSolVectorPtr_;
810  delete numJacStoVectorPtr_;
816  delete externData_.tmpdIdXPtr;
817  delete externData_.tmpdQdXPtr;
818  delete diagonalVectorPtr_;
819 
823 }
824 
825 //-----------------------------------------------------------------------------
826 // Function : DeviceMgr::createDevice
827 // Purpose : This function creates a single device based on the passed
828 // index.
829 // Special Notes :
830 // Scope : protected
831 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
832 // Creation Date : 3/16/00
833 //-----------------------------------------------------------------------------
835 {
836  Device *device = 0;
837 
838  if (model_type_id.defined())
839  {
840  EntityTypeIdDeviceMap::const_iterator it = deviceMap_.find(model_type_id);
841  if (it == deviceMap_.end())
842  {
844 
845  device = Configuration::createDevice(model_type_id, factory_block);
846 
847  deviceMap_[model_type_id] = device;
848  devicePtrVec_.push_back(device);
849 
850  if (device->isPDEDevice())
851  {
852  pdeDevicePtrVec_.push_back(device);
853  }
854  else
855  {
856  nonPdeDevicePtrVec_.push_back(device);
857  }
858  }
859  else
860  device = (*it).second;
861  }
862 
863  return *device;
864 }
865 
866 //-----------------------------------------------------------------------------
867 // Function : DeviceMgr::getModelGroup
868 // Purpose : This function returns the device type index for a given
869 // named string. This assumes that the device names used
870 // in the simulation will obey the spice3f5 netlist language
871 // convention.
872 //
873 // Special Notes :
874 // Scope : public
875 // Creator :
876 // Creation Date : 3/16/00
877 //-----------------------------------------------------------------------------
878 /**
879  * Return the ModelGroup of the device associated with the model type name or device type name.
880  *
881  * The model type to model group map is searched first. If the model is not discovered, then the
882  *
883  * @param model_type_name model type name or device type name
884  *
885  * @return
886  *
887  * @author David G. Baur Raytheon Sandia National Laboratories 1355
888  * @date Mon Sep 23 07:53:04 2013
889  */
890 EntityTypeId DeviceMgr::getModelGroup(const std::string &model_type_name)
891 {
892  EntityTypeId model_group = Configuration::getModelGroup(model_type_name);
893  if (model_group.defined())
894  return model_group;
895 
896  // Use the letter as an index into the deviceIndex map.
897  std::string device_letter(model_type_name, 0, 1);
898  if (device_letter != "Y")
899  {
900  model_group = Configuration::getModelGroup(device_letter);
901  }
902  else {
903  // "Y" device requires special handling. The device type was embedded in
904  // the device name to fit the way things worked for ordinary devices.
905  // The format of the device name for a "Y" device is
906  // "Y%<DeviceType>%<NetlistDevicename>". Extract the device type and
907  // use as the index into the modelTypeNameModelGroupMap map.
908  std::string device_name = model_type_name.substr(model_type_name.find_first_of("%") + 1, model_type_name.find_last_of("%") - 2);
909  model_group = Configuration::getModelGroup(device_name);
910  }
911 
912  return model_group;
913 }
914 
915 //-----------------------------------------------------------------------------
916 // Function : DeviceMgr::addDeviceModel
917 // Purpose :
918 // Special Notes :
919 // Scope : public
920 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
921 // Creation Date : 3/16/00
922 //-----------------------------------------------------------------------------
923 bool DeviceMgr::addDeviceModel(const ModelBlock & model_block)
924 {
925  ModelTypeId model_type;
926  ModelTypeId model_group = Configuration::getModelGroup(model_block.type);
927 
928  if (!model_block.name.empty()) {
929  model_type = Configuration::getModelType(model_block.type, model_block.level);
930 
931  if (!model_type.defined())
932  Report::UserError() << "There is no device " << model_block.type << " of level " << model_block.level << " to define model " << model_block.name;
933  }
934 
935  if (!model_type.defined())
936  model_type = model_group;
937 
938  if (!model_type.defined())
939  return false;
940 
942  Device &device = getDeviceByModelType(model_type);
943  DeviceModel *device_model = device.addModel(model_block, factory_block);
944 
945  modelTypeMap_[model_block.name] = model_type;
946  modelGroupMap_[model_block.name] = model_group;
947 
948  // add the various model vectors:
949  if (device_model != 0)
950  {
951  modelPtrVec_.push_back(device_model);
952 
953  if (model_group == MOSFET1::Traits::modelGroup()) mosfetModelPtrVec_.push_back(device_model);
954  if (model_group == BJT::Traits::modelGroup()) bjtModelPtrVec_.push_back(device_model);
955 
956  if (model_type == Diode::Traits::modelType()) diodeModelPtrVec_.push_back(device_model);
957  if (model_type == MOSFET_B3::Traits::modelType()) bsim3ModelPtrVec_.push_back(device_model);
958  if (model_type == MOSFET_B4::Traits::modelType()) bsim4ModelPtrVec_.push_back(device_model);
959  if (model_type == MOSFET_B3SOI::Traits::modelType()) bsimsoiModelPtrVec_.push_back(device_model);
960  }
961 
962  return device_model != 0;
963 }
964 
965 //-----------------------------------------------------------------------------
966 // Function : DeviceMgr::verifyDeviceInstance
967 // Purpose : This function verifies a device instance prior to
968 // instantiating.
969 //
970 // Theoretically, we could do this in addDeviceInstance() and
971 // not make a device if it fails some verification criteria (a
972 // resistor with zero resistance is the primary case here).
973 // However, later unlinking of redundant devices that are
974 // connected to just one node is difficult after
975 // addDeviceInstance() is called because the device instance
976 // pointer can be placed in many other containers
977 // It could be done, but this is a simpler first step to having the
978 // device manager be in charge of device verification -- rather
979 // than have it in toplogy or IO.
980 //
981 // Special Notes : return true if this device is ok to instantiate, false otherwise
982 // Scope : public
983 // Creator : Richard Schiek, Electrical and Microsystems Modeling
984 // Creation Date : 2/18/2010
985 //-----------------------------------------------------------------------------
987 {
988  EntityTypeId model_type;
989 
990  if (instance_block.getModelName().empty())
991  {
992  model_type = getModelGroup(modelNameFromInstanceName(instance_block));
993  }
994  else
995  {
996  model_type = modelTypeMap_[instance_block.getModelName()];
997  }
998 
999  if (!model_type.defined())
1000  {
1001  Report::UserFatal message;
1002 
1003  message << "Unable to determine model type of device for instance name " << instance_block.getName();
1004  if (instance_block.getModelName() != "")
1005  {
1006  message<< " with model name" + instance_block.getModelName();
1007  }
1008  }
1009  else if (instance_block.bsourceFlag)
1010  {
1011  // This is an E, F, G, or H source that is to be treated as a B source,
1012  // set its type now to BSRC.
1013  model_type = Bsrc::Traits::modelType();
1014  }
1015 
1016  // Check if this is a simple resistor, but with a resistance of zero. if so,
1017  // then return false so we don't make this device.
1019  {
1020  const double zeroResistanceValue = devOptions_.zeroResistanceTol;
1021  // loop over the parameters
1022  std::vector<Param>::iterator currentParam = instance_block.params.begin();
1023  std::vector<Param>::iterator endParam = instance_block.params.end();
1024  while(currentParam != endParam)
1025  {
1026  if ((currentParam->uTag() == "R"))
1027  {
1028  if (currentParam->given())
1029  {
1030  std::vector<std::string> variables, specials;
1031 
1032  // check if this is a time-dependent, or variable-dependent expression.
1033  // If it is, then skip.
1034  Param * devPar = &(*(currentParam));
1035  Util::Param * tmpPar = (dynamic_cast<Util::Param*> (devPar));
1036  // only check if this is an expression-type parameter.
1037  if (tmpPar->getType() == Util::EXPR)
1038  {
1039  Util::Expression tmpExp = tmpPar->getValue<Util::Expression>();
1040  tmpExp.get_names(XEXP_VARIABLE, variables);
1041  tmpExp.get_names(XEXP_SPECIAL, specials);
1042  }
1043 
1044  if (specials.empty() && variables.empty())
1045  {
1046  if (fabs(currentParam->getImmutableValue<double>()) < devOptions_.zeroResistanceTol)
1047  {
1048  // change device type to be the level 3 resistor
1049  return false;
1050  }
1051  }
1052  }
1053  break;
1054  }
1055  currentParam++;
1056  }
1057  }
1058 
1059  return true;
1060 }
1061 
1062 //-----------------------------------------------------------------------------
1063 // Function : DeviceMgr::addDeviceInstance
1064 // Purpose : addDeviceInstance will create a new instance of the
1065 // designated device type. This version of the function
1066 // accepts a parameter list as one of the arguments,
1067 // so it is assumed that a parameter instance will
1068 // also have to be allocated for it.
1069 //
1070 // Special Notes :
1071 // Scope : public
1072 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1073 // Creation Date : 3/16/00
1074 //-----------------------------------------------------------------------------
1076 {
1077  // If the ModelName string is not a null string, use it to get the
1078  // device type index. Otherwise, use the name of the device itself to determine the device.
1079  ModelTypeId model_type;
1080  ModelTypeId model_group;
1081  if (instance_block.getModelName().empty())
1082  {
1083  model_type = getModelGroup(modelNameFromInstanceName(instance_block));
1084  model_group = model_type;
1085  }
1086  else
1087  {
1088  model_type = modelTypeMap_[instance_block.getModelName()];
1089  model_group = modelGroupMap_[instance_block.getModelName()];
1090  }
1091 
1092  if (!model_type.defined())
1093  {
1094  Report::UserError message;
1095  message << "Unable to determine type of device for instance name " << instance_block.getName();
1096  if (instance_block.getModelName() != "")
1097  {
1098  message << " with model name" + instance_block.getModelName();
1099  }
1100  }
1101  else if (instance_block.bsourceFlag)
1102  {
1103  // This is an E, F, G, or H source that is to be treated as a B source,
1104  // set its type now to BSRC.
1105  model_type = Bsrc::Traits::modelType();
1106  }
1107 
1108  // Check if this is a simple resistor, but with a resistance of zero. If so,
1109  // then change the type to RESISTOR3. This variant of the resistor acts like
1110  // a voltage souce with zero voltage difference.
1112  {
1113  const double zeroResistanceValue = devOptions_.zeroResistanceTol;
1114  // loop over the parameters
1115  std::vector<Param>::iterator currentParam = instance_block.params.begin();
1116  std::vector<Param>::iterator endParam = instance_block.params.end();
1117  while(currentParam != endParam)
1118  {
1119  if ((currentParam->uTag() == "R"))
1120  {
1121  if (currentParam->given())
1122  {
1123  std::vector<std::string> variables, specials;
1124 
1125  // check if this is a time-dependent, or variable-dependent expression.
1126  // If it is, then skip.
1127  Param * devPar = &(*(currentParam));
1128  Util::Param * tmpPar = (dynamic_cast<Util::Param*> (devPar));
1129  // only check if this is an expression-type parameter.
1130  if (tmpPar->getType() == Util::EXPR)
1131  {
1132  Util::Expression tmpExp = tmpPar->getValue<Util::Expression>();
1133  tmpExp.get_names(XEXP_VARIABLE, variables);
1134  tmpExp.get_names(XEXP_SPECIAL, specials);
1135  }
1136 
1137  if (specials.empty() && variables.empty())
1138  {
1139  if (fabs(currentParam->getImmutableValue<double>()) < devOptions_.zeroResistanceTol)
1140  {
1141  // change device type to be the level 3 resistor
1142  model_type = Resistor3::Traits::modelType();
1143  }
1144  }
1145  }
1146  break;
1147  }
1148  currentParam++;
1149  }
1150  }
1151 
1152  // Just in case, call the device creator function - if it has already
1153  // been allocated it won't create a redundant one.
1154 
1155  // Add an instance of this type.
1156  Device &device = getDeviceByModelType(model_type);
1157  DeviceInstance *instance = device.addInstance(instance_block, FactoryBlock(devOptions_, solState_, mlData, externData_, commandLine_));
1158 
1159  std::string outputName;
1160  setupIOName(instance->getName(), outputName);
1161 
1162  if ((devicesNeedingLeadCurrentLoads_.find(outputName) != devicesNeedingLeadCurrentLoads_.end()) ||
1164  {
1165  instance->enableLeadCurrentCalc();
1166 
1167  if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
1168  {
1169  dout() << "DeviceMgr::addDeviceInstance Enabling lead current load for device \""
1170  << instance->getName()
1171  << "\" -> \""
1172  << outputName
1173  << "\"" << std::endl;
1174  }
1175  }
1176  else if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
1177  {
1178  dout() << "DeviceMgr::addDeviceInstance Cannot enable lead current load for device \""
1179  << instance->getName()
1180  << "\" -> \""
1181  << outputName
1182  << "\""
1183  << std::endl;
1184  }
1185 
1186  localDeviceCountMap_[device.getDefaultModelName()]++;
1187 
1188  linearSystemFlag_ = linearSystemFlag_ && device.isLinearDevice();
1189 
1190  solState_.PDESystemFlag = solState_.PDESystemFlag || device.isPDEDevice();
1191 
1192  // Set up the instance vectors. These are the main containers used in the load procedures.
1193  instancePtrVec_.push_back(instance);
1194 
1195  // set up the list of pde device instances
1196  // and the list of non-pde devices instances.
1197  if (device.isPDEDevice())
1198  {
1199  pdeInstancePtrVec_.push_back(instance);
1200  }
1201  else
1202  {
1203  nonPdeInstancePtrVec_.push_back(instance);
1204  }
1205 
1206  // set up the list of mosfet instances.
1207  if (model_group == MOSFET1::Traits::modelGroup())
1208  {
1209  mosfetInstancePtrVec_.push_back(instance);
1210  }
1211 
1212  if (model_group == BJT::Traits::modelGroup())
1213  {
1214  bjtInstancePtrVec_.push_back (instance);
1215  }
1216 
1217 
1218 #ifdef Xyce_EXTDEV
1219  if (model_type == ExternDevice::Traits::modelType())
1220  {
1221  extDevInstancePtrVec_.push_back(dynamic_cast<ExternDevice::Instance*>(instance));
1222  extDevIBPtrVec_.push_back(new InstanceBlock(instance_block));
1223  }
1224 #endif
1225 
1226  // set up the independent source map.
1227  if (model_type == Vsrc::Traits::modelType() || model_type == ISRC::Traits::modelType())
1228  {
1229  ExtendedString tmpName(instance_block.getName());
1230  tmpName.toUpper ();
1231  indepSourcePtrMap_[tmpName] = dynamic_cast<SourceInstance*>(instance);
1232  indepSourceInstancePtrVec_.push_back(dynamic_cast<SourceInstance*>(instance));
1233  }
1234 
1235  if (model_type == Vsrc::Traits::modelType())
1236  {
1237  vsrcInstancePtrVec_.push_back(instance);
1238  ExtendedString tmpName(instance_block.getName());
1239  tmpName.toUpper ();
1240  vsrcInstancePtrMap_[tmpName] = dynamic_cast<Vsrc::Instance*>(instance);
1241  }
1242 
1243 #if 0
1244  // ERK. Commenting this out, as the PDE sources cannot be dynamically
1245  // casted to be SourceInstance classes. They can't, because they
1246  // are not derrived from them. The photocurrent capability in the PDE
1247  // devices is just an experiment, not a supported one, so I'll figure
1248  // out a fix for it later.
1249  if (model_type == TWO_D_PDE)
1250  {
1251  // a photocurrent addition to the two d pde can act like a souce
1252  // so add it to our list of independent sources
1253  indepSourceInstancePtrVec_.push_back(dynamic_cast<SourceInstance*>(instance));
1254  }
1255 #endif
1256 
1257  if (instance->plotfileFlag ())
1258  {
1259  plotFileInstancePtrVec_.push_back(instance);
1260  }
1261 
1262  ExtendedString tmpDevName = devOptions_.testJacDeviceName;
1263  tmpDevName.toUpper();
1264  // Set up the vector of devices subject to the jacobian test.
1265  if (instance->getName() == tmpDevName)
1266  {
1267  testJacDevicePtrVec_.push_back(instance);
1268  }
1269 
1270  return instance;
1271 }
1272 
1273 //-----------------------------------------------------------------------------
1274 // Function : DeviceMgr::deleteDeviceInstance
1275 // Purpose :
1276 // Special Notes :
1277 // Scope : public
1278 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1279 // Creation Date : 3/08/01
1280 //-----------------------------------------------------------------------------
1281 bool DeviceMgr::deleteDeviceInstance(const std::string & name)
1282 {
1283  Report::DevelFatal().in("DeviceMgr::deleteDeviceInstance") << "Not ready with the new boilerplate-free device package";
1284 
1285  bool bsuccess = true;
1286 
1287  // bool tmpBool = true;
1288  // EntityTypeId type = getModelGroup(name);
1289 
1290  // DeviceMap::iterator it = deviceMap_.find(type);
1291  // if (it != deviceMap_.end()) {
1292  // // bsuccess &= (*it).second->deleteInstance(name);
1293  // DeviceEntity *entity = (*it).second->findEntity(name);
1294  // DeviceInstance *instance = dynamic_cast<DeviceInstance *>(entity);
1295  // if (instance)
1296  // bsuccess = (*it).second->deleteInstance(instance);
1297  // }
1298 
1299  // note as this is written it ignores lots of other containers
1300  // this may be used for clean up at the end of a run, but
1301  // it is not sufficient to use during simulation setup.
1302  //
1303  // need to remove pointer to the instance "name" from other arrays
1304  // candidate lists are:
1305  // InstanceVector instancePtrVec_;
1306  // InstanceVector bpInstancePtrVec_; // instances with breakpoints functions
1307  // InstanceVector pdeInstancePtrVec_;
1308  // InstanceVector nonPdeInstancePtrVec_;
1309  // InstanceVector mosfetInstancePtrVec_;
1310  // InstanceVector vsrcInstancePtrVec_;
1311  // InstanceVector bjtInstancePtrVec_;
1312  // std::map<std::string, VsrcInstance*> vsrcInstancePtrMap_;
1313  //
1314  // InstanceVector plotFileInstancePtrVec_;
1315  //
1316  // std::map<std::string,SourceInstance*> indepSourcePtrMap_;
1317  // std::vector<SourceInstance*> indepSourceInstancePtrVec_;
1318 
1319  return bsuccess;
1320 }
1321 
1322 //-----------------------------------------------------------------------------
1323 // Function : DeviceMgr::printOutLists
1324 // Purpose : This function will send output to stdout of all the
1325 // allocated model and instance lists.
1326 // Special Notes :
1327 // Scope : public
1328 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1329 // Creation Date : 4/03/00
1330 //-----------------------------------------------------------------------------
1331 // void DeviceMgr::printOutLists()
1332 // {
1333 // if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
1334 // {
1335 // for (DeviceMap::const_iterator it = deviceMap_.begin(); it != deviceMap_.end(); ++it)
1336 // printOutModels(dout(), *(*it).second);
1337 // }
1338 // }
1339 
1340 //-----------------------------------------------------------------------------
1341 // Function : DeviceMgr::debugOutput1
1342 // Purpose :
1343 // Special Notes :
1344 // Scope : public
1345 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1346 // Creation Date : 1/29/07
1347 //-----------------------------------------------------------------------------
1349 {
1350  // dump the fvector and the jdxp vector to files.
1352  {
1353  // To match the numbering scheme of the NLS debug output files,
1354  // it is neccessary to add +1 to the newton iterartion number.
1355  int outIter = solState_.newtonIter + 1;
1356 
1357  // f-vector
1358  char fn_fv[256]; for (int ich = 0; ich < 256; ++ich) fn_fv[ich] = 0;
1359  sprintf(fn_fv, "fvector.%03d.txt", outIter);
1360 
1361  // Note: this needs to change sign to match Spice.
1362  (externData_.fVectorPtr)->scale(-1.0);
1363  (externData_.fVectorPtr)->writeToFile(fn_fv);
1364  (externData_.fVectorPtr)->scale(-1.0);
1365 
1366  // jdxp-vector
1367  char fn_jdxp[256]; for (int ich = 0; ich < 256; ++ich) fn_jdxp[ich] = 0;
1368  sprintf(fn_jdxp, "Jdxp.%03d.txt", outIter);
1369  (externData_.JdxpVectorPtr)->writeToFile(fn_jdxp);
1370 
1371 #ifdef Xyce_DEBUG_VOLTLIM
1372  // the voltlim dx vector.
1373  char fn_dxvl[256]; for (int ich = 0; ich < 256; ++ich) fn_dxvl[ich] = 0;
1374  sprintf(fn_dxvl, "dxVL.%03d.txt", outIter);
1375  (externData_.dxVoltlimVectorPtr)->writeToFile(fn_dxvl);
1376 
1377  // jdx2-vector
1378  char fn_jdx2[256]; for (int ich = 0; ich < 256; ++ich) fn_jdx2[ich] = 0;
1379  sprintf(fn_jdx2, "Jdx2.%03d.txt", outIter);
1380  (externData_.Jdx2VectorPtr)->writeToFile(fn_jdx2);
1381 #endif
1382 
1383  }
1384 }
1385 
1386 //-----------------------------------------------------------------------------
1387 // Function : DeviceMgr::debugOutput2
1388 // Purpose : new-dae version
1389 // Special Notes :
1390 // Scope : public
1391 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1392 // Creation Date : 10/19/08
1393 //-----------------------------------------------------------------------------
1395 {
1396  // dump the fvector and the jdxp vector to files.
1398  {
1399  // To match the numbering scheme of the NLS debug output files,
1400  // it is neccessary to add +1 to the newton iterartion number.
1401  int newtonIter = solState_.newtonIter + 1;
1402  int outputStepNumber = 0;
1403 
1404  if (solState_.tranopFlag)
1405  {
1406  outputStepNumber = 0;
1407  }
1408  else if (solState_.initTranFlag)
1409  {
1410  outputStepNumber = solState_.timeStepNumber+1;
1411  }
1412  else
1413  {
1414  outputStepNumber = solState_.timeStepNumber+1;
1415  }
1416 
1417 #ifdef Xyce_DEBUG_VOLTLIM
1418  // the voltlim dx vector.
1419  char fn_dxvl[256]; for (int ich = 0; ich < 256; ++ich) fn_dxvl[ich] = 0;
1420  sprintf(fn_dxvl, "dxVL.%03d.%03d.txt", outputStepNumber, newtonIter);
1421  (externData_.dxVoltlimVectorPtr)->writeToFile(fn_dxvl);
1422 
1423  // Fdx2-vector
1424  char fn_fdx2[256]; for (int ich = 0; ich < 256; ++ich) fn_fdx2[ich] = 0;
1425  sprintf(fn_fdx2, "Fdx2.%03d.%03d.txt", outputStepNumber, newtonIter);
1426  (externData_.Fdx2VectorPtr)->writeToFile(fn_fdx2);
1427 
1428  // Qdx2-vector
1429  char fn_qdx2[256]; for (int ich = 0; ich < 256; ++ich) fn_qdx2[ich] = 0;
1430  sprintf(fn_qdx2, "Qdx2.%03d.%03d.txt", outputStepNumber, newtonIter);
1431  (externData_.Qdx2VectorPtr)->writeToFile(fn_qdx2);
1432 #endif
1433 
1434  }
1435 }
1436 
1437 //-----------------------------------------------------------------------------
1438 // Function : DeviceMgr::setInitialGuess
1439 // Purpose : This is a function call that sets the initial guess for
1440 // devices that have initial guesses.
1441 //
1442 // Special Notes :
1443 //
1444 // Scope : public
1445 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1446 // Creation Date : 5/02/03
1447 //-----------------------------------------------------------------------------
1448 bool DeviceMgr::setInitialGuess (N_LAS_Vector * solVectorPtr)
1449 {
1450  bool bsuccess = true;
1451 
1452  if (solVectorPtr != 0)
1453  {
1454  externData_.nextSolVectorPtr = solVectorPtr;
1455 
1456  // if two-level, and just the inner problem, only load the PDE devices.
1457  InstanceVector::iterator iter;
1458  InstanceVector::iterator begin;
1459  InstanceVector::iterator end;
1460 
1461  begin = pdeInstancePtrVec_.begin ();
1462  end = pdeInstancePtrVec_.end ();
1463  for (iter=begin; iter!=end;++iter)
1464  {
1465  bool tmpBool = (*iter)->setInitialGuess ();
1466  bsuccess = bsuccess && tmpBool;
1467  }
1468  }
1469 
1470  return bsuccess;
1471 }
1472 
1473 #ifdef Xyce_EXTDEV
1474 //-----------------------------------------------------------------------------
1475 // Function : DeviceMgr::setUpPassThroughParamsMap_()
1476 // Purpose :
1477 // Special Notes :
1478 // Scope : public
1479 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1480 // Creation Date :
1481 //-----------------------------------------------------------------------------
1482 void DeviceMgr::setUpPassThroughParamsMap_()
1483 {
1484  passThroughParamsMap_[ "MOSFET:GAINSCALE" ] = 1;
1485  passThroughParamsMap_[ "MOSFET:GAIN" ] = 1;
1486  passThroughParamsMap_[ "MOSFET:NLTERMSCALE" ] = 1;
1487  passThroughParamsMap_[ "MOSFET:NLTERM" ] = 1;
1488  passThroughParamsMap_[ "MOSFET_ALL:GAINSCALE" ] = 1;
1489  passThroughParamsMap_[ "MOSFET_ALL:NLTERMSCALE" ] = 1;
1490  passThroughParamsMap_[ "MOSFET1:GAINSCALE" ] = 1;
1491  passThroughParamsMap_[ "MOSFET1:NLTERMSCALE" ] = 1;
1492  passThroughParamsMap_[ "MOSFET:W" ] = 1;
1493  passThroughParamsMap_[ "MOSFET:L" ] = 1;
1494  passThroughParamsMap_[ "MOSFET:SIZESCALE" ] = 1;
1495  passThroughParamsMap_[ "MOSFET:TOX" ] = 1;
1496  passThroughParamsMap_[ "TEMP" ] = 1;
1497  passThroughParamsMap_[ "BJT:NF" ] = 1;
1498  passThroughParamsMap_[ "BJT:NR" ] = 1;
1499  passThroughParamsMap_[ "BJT:EXPORD" ] = 1;
1500  //passThroughParamsMap_[ "GSTEPPING" ] = 1;
1501 }
1502 #endif
1503 
1504 //-----------------------------------------------------------------------------
1505 // Function : DeviceMgr::setParam
1506 //
1507 // Purpose : This function sets named parameters (name) to a
1508 // specified value (val).
1509 //
1510 // Special Notes : Used for continuation calculations, as well as possibly
1511 // intrusive sensitivity/optimization calculations. It is
1512 // assumed that this is called after everything (devices,
1513 // solvers, etc.) is set up.
1514 //
1515 // The specified parameter can be either a natural or
1516 // artificial parameter.
1517 //
1518 //
1519 // Scope : public
1520 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1521 // Creation Date : 5/02/03
1522 //-----------------------------------------------------------------------------
1523 bool DeviceMgr::setParam (std::string & name, double val)
1524 {
1525  bool bsuccess = true, success = true;
1526  InstanceVector::const_iterator iter;
1527  InstanceVector::const_iterator begin;
1528  InstanceVector::const_iterator end;
1529 
1530  ModelVector::const_iterator iterM;
1531  ModelVector::const_iterator beginM;
1532  ModelVector::const_iterator endM;
1533 
1534  ExtendedString tmpName(name);
1535  tmpName.toUpper ();
1536 
1537  if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
1538  {
1539  std::string netListFile("");
1540  if (commandLine_.getArgumentValue(std::string("netlist")) != "")
1541  {
1542  netListFile = commandLine_.getArgumentValue(std::string("netlist"));
1543  }
1544 
1545  dout() << netListFile << "\t\t";
1546  dout() << "DeviceMgr::setParam. ";
1547  dout() << name;
1548  dout() << " " << val;
1549  dout() << std::endl;
1550  }
1551 
1552  // There are numerous special cases. Check these first:
1553  // check if this is one of the designated artificial parameters.
1554  if (tmpName == "MOSFET:GAINSCALE" ||
1555  tmpName == "MOSFET:GAIN")
1556  {
1557  solState_.gainScale[0] = val;
1558  solState_.artParameterFlag = true;
1559  }
1560  else if (tmpName == "MOSFET:NLTERMSCALE" ||
1561  tmpName == "MOSFET:NLTERM")
1562  {
1563  solState_.nltermScale = val;
1564  solState_.artParameterFlag = true;
1565  }
1566 #if 0
1567  else if (tmpName == "MOSFET_ALL:GAINSCALE")
1568  {
1569  solState_.gainScale[0] = val;
1570  solState_.mos1GainScale = val;
1571  solState_.mos3GainScale = val;
1572  solState_.artParameterFlag = true;
1573  solState_.mos1ArtParameterFlag = true;
1574  solState_.mos3ArtParameterFlag = true;
1575  }
1576  else if (tmpName == "MOSFET_ALL:NLTERMSCALE")
1577  {
1578  solState_.nltermScale = val;
1579  solState_.mos1NltermScale = val;
1580  solState_.mos3NltermScale = val;
1581  solState_.artParameterFlag = true;
1582  solState_.mos1ArtParameterFlag = true;
1583  solState_.mos3ArtParameterFlag = true;
1584  }
1585  else if (tmpName == "MOSFET_13:GAINSCALE")
1586  {
1587  solState_.mos1GainScale = val;
1588  solState_.mos3GainScale = val;
1589  solState_.mos1ArtParameterFlag = true;
1590  solState_.mos3ArtParameterFlag = true;
1591  }
1592  else if (tmpName == "MOSFET_13:NLTERMSCALE")
1593  {
1594  solState_.mos1NltermScale = val;
1595  solState_.mos3NltermScale = val;
1596  solState_.mos1ArtParameterFlag = true;
1597  solState_.mos3ArtParameterFlag = true;
1598  }
1599  else if (tmpName == "MOSFET1:GAINSCALE")
1600  {
1601  solState_.mos1GainScale = val;
1602  solState_.mos1ArtParameterFlag = true;
1603  }
1604  else if (tmpName == "MOSFET1:NLTERMSCALE")
1605  {
1606  solState_.mos1NltermScale = val;
1607  solState_.mos1ArtParameterFlag = true;
1608  }
1609  else if (tmpName == "MOSFET3:GAINSCALE")
1610  {
1611  solState_.mos3GainScale = val;
1612  solState_.mos3ArtParameterFlag = true;
1613  }
1614  else if (tmpName == "MOSFET3:NLTERMSCALE")
1615  {
1616  solState_.mos3NltermScale = val;
1617  solState_.mos3ArtParameterFlag = true;
1618  }
1619 #endif
1620  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_0")
1621  {
1622  solState_.gainScale[0] = val;
1623  solState_.artParameterFlag = true;
1624  }
1625  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_1")
1626  {
1627  solState_.gainScale[1] = val;
1628  solState_.artParameterFlag = true;
1629  }
1630  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_2")
1631  {
1632  solState_.gainScale[2] = val;
1633  solState_.artParameterFlag = true;
1634  }
1635  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_3")
1636  {
1637  solState_.gainScale[3] = val;
1638  solState_.artParameterFlag = true;
1639  }
1640  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_4")
1641  {
1642  solState_.gainScale[4] = val;
1643  solState_.artParameterFlag = true;
1644  }
1645  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_5")
1646  {
1647  solState_.gainScale[5] = val;
1648  solState_.artParameterFlag = true;
1649  }
1650  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_6")
1651  {
1652  solState_.gainScale[6] = val;
1653  solState_.artParameterFlag = true;
1654  }
1655  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_7")
1656  {
1657  solState_.gainScale[7] = val;
1658  solState_.artParameterFlag = true;
1659  }
1660  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_8")
1661  {
1662  solState_.gainScale[8] = val;
1663  solState_.artParameterFlag = true;
1664  }
1665  else if (tmpName == "MOSFET:GAINSCALE_BLOCK_9")
1666  {
1667  solState_.gainScale[9] = val;
1668  solState_.artParameterFlag = true;
1669  }
1670  else if (tmpName == "MOSFET:L")
1671  {
1673 
1674  double newL = val;
1675 
1676  // now loop over all the mosfet instances, and change the l.
1677  begin = mosfetInstancePtrVec_.begin ();
1678  end = mosfetInstancePtrVec_.end ();
1679  for (iter=begin; iter!=end;++iter)
1680  {
1681  std::string nameL("l");
1682  success = (*iter)->setParam (nameL, newL);
1683  success = success && (*iter)->processParams ();
1684  }
1685 
1686  }
1687  else if (tmpName == "MOSFET:W")
1688  {
1690  double newW = val;
1691 
1692  // now loop over all the mosfet instances, and change the w.
1693  begin = mosfetInstancePtrVec_.begin ();
1694  end = mosfetInstancePtrVec_.end ();
1695  for (iter=begin; iter!=end;++iter)
1696  {
1697  std::string nameW("w");
1698  success = (*iter)->setParam (nameW, newW);
1699  success = success && (*iter)->processParams ();
1700  }
1701 
1702  }
1703  else if (tmpName == "MOSFET:SIZESCALE")
1704  {
1706  solState_.sizeScale = val;
1707 
1708  // What we want at val = 0.0. For all the lengths and widths to have a
1709  // ratio of: L=5u W=175u or L=5u W=270u. Compromise. L/W = 5/200,
1710  // with L actually being 5u.
1711 
1712  double length0 = devOptions_.length0;
1713  double width0 = devOptions_.width0;
1714  // now loop over all the mosfet instances, and change the l, w.
1715  begin = mosfetInstancePtrVec_.begin ();
1716  end = mosfetInstancePtrVec_.end ();
1717  for (iter=begin; iter!=end;++iter)
1718  {
1719  std::string nameL("l");
1720  std::string nameW("w");
1721 
1722  success = (*iter)->scaleParam(nameL, solState_.sizeScale, length0);
1723  success = success || (*iter)->scaleParam(nameW, solState_.sizeScale, width0);
1724  success = success && (*iter)->processParams ();
1725  }
1726 
1727  }
1728  else if (tmpName == "MOSFET:TOX")
1729  {
1731  solState_.sizeScale = val;
1732 
1733  // What we want at val = 0.0. For all the lengths and widths to have a
1734  // ratio of: L=5u W=175u or L=5u W=270u. Compromise. L/W = 5/200,
1735  // with L actually being 5u.
1736 
1737  double tox0 = devOptions_.tox0;
1738 
1739  // loop over all the models and change tox.
1740  beginM = mosfetModelPtrVec_.begin ();
1741  endM = mosfetModelPtrVec_.end ();
1742  for (iterM=beginM; iterM!=endM;++iterM)
1743  {
1744  std::string nameTOX("tox");
1745 
1746  success = (*iterM)->scaleParam(nameTOX, solState_.sizeScale, tox0);
1747 
1748  success = success && (*iterM)->processParams ();
1749  success = success && (*iterM)->processInstanceParams ();
1750  }
1751 
1752  }
1753  else if (tmpName == "VSRCSCALE") // This scalar, val, is assumed to go from 0 to 1
1754  {
1755  int vsrcSize = vsrcInstancePtrVec_.size();
1756  for (int i=0;i<vsrcSize;++i)
1757  {
1758  bool s1 = vsrcInstancePtrVec_[i]->scaleDefaultParam (val);
1759  bool s2 = vsrcInstancePtrVec_[i]->processParams ();
1760  success = success && s1 && s2;
1761  }
1762  }
1763  else if (tmpName == "TEMP")
1764  {
1765  updateTemperature (val);
1766  }
1767  // if this is called, need to be running 2-level newton, and
1768  // need to have called "enablePDEContinuation" first.
1769  else if (tmpName == "PDEALPHA")
1770  {
1771  solState_.pdeAlpha = val; // not important - part of planned refactor.
1772 
1774  {
1775  Report::DevelFatal message;
1776  message << "DeviceMgr::setParam: tried to set pdeAlpha without first calling enablePDEContinuation";
1777  }
1778 
1779  // This should be part of the inner level solve for a 2-level
1780  // algorithm. Set this for the PDE devices.
1781  InstanceVector::iterator iter;
1782  InstanceVector::iterator begin;
1783  InstanceVector::iterator end;
1784  begin = instancePtrVec_.begin ();
1785  end = instancePtrVec_.end ();
1786 
1787  for (iter=begin; iter!=end;++iter)
1788  {
1789  (*iter)->setPDEContinuationAlpha (val);
1790  }
1791  }
1792  else if (tmpName == "PDEBETA")
1793  {
1795 
1796  InstanceVector::iterator iter;
1797  InstanceVector::iterator begin;
1798  InstanceVector::iterator end;
1799  begin = instancePtrVec_.begin ();
1800  end = instancePtrVec_.end ();
1801 
1802  for (iter=begin; iter!=end;++iter)
1803  {
1804  (*iter)->setPDEContinuationBeta (val);
1805  }
1806  }
1807  else if (tmpName == "PDECHARGEALPHA")
1808  {
1809  solState_.chargeAlpha = val;
1810  solState_.chargeHomotopy = true;
1811  }
1812  else if (tmpName == "BJT:BF")
1813  {
1814  double scale = val;
1815  std::string newBF("bf");
1816 
1817  // loop over all the models and change bf
1818  beginM = bjtModelPtrVec_.begin ();
1819  endM = bjtModelPtrVec_.end ();
1820  for (iterM=beginM; iterM!=endM;++iterM)
1821  {
1822  success = (*iterM)->scaleParam(newBF, scale, 0.0);
1823  success = success && (*iterM)->processParams();
1824  success = success && (*iterM)->processInstanceParams();
1825  }
1826  }
1827  else if (tmpName == "BJT:NF")
1828  {
1829  double scale = val;
1830  std::string newNF("nf");
1831 
1832  // loop over all the models and change nf
1833  beginM = bjtModelPtrVec_.begin ();
1834  endM = bjtModelPtrVec_.end ();
1835  for (iterM=beginM; iterM!=endM;++iterM)
1836  {
1837  success = (*iterM)->scaleParam(newNF, scale, 10.0);
1838  success = success && (*iterM)->processParams();
1839  success = success && (*iterM)->processInstanceParams();
1840  }
1841  }
1842  else if (tmpName == "BJT:NR")
1843  {
1844  double scale = val;
1845  std::string newNR("nr");
1846 
1847  // loop over all the models and change nr
1848  beginM = bjtModelPtrVec_.begin ();
1849  endM = bjtModelPtrVec_.end ();
1850  for (iterM=beginM; iterM!=endM;++iterM)
1851  {
1852  success = (*iterM)->scaleParam(newNR, scale, 10.0);
1853  success = success && (*iterM)->processParams();
1854  success = success && (*iterM)->processInstanceParams();
1855  }
1856  }
1857  else if (tmpName == "BJT:EXPORD")
1858  {
1859  devOptions_.exp_order = val;
1861  }
1862  else if (tmpName == "GSTEPPING")
1863  {
1864  // Do nothing!!!! This is not a device variable but is used by the
1865  // AugmentLinSys.
1866  }
1867  else if (tmpName == "DIODE:N")
1868  {
1869  double scale = val;
1870  std::string newN("n");
1871 
1872  // loop over all the models and change n
1873  beginM = diodeModelPtrVec_.begin ();
1874  endM = diodeModelPtrVec_.end ();
1875  for (iterM=beginM; iterM!=endM;++iterM)
1876  {
1877  success = (*iterM)->scaleParam(newN, scale, 10.0);
1878  success = success && (*iterM)->processParams();
1879  success = success && (*iterM)->processInstanceParams();
1880  }
1881  }
1882  else if (tmpName == "GMIN")
1883  {
1885  }
1886  else if (solState_.global_params.find(tmpName) != solState_.global_params.end())
1887  {
1888  if (solState_.global_params[tmpName] != val)
1889  {
1890  solState_.global_params[tmpName] = val;
1891  std::vector<DeviceEntity*>::iterator iter;
1892  std::vector<DeviceEntity*>::iterator begin = dependentPtrVec_.begin();
1893  std::vector<DeviceEntity*>::iterator end = dependentPtrVec_.end();
1894  for (iter=begin; iter!=end;++iter)
1895  {
1896  if ((*iter)->updateGlobalParameters (solState_.global_params));
1897  {
1898  (*iter)->processParams();
1899  (*iter)->processInstanceParams();
1900  }
1901  }
1902  }
1903  }
1904  else
1905  {
1906  // If not artificial, then search for the appropriate natural param(s).
1907  DeviceEntity * dePtr = getDeviceEntity(name);
1908 
1909 #ifdef Xyce_PARALLEL_MPI
1910  double foundParam = 0.0;
1911  double finalParam = 0.0;
1912 #endif
1913  bool entityFound = (dePtr!=0)?true:false;
1914 
1915  if (entityFound)
1916  {
1917  bool found;
1918  std::string paramName = Util::paramNameFromFullParamName(name);
1919  if (paramName == "")
1920  {
1921  found = dePtr->setDefaultParam (val);
1922  }
1923  else
1924  {
1925  found = dePtr->setParam (paramName, val);
1926  }
1927  if (found)
1928  {
1929  dePtr->processParams (); // if this "entity" is a model, then need to
1930  // also do a "processParams" on the related
1931  // instances.
1932  dePtr->processInstanceParams();
1933  }
1934 
1935 #ifdef Xyce_PARALLEL_MPI
1936  foundParam = found?1.0:0.0;
1937 #endif
1938  entityFound = found;
1939  }
1940 
1941 #ifdef Xyce_PARALLEL_MPI
1942  N_PDS_Comm * pdsCommPtr = pdsMgrPtr_->getPDSComm();
1943  pdsCommPtr->barrier();
1944  pdsCommPtr->sumAll(&foundParam, &finalParam, 1);
1945  entityFound = (finalParam != 0.0)?true:false;
1946 #endif
1947 
1948  if(!entityFound)
1949  {
1950  Report::UserFatal0 message;
1951  message << "Unable to find parameter " << name;
1952  }
1953  }
1954 
1955  // Certain parameters should be passed through to the inner solve,
1956  // if there is an inner circuit problem. The names of parameters
1957  // that should be passed through are stored in the map.
1958 #ifdef Xyce_EXTDEV
1959  if (passThroughParamsMap_.find(tmpName) != passThroughParamsMap_.end())
1960  {
1961 
1962  std::vector<ExternDevice::Instance*>::iterator iter;
1963  std::vector<ExternDevice::Instance*>::iterator begin;
1964  std::vector<ExternDevice::Instance*>::iterator end;
1965  begin = extDevInstancePtrVec_.begin ();
1966  end = extDevInstancePtrVec_.end ();
1967 
1968  for (iter=begin; iter!=end;++iter)
1969  {
1970  bool bs1 = (*iter)->setInternalParam (name, val);
1971  }
1972 
1973  }
1974 #endif
1975 
1976  return bsuccess;
1977 }
1978 
1979 //-----------------------------------------------------------------------------
1980 // Function : DeviceMgr::getParam
1981 // Purpose : Returns the current value of a named parameter.
1982 //
1983 // Special Notes : This works in parallel.
1984 //
1985 // If the parameter is not found, this function sets val to
1986 // 0.0, and returns a "false" boolean. It does not invoke the
1987 // error handler.
1988 //
1989 // Scope : public
1990 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1991 // Creation Date : 9/13/04
1992 //-----------------------------------------------------------------------------
1993 bool DeviceMgr::getParamAndReduce(const std::string & name, double & val)
1994 {
1995  val = 0.0;
1996  ExtendedString tmpName(name);
1997  tmpName.toUpper ();
1998  bool entityFound = false;
1999 
2000  // check if this is one of the designated artificial parameters.
2001  if (tmpName == "MOSFET:GAINSCALE")
2002  {
2003  val = solState_.gainScale[0];
2004  entityFound = true;
2005  }
2006  else if (tmpName == "MOSFET:NLTERMSCALE")
2007  {
2008  val = solState_.nltermScale;
2009  entityFound = true;
2010  }
2011  else if (tmpName == "MOSFET:L")
2012  {
2013  val = devOptions_.defl;
2014  entityFound = true;
2015  }
2016  else if (tmpName == "MOSFET:W")
2017  {
2018  val = devOptions_.defw;
2019  entityFound = true;
2020  }
2021  else if (tmpName == "TEMP")
2022  {
2023  val = devOptions_.temp.getImmutableValue<double>();
2024  val -= CONSTCtoK;
2025  entityFound = true;
2026  }
2027  else if (solState_.global_params.find(tmpName) != solState_.global_params.end())
2028  {
2029  val = solState_.global_params[tmpName];
2030  entityFound = true;
2031  }
2032  else
2033  {
2034  DeviceEntity * dePtr = getDeviceEntity(name);
2035  entityFound = dePtr != 0;
2036 
2037  if (entityFound)
2038  {
2039  std::string paramName = Util::paramNameFromFullParamName(name);
2040  entityFound = dePtr->getParam (paramName, val);
2041  if (paramName == "")
2042  entityFound = true;
2043  }
2044 
2045  if (!entityFound)
2046  outputMgrPtr_->getMeasureValue(tmpName, val, entityFound);
2047 
2048 #ifdef Xyce_PARALLEL_MPI
2049  double foundParam = entityFound ? 1 : 0;
2050  double finalParam = 0.0;
2051  double globalVal;
2052  N_PDS_Comm * pdsCommPtr = pdsMgrPtr_->getPDSComm();
2053  pdsCommPtr->barrier();
2054  pdsCommPtr->sumAll(&foundParam, &finalParam, 1);
2055  if (finalParam != 0.0)
2056  {
2057  entityFound = true;
2058  pdsCommPtr->sumAll(&val, &globalVal, 1);
2059  val = globalVal/finalParam;
2060  }
2061 #endif
2062  }
2063 
2064  return entityFound;
2065 }
2066 
2067 bool DeviceMgr::findParam(const std::string & name) const
2068 {
2069  ExtendedString tmpName(name);
2070  tmpName.toUpper ();
2071 
2072  bool entityFound = false;
2073 
2074  // check if this is one of the designated artificial parameters.
2075  if (tmpName == "MOSFET:GAINSCALE")
2076  {
2077  entityFound = true;
2078  }
2079  else if (tmpName == "MOSFET:NLTERMSCALE")
2080  {
2081  entityFound = true;
2082  }
2083  else if (tmpName == "MOSFET:L")
2084  {
2085  entityFound = true;
2086  }
2087  else if (tmpName == "MOSFET:W")
2088  {
2089  entityFound = true;
2090  }
2091  else if (tmpName == "TEMP")
2092  {
2093  entityFound = true;
2094  }
2095 
2096  return entityFound;
2097 }
2098 
2099 double DeviceMgr::getParamNoReduce(const std::string & name) const
2100 {
2101  double val = 0.0;
2102  ExtendedString tmpName(name);
2103  tmpName.toUpper ();
2104 
2105  // check if this is one of the designated artificial parameters.
2106  if (tmpName == "MOSFET:GAINSCALE")
2107  {
2108  val = solState_.gainScale[0];
2109  }
2110  else if (tmpName == "MOSFET:NLTERMSCALE")
2111  {
2112  val = solState_.nltermScale;
2113  }
2114  else if (tmpName == "MOSFET:L")
2115  {
2116  val = devOptions_.defl;
2117  }
2118  else if (tmpName == "MOSFET:W")
2119  {
2120  val = devOptions_.defw;
2121  }
2122  else if (tmpName == "TEMP")
2123  {
2124  val = devOptions_.temp.getImmutableValue<double>();
2125  val -= CONSTCtoK;
2126  }
2127 
2128  return val;
2129 }
2130 
2131 //-----------------------------------------------------------------------------
2132 // Function : DeviceMgr::getParam
2133 // Purpose : Returns the current value of a named parameter.
2134 //
2135 // Special Notes : This works in parallel.
2136 //
2137 // This is different than the other "getParam" function,
2138 // in that it generates a fatal error if the parameter is
2139 // not found.
2140 //
2141 // Scope : public
2142 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2143 // Creation Date : 7/26/03
2144 //-----------------------------------------------------------------------------
2145 double DeviceMgr::getParamAndReduce(const std::string & name)
2146 {
2147  bool bsuccess = false;
2148  double val = 0.0;
2149  bsuccess = getParamAndReduce(name,val);
2150 
2151  if(!bsuccess)
2152  {
2153  Report::UserFatal0 message;
2154  message << "Unable to find parameter " << name;
2155  }
2156 
2157  return val;
2158 }
2159 
2160 //-----------------------------------------------------------------------------
2161 // Function : DeviceMgr::getVsrcLIDs
2162 //
2163 // Purpose : Returns the LID of the voltage drop row from the named
2164 // voltage source.
2165 //
2166 // Special Notes :
2167 // Scope : public
2168 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2169 // Creation Date : 7/26/03
2170 //-----------------------------------------------------------------------------
2172  std::string & srcName, int & li_Pos, int & li_Neg, int & li_Bra)
2173 {
2174  ExtendedString tmpName(srcName);
2175  tmpName.toUpper();
2176  std::map<std::string, Vsrc::Instance *>::iterator iterVsrc = vsrcInstancePtrMap_.find(tmpName);
2177  if (iterVsrc != vsrcInstancePtrMap_.end())
2178  {
2179  Vsrc::Instance * vsrcPtr = iterVsrc->second;
2180  vsrcPtr->getLIDs(li_Pos,li_Neg,li_Bra);
2181  }
2182  else
2183  {
2184 #ifndef Xyce_PARALLEL_MPI
2185  Report::DevelFatal message;
2186  message << "DeviceMgr::getVoltageDropRow: Unable to find source: " << srcName;
2187 #endif
2188  }
2189 
2190  return true;
2191 }
2192 
2193 //-----------------------------------------------------------------------------
2194 // Function : DeviceMgr::updateState
2195 // Purpose : This should be called prior to loadDAEVectors.
2196 // Special Notes :
2197 // Scope : public
2198 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2199 // Creation Date : 11/17/05
2200 //-----------------------------------------------------------------------------
2202  N_LAS_Vector * nextSolVectorPtr,
2203  N_LAS_Vector * currSolVectorPtr,
2204  N_LAS_Vector * lastSolVectorPtr,
2205  N_LAS_Vector * nextStaVectorPtr,
2206  N_LAS_Vector * currStaVectorPtr,
2207  N_LAS_Vector * lastStaVectorPtr,
2208  N_LAS_Vector * nextStoVectorPtr,
2209  N_LAS_Vector * currStoVectorPtr,
2210  N_LAS_Vector * lastStoVectorPtr
2211  )
2212 {
2213  bool bsuccess = true;
2214  bool tmpBool = true;
2215 
2216  tmpBool = setupSolverInfo_();
2217  bsuccess = bsuccess && tmpBool;
2218 
2219  // copy over the passed pointers:
2220  externData_.nextSolVectorPtr = nextSolVectorPtr;
2221  externData_.currSolVectorPtr = currSolVectorPtr;
2222  externData_.lastSolVectorPtr = lastSolVectorPtr;
2223  externData_.nextStaVectorPtr = nextStaVectorPtr;
2224  externData_.currStaVectorPtr = currStaVectorPtr;
2225  externData_.lastStaVectorPtr = lastStaVectorPtr;
2226  externData_.nextStoVectorPtr = nextStoVectorPtr;
2227  externData_.currStoVectorPtr = currStoVectorPtr;
2228  externData_.lastStoVectorPtr = lastStoVectorPtr;
2229 
2230 #ifdef Xyce_PARALLEL_MPI
2231  externData_.nextSolVectorPtr->importOverlap();
2232 #endif
2233 
2234  // Now reset the relevant RAW pointers:
2244 
2245 
2247  // updateIntermediateVars_();
2248 
2249  // if inner problem, only do the PDE loads.
2251  {
2252  // call all the intermediate vars loads:
2253  std::vector<Device*>::iterator iter;
2254  std::vector<Device*>::iterator begin = pdeDevicePtrVec_.begin ();
2255  std::vector<Device*>::iterator end = pdeDevicePtrVec_.end ();
2256  for (iter=begin; iter!=end;++iter)
2257  {
2258  tmpBool = (*iter)->updateState (externData_.nextSolVectorRawPtr,
2260  bsuccess = bsuccess && tmpBool;
2261  }
2262  }
2263  else
2264  {
2265  int numDevices = devicePtrVec_.size();
2266  for(int i=0; i< numDevices; ++i)
2267  {
2268  bsuccess=devicePtrVec_.at(i)->updateState (externData_.nextSolVectorRawPtr,
2270  }
2271  }
2272 
2273 #ifdef Xyce_EXTDEV
2274  updateExternalDevices_();
2275 #endif
2276 
2277 #ifdef Xyce_PARALLEL_MPI
2278  externData_.nextStaVectorPtr->importOverlap();
2279  externData_.nextStoVectorPtr->importOverlap();
2280 #endif
2281 
2282  Report::safeBarrier(pdsMgrPtr_->getPDSComm()->comm());
2283 
2284  return true;
2285 }
2286 
2287 
2288 //-----------------------------------------------------------------------------
2289 // Function : DeviceMgr::loadDAEMatrices
2290 // Purpose : This function loads the various DAE related matrices to
2291 // set up the following expression:
2292 //
2293 // residual: f(x) = dQ/dt + F(x) - B(t) = 0
2294 //
2295 // jacobian: J(x) = d(dQ/dt)dx + dFdx
2296 // = d(dQdx)dt + dFdx
2297 //
2298 // Special Notes : ERK. This function is only called if using the new
2299 // (new-DAE) integrator. As such, it is also used for
2300 // MPDE. It is not used for the old (ODE) integrator.
2301 // The corresponding function for the old integrator
2302 // is loadJacobianMatrix
2303 //
2304 // Note that this function, unlike the loadJacobianMatrix
2305 // function *requires* that vector/matrix pointers
2306 // be passed in to the function. When
2307 // running in new-DAE or MPDE, we can't rely (much) on
2308 // registered vectors. (set up in initializeAll). In
2309 // particular, MPDE cycles through different vector and
2310 // matrix blocks, which each correspond to different
2311 // "fast" time points, and for each block the state
2312 // information is different.
2313 //
2314 // NOTE: This function assumes that all the load matrices
2315 // are zeroed out. That is, dFdx, dQdx are all zeros.
2316 //
2317 // If that isn't true, then this function will not produce
2318 // the correct answer. The reason for doing this
2319 // is MPDE. For the warped case, the entire linear system
2320 // needs to be zeroed out, but the full system includes
2321 // phase equations that never get passed in here.
2322 // That zeroing now happens upstream from here, in either
2323 // the MPDE loader or the time integrator.
2324 //
2325 // Scope : public
2326 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2327 // Creation Date : 03/03/04
2328 //-----------------------------------------------------------------------------
2330  (N_LAS_Vector * tmpSolVectorPtr,
2331  N_LAS_Vector * tmpStateVectorPtr,
2332  N_LAS_Vector * tmpStateDerivVectorPtr,
2333  N_LAS_Vector * tmpStoreVectorPtr,
2334  N_LAS_Matrix * tmpdQdxMatrixPtr,
2335  N_LAS_Matrix * tmpdFdxMatrixPtr)
2336 {
2337  bool bsuccess = true;
2338  bool tmpBool = true;
2339 
2340  // copy over the passed pointers:
2341  (externData_.nextSolVectorPtr) = tmpSolVectorPtr;
2342  bool resetRawMatrixPointers = true;
2343  if (
2344  (externData_.dQdxMatrixPtr == tmpdQdxMatrixPtr) &&
2345  (externData_.dFdxMatrixPtr == tmpdFdxMatrixPtr)
2346  )
2347  {
2348  resetRawMatrixPointers = false;
2349  }
2350  if (resetRawMatrixPointers)
2351  {
2352  externData_.dQdxMatrixPtr = tmpdQdxMatrixPtr;
2353  externData_.dFdxMatrixPtr = tmpdFdxMatrixPtr;
2354  }
2355 
2356  externData_.nextStaVectorPtr = tmpStateVectorPtr;
2357  externData_.nextStaDerivVectorPtr = tmpStateDerivVectorPtr;
2358  externData_.nextStoVectorPtr = tmpStoreVectorPtr;
2359 
2360  // setup the relevant RAW vector pointers:
2361  externData_.nextSolVectorRawPtr = &((*externData_.nextSolVectorPtr)[0]);
2362  externData_.nextStaVectorRawPtr = &((*externData_.nextStaVectorPtr)[0]);
2363  externData_.nextStaDerivVectorRawPtr = &((*externData_.nextStaDerivVectorPtr)[0]);
2364  externData_.nextStoVectorRawPtr = &((*externData_.nextStoVectorPtr)[0]);
2365 
2366 //#ifndef Xyce_NONPOINTER_MATRIX_LOAD
2367  // setup the relevant RAW matrix pointers (down in the devices that need them):
2368  if (resetRawMatrixPointers || solState_.blockAnalysisFlag)
2369  {
2370  this->setupRawMatrixPointers_();
2371  }
2372 //#endif
2373 
2374  InstanceVector::iterator iter;
2375  InstanceVector::iterator begin;
2376  InstanceVector::iterator end;
2377 
2378  // if this is an "inner problem" phase of a Two-Level Newton
2379  // simulation, then only load the PDE devices. Everything else just
2380  // gets "1" on the diagonal.
2381  //
2382  // Note, it is possible to just load 1's using a petra call, so I may
2383  // get rid of the "trivial" matrix stamp stuff soon.
2384 
2385  if (solState_.twoLevelNewtonCouplingMode==INNER_PROBLEM)
2386  {
2387  begin = nonPdeInstancePtrVec_.begin();
2388  end = nonPdeInstancePtrVec_.end();
2389  for (iter=begin; iter!=end;++iter)
2390  {
2391  (*iter)->loadTrivialDAE_FMatrixStamp ();
2392  }
2393 
2394  begin = pdeInstancePtrVec_.begin();
2395  end = pdeInstancePtrVec_.end();
2396  for (iter=begin; iter!=end;++iter)
2397  {
2398  tmpBool = (*iter)->loadDAEdQdx();bsuccess = bsuccess && tmpBool;
2399  tmpBool = (*iter)->loadDAEdFdx();bsuccess = bsuccess && tmpBool;
2400  }
2401  }
2402  // Else, do a normal analytical matrix load.
2403  else
2404  {
2405  int numDevices = devicePtrVec_.size();
2406  for(int i=0; i< numDevices; ++i)
2407  {
2408  bsuccess=devicePtrVec_.at(i)->loadDAEMatrices (*(externData_.dFdxMatrixPtr) , *(externData_.dQdxMatrixPtr));
2409  }
2410  }
2411 
2412  // Run jacobian diagnostic.
2413  if (devOptions_.testJacobianFlag &&
2414  (solState_.timeStepNumber >= devOptions_.testJacStartStep &&
2415  solState_.timeStepNumber <= devOptions_.testJacStopStep)
2416  )
2417  {
2418  if (DEBUG_DEVICE)
2419  devOptions_.debugLevel -= 2;
2420 
2421  // Test just the specified device(s), if the user specified any.
2422  if ((devOptions_.testJacDeviceNameGiven))
2423  {
2424  begin = testJacDevicePtrVec_.begin();
2425  end = testJacDevicePtrVec_.end();
2426  }
2427  else // Test all the devices:
2428  {
2429  begin = instancePtrVec_.begin();
2430  end = instancePtrVec_.end();
2431  }
2432 
2433  for (iter=begin; iter!=end;++iter)
2434  {
2435  (*iter)->testDAEMatrices (nameVec_);
2436  }
2437 
2438  if (DEBUG_DEVICE)
2439  devOptions_.debugLevel += 2;
2440  }
2441 
2442 #if 0
2443  // figure this stuff out later...
2444  // Add in terms for .IC initial conditions if DC OP
2445  if (solState_.twoLevelNewtonCouplingMode==INNER_PROBLEM)
2446  {
2447  if (icLoads_ != NULL && solState_.dcopFlag)
2448  {
2449  double diag = 10000.0;
2450  int size = icLoads_->size();
2451  for (int i = 0; i < size; ++i)
2452  externData_.JMatrixPtr->sumIntoRow((*icLoads_)[i].first, 1, &diag,
2453  &((*icLoads_)[i].first));
2454  }
2455  }
2456 #endif
2457 
2458  //Tell Jacobian, fill is complete allowing accumulation if necessary
2459  externData_.dQdxMatrixPtr->fillComplete();
2460  externData_.dFdxMatrixPtr->fillComplete();
2461 
2462  Report::safeBarrier(pdsMgrPtr_->getPDSComm()->comm());
2463 
2464  if (DEBUG_DEVICE && devOptions_.debugLevel > 1 && solState_.debugTimeFlag)
2465  {
2466  int newtonIter = solState_.newtonIter;
2467  dout() << section_divider << std::endl;
2468  dout() << "Q-matrix: nonlinear iteration = " << newtonIter << "\n";
2469  externData_.dQdxMatrixPtr->printPetraObject(dout());
2470  dout() << std::endl;
2471  dout() << section_divider << std::endl;
2472  dout() << "F-matrix: nonlinear iteration = " << newtonIter << "\n";
2473  externData_.dFdxMatrixPtr->printPetraObject(dout());
2474  dout() << std::endl;
2475  dout() << section_divider << std::endl;
2476  }
2477 
2478  return bsuccess;
2479 }
2480 
2481 //-----------------------------------------------------------------------------
2482 // Function : DeviceMgr::loadDAEVectors
2483 // Purpose : This function loads the various DAE related vectors to
2484 // set up the following expression:
2485 //
2486 // f(x) = dQ/dt + F(x) - B(t) = 0
2487 //
2488 // Special Notes : ERK. This function is only called if using the new
2489 // (new-DAE) integrator. As such, it is also used for
2490 // MPDE. It is not used for the old (ODE) integrator.
2491 // The corresponding function for the old integrator
2492 // is loadRHSVector.
2493 //
2494 // Note that this function, unlike the loadRHSVector
2495 // function *requires* that vectors be passed in. When
2496 // running in new-DAE or MPDE, we can't rely (much) on
2497 // registered vectors. (set up in initializeAll). In
2498 // particular, MPDE cycles through different vector and
2499 // matrix blocks, which each correspond to different
2500 // "fast" time points, and for each block the state
2501 // information is different.
2502 //
2503 // NOTE: This function assumes that all the load vectors
2504 // are zeroed out. That is, F, Q, B, dFdxdVp and dQdxVp
2505 // are all zeros.
2506 //
2507 // If that isn't true, then this function will not produce
2508 // the correct answer. The reason for doing this
2509 // is MPDE. For the warped case, the entire linear system
2510 // needs to be zeroed out, but the full system includes
2511 // phase equations that never get passed in here.
2512 //
2513 // That zeroing now happens upstream from here, in either
2514 // the MPDE loader or the time integrator.
2515 //
2516 // Scope : public
2517 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2518 // Creation Date : 01/26/03
2519 //-----------------------------------------------------------------------------
2521  (N_LAS_Vector * tmpSolVectorPtr,
2522  N_LAS_Vector * tmpCurrSolVectorPtr,
2523  N_LAS_Vector * tmpLastSolVectorPtr,
2524  N_LAS_Vector * tmpStaVectorPtr,
2525  N_LAS_Vector * tmpCurrStaVectorPtr,
2526  N_LAS_Vector * tmpLastStaVectorPtr,
2527  N_LAS_Vector * tmpStaDerivVectorPtr,
2528  N_LAS_Vector * tmpStoVectorPtr,
2529  N_LAS_Vector * tmpCurrStoVectorPtr,
2530  N_LAS_Vector * tmpLastStoVectorPtr,
2531  N_LAS_Vector * tmpStoLeadCurrQCompVectorPtr,
2532  N_LAS_Vector * tmpQVectorPtr,
2533  N_LAS_Vector * tmpFVectorPtr,
2534  N_LAS_Vector * tmpdFdxdVpVectorPtr,
2535  N_LAS_Vector * tmpdQdxdVpVectorPtr)
2536 {
2537  bool bsuccess = true;
2538  bool tmpBool = true;
2539 
2540  // copy over the passed pointers:
2541  externData_.nextSolVectorPtr = tmpSolVectorPtr;
2542  externData_.currSolVectorPtr = tmpCurrSolVectorPtr;
2543  externData_.lastSolVectorPtr = tmpLastSolVectorPtr;
2544  externData_.daeQVectorPtr = tmpQVectorPtr;
2545  externData_.daeFVectorPtr = tmpFVectorPtr;
2546  externData_.dFdxdVpVectorPtr = tmpdFdxdVpVectorPtr;
2547  externData_.dQdxdVpVectorPtr = tmpdQdxdVpVectorPtr;
2548  externData_.nextStaVectorPtr = tmpStaVectorPtr;
2549  externData_.currStaVectorPtr = tmpCurrStaVectorPtr;
2550  externData_.lastStaVectorPtr = tmpLastStaVectorPtr;
2551  externData_.storeLeadCurrQCompPtr = tmpStoLeadCurrQCompVectorPtr;
2552  externData_.nextStaDerivVectorPtr = tmpStaDerivVectorPtr;
2553  externData_.nextStoVectorPtr = tmpStoVectorPtr;
2554  externData_.currStoVectorPtr = tmpCurrStoVectorPtr;
2555  externData_.lastStoVectorPtr = tmpLastStoVectorPtr;
2556 
2557  // Make sure all boundary data is valid in the solution vector
2558 #ifdef Xyce_PARALLEL_MPI
2559  externData_.nextSolVectorPtr->importOverlap();
2560  externData_.nextStaDerivVectorPtr->importOverlap();
2561 #endif
2562 
2563  // Set up the relevant RAW Pointers:
2564  setupRawVectorPointers_ ();
2565 
2566  // call all the intermediate vars loads:
2567  std::vector<Device*>::iterator iter;
2568  std::vector<Device*>::iterator begin;
2569  std::vector<Device*>::iterator end;
2570 
2571  // if inner problem, only do the PDE loads.
2572  if (solState_.twoLevelNewtonCouplingMode==INNER_PROBLEM)
2573  {
2574  begin = pdeDevicePtrVec_.begin ();
2575  end = pdeDevicePtrVec_.end ();
2576  }
2577  else
2578  {
2579  begin = devicePtrVec_.begin ();
2580  end = devicePtrVec_.end ();
2581  }
2582 
2583  //updateDependentParameters_();
2584 
2585 #ifndef Xyce_EXCLUDE_SECONDARY_STATE
2586  for (iter=begin; iter!=end;++iter)
2587  {
2588  tmpBool = (*iter)->updateSecondaryState (externData_.nextStaDerivVectorRawPtr, externData_.nextStoVectorRawPtr);
2589  bsuccess = bsuccess && tmpBool;
2590  }
2591 #endif // Xyce_EXCLUDE_SECONDARY_STATE
2592 
2593 #ifdef Xyce_PARALLEL_MPI
2594  externData_.nextStaVectorPtr->importOverlap();
2595  externData_.nextStoVectorPtr->importOverlap();
2596 #endif
2597 
2598  if (solState_.twoLevelNewtonCouplingMode==INNER_PROBLEM)
2599  {
2600  int numDevices = pdeDevicePtrVec_.size();
2601  for(int i=0; i< numDevices; ++i)
2602  {
2603  bsuccess=pdeDevicePtrVec_.at(i)->loadDAEVectors(externData_.nextSolVectorRawPtr,
2604  externData_.daeFVectorRawPtr,
2605  externData_.daeQVectorRawPtr,
2606  externData_.nextStoVectorRawPtr,
2607  externData_.storeLeadCurrQCompRawPtr);
2608  }
2609  }
2610  else
2611  {
2612  int numDevices = devicePtrVec_.size();
2613  for(int i=0; i< numDevices; ++i)
2614  {
2615  bsuccess=devicePtrVec_.at(i)->loadDAEVectors(externData_.nextSolVectorRawPtr,
2616  externData_.daeFVectorRawPtr,
2617  externData_.daeQVectorRawPtr,
2618  externData_.nextStoVectorRawPtr,
2619  externData_.storeLeadCurrQCompRawPtr);
2620  }
2621  }
2622 
2623  // dump to the screen:
2624  if (DEBUG_DEVICE && devOptions_.debugLevel > 1 && solState_.debugTimeFlag)
2625  {
2626  int newtonIter = solState_.newtonIter;
2627  dout() << "Q-vector: nonlinear iteration = " << newtonIter << "\n";
2628  externData_.daeQVectorPtr->printPetraObject(std::cout);
2629  dout() << std::endl;
2630  dout() << "F-vector: nonlinear iteration = " << newtonIter << "\n";
2631  externData_.daeFVectorPtr->printPetraObject(std::cout);
2632  dout() << std::endl;
2633 
2634  if (devOptions_.voltageLimiterFlag)
2635  {
2636  dout() << "\n\n dFdxdVp vector: nonlinear iteration = " << newtonIter << "\n";
2637  externData_.dFdxdVpVectorPtr->printPetraObject(std::cout);
2638  dout() << std::endl;
2639  dout() << "\n\n dQdxdVp vector: nonlinear iteration = " << newtonIter << "\n";
2640  externData_.dQdxdVpVectorPtr->printPetraObject(std::cout);
2641  dout() << std::endl;
2642  }
2643 
2644  debugOutput2();
2645  }
2646 
2647  // Update parallel if necessary
2648  externData_.daeQVectorPtr->fillComplete();
2649  externData_.daeFVectorPtr->fillComplete();
2650  externData_.dFdxdVpVectorPtr->fillComplete();
2651  externData_.dQdxdVpVectorPtr->fillComplete();
2652 
2653  Report::safeBarrier(pdsMgrPtr_->getPDSComm()->comm());
2654 
2655 #ifdef Xyce_SIZEOF
2656  int size = sizeof(*this);
2657  dout() << "Size of device package after vector load = " << size << std::endl;
2658 #endif
2659 
2660  return true;
2661 }
2662 
2663 //-----------------------------------------------------------------------------
2664 // Function : DeviceMgr::loadDeviceMask ()
2665 // Purpose : let devices set elements of a mask telling the time
2666 // integrator what equations should be ignored in taking
2667 // weighted norms for error control purposes.
2668 // Special Notes : Devices should *only* zero internal variables, and then
2669 // only those that absolutely should never be used to
2670 // control step size (e.g. excess phase variables in BJTs)
2671 // Scope : public
2672 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
2673 // Creation Date : 01/18/07
2674 //-----------------------------------------------------------------------------
2676 {
2677 
2678  // call all the intermediate vars loads:
2679  InstanceVector::iterator iter;
2680  InstanceVector::iterator begin;
2681  InstanceVector::iterator end;
2682 
2683  begin = instancePtrVec_.begin ();
2684  end = instancePtrVec_.end ();
2685 
2686  nonTrivialDeviceMaskFlag = false;
2687 
2688  for (iter=begin; iter!=end;++iter)
2689  {
2690  nonTrivialDeviceMaskFlag |= (*iter)->loadDeviceMask();
2691  }
2692 
2693  externData_.deviceMaskVectorPtr->fillComplete();
2694 
2695  // make sure the system's flag reflects ours:
2696  externData_.lasSysPtr->setNonTrivialDeviceMaskFlag(nonTrivialDeviceMaskFlag);
2697 
2698  return nonTrivialDeviceMaskFlag;
2699 }
2700 
2701 //-----------------------------------------------------------------------------
2702 // Function : DeviceMgr::addGlobalPar ()
2703 // Purpose :
2704 // Special Notes :
2705 // Scope : public
2706 // Creator : Dave Shirley, PSSI
2707 // Creation Date : 11/18/05
2708 //-----------------------------------------------------------------------------
2709 void DeviceMgr::addGlobalPar (Util::Param & par)
2710 {
2711  int pos;
2712  if (par.getType() == Util::EXPR)
2713  {
2714  std::vector<std::string> variables, specials;
2715  std::vector<std::string>::iterator vs_i;
2716  double val;
2717 
2718  solState_.global_expressions.push_back(par.getValue<Util::Expression>());
2719  solState_.global_exp_names.push_back(par.uTag());
2720  pos = solState_.global_expressions.size()-1;
2721  Util::Expression *e = &(solState_.global_expressions[pos]);
2722  e->get_names(XEXP_VARIABLE, variables);
2723  e->get_names(XEXP_SPECIAL, specials);
2724  if (!specials.empty())
2725  {
2726  e->set_sim_time(solState_.currTime);
2727  }
2728  if (!variables.empty())
2729  {
2730  for (vs_i=variables.begin() ; vs_i!=variables.end() ; ++vs_i)
2731  e->set_var(*vs_i,solState_.global_params[*vs_i]);
2732  }
2733  e->evaluateFunction (val);
2734  solState_.global_params[par.uTag()] = val;
2735  }
2736  else
2737  {
2738  solState_.global_params[par.uTag()] = par.getImmutableValue<double>();
2739  }
2740 }
2741 
2742 
2743 //-----------------------------------------------------------------------------
2744 // Function : DeviceMgr::getGlobalPar ()
2745 // Purpose :
2746 // Special Notes :
2747 // Scope : public
2748 // Creator : Rich Schie, SNL, Electrical Systems Modeling
2749 // Creation Date : 01/25/13
2750 //-----------------------------------------------------------------------------
2751 double DeviceMgr::getGlobalPar (const std::string & parName) const
2752 {
2753  double retVal = 0;
2754  std::map<std::string,double>::const_iterator parLocItr = solState_.global_params.find(parName);
2755  if (parLocItr != solState_.global_params.end())
2756  {
2757  // extract the value for return
2758  retVal = parLocItr->second;
2759  }
2760  else
2761  {
2762  Report::UserFatal0 message;
2763  message << "Could not find global parameter \"" << parName << "\"";
2764  }
2765  return retVal;
2766 }
2767 
2768 const double *DeviceMgr::findGlobalPar (const std::string & parName) const
2769 {
2770  std::map<std::string,double>::const_iterator it = solState_.global_params.find(parName);
2771  if (it != solState_.global_params.end())
2772  return &(*it).second;
2773 
2774  return 0;
2775 }
2776 
2777 #if 0
2778 //-----------------------------------------------------------------------------
2779 // Function : DeviceMgr::loadPerturbationVector_ ()
2780 // Purpose : This function sets up the perturbation vector which
2781 // is needed in for the numerical Jacobian calculation.
2782 //
2783 // Special Notes : The formula is copied over from MPSalsa's num_jac_delta
2784 // function in the file rf_fill_num_jac.c.
2785 //
2786 // Note that the bracket operator uses *local* indexing.
2787 //
2788 // Scope : private
2789 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2790 // Creation Date : 6/21/00
2791 //-----------------------------------------------------------------------------
2792 
2793 bool DeviceMgr::loadPerturbationVector_()
2794 {
2795  int i;
2796  int isize = lasSysPtr_->getSolutionSize();
2797  for (i = 0; i < isize; ++i)
2798  (*(externData_.perturbVectorPtr))[i] =
2799  solState_.numJacSqrtEta *
2800  (1.0 + fabs((*(externData_.nextSolVectorPtr))[i]));
2801 
2802  return true;
2803 }
2804 #endif
2805 
2806 //-----------------------------------------------------------------------------
2807 // Function : DeviceMgr::updateIntermediateVars_
2808 // Purpose : This function calls updateIntermediateVars
2809 // for the current devices.
2810 // Special Notes :
2811 // Scope : private
2812 // Creator : Rich Schiek, SNL, Parallel Computational Sciences
2813 // Creation Date : 12/14/2006
2814 //-----------------------------------------------------------------------------
2816 {
2817  bool bsuccess = true;
2818 
2819  InstanceVector::iterator iter;
2820  InstanceVector::iterator begin =instancePtrVec_.begin();
2821  InstanceVector::iterator end =instancePtrVec_.end();
2822  for (iter=begin; iter!=end;++iter)
2823  {
2824  (*iter)->updateIntermediateVars ();
2825  }
2826 
2827  return bsuccess;
2828 }
2829 
2830 //-----------------------------------------------------------------------------
2831 // Function : DeviceMgr::updatePrimaryState_
2832 // Purpose : This function updates primary states
2833 // for the present time step.
2834 // Special Notes :
2835 // Scope : private
2836 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2837 // Creation Date : 6/21/00
2838 //-----------------------------------------------------------------------------
2840 {
2841  bool bsuccess = true;
2842 
2843  InstanceVector::iterator iter;
2844  InstanceVector::iterator begin =instancePtrVec_.begin();
2845  InstanceVector::iterator end =instancePtrVec_.end();
2846  for (iter=begin; iter!=end;++iter)
2847  {
2848  (*iter)->updatePrimaryState ();
2849  }
2850 
2851  return bsuccess;
2852 }
2853 
2854 //-----------------------------------------------------------------------------
2855 // Function : DeviceMgr::updateSecondaryState_
2856 // Purpose : This function function updates secondary states
2857 // for the present time step.
2858 // Special Notes :
2859 // Scope : private
2860 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2861 // Creation Date : 6/21/00
2862 //-----------------------------------------------------------------------------
2864 {
2865  bool bsuccess = true;
2866 
2867  InstanceVector::iterator iter;
2868  InstanceVector::iterator begin =instancePtrVec_.begin();
2869  InstanceVector::iterator end =instancePtrVec_.end();
2870  for (iter=begin; iter!=end;++iter)
2871  {
2872  (*iter)->updateSecondaryState ();
2873  }
2874 
2875  return bsuccess;
2876 }
2877 
2878 //----------------------------------------------------------------------------
2879 // Function : DeviceMgr::updateDependentParameters_
2880 // Purpose : This function updates all dependent parameters for
2881 // the current time step.
2882 // Special Notes : This was evolved from updateTimeDependentParameters_
2883 // Scope : private
2884 // Creator : Dave Shirley
2885 // Creation Date : 08/17/06
2886 //----------------------------------------------------------------------------
2888 {
2889  bool bsuccess = true;
2890  bool tmpBool = true;
2891  N_LAS_Vector * solVectorPtr = externData_.nextSolVectorPtr;
2892 
2893  std::map<std::string,double> & gp = solState_.global_params;
2894  std::vector<Util::Expression> & ge = solState_.global_expressions;
2895 
2897  parameterChanged_ = true;
2898  if (!ge.empty())
2899  {
2900  // Update global params for new time and other global params
2901  std::vector<std::string> variables;
2902  std::vector<std::string>::iterator vs_i;
2903  std::vector<std::string>::iterator vs_end;
2904  double val;
2905  bool changed;
2906 
2907  int pos = 0;
2908  std::vector<Util::Expression>::iterator g_i = ge.begin();
2909  std::vector<Util::Expression>::iterator g_end = ge.end();
2910  for (; g_i != g_end; ++g_i)
2911  {
2912  changed = false;
2913  g_i->get_names(XEXP_VARIABLE, variables);
2914  if (g_i->set_sim_time(solState_.currTime))
2915  changed = true;
2916  if (!variables.empty())
2917  {
2918  vs_i=variables.begin();
2919  vs_end=variables.end();
2920  for (; vs_i!=vs_end; ++vs_i)
2921  {
2922  if (g_i->set_var(*vs_i,gp[*vs_i]))
2923  changed = true;
2924  }
2925  }
2926  if (changed)
2927  {
2928  parameterChanged_ = true;
2929  g_i->evaluateFunction (val);
2930  gp[solState_.global_exp_names[pos]] = val;
2931  }
2932  ++pos;
2933  }
2934  }
2935 
2936  // do the models:
2937  if (firstDependent)
2938  {
2939  dependentPtrVec_.clear();
2940  firstDependent = false;
2941 
2942  ModelVector::iterator iterM;
2943  ModelVector::iterator beginM =modelPtrVec_.begin();
2944  ModelVector::iterator endM =modelPtrVec_.end();
2945  for (iterM=beginM; iterM!=endM;++iterM)
2946  {
2947  if (!(*iterM)->getDependentParams().empty())
2948  {
2949  dependentPtrVec_.push_back(static_cast<DeviceEntity *>(*iterM));
2950  tmpBool = (*iterM)->updateGlobalParameters(gp);
2951  bsuccess = bsuccess && tmpBool;
2952  tmpBool = (*iterM)->updateDependentParameters (*solVectorPtr);
2953  bsuccess = bsuccess && tmpBool;
2954  (*iterM)->processParams();
2955  (*iterM)->processInstanceParams();
2956  }
2957  }
2958 
2959  // do the instances
2960  InstanceVector::iterator iter;
2961  InstanceVector::iterator begin =instancePtrVec_.begin();
2962  InstanceVector::iterator end =instancePtrVec_.end();
2963  for (iter=begin; iter!=end;++iter)
2964  {
2965  if (!(*iter)->getDependentParams().empty())
2966  {
2967  dependentPtrVec_.push_back(static_cast<DeviceEntity *>(*iter));
2968  tmpBool = (*iter)->updateGlobalParameters (gp);
2969  bsuccess = bsuccess && tmpBool;
2970  tmpBool = (*iter)->updateDependentParameters (*solVectorPtr);
2971  bsuccess = bsuccess && tmpBool;
2972  (*iter)->processParams();
2973  }
2974  }
2975  }
2976  else
2977  {
2978  bool changed;
2979  std::vector<DeviceEntity*>::iterator iter;
2980  std::vector<DeviceEntity*>::iterator begin = dependentPtrVec_.begin();
2981  std::vector<DeviceEntity*>::iterator end = dependentPtrVec_.end();
2982  for (iter=begin; iter!=end;++iter)
2983  {
2984  changed = false;
2985  if (parameterChanged_)
2986  {
2987  tmpBool = (*iter)->updateGlobalParameters (gp);
2988  changed = changed || tmpBool;
2989  bsuccess = bsuccess && tmpBool;
2990  }
2991  tmpBool = (*iter)->updateDependentParameters (*solVectorPtr);
2992  changed = changed || tmpBool;
2993  bsuccess = bsuccess && tmpBool;
2994  if (changed)
2995  {
2996  (*iter)->processParams();
2997  (*iter)->processInstanceParams();
2998  }
2999  }
3000  }
3002  parameterChanged_ = false;
3003 
3004  return bsuccess;
3005 }
3006 
3007 
3008 //-----------------------------------------------------------------------------
3009 // Function : DeviceMgr::loadBVectorsforAC
3010 // Purpose : This function loads the B-vector contributions for sources.
3011 // Special Notes :
3012 // Scope : public
3013 // Creator : Ting Mei, SNL
3014 // Creation Date :
3015 //-----------------------------------------------------------------------------
3016 bool DeviceMgr::loadBVectorsforAC(N_LAS_Vector * bVecRealPtr,
3017  N_LAS_Vector * bVecImagPtr)
3018 {
3019  bool bsuccess = true;
3020 
3021 // setupSolverInfo_ ();
3022 
3023 // copy over the passed pointers:
3024  externData_.bVecRealPtr = bVecRealPtr;
3025  externData_.bVecImagPtr = bVecImagPtr;
3026 
3027 #ifdef Xyce_PARALLEL_MPI
3028  externData_.nextSolVectorPtr->importOverlap();
3029 #endif
3030  // Now reset the relevant RAW pointers:
3033 
3034  std::vector<SourceInstance*>::iterator vIter;
3035  std::vector<SourceInstance*>::iterator vBegin =indepSourceInstancePtrVec_.begin();
3036  std::vector<SourceInstance*>::iterator vEnd =indepSourceInstancePtrVec_.end();
3037  for (vIter=vBegin; vIter!=vEnd;++vIter)
3038  {
3039  (*vIter)->loadBVectorsforAC(externData_.bVecRealRawPtr, externData_.bVecImagRawPtr);
3040  }
3041 
3042  return bsuccess;
3043 }
3044 
3045 //-----------------------------------------------------------------------------
3046 // Function : DeviceMgr::getBMatrixEntriesforMOR()
3047 // Purpose : This function obtains the indices for the B-vector contributions for sources.
3048 // Special Notes :
3049 // Scope : public
3050 // Creator : Heidi Thornquist and Ting Mei, SNL
3051 // Creation Date :
3052 //-----------------------------------------------------------------------------
3053 bool DeviceMgr::getBMatrixEntriesforMOR(std::vector<int>& bMatEntriesVec,
3054  std::vector<int>& bMatPosEntriesVec)
3055 {
3056  bool bsuccess = true;
3057 
3058  int lpos, lneg, lbra;
3059  std::vector<SourceInstance *>::iterator vIter;
3060  std::vector<SourceInstance *>::iterator vBegin = indepSourceInstancePtrVec_.begin();
3061  std::vector<SourceInstance *>::iterator vEnd = indepSourceInstancePtrVec_.end();
3062 
3063  for (vIter=vBegin; vIter!=vEnd;++vIter)
3064  {
3065  Vsrc::Instance* vsrc = dynamic_cast<Vsrc::Instance *>(*vIter);
3066  if (vsrc != 0)
3067  {
3068  vsrc->getLIDs(lpos, lneg, lbra);
3069  bMatEntriesVec.push_back(lbra);
3070  bMatPosEntriesVec.push_back(lpos);
3071  }
3072  }
3073 
3074  return bsuccess;
3075 }
3076 
3077 //-----------------------------------------------------------------------------
3078 // Function : DeviceMgr::updateSources
3079 // Purpose : This function function updates sources for the present
3080 // time step.
3081 // Special Notes :
3082 // Scope : public
3083 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
3084 // Creation Date : 5/26/00
3085 //-----------------------------------------------------------------------------
3087 {
3088  bool bsuccess = true;
3089 
3090  setupSolverInfo_ ();
3091 
3092  std::vector<SourceInstance*>::iterator vIter;
3093  std::vector<SourceInstance*>::iterator vBegin =indepSourceInstancePtrVec_.begin();
3094  std::vector<SourceInstance*>::iterator vEnd =indepSourceInstancePtrVec_.end();
3095  for (vIter=vBegin; vIter!=vEnd;++vIter)
3096  {
3097  (*vIter)->updateSource();
3098  }
3099 
3100  return bsuccess;
3101 }
3102 
3103 //-----------------------------------------------------------------------------
3104 // Function : DeviceMgr::setICs
3105 // Purpose : This function function sets initial conditions for devices
3106 // Special Notes :
3107 // Scope : public
3108 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
3109 // Creation Date : 9/13/00
3110 //-----------------------------------------------------------------------------
3112  N_LAS_Vector * tmpSolVectorPtr,
3113  N_LAS_Vector * tmpCurrSolVectorPtr,
3114  N_LAS_Vector * tmpLastSolVectorPtr,
3115  N_LAS_Vector * tmpStaVectorPtr,
3116  N_LAS_Vector * tmpCurrStaVectorPtr,
3117  N_LAS_Vector * tmpLastStaVectorPtr,
3118  N_LAS_Vector * tmpStaDerivVectorPtr,
3119  N_LAS_Vector * tmpStoVectorPtr,
3120  N_LAS_Vector * tmpCurrStoVectorPtr,
3121  N_LAS_Vector * tmpLastStoVectorPtr,
3122  N_LAS_Vector * tmpQVectorPtr,
3123  N_LAS_Vector * tmpFVectorPtr,
3124  N_LAS_Vector * tmpdFdxdVpVectorPtr,
3125  N_LAS_Vector * tmpdQdxdVpVectorPtr)
3126 {
3127  bool bsuccess = true;
3128 
3129  // copy over the passed pointers:
3130  externData_.nextSolVectorPtr = tmpSolVectorPtr;
3131  externData_.currSolVectorPtr = tmpCurrSolVectorPtr;
3132  externData_.lastSolVectorPtr = tmpLastSolVectorPtr;
3133  externData_.daeQVectorPtr = tmpQVectorPtr;
3134  externData_.daeFVectorPtr = tmpFVectorPtr;
3135  externData_.dFdxdVpVectorPtr = tmpdFdxdVpVectorPtr;
3136  externData_.dQdxdVpVectorPtr = tmpdQdxdVpVectorPtr;
3137  externData_.nextStaVectorPtr = tmpStaVectorPtr;
3138  externData_.currStaVectorPtr = tmpCurrStaVectorPtr;
3139  externData_.lastStaVectorPtr = tmpLastStaVectorPtr;
3140  externData_.nextStaDerivVectorPtr = tmpStaDerivVectorPtr;
3141  externData_.nextStoVectorPtr = tmpStoVectorPtr;
3142  externData_.currStoVectorPtr = tmpCurrStoVectorPtr;
3143  externData_.lastStoVectorPtr = tmpLastStoVectorPtr;
3144 
3145  // Make sure all boundary data is valid in the solution vector
3146 #ifdef Xyce_PARALLEL_MPI
3147  externData_.nextSolVectorPtr->importOverlap();
3148  externData_.nextStaDerivVectorPtr->importOverlap();
3149 #endif
3150 
3151  // if IC's on devices are set, we need to ensure that the
3152  // raw pointers are up to date first.
3154 
3155  InstanceVector::iterator iter;
3156  InstanceVector::iterator begin =instancePtrVec_.begin();
3157  InstanceVector::iterator end =instancePtrVec_.end();
3158  for (iter=begin; iter!=end;++iter)
3159  {
3160  (*iter)->setIC ();
3161  }
3162 
3163  return bsuccess;
3164 }
3165 
3166 //-----------------------------------------------------------------------------
3167 // Function : DeviceMgr::getLinearSystemFlag
3168 // Purpose :
3169 // Special Notes :
3170 // Scope : public
3171 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3172 // Creation Date : 10/17/00
3173 //-----------------------------------------------------------------------------
3175 {
3176  return linearSystemFlag_;
3177 }
3178 
3179 //-----------------------------------------------------------------------------
3180 // Function : DeviceMgr::getVoltageLimiterFlag
3181 // Purpose :
3182 // Special Notes :
3183 // Scope : public
3184 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3185 // Creation Date : 03/11/04
3186 //-----------------------------------------------------------------------------
3188 {
3190 }
3191 
3192 //-----------------------------------------------------------------------------
3193 // Function : DeviceMgr::getPDESystemFlag
3194 // Purpose :
3195 // Special Notes :
3196 // Scope : public
3197 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3198 // Creation Date : 04/25/01
3199 //-----------------------------------------------------------------------------
3201 {
3202  return solState_.PDESystemFlag;
3203 }
3204 
3205 //-----------------------------------------------------------------------------
3206 // Function : DeviceMgr::runParameterTests
3207 // Purpose : The purpose of this function is to test out the processing
3208 // of various device parameters.
3209 // Special Notes :
3210 // Scope : public
3211 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3212 // Creation Date : 02/14/01
3213 //-----------------------------------------------------------------------------
3214 bool DeviceMgr::runParameterTests(std::string & deviceName)
3215 {
3216  bool bsuccess = true;
3217 
3218  return bsuccess;
3219 }
3220 
3221 //-----------------------------------------------------------------------------
3222 // Function : DeviceMgr::output
3223 // Purpose :
3224 // Special Notes :
3225 // Scope : public
3226 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3227 // Creation Date : 4/13/01
3228 //-----------------------------------------------------------------------------
3230 {
3231  bool bsuccess = true;
3232  bool tmpBool = true;
3233 
3234  InstanceVector::iterator iter;
3235  InstanceVector::iterator begin = plotFileInstancePtrVec_.begin ();
3236  InstanceVector::iterator end = plotFileInstancePtrVec_.end ();
3237  for (iter=begin; iter!=end;++iter)
3238  {
3239  tmpBool = (*iter)->outputPlotFiles ();
3240  bsuccess = bsuccess && tmpBool;
3241  }
3242 
3243  // only output .OP information once.
3245  {
3246  dotOpOutput();
3247  }
3248 
3249  return bsuccess;
3250 }
3251 
3252 //-----------------------------------------------------------------------------
3253 // Function : DeviceMgr::finishOutput
3254 // Purpose : Same as output, only this one forces the output.
3255 //
3256 // Special Notes : This function was neccessary with the implementation of
3257 // outputInterval. The final output, which needs to
3258 // happen after the transient is over, won't neccessarily
3259 // happen with outputInterval enabled.
3260 //
3261 // Scope : public
3262 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3263 // Creation Date : 6/19/04
3264 //-----------------------------------------------------------------------------
3266 {
3267  bool bsuccess = true;
3268  bool tmpBool = true;
3269 
3270  solState_.forceFinalOutput = true;
3271  tmpBool = output ();
3272  bsuccess = bsuccess && tmpBool;
3273  solState_.forceFinalOutput = false;
3274 
3275  return bsuccess;
3276 }
3277 
3278 //-----------------------------------------------------------------------------
3279 // Function : DeviceMgr::dotOpOutput
3280 // Purpose :
3281 // Special Notes : This is a quick-and-dirty implementation, to get something
3282 // working quickly.
3283 // Scope : public
3284 // Creator : Eric R. Keiter, SNL
3285 // Creation Date : 5/3/12
3286 //-----------------------------------------------------------------------------
3288 {
3289  dotOpOutputFlag = true;
3290 
3291  std::map<std::string, Device *> device_map;
3292  for (EntityTypeIdDeviceMap::const_iterator it = deviceMap_.begin(); it != deviceMap_.end(); ++it)
3293  device_map[(*it).second->getName()] = (*it).second;
3294 
3295  lout() << section_divider << "\n"
3296  << "Operating point information:";
3297 
3298  for (std::map<std::string, Device *>::const_iterator it = device_map.begin(); it != device_map.end(); ++it)
3299  Xyce::Device::printDotOpOutput(lout(), *(*it).second);
3300 
3301  lout() << section_divider << std::endl;
3302 }
3303 
3304 //-----------------------------------------------------------------------------
3305 // Function : DeviceMgr::setGlobalFlags
3306 // Purpose :
3307 // Special Notes :
3308 // Scope : public
3309 // Creator : Eric R. Keiter, SNL
3310 // Creation Date : 11/2/12
3311 //-----------------------------------------------------------------------------
3313 {
3314 #ifdef Xyce_PARALLEL_MPI
3315  // just in case this has not been synchronized in parallel
3316  double pdeSys_glob=0.0;
3317  double pdeSys_par = solState_.PDESystemFlag?1.0:0.0;
3318 
3319  N_PDS_Comm *pdsCommPtr = pdsMgrPtr_->getPDSComm();
3320  pdsCommPtr->barrier();
3321  pdsCommPtr->sumAll(&pdeSys_par, &pdeSys_glob, 1);
3322  solState_.PDESystemFlag = (pdeSys_glob != 0.0)?true:false;
3323 
3324 #if 0
3326  dout() << "PDESystemFlag = TRUE"<<std::endl;
3327  else
3328  dout() << "PDESystemFlag = FALSE"<<std::endl;
3329 #endif
3330 #endif
3331 
3332  return;
3333 }
3334 
3335 //-----------------------------------------------------------------------------
3336 // Function : DeviceMgr::getBreakPoints
3337 // Purpose :
3338 // Special Notes :
3339 // Scope : public
3340 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3341 // Creation Date : 6/08/01
3342 //-----------------------------------------------------------------------------
3343 bool DeviceMgr::getBreakPoints (std::vector<Util::BreakPoint> & breakPointTimes)
3344 {
3345  InstanceVector::iterator iterI;
3346  ModelVector::iterator iterM;
3347  bool bsuccess = true;
3348  bool tmpBool = true;
3349 
3350  tmpBool = setupSolverInfo_();
3351  bsuccess = bsuccess && tmpBool;
3353 
3354  // For some devices we only need to set breakpoints caused by discontinuities
3355  // in their parameters:
3356 
3357  for (iterM = modelPtrVec_.begin() ; iterM != modelPtrVec_.end() ; ++iterM)
3358  {
3359  if (!(*iterM)->getDependentParams().empty())
3360  {
3361  tmpBool = (*iterM)->getParamBreakpoints(breakPointTimes);
3362  bsuccess = bsuccess && tmpBool;
3363  }
3364  }
3365 
3366  for (iterI = instancePtrVec_.begin() ; iterI != instancePtrVec_.end() ; ++iterI)
3367  {
3368  if (!(*iterI)->getDependentParams().empty())
3369  {
3370  tmpBool = (*iterI)->getParamBreakpoints(breakPointTimes);
3371  bsuccess = bsuccess && tmpBool;
3372  }
3373  }
3374 
3375  // Breakpoints for global params:
3376  std::vector<Util::Expression>::iterator globalExp_i =
3377  solState_.global_expressions.begin();
3378  std::vector<Util::Expression>::iterator globalExp_end =
3380  for (; globalExp_i != globalExp_end; ++globalExp_i)
3381  {
3382  double bTime = globalExp_i->get_break_time();
3383  if (bTime > solState_.currTime)
3384  breakPointTimes.push_back(bTime);
3385  }
3386 
3388  {
3389  InstanceVector::iterator beginI = instancePtrVec_.begin ();
3390  InstanceVector::iterator endI = instancePtrVec_.end ();
3391 
3392  for (iterI=beginI;iterI!=endI;++iterI)
3393  {
3394  // this function returns false if it is the base class, and true otherwise.
3395  bool functionSetup = (*iterI)->getInstanceBreakPoints (breakPointTimes);
3396  if (functionSetup)
3397  {
3398  bpInstancePtrVec_.push_back(*iterI);
3399  }
3400  }
3402  }
3403  else
3404  {
3405  InstanceVector::iterator beginI = bpInstancePtrVec_.begin ();
3406  InstanceVector::iterator endI = bpInstancePtrVec_.end ();
3407  for (iterI=beginI;iterI!=endI;++iterI)
3408  {
3409  bool functionSetup = (*iterI)->getInstanceBreakPoints (breakPointTimes);
3410  }
3411  }
3412 
3413 #ifdef Xyce_EXTDEV
3414  std::vector<ExternDevice::Instance*>::iterator iter;
3415  std::vector<ExternDevice::Instance*>::iterator begin;
3416  std::vector<ExternDevice::Instance*>::iterator end;
3417  begin = extDevInstancePtrVec_.begin ();
3418  end = extDevInstancePtrVec_.end ();
3419  for (iter=begin; iter!=end;++iter)
3420  {
3421  (*iter)->getBreakPoints (breakPointTimes);
3422  }
3423 #endif
3424 
3425  return bsuccess;
3426 
3427 }
3428 
3429 //-----------------------------------------------------------------------------
3430 // Function : DeviceMgr::setupSolverInfo_
3431 //
3432 // Purpose :
3433 //
3434 // Special Notes : This function gets called a lot, and this can be kind of
3435 // confusing. Probably, this function is being used to handle
3436 // too many different types of data.
3437 //
3438 // For example, it gets called at the beginning
3439 // of the "updateSources" function. Why? Because the sources
3440 // need to know which step we are at, and/or what the current
3441 // time is, to do their update properly.
3442 //
3443 // However, at the moment, updateSources also provides
3444 // information that setupSolverInfo needs. Only after the
3445 // sources have been updated do we know if a sweep source has
3446 // been reset. And, the sweepSourceResetFlag is used by
3447 // setupSolverInfo, to set up the initJctFlag boolean.
3448 // So it will need to be called at least one more
3449 // time, at the beginning of the RHS load. (which it is).
3450 //
3451 // Anyway, any of the functions that are called from the
3452 // outside, such as: updateSources, loadRHSVector,
3453 // loadJacobianMatrix, etc.... have no way of knowing when,
3454 // w.r.t. the solvers they are being called. The only way
3455 // to do this properly is to have each of them request
3456 // the current solver state, before they go to do their
3457 // work. Hence, this function is called a lot.
3458 //
3459 // Unfortunately, this has led to a somewhat sloppy and
3460 // confusing interface between the solvers and the
3461 // device package. I wanted to avoid having a lot of
3462 // function arguments being passed around for each of
3463 // these functions, in part because the calling code
3464 // (NLS) doesn't know everything. - NLS knows about the newton
3465 // step, but it doesn't know the time step, for example.
3466 //
3467 // At some point I hope to refactor this.
3468 //
3469 // Scope : private
3470 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3471 // Creation Date : 7/30/01
3472 //-----------------------------------------------------------------------------
3474 {
3475  bool bsuccess = true;
3476 
3477  N_TIA_TimeIntInfo & tiInfo = solState_.tiInfo;
3478  N_NLS_NonLinInfo & nlInfo = solState_.nlInfo;
3479 
3480  // Time integration info:
3481  anaIntPtr_->getTimeIntInfo(tiInfo);
3482  solState_.pdt = tiInfo.pdt;
3485  solState_.currTime = tiInfo.nextTime;
3486  solState_.finalTime = tiInfo.finalTime;
3488  solState_.bpTol = tiInfo.bpTol;
3489  solState_.currentOrder = tiInfo.currentOrder; // BNB
3490  solState_.usedOrder = tiInfo.usedOrder; // BNB
3491 
3492  if (solState_.mpdeOnFlag == 1)
3493  {
3494  solState_.dcopFlag = 0;
3495  solState_.initTranFlag = 1;
3497  }
3498  else
3499  {
3500  solState_.dcopFlag = tiInfo.dcopFlag;
3503  }
3504 
3506  solState_.acopFlag = tiInfo.acopFlag;
3507  solState_.tranopFlag = tiInfo.tranopFlag;
3511 
3513 // solState_.initTranFlag = tiInfo.initTranFlag;
3514 // solState_.beginIntegrationFlag = tiInfo.beginIntegrationFlag;
3515 
3519 
3520  // Nonlinear solver info:
3521  nlsMgrPtr_->getNonLinInfo(nlInfo);
3522  solState_.newtonIter = nlInfo.newtonIter;
3524 
3525  // Get LOCA-specific information. Note - in general, LOCA is only used for
3526  // steady state calculations - there isn't much point in using it
3527  // for transient. A common case is one where LOCA is used for the
3528  // tranOP, but not for the subsequent transient phase. The
3529  // locaEnabledFlag should switch from true to false under
3530  // that scenario, once the transient phase starts.
3532  if (solState_.locaEnabledFlag) // if no LOCA, these are 0, true, respectively.
3533  {
3537  }
3538  // Done with LOCA information.
3539 
3540  // Setup the initialize junctions flag.
3541  // The initJct flag should only be true if we are at the first Newton step of
3542  // an initial point in the calculation. Examples include:
3543  // - 1st Newton step of the DCOP initialization for transient (tranOp)
3544  // - 1st Newton step of first DC sweep step.
3545  // - 1st Newton step of a sweep that has been reset. That typically
3546  // happens if the sweep is multi-dimensional, and the inner loop has
3547  // cycled back to the beginning again.
3548  //
3549  bool resetFlag = (solState_.timeStepNumber==0) || (solState_.sweepSourceResetFlag);
3550 
3551  // Do this if using LOCA for a DC or tranop calculation.
3553  {
3554  resetFlag = resetFlag && (solState_.continuationStepNumber==0);
3555  }
3556 
3558  (solState_.newtonIter==0) &&
3560  !solState_.firstSolveComplete && resetFlag);
3561 
3562  // initFixFlag: try to mimic "MODEINITFIX" of SPICE. This is set if:
3563  // DCOP or TranOP
3564  // Not first iteration
3565  // Any device not converged
3566 
3568  !(allDevsConverged()) &&
3569  (solState_.newtonIter!=0) &&
3571  !solState_.firstSolveComplete && resetFlag);
3572 
3573  if (solState_.dcopFlag)
3574  {
3578  }
3579 
3580  // One final check. See if the "external state" has been set. If so,
3581  // check to see if it has the initJctFlag set. If not, then we probably
3582  // shouldn't either. The external state comes from a higher up level
3583  // in a multi-level newton solve.
3584  //
3585  // This should be made more detailed later.
3586  if (externalStateFlag_)
3587  {
3589  {
3591  }
3592  }
3593 
3594  // The first DCOP step of a "double DCOP" simulation is a special case,
3595  // in which the nonlinear poisson is solved in place of drift-diffusion
3596  // equations for the PDE devices. For this initialization problem, the
3597  // circuit subproblem should not be included.
3598  if ((solState_.doubleDCOPEnabled) &&
3599  (solState_.dcopFlag) &&
3600  (solState_.doubleDCOPStep == 0))
3601  {
3603  }
3604 
3605  // if necessary, set up the names vector
3607  {
3608  NodeNamePairMap & nodeNames = outputMgrPtr_->getAllNodes();
3609  int nodeNameSize = nodeNames.size();
3610  nameVec_.resize(nodeNameSize+1,"gnd");
3611  NodeNamePairMap::iterator mapI, mapEnd;
3612  mapEnd = nodeNames.end();
3613  mapI = nodeNames.begin();
3614  for (; mapI != mapEnd ; ++mapI)
3615  {
3616  nameVec_[(*mapI).second.first] = (*mapI).first;
3617  }
3618  }
3619 
3620  if (DEBUG_DEVICE) {
3622  {
3623  dout() << solState_;
3624  }
3625 
3631  }
3632 
3633  return bsuccess;
3634 }
3635 
3636 //-----------------------------------------------------------------------------
3637 // Function : DeviceMgr::setupRawVectorPointers_
3638 // Purpose : set up raw pointers
3639 // Special Notes :
3640 // Scope : public
3641 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3642 // Creation Date : 11/25/08
3643 //-----------------------------------------------------------------------------
3645 {
3646  if (externData_.daeQVectorPtr != 0)
3647  {
3649  }
3650 
3651  if (externData_.daeFVectorPtr != 0)
3652  {
3654  }
3655 
3656  if (externData_.dFdxdVpVectorPtr != 0)
3657  {
3659  }
3660 
3661  if (externData_.dQdxdVpVectorPtr != 0)
3662  {
3664  }
3665 
3666  if (externData_.nextSolVectorPtr != 0)
3667  {
3669  }
3670 
3671  if (externData_.currSolVectorPtr != 0)
3672  {
3674  }
3675 
3676  if (externData_.lastSolVectorPtr != 0)
3677  {
3679  }
3680 
3681  if (externData_.nextStaVectorPtr != 0)
3682  {
3684  }
3685 
3686  if (externData_.currStaVectorPtr != 0)
3687  {
3689  }
3690 
3691  if (externData_.lastStaVectorPtr != 0)
3692  {
3694  }
3695 
3697  {
3699  }
3700 
3701  if (externData_.nextStoVectorPtr != 0)
3702  {
3704  }
3705 
3706  if (externData_.currStoVectorPtr != 0)
3707  {
3709  }
3710 
3711  if (externData_.lastStoVectorPtr != 0)
3712  {
3714  }
3715 
3717  {
3719  }
3720 
3721  return true;
3722 }
3723 
3724 //-----------------------------------------------------------------------------
3725 // Function : DeviceMgr::setupRawMatrixPointers_
3726 // Purpose : set up raw pointers for matrices
3727 // Special Notes :
3728 // Scope : public
3729 // Creator : Todd Coffey, 1414
3730 // Creation Date : 06/03/09
3731 //-----------------------------------------------------------------------------
3733 {
3734  InstanceVector::iterator iter;
3735  InstanceVector::iterator begin;
3736  InstanceVector::iterator end;
3737  begin = instancePtrVec_.begin();
3738  end = instancePtrVec_.end();
3739  for (iter=begin; iter!=end;++iter)
3740  {
3741  (*iter)->setupPointers();
3742  }
3743  return true;
3744 }
3745 
3746 //-----------------------------------------------------------------------------
3747 // Function : DeviceMgr::getMaxTimeStepSize
3748 // Purpose :
3749 // Special Notes :
3750 // Scope : public
3751 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
3752 // Creation Date : 7/31/01
3753 //-----------------------------------------------------------------------------
3755 {
3756  double maxStep = devOptions_.defaultMaxTimeStep;
3757 
3758  InstanceVector::iterator iter;
3759  InstanceVector::iterator begin =instancePtrVec_.begin();
3760  InstanceVector::iterator end =instancePtrVec_.end();
3761  for (iter=begin; iter!=end;++iter)
3762  {
3763  double step = (*iter)->getMaxTimeStepSize ();
3764  SourceInstance * srcInst = dynamic_cast<SourceInstance*>(*iter);
3765  if (!srcInst || !srcInst->getFastSourceFlag())
3766  maxStep = Xycemin(step, maxStep);
3767  }
3768 
3769  return maxStep;
3770 }
3771 
3772 
3773 //-----------------------------------------------------------------------------
3774 // Function : DeviceMgr::declareCurrentStepAsBreakpoint
3775 // Purpose : If during a device load, a device must act in a discontinuous
3776 // fashion, let the analysis manager know that this step should
3777 // be treated as such.
3778 // Special Notes :
3779 // Scope : public
3780 // Creator : Richard Schiek, Electrical and Microsystems Modeling
3781 // Creation Date : 3/5/2010
3782 //-----------------------------------------------------------------------------
3784 {
3786 }
3787 
3788 //-----------------------------------------------------------------------------
3789 // Function : DeviceMgr::enablePDEContinuation
3790 // Purpose : This function turns on the Continuation flag, which lets
3791 // the devices which are Continuation enabled know that they
3792 // need to set up their variable parameters.
3793 //
3794 // Special Notes : Currently, only PDE devices can take advantage of this
3795 // capability, and it is only used in the context of two-level
3796 // Newton.
3797 //
3798 // Scope : public
3799 // Creator : Eric R. Keiter, SNL, Computational Sciences
3800 // Creation Date : 10/22/02
3801 //-----------------------------------------------------------------------------
3803 {
3804  if (DEBUG_DEVICE)
3805  dout() << "DeviceMgr::enablePDEContinuation" << std::endl;
3806 
3807  bool bsuccess = true;
3811 
3812  InstanceVector::iterator iter;
3813  InstanceVector::iterator begin =instancePtrVec_.begin();
3814  InstanceVector::iterator end =instancePtrVec_.end();
3815 
3816  for (iter=begin; iter!=end;++iter)
3817  {
3818  bool tmpSuccess = (*iter)->enablePDEContinuation();
3819  bsuccess = bsuccess && tmpSuccess;
3820  }
3821 
3822  // if any of the devices feels that it needs more than the specified
3823  // number of continuation steps, re-do, with the new step number.
3825  {
3826  for (iter=begin; iter!=end;++iter)
3827  {
3828  bool tmpSuccess = (*iter)->enablePDEContinuation();
3829  bsuccess = bsuccess && tmpSuccess;
3830  }
3831  }
3832 
3833  int returnedSteps;
3834 
3835  if (!bsuccess) returnedSteps = -1;
3836  else returnedSteps = solState_.maxPDEContinuationSteps;
3837 
3838  return returnedSteps;
3839 }
3840 
3841 //-----------------------------------------------------------------------------
3842 // Function : DeviceMgr::disablePDEContinuation
3843 // Purpose :
3844 // Special Notes :
3845 // Scope : public
3846 // Creator : Eric R. Keiter, SNL, Computational Sciences
3847 // Creation Date : 10/22/02
3848 //-----------------------------------------------------------------------------
3850 {
3851  bool bsuccess = true;
3853 
3854  InstanceVector::iterator iter;
3855  InstanceVector::iterator begin =instancePtrVec_.begin();
3856  InstanceVector::iterator end =instancePtrVec_.end();
3857  for (iter=begin; iter!=end;++iter)
3858  {
3859  bool tmpSuccess = (*iter)->disablePDEContinuation();
3860  bsuccess = bsuccess && tmpSuccess;
3861  }
3862 
3863  return bsuccess;
3864 }
3865 
3866 //-----------------------------------------------------------------------------
3867 // Function : DeviceMgr::calcPDESubProblemInfo
3868 //
3869 // Purpose : Determines the number of PDE sub-problems.,
3870 //
3871 // This is mainly used/needed for 2-level problems.
3872 //
3873 // Also determines the number of interface nodes per
3874 // sub-problem (ie number of electrodes on each device).
3875 //
3876 // Special Notes : Need to modify to work correctly in parallel, probably.
3877 //
3878 // Scope : public
3879 // Creator : Eric R. Keiter, SNL, Computational Sciences
3880 // Creation Date : 12/03/02
3881 //-----------------------------------------------------------------------------
3883 {
3884  bool bsuccess = true;
3885 
3887 
3888  // now set up numInterfaceNodes_;
3890 
3891  for (int i=0;i<numPDEDevices_;++i)
3892  {
3893  numInterfaceNodes_[i] = pdeInstancePtrVec_[i]->getNumExtVars ();
3894  }
3895 
3896  calledBeforeCSPI = true;
3897 
3898  return bsuccess;
3899 }
3900 
3901 //-----------------------------------------------------------------------------
3902 // Function : DeviceMgr::getNumInterfaceNodes
3903 // Purpose : returns the vector calculaed in calcPDESubProblemInfo.
3904 // Special Notes :
3905 // Scope : public
3906 // Creator : Eric R. Keiter, SNL, Computational Sciences
3907 // Creation Date : 12/03/02
3908 //-----------------------------------------------------------------------------
3909 void DeviceMgr::getNumInterfaceNodes (std::vector<int> & numINodes)
3910 {
3911  if (!calledBeforeCSPI)
3912  {
3914  }
3915 
3916  int size = numINodes.size ();
3917  int size2 = numInterfaceNodes_.size();
3918 
3919  if (size < size2) numINodes.resize(size2);
3920 
3921  for (int i=0;i<size2;++i)
3922  {
3923  numINodes[i] = numInterfaceNodes_[i];
3924  }
3925 }
3926 
3927 //-----------------------------------------------------------------------------
3928 // Function : DeviceMgr::loadCouplingRHS
3929 // Purpose :
3930 // Special Notes :
3931 // Scope : public
3932 // Creator : Eric R. Keiter, SNL, Computational Sciences
3933 // Creation Date : 12/03/02
3934 //-----------------------------------------------------------------------------
3935 bool DeviceMgr::loadCouplingRHS (int iPDEDevice, int iElectrode, N_LAS_Vector * dfdvPtr)
3936 {
3937  return pdeInstancePtrVec_[iPDEDevice]->loadDFDV(iElectrode,dfdvPtr);
3938 }
3939 
3940 //-----------------------------------------------------------------------------
3941 // Function : DeviceMgr::calcCouplingTerms
3942 // Purpose :
3943 // Special Notes :
3944 // Scope : public
3945 // Creator : Eric R. Keiter, SNL, Computational Sciences
3946 // Creation Date : 12/03/02
3947 //-----------------------------------------------------------------------------
3948 bool DeviceMgr::calcCouplingTerms (int iPDEDevice, int iElectrode, const N_LAS_Vector * dxdvPtr)
3949 {
3950  return pdeInstancePtrVec_[iPDEDevice]->calcConductance(iElectrode, dxdvPtr);
3951 }
3952 
3953 //-----------------------------------------------------------------------------
3954 // Function : DeviceMgr::raiseDebugLevel
3955 // Purpose :
3956 // Special Notes :
3957 // Scope : public
3958 // Creator : Eric R. Keiter, SNL, Computational Sciences
3959 // Creation Date : 04/23/03
3960 //-----------------------------------------------------------------------------
3961 bool DeviceMgr::raiseDebugLevel(int increment)
3962 {
3963  if (DEBUG_DEVICE)
3964  devOptions_.debugLevel += increment;
3965 
3966  return true;
3967 }
3968 
3969 //-----------------------------------------------------------------------------
3970 // Function : DeviceMgr::getDACDeviceNames
3971 // Purpose : Get a list of names of all DACs in the circuit
3972 // Special Notes :
3973 // Scope : public
3974 // Creator : Tom Russo, SNL, Component Information and MOdels
3975 // Creation Date : 05/05/04
3976 //-----------------------------------------------------------------------------
3977 bool DeviceMgr::getDACDeviceNames(std::vector< std::string > & dacNames)
3978 {
3979 
3980  bool bSuccess = true;
3981 
3982  dacNames.clear();
3983 
3984  // find the device index for DAC devices:
3985 
3986  EntityTypeId dac_model_type_id = DAC::Traits::modelGroup(); // getModelGroup("Y%DAC%DUMMYDAC");
3987 
3988  // get the singleton for the DAC device
3989  Device* devicePtr = getDevice(dac_model_type_id);
3990 
3991  // If it wasn't found, there were no DAC devices
3992  if (!devicePtr)
3993  {
3994  Report::UserWarning0 message;
3995  message << "Circuit does not have any DAC devices";
3996  }
3997  else
3998  {
3999  DAC::Master* DACPtr = dynamic_cast<DAC::Master*>(devicePtr);
4000  bSuccess = DACPtr->getDACDeviceNames(dacNames);
4001  }
4002 
4003  return bSuccess;
4004 }
4005 
4006 //-----------------------------------------------------------------------------
4007 // Function : DeviceMgr::getADCMap
4008 // Purpose : Get instance params for all ADCs in the circuit
4009 // Special Notes :
4010 // Scope : public
4011 // Creator : Tom Russo, SNL, Component Information and MOdels
4012 // Creation Date : 05/05/04
4013 //-----------------------------------------------------------------------------
4014 bool DeviceMgr::getADCMap(std::map<std::string,std::map<std::string,double> >&ADCMap)
4015 {
4016 
4017  bool bSuccess = true;
4018 
4019  ADCMap.clear();
4020 
4021  // find the device index for ADC devices:
4022 
4023  EntityTypeId adc_model_type_id = ADC::Traits::modelGroup(); // getModelGroup("Y%ADC%DUMMYADC");
4024 
4025  // get the singleton for the ADC device
4026  Device* devicePtr = getDevice(adc_model_type_id);
4027 
4028  // If it wasn't found, there were no ADC devices
4029  if (!devicePtr)
4030  {
4031  Report::UserWarning0 message;
4032  message << "Circuit does not have any ADC devices";
4033  }
4034  else
4035  {
4036  ADC::Master* ADCPtr = dynamic_cast<ADC::Master*>(devicePtr);
4037  bSuccess = ADCPtr->getADCMap(ADCMap);
4038  }
4039 
4040  return bSuccess;
4041 }
4042 
4043 //----------------------------------------------------------------------------
4044 // Function : updateTimeVoltagePairs
4045 // Purpose : Update the DAC devices in a circuit by adding the set
4046 // of time and voltage pairs built up on the "digital side"
4047 // since the last update and by removing the time-voltage
4048 // pairs for times that pre-date the given simulation time.
4049 // Special Notes : The current method for locating DAC instances
4050 // works for the serial case only. The parallel
4051 // case will be added in later modifications.
4052 // Function moved from N_CIR_Xyce class by TVR, 05/07/2004
4053 // Scope :
4054 // Creator : Tom Russo
4055 // Creation Date : 05/07/2004
4056 //----------------------------------------------------------------------------
4058  std::map< std::string, std::vector< std::pair<double,double> >* > const & timeVoltageUpdateMap)
4059 {
4060  bool bSuccess = true;
4061 
4062  // Get the device index for DAC devices. Note that Xyce's convention
4063  // for DAC device naming breaks the Netlist usual conventions.
4064  // Also note that the Device Instance name supplied here does
4065  // not have to be for an instance that really exists, just one
4066  // that meets the naming convention for the given type of device.
4067  EntityTypeId dac_model_type_id = DAC::Traits::modelGroup(); // getModelGroup("Y%DAC%DUMMYDAC");
4068 
4069  // Get the singleton for the "DAC" type of device.
4070  Device* devicePtr = getDevice(dac_model_type_id);
4071 
4072  if (!devicePtr)
4073  {
4074  // not a failure, there are no DACs
4075  }
4076  else
4077  {
4078  // Get all of the instances associated with devicePtr.
4079  std::vector<DeviceInstance*> deviceInstances;
4080  getDeviceInstances(*devicePtr, std::back_inserter(deviceInstances));
4081 
4082  // Update each of the DAC device instances in turn.
4083  InstanceVector::iterator iterI;
4084  InstanceVector::iterator beginI = deviceInstances.begin();
4085  InstanceVector::iterator endI = deviceInstances.end();
4086  for (iterI = beginI; iterI != endI; ++iterI)
4087  {
4088  DAC::Instance* dacInstancePtr = dynamic_cast<DAC::Instance*>(*iterI);
4089  // Get the name of the given DAC device instance.
4090  std::string const & dacName(dacInstancePtr->getName());
4091  // Try to find an entry for that DAC in the map.
4092  std::map< std::string, std::vector< std::pair<double,double> >* >::const_iterator mapIter;
4093  mapIter = timeVoltageUpdateMap.find(dacName);
4094  if (mapIter == timeVoltageUpdateMap.end())
4095  {
4096  // See if there is an entry for a stripped down version
4097  // of the DAC name.
4098  //string strippedDacName(dacName.substr(
4099  // dacName.find_last_of("%") + 1, dacName.length() - 1));
4100 
4101  mapIter = timeVoltageUpdateMap.find(dacName);
4102  if (mapIter == timeVoltageUpdateMap.end())
4103  {
4104  Report::UserWarning0 message;
4105  message << "Could not find DAC " << dacName;
4106  continue;
4107  }
4108  }
4109 
4110  if (DEBUG_DEVICE)
4111  dout() << "DeviceMgr::updateTimeVoltagePairs: found DAC with name: "
4112  << dacName << "\n";
4113 
4114  // Update the time-voltage pairs for the given DAC instance.
4115  if (!dacInstancePtr->updateTVVEC(*(*mapIter).second))
4116  {
4117  Report::UserWarning0 message;
4118  message << "Failed to update the time-voltage pairs for the DAC " << dacName;
4119  continue;
4120  }
4121  }
4122  }
4123 
4124  return bSuccess;
4125 }
4126 
4127 //----------------------------------------------------------------------------
4128 // Function : DeviceMgr::setADCWidths
4129 // Purpose : Set the widths of every ADC instance given a map of names
4130 // and widths
4131 // Special Notes :
4132 // Scope : public
4133 // Creator : Tom Russo, SNL, Component Information and Models
4134 // Creation Date : 07/29/2002
4135 //----------------------------------------------------------------------------
4136 bool DeviceMgr::setADCWidths(std::map<std::string,int> const & ADCWidthMap)
4137 {
4138  bool bSuccess = true;
4139  if (DEBUG_DEVICE)
4140  dout() << "entering DeviceMgr::setADCWidths " << std::endl;
4141 
4142  // Get the device index for ADC devices. Note that Xyce's convention
4143  // for ADC device naming breaks the Netlist usual conventions.
4144  // Also note that the Device Instance name supplied here does
4145  // not have to be for an instance that really exists, just one
4146  // that meets the naming convention for the given type of device.
4147  EntityTypeId adc_model_type_id = ADC::Traits::modelGroup(); // getModelGroup("Y%ADC%DUMMYADC");
4148 
4149  // Get the singleton for the "ADC" type of device.
4150  Device* devicePtr = getDevice(adc_model_type_id);
4151 
4152  if (!devicePtr)
4153  {
4154  // This is not a failure, just means there aren't any ADCs
4155  }
4156  else
4157  {
4158  // Get all of the instances associated with devicePtr.
4159  std::vector<DeviceInstance*> deviceInstances;
4160  getDeviceInstances(*devicePtr, std::back_inserter(deviceInstances));
4161 
4162  // Update each of the ADC device instances in turn.
4163  InstanceVector::iterator iterI;
4164  InstanceVector::iterator beginI = deviceInstances.begin();
4165  InstanceVector::iterator endI = deviceInstances.end();
4166  for (iterI = beginI; iterI != endI; ++iterI)
4167  {
4168  ADC::Instance* adcInstancePtr = dynamic_cast<ADC::Instance*>(*iterI);
4169  // Get the name of the given ADC device instance.
4170  std::string const & adcName(adcInstancePtr->getName());
4171  // Try to find an entry for that ADC in the map.
4172  std::map< std::string, int >::const_iterator mapIter;
4173  mapIter = ADCWidthMap.find(adcName);
4174  if (mapIter == ADCWidthMap.end())
4175  {
4176  // See if there is an entry for a stripped down version
4177  // of the ADC name.
4178  //string strippedAdcName(adcName.substr(
4179  // adcName.find_last_of("%") + 1, adcName.length() - 1));
4180 
4181  mapIter = ADCWidthMap.find(adcName);
4182  if (mapIter == ADCWidthMap.end())
4183  {
4184  Report::UserWarning0 message;
4185  message << "Could not find ADC " << adcName;
4186  continue;
4187  }
4188  }
4189 
4190  if (DEBUG_DEVICE)
4191  dout() << "DeviceMgr::setADCWidths found ADC with name: "
4192  << adcName << " and will set bit vector width to: "
4193  << (*mapIter).second << "\n";
4194 
4195  // Update the time-voltage pairs for the given DAC instance.
4196  if (!adcInstancePtr->setBitVectorWidth((*mapIter).second))
4197  {
4198  Report::UserWarning0 message;
4199  message << "Failed to update the width for ADC " << adcName;
4200  continue;
4201  }
4202  }
4203  }
4204 
4205  return bSuccess;
4206 }
4207 
4208 //-----------------------------------------------------------------------------
4209 // Function : DeviceMgr::getTimeVoltagePairs
4210 // Purpose : Get time/voltage pairs from all ADCs in the circuit
4211 // Special Notes :
4212 // Scope : public
4213 // Creator : Tom Russo, SNL, Component Information and MOdels
4214 // Creation Date : 05/05/04
4215 //-----------------------------------------------------------------------------
4217  std::map<std::string, std::vector< std::pair<double,double> > >&TimeVoltageMap)
4218 {
4219  bool bSuccess = true;
4220 
4221  TimeVoltageMap.clear();
4222 
4223  // find the device index for ADC devices:
4224 
4225  EntityTypeId adc_model_type_id = ADC::Traits::modelGroup(); // getModelGroup("Y%ADC%DUMMYADC");
4226 
4227  // get the singleton for the ADC device
4228  Device* devicePtr = getDevice(adc_model_type_id);
4229 
4230  // If it wasn't found, there were no ADC devices
4231  if (devicePtr)
4232  {
4233  ADC::Master* ADCPtr = dynamic_cast<ADC::Master*>(devicePtr);
4234  bSuccess = ADCPtr->getTimeVoltagePairs(TimeVoltageMap);
4235  }
4236 
4237  return bSuccess;
4238 }
4239 
4240 //-----------------------------------------------------------------------------
4241 // Function : DeviceMgr::getDeviceNames
4242 // Purpose : Get a list of names of all devices of given type in the
4243 // circuit
4244 // Special Notes : "deviceType" is a string of the form that a device of the
4245 // given type would have in the netlist, e.g. "R1" for a
4246 // resistor or "Y%XYGRA%DUMMY" for a Xygra device.
4247 // Scope : public
4248 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4249 // Creation Date : 08/25/08
4250 //-----------------------------------------------------------------------------
4251 bool DeviceMgr::getDeviceNames(const std::string & model_type_name, std::vector< std::string > & deviceNames)
4252 {
4253 
4254  bool bSuccess = false;
4255 
4256  deviceNames.clear();
4257 
4258  // find the device index for given type of device:
4259  EntityTypeId device_model_type_id = getModelGroup(model_type_name);
4260 
4261  // get the singleton for the device
4262  Device* devicePtr = getDevice(device_model_type_id);
4263 
4264  // If it wasn't found, there were no devices of this type
4265  if (!devicePtr)
4266  {
4267  Report::UserWarning0 message;
4268  message << "Circuit does not have any devices matching " << model_type_name;
4269  bSuccess = false; // this is not a failure, though
4270  }
4271  else
4272  {
4273  bSuccess = true;
4274  Xyce::Device::getDeviceNames(*devicePtr, std::back_inserter(deviceNames));
4275  }
4276 
4277  return bSuccess;
4278 }
4279 
4280 //-----------------------------------------------------------------------------
4281 // Function : DeviceMgr::getXygraInstancePtr_
4282 // Purpose : Returns the pointer to a named Xygra device instance
4283 // Special Notes :
4284 // Scope : PRIVATE
4285 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4286 // Creation Date : 08/27/08
4287 //-----------------------------------------------------------------------------
4288 Xygra::Instance * DeviceMgr::getXygraInstancePtr_(const std::string & deviceName)
4289 {
4290  std::map<std::string,Xygra::Instance *>::iterator mapIter;
4291 
4292  // See if we've looked this up before.
4293  mapIter = xygraPtrMap_.find(deviceName);
4294 
4295  if (mapIter == xygraPtrMap_.end())
4296  {
4297 
4298  // we haven't looked it up before, do so now.
4299  // find the device index for given type of devices:
4300  EntityTypeId xygra_model_type_id = Xygra::Traits::modelGroup(); // getModelGroup("Y%XYGRA%DUMMY");
4301 
4302  // get the singleton for the device
4303  Device* devicePtr = getDevice(xygra_model_type_id);
4304  // If it wasn't found, there were no devices of this type
4305  if (!devicePtr)
4306  {
4307  Report::UserFatal message;
4308  message << "Circuit does not have any Xygra devices";
4309  return 0; // never reached, just shut up compiler warnings
4310  }
4311  else
4312  {
4313  // we have some, so get 'em.
4314  std::vector<DeviceInstance*> deviceInstances;
4315  getDeviceInstances(*devicePtr, std::back_inserter(deviceInstances));
4316 
4317  int theNamedInstanceIndex = -1;
4318 
4319  int numInstances = deviceInstances.size();
4320  for (int i = 0 ; i < numInstances; ++i)
4321  {
4322  if (deviceInstances[i]->getName() == deviceName)
4323  {
4324  theNamedInstanceIndex = i;
4325  break;
4326  }
4327  }
4328  if (theNamedInstanceIndex == -1)
4329  {
4330  Report::UserFatal message;
4331  message << "No Xygra device named " << deviceName;
4332  }
4333  Xygra::Instance* xygraInstancePtr = dynamic_cast<Xygra::Instance*>(deviceInstances[theNamedInstanceIndex]);
4334  xygraPtrMap_[deviceName] = xygraInstancePtr;
4335  }
4336  }
4337 
4338  // when we get here we've either already had the pointer in our map, or
4339  // we just put it there. All other cases were fatal errors and would have
4340  // kept us from getting here.
4341  return xygraPtrMap_[deviceName];
4342 }
4343 
4344 //-----------------------------------------------------------------------------
4345 // Function : DeviceMgr::xygraGetNumNodes
4346 // Purpose : Returns the number of nodes that a given Xygra instance
4347 // has, given the name of that instance in the netlist.
4348 // Special Notes :
4349 // Scope : public
4350 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4351 // Creation Date : 08/27/08
4352 //-----------------------------------------------------------------------------
4353 int DeviceMgr::xygraGetNumNodes(const std::string & deviceName)
4354 {
4355  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4356  return xygraInstancePtr -> getNumNodes();
4357 }
4358 
4359 //-----------------------------------------------------------------------------
4360 // Function : DeviceMgr::xygraGetNumWindings
4361 // Purpose : Returns the number of windings that a given Xygra instance
4362 // has, given the name of that instance in the netlist.
4363 // Special Notes :
4364 // Scope : public
4365 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4366 // Creation Date : 08/27/08
4367 //-----------------------------------------------------------------------------
4368 int DeviceMgr::xygraGetNumWindings(const std::string & deviceName)
4369 {
4370  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4371  return xygraInstancePtr -> getNumWindings();
4372 }
4373 
4374 //-----------------------------------------------------------------------------
4375 // Function : DeviceMgr::xygraGetCoilWindings
4376 // Purpose : Returns the number of windings that a given Xygra instance
4377 // has in each coil, given the name of that instance in the
4378 // netlist.
4379 // Special Notes :
4380 // Scope : public
4381 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4382 // Creation Date : 09/15/08
4383 //-----------------------------------------------------------------------------
4384 void DeviceMgr::xygraGetCoilWindings(const std::string & deviceName,
4385  std::vector<int> & cW)
4386 {
4387  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4388  xygraInstancePtr -> getCoilWindings(cW);
4389 }
4390 
4391 //-----------------------------------------------------------------------------
4392 // Function : DeviceMgr::xygraGetCoilNames
4393 // Purpose : Returns the names of each coil in a given Xygra instance
4394 // given the name of that instance in the netlist.
4395 // Special Notes :
4396 // Scope : public
4397 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4398 // Creation Date : 09/29/08
4399 //-----------------------------------------------------------------------------
4400 void DeviceMgr::xygraGetCoilNames(const std::string & deviceName,
4401  std::vector<std::string> & cN)
4402 {
4403  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4404  xygraInstancePtr -> getCoilNames(cN);
4405 }
4406 
4407 //-----------------------------------------------------------------------------
4408 // Function : DeviceMgr::xygraSetConductances
4409 // Purpose : Sets th conductance matrix on the specified Xygra device
4410 // Special Notes :
4411 // Scope : public
4412 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4413 // Creation Date : 08/27/08
4414 //-----------------------------------------------------------------------------
4415 bool DeviceMgr::xygraSetConductances(const std::string & deviceName,
4416  const std::vector<std::vector<double> > & cM)
4417 {
4418  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4419  return xygraInstancePtr -> setConductances(cM);
4420 }
4421 
4422 //-----------------------------------------------------------------------------
4423 // Function : DeviceMgr::xygraSetK
4424 // Purpose : Sets the K matrix on the specified Xygra device
4425 // Special Notes :
4426 // Scope : public
4427 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4428 // Creation Date : 08/27/08
4429 //-----------------------------------------------------------------------------
4430 bool DeviceMgr::xygraSetK(const std::string & deviceName,
4431  const std::vector<std::vector<double> > & kM,
4432  const double t)
4433 {
4434  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4435  return xygraInstancePtr -> setK(kM,t);
4436 }
4437 
4438 //-----------------------------------------------------------------------------
4439 // Function : DeviceMgr::xygraSetSources
4440 // Purpose : Set the S vector on named device
4441 // Special Notes :
4442 // Scope : public
4443 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4444 // Creation Date : 08/27/08
4445 //-----------------------------------------------------------------------------
4446 bool DeviceMgr::xygraSetSources(const std::string & deviceName,
4447  const std::vector<double> & sV,
4448  const double t)
4449 {
4450  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4451  return xygraInstancePtr -> setSources(sV,t);
4452 }
4453 
4454 
4455 //-----------------------------------------------------------------------------
4456 // Function : DeviceMgr::xygraGetVoltages
4457 // Purpose : Retrieve the voltages on nodes for named Xygra device
4458 // Special Notes :
4459 // Scope : public
4460 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
4461 // Creation Date : 08/27/08
4462 //-----------------------------------------------------------------------------
4463 bool DeviceMgr::xygraGetVoltages(const std::string & deviceName,
4464  std::vector<double> & vN)
4465 {
4466  Xygra::Instance * xygraInstancePtr = getXygraInstancePtr_(deviceName);
4467  return xygraInstancePtr -> getVoltages(vN);
4468 }
4469 
4470 
4471 //-----------------------------------------------------------------------------
4472 // Function : DeviceMgr::getHomotopyBlockSize
4473 // Purpose : Returns the number of mosfet gainscale blocks (a value
4474 // in the device options).
4475 // Special Notes : Needed for block homotopy on gainscale.
4476 // Scope : public
4477 // Creator : Roger P. Pawlowski, SNL, Computational Sciences
4478 // Creation Date : 01/26/2005
4479 //-----------------------------------------------------------------------------
4481 {
4483 }
4484 
4485 //-----------------------------------------------------------------------------
4486 // Function : DeviceMgr::updateTemperature
4487 // Purpose :
4488 // Special Notes :
4489 // Scope : public
4490 // Creator : Eric R. Keiter, SNL, Computational Sciences
4491 // Creation Date : 10/26/04
4492 //-----------------------------------------------------------------------------
4494 {
4495  bool bsuccess = true, success = true;
4496 
4497  // convert to kelvin:
4498  double Ctemp = val;
4499  double Ktemp = val + CONSTCtoK;
4500 
4501  if (DEBUG_DEVICE && devOptions_.debugLevel > 0 && solState_.debugTimeFlag)
4502  dout() << "In DeviceMgr::updateTemperature. new C temp = " << Ctemp << " K temp = " << Ktemp << std::endl;
4503 
4504  // First set the global temp. This is used in each device if the "tempGiven"
4505  // variable is false. This should be in Kelvin.
4506  devOptions_.temp.setVal(Ktemp);
4507 
4508  // loop over the bsim3 models and delete the size dep params.
4509  std::vector<DeviceModel *>::const_iterator iterM;
4510  std::vector<DeviceModel *>::const_iterator beginM = bsim3ModelPtrVec_.begin ();
4511  std::vector<DeviceModel *>::const_iterator endM = bsim3ModelPtrVec_.end ();
4512  for (iterM=beginM;iterM!=endM;++iterM)
4513  {
4514  (*iterM)->clearTemperatureData ();
4515  }
4516 
4517  // loop over the bsim4 models and delete the size dep params.
4518  beginM = bsim4ModelPtrVec_.begin ();
4519  endM = bsim4ModelPtrVec_.end ();
4520  for (iterM=beginM;iterM!=endM;++iterM)
4521  {
4522  (*iterM)->clearTemperatureData ();
4523  }
4524 
4525  // loop over the b3soi models and delete the size dep params.
4526  beginM = bsimsoiModelPtrVec_.begin ();
4527  endM = bsimsoiModelPtrVec_.end ();
4528  for (iterM=beginM;iterM!=endM;++iterM)
4529  {
4530  (*iterM)->clearTemperatureData ();
4531  }
4532 
4533 
4534  // Loop over all models, call processParams, with CTemp.
4535  // "XYCEADMS*TEMP is there to force Verilog devices, which might have
4536  // temperature dependence through "$temperature" instead of a "TEMP"
4537  // parameter, to work properly. If so, they need the temperature set in
4538  // Kelvin.
4539  std::string tname("TEMP");
4540  std::string tname2("XYCEADMSMODTEMP");
4541  std::string tname3("XYCEADMSINSTTEMP");
4542  beginM = modelPtrVec_.begin();
4543  endM = modelPtrVec_.end();
4544  for (iterM=beginM; iterM!=endM;++iterM)
4545  {
4546  success = (*iterM)->setParam (tname, Ctemp);
4547  success = (*iterM)->setParam (tname2, Ktemp) || success;
4548  success = success && (*iterM)->processParams ();
4549  }
4550 
4551  // Loop over device instances, and set the temperature. This should be
4552  // in C, if going through processParams, and K if going through
4553  // the updateTemperature function.
4554  InstanceVector::const_iterator iter;
4555  InstanceVector::const_iterator begin;
4556  InstanceVector::const_iterator end;
4557 
4558  begin = instancePtrVec_.begin();
4559  end = instancePtrVec_.end();
4560  for (iter=begin; iter!=end;++iter)
4561  {
4562  success = (*iter)->setParam (tname, Ctemp);
4563  success = (*iter)->setParam (tname3, Ktemp) || success;
4564  success = success && (*iter)->processParams ();
4565  }
4566 
4567  return bsuccess;
4568 }
4569 
4570 //-----------------------------------------------------------------------------
4571 // Function : DeviceMgr::allDevsConverged
4572 // Purpose : Check whether any device has taken an action that renders
4573 // normal convergence checks invalid (i.e. that the current
4574 // step must be assumed unconverged).
4575 // Special Notes :
4576 // Scope : public
4577 // Creator : Tom Russo, SNL, Component Information and Models
4578 // Creation Date : 03/22/05
4579 //-----------------------------------------------------------------------------
4581 {
4582  bool allDevsConv = true;
4583 #ifdef Xyce_PARALLEL_MPI
4584  double dc_par;
4585  double dc_glob;
4586 #endif
4587 
4588  // if two-level, and just the inner problem, only check the PDE devices,
4589  // coz those are all we loaded.
4590  InstanceVector::iterator iter;
4591  InstanceVector::iterator begin;
4592  InstanceVector::iterator end;
4594  {
4595  begin = pdeInstancePtrVec_.begin ();
4596  end = pdeInstancePtrVec_.end ();
4597  }
4598  else
4599  {
4600  begin = instancePtrVec_.begin ();
4601  end = instancePtrVec_.end ();
4602  }
4603  for (iter=begin; iter!=end;++iter)
4604  {
4605  bool tmpBool = (*iter)->isConverged();
4606  allDevsConv = allDevsConv && tmpBool;
4607  }
4608 
4609 #ifdef Xyce_PARALLEL_MPI
4610  // Take care of moving this info across all processors and getting
4611  // a global answer
4612  dc_glob=0.0;
4613 
4614  if (allDevsConv)
4615  dc_par=0.0;
4616  else
4617  dc_par=1.0;
4618 
4619  N_PDS_Comm *pdsCommPtr = pdsMgrPtr_->getPDSComm();
4620  pdsCommPtr->barrier();
4621  pdsCommPtr->sumAll(&dc_par, &dc_glob, 1);
4622 
4623  // If any processor has allDevConverged_ false, dc_glob will be nonzero.
4624  if (dc_glob == 0.0)
4625  allDevsConv = true;
4626  else
4627  allDevsConv = false;
4628 #endif
4629 
4630  if (DEBUG_DEVICE && devOptions_.debugLevel > 0)
4631  {
4632  if (allDevsConv)
4633  {
4634  dout() << "All devices converged!" << std::endl;
4635  }
4636  else
4637  {
4638  dout() << "At least one device NOT converged!" << std::endl;
4639  }
4640  }
4641 
4642  return allDevsConv;
4643 }
4644 
4645 //-----------------------------------------------------------------------------
4646 // Function : DeviceMgr::innerDevsConverged
4647 // Purpose :
4648 // Special Notes :
4649 // Scope : public
4650 // Creator : Eric Keiter, SNL
4651 // Creation Date : 03/22/06
4652 //-----------------------------------------------------------------------------
4654 {
4655  bool innerDevsConv = true;
4656 
4657 #ifdef Xyce_EXTDEV
4658 
4659 #ifdef Xyce_PARALLEL_MPI
4660  double dc_par;
4661  double dc_glob;
4662 #endif
4663 
4664  std::vector<ExternDevice::Instance*>::iterator iter;
4665  std::vector<ExternDevice::Instance*>::iterator begin;
4666  std::vector<ExternDevice::Instance*>::iterator end;
4667  begin = extDevInstancePtrVec_.begin ();
4668  end = extDevInstancePtrVec_.end ();
4669 
4670  for (iter=begin; iter!=end;++iter)
4671  {
4672  bool tmpFlag = (*iter)->isInnerSolveConverged();
4673  innerDevsConv = innerDevsConv && tmpFlag;
4674  }
4675 
4676 #ifdef Xyce_PARALLEL_MPI
4677  // Take care of moving this info across all processors and getting
4678  // a global answer
4679  dc_glob=0.0;
4680 
4681  if (innerDevsConv)
4682  dc_par=0.0;
4683  else
4684  dc_par=1.0;
4685 
4686  N_PDS_Comm *pdsCommPtr = pdsMgrPtr_->getPDSComm();
4687  pdsCommPtr->barrier();
4688  pdsCommPtr->sumAll(&dc_par, &dc_glob, 1);
4689 
4690  // If any processor has innerDevConverged_ false, dc_glob will be nonzero.
4691  if (dc_glob == 0.0)
4692  innerDevsConv = true;
4693  else
4694  innerDevsConv = false;
4695 #endif
4696 
4697 #endif // ext-dev
4698 
4699  return innerDevsConv;
4700 }
4701 
4702 #ifdef Xyce_EXTDEV
4703 //-----------------------------------------------------------------------------
4704 // Function : DeviceMgr::setupExternalDevices
4705 // Purpose : In parallel, we need to setup all external devices
4706 // and appropriately setup the list of instances
4707 // Special Notes :
4708 // Scope : public
4709 // Creator : Robert Hoekstra, SNL, Elec. & MicroSystems Modeling
4710 // Creation Date : 03/10/06
4711 //-----------------------------------------------------------------------------
4712 bool DeviceMgr::setupExternalDevices()
4713 {
4714  N_PDS_Comm * pdsCommPtr = pdsMgrPtr_->getPDSComm();
4715 
4716 #ifdef Xyce_PARALLEL_MPI
4717  int procID = pdsCommPtr->procID();
4718  int numProc = pdsCommPtr->numProc();
4719 
4720  int numExt = extDevInstancePtrVec_.size();
4721  int numExtTotal = 0;
4722  pdsCommPtr->sumAll(&numExt, &numExtTotal, 1);
4723 
4724  std::vector<ExternDevice::Instance*> tmpVec = extDevInstancePtrVec_;
4725 
4726  //resetup the instance vector to have a size totally the global
4727  //number of ext devices
4728  if (numExtTotal > 0)
4729  {
4730  extDevInstancePtrVec_.resize(numExtTotal);
4731 
4732  int loc = 0;
4733  // const int bufSize = 1000;
4734  // char buf[bufSize];
4735  for(int proc = 0; proc < numProc; ++proc)
4736  {
4737  int cnt = 0;
4738  if (proc == procID) cnt = numExt;
4739  pdsCommPtr->bcast(&cnt, 1, proc);
4740 
4741  for(int i = 0; i < cnt; ++i)
4742  {
4743  if (proc == procID)
4744  {
4745  int size = extDevIBPtrVec_[i]->packedByteCount();
4746  int bufSize = size+100;
4747  char *buf=new char[bufSize];
4748  pdsCommPtr->bcast(&size, 1, proc);
4749  int pos = 0;
4750  extDevIBPtrVec_[i]->pack(buf, bufSize, pos, pdsCommPtr);
4751  pdsCommPtr->bcast(buf, size, proc);
4752  extDevInstancePtrVec_[loc] = tmpVec[i];
4753  delete [] buf;
4754  }
4755  else
4756  {
4757  int size = 0;
4758  pdsCommPtr->bcast(&size, 1, proc);
4759  int bufSize = size+100;
4760  char *buf=new char[bufSize];
4761  pdsCommPtr->bcast(buf, size, proc);
4762  int pos = 0;
4763  InstanceBlock instance_block;
4764  instance_block.unpack(buf, bufSize, pos, pdsCommPtr);
4765  extDevInstancePtrVec_[loc] = addExtDeviceInstance_(instance_block);
4766  delete [] buf;
4767  }
4768  extDevInstancePtrVec_[loc]->setOwningProc(proc);
4769  extDevInstancePtrVec_[loc]->setComm(pdsCommPtr);
4770  ++loc;
4771  }
4772  }
4773 
4774  assert(loc == numExtTotal);
4775  }
4776 #else
4777  for (std::vector<ExternDevice::Instance *>::iterator it = extDevInstancePtrVec_.begin(); it != extDevInstancePtrVec_.end(); ++it)
4778  (*it)->setComm(pdsCommPtr);
4779 #endif
4780  return true;
4781 }
4782 
4783 //-----------------------------------------------------------------------------
4784 // Function : DeviceMgr::updateExternalDevices_
4785 // Purpose : Do the actual solve of the external devices
4786 // Special Notes :
4787 // Scope : public
4788 // Creator : Robert Hoekstra, SNL, Elec. & MicroSystems Modeling
4789 // Creation Date : 03/10/06
4790 //-----------------------------------------------------------------------------
4791 void DeviceMgr::updateExternalDevices_()
4792 {
4793  std::vector<ExternDevice::Instance*>::iterator iter;
4794  std::vector<ExternDevice::Instance*>::iterator begin;
4795  std::vector<ExternDevice::Instance*>::iterator end;
4796  begin = extDevInstancePtrVec_.begin ();
4797  end = extDevInstancePtrVec_.end ();
4798  for (iter=begin; iter!=end;++iter)
4799  {
4800  (*iter)->runExternalDevice();
4801  }
4802 }
4803 
4804 //-----------------------------------------------------------------------------
4805 // Function : DeviceMgr::addExtDeviceInstance_
4806 // Purpose : adds an external device instance on the processors
4807 // : that don't actually own it.
4808 // Special Notes :
4809 // Scope : public
4810 // Creator : Robert Hoekstra, SNL, Parallel Computational Sciences
4811 // Creation Date : 3/16/06
4812 //-----------------------------------------------------------------------------
4813 ExternDevice::Instance *
4814 DeviceMgr::addExtDeviceInstance_(InstanceBlock & instance_block)
4815 {
4816  ModelTypeId model_type;
4817 
4818  if (instance_block.getModelName().empty())
4819  {
4820  model_type = getModelGroup(modelNameFromInstanceName(instance_block));
4821  }
4822  else
4823  {
4824  model_type = modelTypeMap_[instance_block.getModelName()];
4825  }
4826 
4827  if (!model_type.defined())
4828  {
4829  Report::UserError message;
4830  message << "Unable to determine type of device for instance name " << instance_block.getName();
4831  if (instance_block.getModelName() != "")
4832  {
4833  message << " with model name" + instance_block.getModelName();
4834  }
4835  }
4836 
4837  // Add an instance of this type.
4838  Device &device = getDeviceByModelType(model_type);
4839  DeviceInstance *instance = device.addInstance(instance_block, FactoryBlock(devOptions_, solState_, mlData, externData_, commandLine_));
4840 
4841  ExternDevice::Instance *external_instance = dynamic_cast<ExternDevice::Instance*>(instance);
4842 
4843  return external_instance;
4844 }
4845 #endif // Xyce_EXTDEV
4846 
4847 //-----------------------------------------------------------------------------
4848 // Function : DeviceMgr::homotopyStepSuccess
4849 // Purpose :
4850 // Special Notes : Needed for 2-level
4851 // Scope : public
4852 // Creator : Eric R. Keiter, SNL
4853 // Creation Date : 03/20/06
4854 //-----------------------------------------------------------------------------
4856  (const std::vector<std::string> & paramNames,
4857  const std::vector<double> & paramVals)
4858 {
4859 #ifdef Xyce_EXTDEV
4860  int numExt = extDevInstancePtrVec_.size();
4861  std::vector<ExternDevice::Instance*>::iterator iter;
4862  std::vector<ExternDevice::Instance*>::iterator begin;
4863  std::vector<ExternDevice::Instance*>::iterator end;
4864  begin = extDevInstancePtrVec_.begin ();
4865  end = extDevInstancePtrVec_.end ();
4866  for (iter=begin; iter!=end;++iter)
4867  {
4868  (*iter)->homotopyStepSuccess (paramNames, paramVals);
4869  }
4870 #endif // Xyce_EXTDEV
4871 
4872  return;
4873 }
4874 
4875 //-----------------------------------------------------------------------------
4876 // Function : DeviceMgr::homotopyStepFailure
4877 // Purpose :
4878 // Special Notes : Needed for 2-level
4879 // Scope : public
4880 // Creator : Eric R. Keiter, SNL
4881 // Creation Date : 03/30/06
4882 //-----------------------------------------------------------------------------
4884 {
4885 #ifdef Xyce_EXTDEV
4886  int numExt = extDevInstancePtrVec_.size();
4887  std::vector<ExternDevice::Instance*>::iterator iter;
4888  std::vector<ExternDevice::Instance*>::iterator begin;
4889  std::vector<ExternDevice::Instance*>::iterator end;
4890  begin = extDevInstancePtrVec_.begin ();
4891  end = extDevInstancePtrVec_.end ();
4892  for (iter=begin; iter!=end;++iter)
4893  {
4894  (*iter)->homotopyStepFailure ();
4895  }
4896 #endif // Xyce_EXTDEV
4897 
4898  return;
4899 }
4900 
4901 //-----------------------------------------------------------------------------
4902 // Function : DeviceMgr::stepSuccess
4903 // Purpose :
4904 // Special Notes :
4905 // Scope : public
4906 // Creator : Eric R. Keiter, SNL
4907 // Creation Date : 03/12/06
4908 //-----------------------------------------------------------------------------
4909 void DeviceMgr::stepSuccess (int analysis)
4910 {
4911 #ifdef Xyce_EXTDEV
4912  int numExt = extDevInstancePtrVec_.size();
4913  std::vector<ExternDevice::Instance *>::iterator iter;
4914  std::vector<ExternDevice::Instance *>::iterator begin;
4915  std::vector<ExternDevice::Instance *>::iterator end;
4916  begin = extDevInstancePtrVec_.begin ();
4917  end = extDevInstancePtrVec_.end ();
4918  for (iter=begin; iter!=end;++iter)
4919  {
4920  (*iter)->stepSuccess (analysis);
4921  }
4922 #endif // Xyce_EXTDEV
4923 
4924  return;
4925 }
4926 
4927 //-----------------------------------------------------------------------------
4928 // Function : DeviceMgr::stepFailure
4929 // Purpose :
4930 // Special Notes :
4931 // Scope : public
4932 // Creator : Eric R. Keiter, SNL
4933 // Creation Date : 03/12/06
4934 //-----------------------------------------------------------------------------
4935 void DeviceMgr::stepFailure (int analysis)
4936 {
4937 #ifdef Xyce_EXTDEV
4938  int numExt = extDevInstancePtrVec_.size();
4939  std::vector<ExternDevice::Instance*>::iterator iter;
4940  std::vector<ExternDevice::Instance*>::iterator begin;
4941  std::vector<ExternDevice::Instance*>::iterator end;
4942  begin = extDevInstancePtrVec_.begin ();
4943  end = extDevInstancePtrVec_.end ();
4944  for (iter=begin; iter!=end;++iter)
4945  {
4946  (*iter)->stepFailure (analysis);
4947  }
4948 #endif // Xyce_EXTDEV
4949 
4950  return;
4951 }
4952 
4953 //-----------------------------------------------------------------------------
4954 // Function : DeviceMgr::acceptStep
4955 // Purpose : Communicate to devices that the current step is accepted
4956 // Special Notes :
4957 // Scope : public
4958 // Creator : Tom Russo, SNL
4959 // Creation Date : 01/23/07
4960 //-----------------------------------------------------------------------------
4962 {
4963  // The time history for the LTRA device(s) has to be tracked
4964  // separately because it can be truncated if the user specifies that
4965  // option. This has to be called before
4966  // LTRAInstance::acceptStep(). Note that the DCOP is stored at
4967  // index zero and the first time step is stored at index 1 for the
4968  // time history vectors associated with the LTRA
4969  if (solState_.dcopFlag)
4970  {
4974  }
4975  else
4976  {
4979  {
4982  }
4984  }
4985 
4986  // make sure we have the right solver state. Putting this here
4987  // makes it essential that acceptStep be called BEFORE any changes have
4988  // been made to the solution or state vectors (e.g. rotating them) and
4989  // while "nextTime" in the solver still references the time for which the
4990  // solution vector is valid.
4991 
4992  bool tmpBool = setupSolverInfo_();
4994 
4995  for (InstanceVector::iterator iter = instancePtrVec_.begin(); iter != instancePtrVec_.end(); ++iter)
4996  {
4997  (*iter)->acceptStep();
4998  }
4999 
5000  // If the TRYCOMPACT option is set then the LTRA model will try to
5001  // compact the amount of data stored and speed up the convolutions. If
5002  // any of the LTRA instances request this, done in their acceptStep()
5003  // member function, then perform the time-step compaction here.
5005  {
5008 
5010 
5011  // reset the flag for the next time step
5012  solState_.ltraDoCompact = false;
5013  }
5014 }
5015 
5016 
5017 //-----------------------------------------------------------------------------
5018 // Function : DeviceMgr::getInitialQnorm
5019 // Purpose :
5020 // Special Notes :
5021 // Scope : public
5022 // Creator : Eric R. Keiter, SNL
5023 // Creation Date : 03/12/07
5024 //-----------------------------------------------------------------------------
5025 bool DeviceMgr::getInitialQnorm (std::vector<N_TIA_TwoLevelError> & tleVec)
5026 {
5027  bool bsuccess = true;
5028 
5029 #ifdef Xyce_EXTDEV
5030  int numExt = extDevInstancePtrVec_.size();
5031 
5032  tleVec.resize(numExt);
5033 
5034  std::vector<ExternDevice::Instance*>::iterator iter;
5035  std::vector<ExternDevice::Instance*>::iterator begin;
5036  std::vector<ExternDevice::Instance*>::iterator end;
5037  begin = extDevInstancePtrVec_.begin ();
5038  end = extDevInstancePtrVec_.end ();
5039 
5040  int iext=0;
5041  for (iter=begin; iter!=end;++iter,++iext)
5042  {
5043  bool bs1 = (*iter)->getInitialQnorm (tleVec[iext]);
5044  bsuccess = bsuccess && bs1;
5045  }
5046 #endif // Xyce_EXTDEV
5047 
5048  return bsuccess;
5049 }
5050 
5051 //-----------------------------------------------------------------------------
5052 // Function : DeviceMgr::getInnerLoopErrorSums
5053 // Purpose :
5054 // Special Notes :
5055 // Scope : public
5056 // Creator : Eric R. Keiter, SNL
5057 // Creation Date : 03/12/06
5058 //-----------------------------------------------------------------------------
5060  std::vector<N_TIA_TwoLevelError> & tleVec)
5061 {
5062  bool bsuccess = true;
5063 
5064 #ifdef Xyce_EXTDEV
5065  int numExt = extDevInstancePtrVec_.size();
5066 
5067  tleVec.resize(numExt);
5068 
5069  std::vector<ExternDevice::Instance*>::iterator iter;
5070  std::vector<ExternDevice::Instance*>::iterator begin;
5071  std::vector<ExternDevice::Instance*>::iterator end;
5072  begin = extDevInstancePtrVec_.begin ();
5073  end = extDevInstancePtrVec_.end ();
5074 
5075  int iext=0;
5076  for (iter=begin; iter!=end;++iter,++iext)
5077  {
5078  bool bs1 = (*iter)->getInnerLoopErrorSum (tleVec[iext]);
5079  bsuccess = bsuccess && bs1;
5080  }
5081 #endif // Xyce_EXTDEV
5082 
5083  return bsuccess;
5084 }
5085 
5086 //-----------------------------------------------------------------------------
5087 // Function : DeviceMgr::updateStateArrays()
5088 // Purpose :
5089 // Special Notes :
5090 // Scope : public
5091 // Creator : Eric R. Keiter, SNL
5092 // Creation Date : 03/12/06
5093 //-----------------------------------------------------------------------------
5095 {
5096  bool bsuccess = true;
5097 
5098 #ifdef Xyce_EXTDEV
5099 
5100  std::vector<ExternDevice::Instance*>::iterator iter;
5101  std::vector<ExternDevice::Instance*>::iterator begin;
5102  std::vector<ExternDevice::Instance*>::iterator end;
5103  begin = extDevInstancePtrVec_.begin ();
5104  end = extDevInstancePtrVec_.end ();
5105 
5106  for (iter=begin; iter!=end;++iter)
5107  {
5108  bool bs1 = (*iter)->updateStateArrays();
5109  bsuccess = bsuccess && bs1;
5110  }
5111 #endif // Xyce_EXTDEV
5112 
5113  return bsuccess;
5114 }
5115 
5116 
5117 //-----------------------------------------------------------------------------
5118 // Function : DeviceMgr::startTimeStep
5119 // Purpose :
5120 // Special Notes :
5121 // Scope : public
5122 // Creator : Eric R. Keiter, SNL
5123 // Creation Date : 03/20/06
5124 //-----------------------------------------------------------------------------
5126 {
5127  bool bsuccess = true;
5128  bool tmpBool = setupSolverInfo_();
5129 
5130 #ifdef Xyce_EXTDEV
5131  std::vector<ExternDevice::Instance*>::iterator iter;
5132  std::vector<ExternDevice::Instance*>::iterator begin;
5133  std::vector<ExternDevice::Instance*>::iterator end;
5134  begin = extDevInstancePtrVec_.begin ();
5135  end = extDevInstancePtrVec_.end ();
5136 
5137  for (iter=begin; iter!=end;++iter)
5138  {
5139  bool bs1 = (*iter)->startTimeStep ();
5140  bsuccess = bsuccess && bs1;
5141  }
5142 #endif // Xyce_EXTDEV
5143 
5144  return bsuccess;
5145 }
5146 
5147 
5148 //-----------------------------------------------------------------------------
5149 // Function : DeviceMgr::setExternalSolverState
5150 // Purpose :
5151 // Special Notes :
5152 // Scope : public
5153 // Creator : Eric R. Keiter, SNL
5154 // Creation Date : 03/20/06
5155 //-----------------------------------------------------------------------------
5157 {
5158  externalStateFlag_ = true;
5159  solStateExternal_ = ss;
5160  return;
5161 }
5162 
5163 //-----------------------------------------------------------------------------
5164 // Function : DeviceMgr::restartDataSize
5165 // Purpose :
5166 // Special Notes :
5167 // Scope : public
5168 // Creator : Eric R. Keiter, SNL
5169 // Creation Date : 06/26/2013
5170 //-----------------------------------------------------------------------------
5172 {
5173  int numdoubles = solState_.ltraTimePoints.size();
5174  int numSize_t = 3;
5175  int count = sizeof(double) * (numdoubles);
5176  count += sizeof(size_t) * numSize_t;
5177 
5178  // bump up size for unpacked data. This is an empirical multiplier.
5179  if (!pack)
5180  {
5181  count *= 3;
5182  }
5183 
5184  return count;
5185 }
5186 
5187 //-----------------------------------------------------------------------------
5188 // Function : DeviceMgr::dumpRestartData
5189 // Purpose : Output restart data.
5190 // Special Notes : This function is called by the restart manager to output
5191 // persistent data for the device package. It should NOT
5192 // include any data from individual devices, as that restart
5193 // data is collected elsewhere.
5194 // Scope :
5195 // Creator : Eric R. Keiter, SNL
5196 // Creation Date : 06/26/2013
5197 //-----------------------------------------------------------------------------
5199 (char * buf, int bsize, int & pos, N_PDS_Comm * comm, bool pack)
5200 {
5201  bool retval=true;
5202 
5203  if (pack)
5204  {
5205  size_t size=solState_.ltraTimePoints.size();
5206  comm->pack(&(solState_.ltraTimeIndex), 1, buf, bsize, pos);
5207  comm->pack(&(solState_.ltraTimeHistorySize), 1, buf, bsize, pos);
5208  comm->pack(&(size), 1, buf, bsize, pos);
5209  comm->pack(&(solState_.ltraTimePoints[0]), size, buf, bsize, pos);
5210  }
5211  else
5212  {
5213  int count = restartDataSize(false);
5214  int startIndex = pos;
5215  for(int i = startIndex; i < (startIndex+count); ++i) buf[i] = ' ';
5216 
5217  size_t size=solState_.ltraTimePoints.size();
5218  std::ostringstream ost;
5219  ost.width(24);ost.precision(16);ost.setf(std::ios::scientific);
5220  ost << solState_.ltraTimeIndex << " ";
5221  ost << solState_.ltraTimeHistorySize << " ";
5222 #ifdef Xyce_DEBUG_RESTART
5223  dout() <<
5224  "DeviceMgr::getRestartData: ltraTimeIndex = " << solState_.ltraTimeIndex <<std::endl;
5225  dout() <<
5226  "DeviceMgr::getRestartData: ltraTimeHistorySize = " << solState_.ltraTimeHistorySize <<std::endl;
5227 #endif
5228  ost << size << " ";
5229  for (int i=0;i<size;i++)
5230  {
5231  ost << solState_.ltraTimePoints[i] << " ";
5232 #ifdef Xyce_DEBUG_RESTART
5233  dout() <<
5234  "DeviceMgr::dumpRestartData: ltraTimePoints["<<i<<"] ="
5235  << solState_.ltraTimePoints[i]<<std::endl;
5236 #endif
5237  }
5238 
5239  std::string data(ost.str());
5240  for(unsigned int i = 0; i < data.length(); ++i) buf[startIndex+i] = data[i];
5241 
5242  // The line above copies the characters of the data string into buf,
5243  // but doesn't null-terminate buf.
5244  // it is essential to terminate the buffer with a null, or attempts
5245  // to construct a string object from it will get memory access problems.
5246  buf[startIndex+data.length()] = '\0';
5247  pos += data.length();
5248  }
5249 
5250  return retval;
5251 }
5252 
5253 //-----------------------------------------------------------------------------
5254 // Function : DeviceMgr::restoreRestartData
5255 // Purpose : Load restart data.
5256 // Special Notes :
5257 // Scope :
5258 // Creator : Eric R. Keiter, SNL
5259 // Creation Date : 06/26/2013
5260 //-----------------------------------------------------------------------------
5261 bool DeviceMgr::restoreRestartData(char * buf, int bsize, int & pos, N_PDS_Comm * comm, bool pack)
5262 {
5263  bool retval=true;
5264 
5265  if (pack)
5266  {
5267  comm->unpack(buf, bsize, pos, &(solState_.ltraTimeIndex), 1);
5268  comm->unpack(buf, bsize, pos, &(solState_.ltraTimeHistorySize), 1);
5269  size_t size=0;
5270  comm->unpack(buf, bsize, pos, &(size), 1);
5271  solState_.ltraTimePoints.resize(size);
5272  comm->unpack(buf, bsize, pos, &(solState_.ltraTimePoints[0]), size);
5273  }
5274  else
5275  {
5276  std::string str1(buf);
5277  int length = str1.size() - pos;
5278  std::string str2(str1,pos,length);
5279 
5280  std::istringstream ist(str2);
5281 
5282  ist >> solState_.ltraTimeIndex;
5284 #ifdef Xyce_DEBUG_RESTART
5285  dout() <<
5286  "DeviceMgr::restoreRestartData: ltraTimeIndex = " << solState_.ltraTimeIndex <<std::endl;
5287  dout() <<
5288  "DeviceMgr::restoreRestartData: ltraTimeHistorySize = " << solState_.ltraTimeHistorySize <<std::endl;
5289 #endif
5290  size_t size=0;
5291  ist >> size;
5292  solState_.ltraTimePoints.resize(size);
5293  for (int i=0;i<size;++i)
5294  {
5295  ist >> solState_.ltraTimePoints[i];
5296 #ifdef Xyce_DEBUG_RESTART
5297  dout() << "DeviceMgr::restoreRestartData: ltraTimePoints["<<i<<"] = " << solState_.ltraTimePoints[i] << std::endl;
5298 #endif
5299  }
5300 
5301  pos += ist.tellg();
5302  }
5303 
5304  return retval;
5305 }
5306 
5307 // ----------------------------------------------------------------------------
5308 // Function : setupIOName
5309 //
5310 // Purpose : This function takes the device instance name and creates
5311 // an appropriate "outputName" to be used for file outputs.
5312 //
5313 // Special Notes :
5314 // Scope : public
5315 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
5316 // Creation Date : 04/26/2013
5317 // ----------------------------------------------------------------------------
5318 void setupIOName (const std::string & name, std::string & outputName)
5319 {
5320  // get rid of the y-device prefix.
5321  std::string::size_type pos1 = name.find_first_of("Y%");
5322  std::string::size_type pos2 = name.find_last_of("%");
5323 
5324  if (pos1 != std::string::npos && pos2 != std::string::npos)
5325  {
5326  std::string tmp1 = "";
5327  if (pos1 > 0) tmp1 = name.substr(0,pos1);
5328  std::string tmp2 = name.substr(pos2+1, name.length()-1);
5329  outputName = tmp1 + tmp2;
5330  }
5331  else
5332  {
5333  outputName = name;
5334  }
5335 
5336  return;
5337 }
5338 
5339 //-----------------------------------------------------------------------------
5340 // Function : DeviceSensitivites::getDeviceEntity
5341 // Purpose :
5342 // Special Notes :
5343 // Scope : public
5344 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
5345 // Creation Date : 5/02/03
5346 //-----------------------------------------------------------------------------
5347 DeviceEntity * DeviceMgr::getDeviceEntity(const std::string & full_param_name) const
5348 {
5349  DeviceEntityMap::iterator it = nameDevEntityMap_.find(full_param_name);
5350  if (it == nameDevEntityMap_.end() || !(*it).second)
5351  {
5352  DeviceEntity *device_entity = findDeviceEntity(deviceMap_.begin(), deviceMap_.end(), Xyce::Util::entityNameFromFullParamName(full_param_name));
5353  nameDevEntityMap_[full_param_name] = device_entity;
5354  return device_entity;
5355  }
5356  else
5357  return (*it).second;
5358 }
5359 
5360 } // namespace Device
5361 } // namespace Xyce