Xyce  6.1
N_ANP_Transient.C
Go to the documentation of this file.
1 //-----------------------------------------------------------------------------
2 // Copyright Notice
3 //
4 // Copyright 2002 Sandia Corporation. Under the terms
5 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S.
6 // Government retains certain rights in this software.
7 //
8 // Xyce(TM) Parallel Electrical Simulator
9 // Copyright (C) 2002-2015 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_ANP_Transient.C,v $
27 // Purpose : Transient analysis functions.
28 // Special Notes :
29 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
30 // Creation Date : 01/24/08
31 //
32 // Revision Information:
33 // ---------------------
34 // Revision Number: $Revision: 1.237.2.2 $
35 // Revision Date : $Date: 2015/11/21 01:21:41 $
36 // Current Owner : $Author: tmei $
37 //-----------------------------------------------------------------------------
38 
39 #include <Xyce_config.h>
40 
41 #include <sstream>
42 #include <iomanip>
43 
44 #include <N_ANP_Transient.h>
45 
46 #include <N_ANP_AnalysisManager.h>
47 #include <N_ANP_OutputMgrAdapter.h>
48 #include <N_ANP_Report.h>
49 #include <N_ERH_Progress.h>
50 #include <N_IO_CmdParse.h>
51 #include <N_IO_CircuitBlock.h>
52 #include <N_IO_OptionBlock.h>
53 #include <N_IO_OutputMgr.h>
54 #include <N_IO_PkgOptionsMgr.h>
55 #include <N_IO_RestartMgr.h>
56 #include <N_LAS_System.h>
57 #include <N_LOA_Loader.h>
59 #include <N_MPDE_Manager.h>
61 #include <N_NLS_ReturnCodes.h>
62 #include <N_PDS_Comm.h>
63 #include <N_PDS_MPI.h>
64 #include <N_PDS_Serial.h>
65 #include <N_TIA_DataStore.h>
67 #include <N_TIA_OneStep.h>
68 #include <N_TIA_StepErrorControl.h>
70 #include <N_TOP_Topology.h>
71 #include <N_UTL_Diagnostic.h>
72 #include <N_UTL_ExpressionData.h>
73 #include <N_UTL_ExtendedString.h>
74 #include <N_UTL_Factory.h>
75 #include <N_UTL_FeatureTest.h>
76 #include <N_UTL_MachDepParams.h>
77 #include <N_UTL_NoCase.h>
78 #include <N_UTL_Param.h>
79 #include <N_UTL_Timer.h>
80 
81 namespace Xyce {
82 namespace Analysis {
83 
84 void writeConductanceFile(const std::vector<std::string> &device_names, Nonlinear::ConductanceExtractor &conductance_extractor, const std::string &filename);
85 
86 //-----------------------------------------------------------------------------
87 // Function : Transient::Transient(AnalysisManager &manager)
88 // Purpose : constructor
89 // Special Notes :
90 // Scope : public
91 // Creator : Rich Schiek, SNL
92 // Creation Date : 3/11/06
93 //-----------------------------------------------------------------------------
95  AnalysisManager & analysis_manager,
96  Linear::System & linear_system,
97  Nonlinear::Manager & nonlinear_manager,
98  Loader::Loader & loader,
99  Topo::Topology & topology,
100  IO::InitialConditionsManager & initial_conditions_manager,
101  IO::RestartMgr & restart_manager,
102  OutputAdapter * output_adapter,
103  HB * hb_analysis,
104  N_MPDE_Manager * mpde_manager)
105  : AnalysisBase(analysis_manager, "Transient"),
106  StepEventListener(&analysis_manager),
107  comm_(analysis_manager.getPDSManager()->getPDSComm()->comm()),
108  analysisManager_(analysis_manager),
109  loader_(loader),
110  linearSystem_(linear_system),
111  nonlinearManager_(nonlinear_manager),
112  topology_(topology),
113  initialConditionsManager_(initial_conditions_manager),
114  restartManager_(restart_manager),
115  outputManagerAdapter_(analysis_manager.getOutputManagerAdapter()),
116  outputAdapter_(output_adapter),
117  tiaParams_(),
118  sensFlag_(analysis_manager.getSensFlag()),
119  initialIntegrationMethod_(TimeIntg::OneStep::type),
120  firstTranOutput_(true),
121  isPaused(false),
122  dcopFlag_(true),
123  startDCOPtime(0.0),
124  startTRANtime_(0.0),
125  endTRANtime_(0.0),
126  gui_(analysisManager_.getCommandLine().argExists("-gui")),
127  maxTimeStepExpressionString_(),
128  maxTimeStepExpression_(0),
129  firstTime(true),
130  oldPercentComplete(0.0),
131  startSimTime(-1.0),
132  nextRestartSaveTime_(0.0),
133  dcStats(0),
134  tranStats(0),
135  exitTime(0.0),
136  exitStep(-1),
137  integrationMethod(7),
138  historyTrackingDepth(25),
139  passNLStall(false),
140  saveTimeStepsFlag(false),
141  condTestFlag(false),
142  condTestDeviceNames(),
143  hbAnalysis_(hb_analysis),
144  mpdeManager_(mpde_manager)
145 {}
146 
147 void Transient::notify(const StepEvent &event)
148 {
149  if (event.state_ == StepEvent::STEP_STARTED)
150  {
152 
155  dcopFlag_ = false;
157 
158  if (timeQueue_.get_size() != 0)
159  {
160  // these set_size calls will also "reset" the queue.
161  timeQueue_.reset_queue();
162  timeStepQueue_.reset_queue();
163  stepStatusQueue_.reset_queue();
164  estErrorOverTolQueue_.reset_queue();
165  nonlinearSolverStatusQueue_.reset_queue();
167  nonlinearSolverMaxNormQueue_.reset_queue();
168  nonlinearSolverMaxNormIndexQueue_.reset_queue();
169  }
170  }
171 }
172 
173 //-----------------------------------------------------------------------------
174 // Function : Transient::setAnalysisParams
175 // Purpose :
176 // Special Notes : These are from the .TRAN statement.
177 // Scope : public
178 // Creator : Eric Keiter, SNL
179 // Creation Date : 6/21/10
180 //-----------------------------------------------------------------------------
182  const Util::OptionBlock & option_block)
183 {
184  for (Util::ParamList::const_iterator it = option_block.begin(), end = option_block.end(); it != end; ++it)
185  {
186  const Util::Param &param = *it;
187 
188  if (tiaParams_.setAnalysisOption(param))
189  ;
190  else if (param.uTag() == "NOOP" ||
191  param.uTag() == "UIC")
192  {
193  setNOOP(true);
194  }
195  else if (param.uTag() == "MAXTIMEEXPRESSION")
196  {
197  // an expression was given which should specify what
198  // max time step to use based on the current simulation
199  // time. The expected format of this is
200  // {schedule( t0, max_del_t0, t1, max_del_t1, ...)}
201  // we'll just store the expression as a string for now
202  // as we need to make sure other classes are up and running
203  // before we can create the actual expression. That will
204  // happen in Transient class as it will ultimately use this
205  maxTimeStepExpressionString_ = param.stringValue();
206  }
207  else
208  IO::ParamError(option_block, param) << "Unrecognized analysis option";
209  }
210 
212  {
213  UserFatal(*this) << "Final time of " << tiaParams_.finalTime
214  << " is earlier or same as start time of " << tiaParams_.initialOutputTime << std::endl
215  << " Check netlist for invalid .TRAN specification";
216  }
217 
218  // if starting time steps is baloney, set then to a default value.
219  // ERK. This trap is redudant with an identical one in step error
220  // control.
221  if ( tiaParams_.initialTimeStep <= 0.0 )
222  {
223  tiaParams_.initialTimeStep = 1.0e-10;
224  }
225 
226  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
227  {
228  dout() << std::endl
229  << section_divider << std::endl
230  << " Transient simulation parameters" << std::endl
231  << " initial time = " << tiaParams_.initialTime << std::endl
232  << " final time = " << tiaParams_.finalTime << std::endl
233  << " starting time step = " << tiaParams_.initialTimeStep << std::endl
234  << " initialOutputTime (time of first output) = " << tiaParams_.initialOutputTime << std::endl;
235 
236  if (!getNOOP())
237  {
238  dout() << " NOOP/UIC is NOT set" << std::endl;
239  }
240  else
241  {
242  dout() << " NOOP/UIC is set" << std::endl;
243  }
244 
245  dout() << section_divider << std::endl;
246  }
247 
248  if (!maxTimeStepExpressionString_.empty())
249  {
250  // set-up expression object for getting a user specified, time dependent max time step value
251  delete maxTimeStepExpression_;
252 
253  maxTimeStepExpression_ = new Util::ExpressionData(maxTimeStepExpressionString_);
254  }
255 
256  // historySize_ should can be set from the .options timeint line. Use default in tiaParams
257  // as that will be overwritten if the user set it via .options. Also, if it's less than
258  // or equal to zero assume that the user wants this turned off.
259  // We'll store the attempted time step, time step status,
260  // estimated error over tolerance, non-linear solver status and non-linear solver norm
261  // for each step, up to the last historySize_ steps.
262 
263  if (historyTrackingDepth > 0 )
264  {
265  int size = historyTrackingDepth;
266  timeQueue_.set_size( size );
267  timeStepQueue_.set_size( size );
268  stepStatusQueue_.set_size( size );
269  estErrorOverTolQueue_.set_size( size );
270  nonlinearSolverStatusQueue_.set_size( size );
271  nonlinearSolverNumIterationsQueue_.set_size( size );
272  nonlinearSolverMaxNormQueue_.set_size( size );
273  nonlinearSolverMaxNormIndexQueue_.set_size( size );
274  }
275 
276  return true;
277 }
278 
279 //-----------------------------------------------------------------------------
280 // Function : AnalysisManager::setTranOptions
281 // Purpose :
282 // Special Notes : These are from '.options timeint'
283 // Scope : public
284 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
285 // Creation Date : 04/18/02
286 //-----------------------------------------------------------------------------
288  const Util::OptionBlock & option_block)
289 {
290  for (Util::ParamList::const_iterator it = option_block.begin(), end = option_block.end(); it != end; ++it)
291  {
292  const Util::Param &param = (*it);
293 
294  if (param.uTag() == "METHOD")
295  {
296  if (param.isInteger())
297  integrationMethod = param.getImmutableValue<int>();
298  else
299  {
300  ExtendedString stringVal ( param.stringValue() );
301  stringVal.toUpper();
302 
303  if (stringVal == "TRAP" || stringVal == "TRAPEZOIDAL")
304  integrationMethod = 7;
305  else if (stringVal == "BDF")
306  integrationMethod = 6;
307  else if (stringVal == "GEAR")
308  integrationMethod = 8;
309  else
310  {
311  IO::ParamError(option_block, param) << "Unsupported transient method type";
312  }
313  }
314 
315  }
316  else if (param.uTag()=="EXITTIME" )
317  exitTime = param.getImmutableValue<double>();
318  else if (param.uTag()=="EXITSTEP" )
319  exitStep = param.getImmutableValue<int>();
320  else if (param.uTag() == "HISTORYTRACKINGDEPTH" )
321  historyTrackingDepth = param.getImmutableValue<int>();
322  else if (param.uTag() == "PASSNLSTALL")
323  passNLStall = param.getImmutableValue<bool>();
324  else if (param.uTag() == "CONDTEST")
325  condTestFlag = static_cast<bool> (param.getImmutableValue<int>());
326  else if (param.uTag() == "CONDTESTDEVICENAME")
327  condTestDeviceNames.push_back(param.stringValue() );
328  else if (param.uTag() == "DAESTATEDERIV" )
329  analysisManager_.setDAEStateDerivFlag(static_cast<bool> (param.getImmutableValue<int>()));
330  else if (param.uTag() == "DEBUGLEVEL" )
331  IO::setTimeIntegratorDebugLevel(analysisManager_.getCommandLine(), param.getImmutableValue<int>());
332  else if (nonlinearManager_.setReturnCodeOption(param))
333  ;
334  else if (tiaParams_.setTimeIntegratorOption(param))
335  ;
336  else if (setDCOPOption(param))
337  ;
338  else
339  IO::ParamError(option_block, param) << "Not a recognized time integration option";
340  }
341 
342  return true;
343 }
344 
345 //-----------------------------------------------------------------------------
346 // Function : Transient::run()
347 // Purpose :
348 // Special Notes :
349 // Scope : public
350 // Creator : Rich Schiek, SNL
351 // Creation Date : 3/11/06
352 //-----------------------------------------------------------------------------
354 {
355  isPaused = false;
356 
357  bool bsuccess = false;
358 
360  {
361  bsuccess = resuming() && doLoopProcess() && doFinish();
362  }
363  else
364  {
365  bsuccess = doInit() && doTranOP () && doLoopProcess() && doFinish();
366  }
367 
368  if (condTestFlag)
369  {
371  }
372 
373  return bsuccess;
374 }
375 
376 //-----------------------------------------------------------------------------
377 // Function : Transient::resuming()
378 // Purpose :
379 // Special Notes :
380 // Scope : public
381 // Creator : Rich Schiek, SNL
382 // Creation Date : 3/11/06
383 //-----------------------------------------------------------------------------
385 {
386  bool bsuccess = true;
387 
388  if (sensFlag_)
389  {
390  Stats::StatTop _sensitivityStat("Sensitivity");
391 
393  }
394 
396 
398  {
399  // we're resuming from a previous transient simulation
400  // this is an ugly side effect of the analysis manager's deleting
401  // the transient object after it returned in a paused state
402  // need to fix this in Xyce 6.0 . RLS 12/22/2009
403  dcopFlag_ = false;
404 
405  // we default firstTranOutput_ to true to force the first time point to be output
406  // however, if we're resuming, then we need this to be false
407  // this is really a defect of a paused simulation's Transient object
408  // being deleted by the AnalysisManager and then a new one being created
409  // when the simulation is resumed. Need to fully fix this. RLS 12/22/2009
410  firstTranOutput_ = false;
411  }
412 
413  // in a 2 level problem, we can be asked to resume
414  // without first making the integration method. So
415  // catch that.
417  {
420  }
421 
422  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
423  dout() << " transient init called with resume true " << std::endl;
425 
426  // reset min error tracking variables
427  // if the step number is less than zero we'll assume there is no valid
428  // min. estimated error over tol or an associated time step. This frees us
429  // from putting Machine::Big here and trying to do something with that.
431  minEstErrorOverTol = 0.0;
433 
434  return bsuccess;
435 }
436 
437 //-----------------------------------------------------------------------------
438 // Function : Transient::init()
439 // Purpose :
440 // Special Notes :
441 // Scope : public
442 // Creator : Rich Schiek, SNL
443 // Creation Date : 3/11/06
444 //-----------------------------------------------------------------------------
446 {
447  bool bsuccess = true;
448 
449  if (sensFlag_)
450  {
451  Stats::StatTop _sensitivityStat("Sensitivity");
452 
454  }
455 
457 
458  dcopFlag_ = !getNOOP();
459 
461 
463 
464  if (restartManager_.isRestarting())
465  {
467 
470 
471  dcopFlag_ = false;
472  analysisManager_.setTwoLevelMode(Analysis::TWO_LEVEL_MODE_TRANSIENT);
473 
474  // Update vectors with off proc values.
475  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->nextSolutionPtr);
476  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->currSolutionPtr);
477  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->nextStatePtr);
478  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->currStatePtr);
479  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->nextStorePtr);
480  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->currStorePtr);
481 
482  // Set the nonlinear solver parameters to those appropriate for the
483  // transient solution. If starting from here, we're not doing a DCOP
484  // calculation first - we're jumping right into the transient.
486  }
487  else // not restart
488  {
489  if (dcopFlag_)
490  {
491  // Get set to do the operating point.
494  }
495  else // otherwise NOOP/UIC
496  {
499  }
500 
501  // This setInitialGuess call is to up an initial guess in the
502  // devices that have them (usually PDE devices). This is DIFFERENT
503  // than an initial condition.
505 
506  // 12/13/07 tscoffe/tmei: .ic should not be applied to MPDE currently.
507  // A new mechanism must be set up for this, e.g. .mpde_ic
508  if (!mpdeManager_ || mpdeManager_->getTransientNeedsToLoadInitialConditionsAndInitializeProblem())
509  {
510  // If available, set initial solution. This may be from a DCOP restart,
511  // a .IC, or a .NODESET line. These can be used in both the UIC/NOOP
512  // case, as well as the DCOP case, so they need to be outside the if-statement.
515  topology_.getSolutionNodeNameMap(),
518 
519  if (!dcopFlag_)
520  {
521  // this "initializeProblem" call is to set the IC's in devices that
522  // have them. This is done IN PLACE of the operating point.
539 
540  // Do this to populate the q-vector:
541  // since we're also skipping the DC OP, this call will
542  // also force the loader to propagate the state vector to the
543  // device manager which updates state vector seen by the devices.
545  }
546  }
547 
548  // Set a constant history.
552 
553  // Update vectors with off proc values.
554  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->nextSolutionPtr);
555  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->currSolutionPtr);
556  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->nextStatePtr);
557  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->currStatePtr);
558  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->nextStorePtr);
559  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->currStorePtr);
560 
561  // if we are skipping the DCOP, but .sens was requested, then call this here.
562  if (!dcopFlag_ && !mpdeManager_ && sensFlag_)
563  {
565 
567  }
568 
569  if (!dcopFlag_)
570  {
571  // Now do a NOOP output. ERK: 08/30/2007 This isn't the best place to
572  // put this, but it will have to do for now. If this isn't here, then
573  // NOOP/UIC simulations don't output at t=0.0 in the *prn file.
574  noopOutputs ();
575  }
576 
577  stepNumber = 0;
578  tranStepNumber = 0;
580  }
582  // if we're resuming, this was already done prior to pausing, and doing
583  // it again screws us up
584  double suggestedMaxTime = 0.0;
586  {
587  if (maxTimeStepExpression_->setup(comm_,
588  outputManagerAdapter_.getOutputManager().getOpBuilderManager(),
589  outputManagerAdapter_.getOutputManager().getMainContextFunctionMap(),
590  outputManagerAdapter_.getOutputManager().getMainContextParamMap(),
591  outputManagerAdapter_.getOutputManager().getMainContextGlobalParamMap()) == Util::ExpressionData::READY)
592  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_,
593  outputManagerAdapter_.getOutputManager().getCircuitTime(),
597  }
601 
603 
604  // reset min error tracking variables
605  // if the step number is less than zero we'll assume there is no valid
606  // min. estimated error over tol or an associated time step. This frees us
607  // from putting Machine::Big here and trying to do something with that.
609  minEstErrorOverTol = 0.0;
611 
612  return bsuccess;
613 }
614 
615 //-----------------------------------------------------------------------------
616 // Function : Transient::doTranOP ()
617 // Purpose : Computes the DCOP calcualtion that precedes transient loop.
618 // Special Notes :
619 // Scope : public
620 // Creator : Dave Baur
621 // Creation Date :
622 //-----------------------------------------------------------------------------
624 {
625  bool bsuccess = true;
626 
627  Stats::Stat _transientStat(Stats::StatTop::getTop());
628  Stats::TimeBlock _transientTimer(_transientStat);
629 
630  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::INITIALIZE, AnalysisEvent::TRAN));
631 
632  // Transient time stepping loop:
633  while (dcopFlag_)
634  {
635  if (VERBOSE_TIME)
636  printStepHeader(Xyce::lout());
637 
638  printProgress(Xyce::lout());
639 
640  // ------------------------------------------------------------------------
641  // If the flag is set to switch integration methods, do that here.
642  // For example, switch from operating point to transient backward euler.
644  {
646  }
647 
648  // ------------------------------------------------------------------------
649  // Set the step size, current time and next time.
650 
652  comm_,
657 
658  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
659  {
660  dout() << std::endl;
661  dout() << "Transient::loopProcess()" << std::endl;
662  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
663  dout() << "analysisManager_.getStepErrorControl().stepAttemptStatus = " << analysisManager_.getStepErrorControl().stepAttemptStatus << std::endl;
664  }
665 
666  if (beginningIntegration &&
668  {
669  // ------------------------------------------------------------------------
670  // 07/29/04 TSC: initial step-size selection is now done in the
671  // integration method initialize call under the DAE formulation. This
672  // segregates codes changes better and makes sense to do as an
673  // initialization step even if its changed later.
675  double suggestedMaxTime=0.0;
677  {
678  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
680  }
683  }
684 
685  // ------------------------------------------------------------------------
686  // If we've switched the integration method, we need to obtain the
687  // corrector derivative only after we've updated the TimeInfo.
689  {
692  }
693 
694  // Ask the method to update its coefficients
696 
698 
699  // ------------------------------------------------------------------------
700  // Perform the time step:
702 
703  // ------------------------------------------------------------------------
705  {
707  }
709  {
711  bsuccess = false;
712  break;
713  }
714  }
715 
718 
719  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::FINISH, AnalysisEvent::TRAN));
720 
721  return bsuccess;
722 }
723 
724 
725 //-----------------------------------------------------------------------------
726 // Function : Transient::doLoopProcess()
727 // Purpose : Conduct the time stepping loop.
728 // Special Notes :
729 // Scope : public
730 // Creator : Rich Schiek, SNL
731 // Creation Date : 3/11/06
732 //-----------------------------------------------------------------------------
734 {
735  bool bsuccess = true;
736 
737  Stats::Stat _transientStat(Stats::StatTop::getTop());
738  Stats::TimeBlock _transientTimer(_transientStat);
739 
740  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::INITIALIZE, AnalysisEvent::TRAN));
741 
742  // Transient time stepping loop:
744  {
745  if (VERBOSE_TIME)
746  printStepHeader(Xyce::lout());
747 
748  printProgress(Xyce::lout());
749 
750  // ------------------------------------------------------------------------
751  // If the flag is set to switch integration methods, do that here.
752  // For example, switch from operating point to transient backward euler.
753 
755  {
757  }
758 
759  // ------------------------------------------------------------------------
760  // Set the step size, current time and next time.
761 
763  comm_,
768 
769  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
770  {
771  dout() << std::endl;
772  dout() << "Transient::loopProcess()" << std::endl;
773  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
774  dout() << "analysisManager_.getStepErrorControl().stepAttemptStatus = " << analysisManager_.getStepErrorControl().stepAttemptStatus << std::endl;
775  }
776 
777  if (beginningIntegration &&
779  {
780  // ------------------------------------------------------------------------
781  // 07/29/04 TSC: initial step-size selection is now done in the
782  // integration method initialize call under the DAE formulation. This
783  // segregates codes changes better and makes sense to do as an
784  // initialization step even if its changed later.
786  double suggestedMaxTime=0.0;
788  {
789  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
791  }
794  }
795 
796  // ------------------------------------------------------------------------
797  // If we've switched the integration method, we need to obtain the
798  // corrector derivative only after we've updated the TimeInfo.
800  {
803  }
804 
805  if (VERBOSE_TIME)
807 
808  // ------------------------------------------------------------------------
809  // Set the nonlinear solver parameters to those appropriate for the
810  // transient solution, if neccessary.
812 
813  // Ask the method to update its coefficients
815 
817 
818  // ------------------------------------------------------------------------
819  // Perform the time step:
821 
822  // ------------------------------------------------------------------------
824  {
826  }
827  else if (passNLStall
830  {
831  // potentially a VERY dangerous options.
832  // if the non-linear solver is stalling, and we're very close to a min
833  // time step, then calls this failure a pass
835  {
836  {
837  UserWarning(*this) << "Nonlinear solver stalled. Calling this a pass";
838  }
839 
841  }
842  // another VERY dangerous options.
843  // if the non-linear solver is reporting too big of an update, and we're very close to a min
844  // time step, then calls this failure a pass
846  {
847  {
848  UserWarning(*this) << "Update too big. Calling this a pass";
849  }
850 
852  }
853  // another VERY dangerous options.
854  // if the non-linear solver is not converging in the max number of steps,
855  // and we're very close to a min time step, then calls this failure a pass
856  //
857  // if( analysisManager_.getStepErrorControl().newtonConvergenceStatus == -1)
858  // {
859  // Report::UserWarning0() << "Too many steps, calling this a pass";
860  // processSuccessfulStep();
861  // }
862  else
863  {
864  // process this failed step as we would have by default.
865  bool b1 = doProcessFailedStep();
866  if (!b1)
867  {
868  bsuccess = false;
869  break;
870  }
871  }
872  }
873  else // stepAttemptStatus (ie do this if the step FAILED)
874  {
875  bool b1 = doProcessFailedStep();
876  if (!b1)
877  {
878  bsuccess = false;
879  break;
880  }
881  } // stepAttemptStatus
882 
883  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
884  {
885  dout() << std::endl;
886  dout() << " Here we are, just before checking whether to pause. " << std::endl;
887  dout() << " minTimeStep = " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
888  dout() << " final time = " << tiaParams_.finalTime << std::endl;
889  dout() << " pause time = " << analysisManager_.getPauseTime() << std::endl;
890  dout() << " initial time = " << analysisManager_.getStepErrorControl().initialTime << std::endl;
891  dout() << " current time = " << analysisManager_.getStepErrorControl().currentTime << std::endl;
893  {
894  dout() << " Pause time and current time equal " << std::endl;
895  }
896  else
897  {
898  dout() << " difference between current and pause times is "
900  }
902  {
903  dout() << " Pause time and initial time equal " << std::endl;
904  }
905  }
906 
908  {
909  // Failure at this point only indicates that the simulation
910  // is paused and may be resumed.
911  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
912  {
913  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
914  }
915 
917  isPaused = true;
918  bsuccess = true;
919  break;
920  }
921 
922  // If the exit time has been exceeded, exit.
924  {
925  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
926  bsuccess = true;
927  break;
928  }
929 
930  if (exitStep != -1 && static_cast<int>(stepNumber) == exitStep)
931  {
932  lout() << "Exit step. Exiting transient loop\n" << std::endl;
933  bsuccess = true;
934  break;
935  }
936 
937  } // end of time loop
938 
941 
942  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::FINISH, AnalysisEvent::TRAN));
943 
944  return bsuccess;
945 }
946 
947 
948 //-----------------------------------------------------------------------------
949 // Function : Transient::mixedSignalStep
950 // Purpose :
951 // Special Notes : Habanero API function
952 // Scope : public
953 // Creator : Eric Keiter, SNL
954 // Creation Date : 3/04/09
955 //-----------------------------------------------------------------------------
956 bool Transient::mixedSignalStep(double maxTimeStepFromHabanero)
957 {
958  preMixedSignalStepDetails(maxTimeStepFromHabanero);
959 
961 
962  return true;
963 }
964 
965 //-----------------------------------------------------------------------------
966 // Function : Transient::preMixedSignalStepDetails
967 // Purpose :
968 // Special Notes : Habanero API function
969 // Scope : private_
970 // Creator : Eric Keiter, SNL
971 // Creation Date : 3/04/09
972 //-----------------------------------------------------------------------------
974  double maxTimeStepFromHabanero)
975 {
976  if (VERBOSE_TIME)
977  printStepHeader(Xyce::lout());
978 
979  printProgress(Xyce::lout());
980 
981  // ------------------------------------------------------------------------
982  // If the flag is set to switch integration methods, do that here.
983  // For example, switch from operating point to transient backward euler.
984 
986  {
988  }
989 
990  // ------------------------------------------------------------------------
991  // Set the step size, current time and next time.
993  comm_,
998 
999  // ------------------------------------------------------------------------
1000  // If a max time is set from Habanero, impose it now that stopTime is updated.
1001  if (maxTimeStepFromHabanero > 0)
1002  {
1003  double currentTimeStep = std::min(maxTimeStepFromHabanero, analysisManager_.getStepErrorControl().currentTimeStep);
1005  }
1006 
1007  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1008  {
1009  dout() << std::endl;
1010  dout() << "Transient::loopProcess()" << std::endl;
1011  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
1012  dout() << "analysisManager_.getStepErrorControl().stepAttemptStatus = " << analysisManager_.getStepErrorControl().stepAttemptStatus << std::endl;
1013  }
1014 
1015  if (beginningIntegration &&
1017  {
1018  // ------------------------------------------------------------------------
1019  // 07/29/04 TSC: initial step-size selection is now done in the
1020  // integration method initialize call under the DAE formulation. This
1021  // segregates codes changes better and makes sense to do as an
1022  // initialization step even if its changed later.
1024  double suggestedMaxTime=0.0;
1026  {
1027  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
1029  }
1032  }
1033 
1034  // ------------------------------------------------------------------------
1035  // If we've switched the integration method, we need to obtain the
1036  // corrector derivative only after we've updated the TimeInfo.
1038  {
1041  }
1042 
1043  if (VERBOSE_TIME &&!dcopFlag_)
1045 
1046  // ------------------------------------------------------------------------
1047  // Set the nonlinear solver parameters to those appropriate for the
1048  // transient solution, if neccessary.
1049  if (!dcopFlag_)
1050  {
1052  }
1053 
1054  // Ask the method to update its coefficients
1056 }
1057 
1058 //-----------------------------------------------------------------------------
1059 // Function : Transient::finalizeMixedSignalStep
1060 // Purpose :
1061 // Special Notes : Habanero API function
1062 // Scope : public
1063 // Creator : Eric Keiter, SNL
1064 // Creation Date : 3/04/09
1065 //-----------------------------------------------------------------------------
1067 {
1068  bool recoverableFailureFlag = true;
1069 
1071  {
1073  }
1075  {
1077  recoverableFailureFlag = false;
1078  }
1079  // Transient
1080  else
1081  {
1083  {
1085  }
1086  else if (passNLStall
1089  {
1090  // potentially a VERY dangerous options.
1091  // if the non-linear solver is stalling, and we're very close to a min
1092  // time step, then calls this failure a pass
1093 
1095  {
1096  Report::UserWarning0() << "Nonlinear solver stalled, calling this a pass";
1098  }
1099  // another VERY dangerous options.
1100  // if the non-linear solver is reporting too big of an update, and we're very close to a min
1101  // time step, then calls this failure a pass
1103  {
1104  Report::UserWarning0() << "Update too big, calling this a pass";
1106  }
1107  // another VERY dangerous options.
1108  // if the non-linear solver is not converging in the max number of steps,
1109  // and we're very close to a min time step, then calls this failure a pass
1110  //
1111  // if( analysisManager_.getStepErrorControl().newtonConvergenceStatus == -1)
1112  // {
1113  // Report::UserWarning0() << "?Too many steps, calling this a pass";
1114  // processSuccessfulStep();
1115  // }
1116  else
1117  {
1118  // process this failed step as we would have by default.
1119  recoverableFailureFlag = doProcessFailedStep();
1120  }
1121  }
1122  else // stepAttemptStatus (ie do this if the step FAILED)
1123  {
1124  recoverableFailureFlag = doProcessFailedStep();
1125  }
1126  } // transient
1127 
1128  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1129  {
1130  dout() << std::endl;
1131  dout() << " Here we are, just before checking whether to pause. " << std::endl;
1132  dout() << " minTimeStep = " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
1133  dout() << " final time = " << tiaParams_.finalTime << std::endl;
1134  dout() << " pause time = " << analysisManager_.getPauseTime() << std::endl;
1135  dout() << " initial time = " << analysisManager_.getStepErrorControl().initialTime << std::endl;
1136  dout() << " current time = " << analysisManager_.getStepErrorControl().currentTime << std::endl;
1138  {
1139  dout() << " Pause time and current time equal " << std::endl;
1140  }
1141  else
1142  {
1143  dout() << " difference between current and pause times is " << analysisManager_.getPauseTime() - analysisManager_.getStepErrorControl().currentTime << std::endl;
1144  }
1146  {
1147  dout() << " Pause time and initial time equal " << std::endl;
1148  }
1149  }
1150 
1152  {
1153  // Failure at this point only indicates that the simulation
1154  // is paused and may be resumed.
1155  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1156  {
1157  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
1158  }
1159 
1161  isPaused = true;
1162  recoverableFailureFlag = false;
1163  }
1164 
1165  // If the exit time has been exceeded, exit.
1167  {
1168 
1169  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
1170  recoverableFailureFlag = false;
1171  }
1172 
1173  if (exitStep != -1 && static_cast<int>(stepNumber) == exitStep)
1174  {
1175  lout() <<"Exit step. Exiting transient loop\n" << std::endl;
1176  recoverableFailureFlag = false;
1177  }
1178 
1179  return recoverableFailureFlag;
1180 }
1181 
1182 //-----------------------------------------------------------------------------
1183 // Function : Transient::processSuccessfulDCOP()
1184 // Purpose :
1185 // Special Notes :
1186 // Scope : public
1187 // Creator : Rich Schiek, SNL
1188 // Creation Date : 3/11/06
1189 //-----------------------------------------------------------------------------
1191 {
1192  Stats::StatTop _processSuccessfulDCOPStat("Successful DCOP Steps");
1193  Stats::TimeBlock _processSuccessfulDCOPTimer(_processSuccessfulDCOPStat);
1194 
1195  bool bsuccess = true;
1196 
1198 
1199  if (sensFlag_ && !firstDoubleDCOPStep() )
1200  {
1202  }
1203 
1205 
1206  // Communicate down to the device level that the step has been accepted.
1207  // This must be done before the "times" get rotated, and certainly before
1208  // the vectors get rotated. The primary target for this call is the
1209  // transmission line device, which needs to know when it has a valid
1210  // solution so it can save history. (And now the ADC/DAC devices too)
1211  // needs to happen before dcopFlag_ is set to false.
1212  loader_.acceptStep();
1213 
1214  // Reset some settings (to switch from DCOP to transient, if not the
1215  // first step of a "double" DCOP.
1216  if ( firstDoubleDCOPStep() ) // (pde-only)
1217  {
1218  dcopFlag_ = true;
1221  }
1222  else
1223  {
1224  dcopFlag_ = false;
1228  beginningIntegration = true;
1229  }
1230 
1234 
1236 
1237  tranopOutputs();
1238 
1239  // Now that output has been called, update the doubleDCOP step
1240  // if neccessary. (Only matters for pde problems)
1241  // doubleDCOPStep_ = lastDCOPStep_;
1242  nextDCOPStep();
1243 
1244  //Test and save restart if necessary
1246  {
1247  if (DEBUG_RESTART)
1248  dout() << "\n " << analysisManager_.getCommandLine().getArgumentValue("netlist")
1249  << " Calling dumpRestart" << std::endl;
1250 
1252  topology_,
1254  restartManager_.getJobName(),
1255  restartManager_.getPack(),
1256  analysisManager_.getStepErrorControl().currentTime);
1257 
1258  if (DEBUG_RESTART)
1259  dout() << " Done Calling dumpRestart" << std::endl;
1260  }
1261 
1262  // This output call is for device-specific output, such as .OP,
1263  // or internal plot output from PDE(TCAD) devices.
1265 
1267 
1269 
1270  return bsuccess;
1271 }
1272 
1273 //-----------------------------------------------------------------------------
1274 // Function : Transient::doProcessSuccessfulStep()
1275 // Purpose :
1276 // Special Notes :
1277 // Scope : public
1278 // Creator : Rich Schiek, SNL
1279 // Creation Date : 3/11/06
1280 //-----------------------------------------------------------------------------
1282 {
1283  Stats::StatTop _processSuccessfulStepStat("Successful Step");
1284  Stats::TimeBlock _processSuccessfulStepTimer(_processSuccessfulStepStat);
1285 
1287 
1289 
1290  if (timeQueue_.get_size() != 0)
1291  {
1292  // store status of this step
1295  stepStatusQueue_.push_back( 1 );
1301  }
1302 
1303  if (sensFlag_)
1304  {
1307  }
1308 
1309  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1310  {
1311  dout() << " Transient::processSuccessfulStep()" << std::endl
1312  << "Newton step succeeded:" << std::endl
1313  << "nextSolutionPtr: " << std::endl;
1314 
1315  analysisManager_.getDataStore()->nextSolutionPtr->printPetraObject(dout());
1316  dout() << std::endl;
1317  }
1318 
1319  // Set things up for the next time step, based on if this one was
1320  // successful.
1321 
1322  // This output call is for device-specific output (like from a PDE device,
1323  // outputting mesh-based tecplot files). It will only work in parallel if on
1324  // a machine where all processors have I/O capability.
1325  // Note: this output needs to happen before the "times" get rotated.
1327 
1328  // Communicate down to the device level that the step has been accepted.
1329  // This must be done before the "times" get rotated, and certainly before
1330  // the vectors get rotated. The primary target for this call is the
1331  // transmission line device, which needs to know when it has a valid
1332  // solution so it can save history.
1333  loader_.acceptStep();
1334 
1335  // current time will get updated in completeStep(). We'll save its value
1336  // for the moment so it can be saved if needed with the rest of the
1337  // solution if tiaParams_.saveTimeStepsFlag is set.
1338  // This fixes an off by one bug in getting the right time value and
1339  // keeps the real solutions associated with that value too.
1340  double currentTime = analysisManager_.getStepErrorControl().currentTime;
1341  double suggestedMaxTime = 0.0;
1343  {
1344  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
1346  }
1350 
1351  if (VERBOSE_TIME && isActive(Diag::TIME_PARAMETERS))
1352  dout() << "Transient Analysis: accepting time step" << std::endl;
1353 
1355 
1357  {
1358  dout().precision(15);
1359  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = " << analysisManager_.getStepErrorControl().TimeStepLimitedbyBP << "\n" << std::endl;
1360  dout() << "ERROROPTION=1: NL Its = " << analysisManager_.getStepErrorControl().nIterations << "\n" << std::endl;
1361  dout() << "ERROROPTION=1: New DeltaT = " << analysisManager_.getStepErrorControl().currentTimeStep << "\n" << std::endl;
1362  }
1363 
1364  stepNumber += 1;
1365  tranStepNumber += 1;
1368 
1372 
1373  // --------------------------------------------------------------------
1374  // Check to see if we have hit the end or a discontinuity point. The
1375  // next discontinuity point is represented by the stopTime variable.
1376 
1377  // Note: make sure that when we check for discontinuity point, we take
1378  // into account the possibility of roundoff error. Use the same bpTol
1379  // as is used in function updateBreakPoints.
1380  double bpTol = analysisManager_.getStepErrorControl().getBreakPointLess().tolerance_;
1381 
1382  if (tiaParams_.bpEnable)
1383  {
1386  timeDiff1 = fabs(timeDiff1);
1387  timeDiff2 = fabs(timeDiff2);
1388 
1389  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1390  {
1391  dout() << " Checking whether to set breakpointrestartstep" << std::endl;
1392  dout() << " current - stop = " << timeDiff1 << std::endl;
1393  dout() << " current - final = " << timeDiff2 << std::endl;
1394  dout() << " bpTol = " << bpTol << std::endl;
1395  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1396  dout() << " setting breakPointRestartStep to " << tranStepNumber;
1397  }
1398 
1399  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1400  {
1402  }
1403  }
1404 
1406  {
1407  beginningIntegration = true;
1408  }
1409  else
1410  {
1411  beginningIntegration = false;
1412  }
1413 
1415  {
1417  }
1419  {
1422  }
1423 
1424  if (saveTimeStepsFlag)
1425  {
1426  analysisManager_.getDataStore()->timeSteps.push_back(currentTime);
1428  Linear::Vector * aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currSolutionPtr) );
1429  analysisManager_.getDataStore()->fastTimeSolutionVec.push_back( aVecPtr );
1430  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currStatePtr) );
1431  analysisManager_.getDataStore()->fastTimeStateVec.push_back( aVecPtr );
1432  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->daeQVectorPtr) );
1433  analysisManager_.getDataStore()->fastTimeQVec.push_back( aVecPtr );
1434  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currStorePtr) );
1435  analysisManager_.getDataStore()->fastTimeStoreVec.push_back( aVecPtr );
1436  }
1437 
1438  // 03/16/04 tscoffe: This is where the solution pointers are rotated.
1440 
1441  if (DEBUG_ANALYSIS & DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
1443 
1444  {
1445  if (DEBUG_ANALYSIS)
1446  {
1447  Stats::StatTop _outputStat("Output");
1448  Stats::TimeBlock _outputTimer(_outputStat);
1449  }
1450 
1451  tranStepOutputs ();
1452  }
1453 
1454  // Test and save restart if necessary
1457  topology_,
1459  restartManager_.getJobName(),
1460  restartManager_.getPack(),
1461  analysisManager_.getStepErrorControl().currentTime);
1462 
1463  analysisManager_.getStepErrorControl().previousCallStepSuccessful = true;
1464 
1465  // reset min error tracking variables
1466  // if the step number is less than zero we'll assume there is no valid
1467  // min. estimated error over tol or an associated time step. This frees us
1468  // from putting Machine::Big here and trying to do something with that.
1470 
1471  return true;
1472 }
1473 
1474 
1475 //-----------------------------------------------------------------------------
1476 // Function : Transient::processFailedStep
1477 // Purpose :
1478 // Special Notes :
1479 // Scope : public
1480 // Creator : Rich Schiek, SNL
1481 // Creation Date : 3/11/06
1482 //-----------------------------------------------------------------------------
1484 {
1485  Stats::StatTop _processFailedStat("Failed Steps");
1486  Stats::TimeBlock _processFailedTimer(_processFailedStat);
1487 
1489  {
1490  Stats::StatTop _nonlinearConvergenceFailureStat("Nonlinear Failure");
1491  Stats::TimeBlock _nonlinearConvergenceFailureTimer(_nonlinearConvergenceFailureStat);
1492  }
1493 
1494  bool bsuccess = true;
1495 
1497 
1498  if (timeQueue_.get_size() != 0)
1499  {
1500  // store status of this step
1503  stepStatusQueue_.push_back( 0 );
1509  }
1510 
1511  // save some info about this step
1512  double estOverTol = analysisManager_.getStepErrorControl().getEstOverTol();
1513  if( (stepNumberAtMinEstErrorOverTol < 0) || ( estOverTol < minEstErrorOverTol ) )
1514  {
1515  // our first failed step, so automatically save info
1519  }
1520 
1522 
1523  // DO NOT REMOVE THIS OUTPUT LINE. It is depended upon by the TIA/ERROROPTION
1524  // test case, which will fail if this output doesn't happen.
1525  if (VERBOSE_TIME)
1526  {
1527  dout() << "Transient Analysis: rejecting time step" << std::endl;
1528  }
1529 
1531 
1533  {
1534  dout().precision(15);
1535  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = "
1536  << analysisManager_.getStepErrorControl().TimeStepLimitedbyBP << "\n" << std::endl;
1537  dout() << "ERROROPTION=1: NL Its = "
1538  << analysisManager_.getStepErrorControl().nIterations << "\n" << std::endl;
1539  dout() << "ERROROPTION=1: New DeltaT = "
1540  << analysisManager_.getStepErrorControl().currentTimeStep << "\n" << std::endl;
1541  }
1542 
1543  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1544  {
1545  dout() << " Transient::processFailedStep" << std::endl
1546  << "Newton step failed:" << std::endl
1547  << "nextSolutionPtr: " << std::endl;
1548  analysisManager_.getDataStore()->nextSolutionPtr->printPetraObject(dout());
1549  dout() << std::endl;
1550  }
1551 
1554 
1557  {
1558  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1559  {
1560  dout() << "currTimeStep: " << analysisManager_.getStepErrorControl().currentTimeStep << std::endl;
1561  dout() << "minTimeStep: " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
1562  }
1563 
1564  // before we exit with a time step too small error, check if minTimeStepRecoveryCounter is greater than zero
1565  // if it is, then the user wants us to try to accept the step that had the minimum
1566  // estimated error over tol.
1568  {
1569  lout() << "Attempting to retake and accept step where estimated error over tolerance was: "
1571  << " and time step was: " << timeStepAtMinEstErrorOverTol << std::endl;
1572 
1575  }
1576  else
1577  {
1578  logQueuedData();
1579  lout() << "Time step too small near step number: " << stepNumber
1580  << " Exiting transient loop.\n" << std::endl;
1581 
1582  bsuccess = false;
1583  }
1584  }
1585 
1587  {
1588  logQueuedData();
1589  lout() << "Newton solver failed in constant time step mode. Exiting transient loop.\n" << std::endl;
1590 
1591  bsuccess = false;
1592  }
1593 
1594  if (exitStep != -1 && static_cast<int>(stats_.successStepsThisParameter_) == exitStep - 1)
1595  {
1596  logQueuedData();
1597  lout() << "Exit Step. Exiting transient loop\n" << std::endl;
1598  bsuccess = false;
1599  }
1600 
1601 #if 1
1602  if (VERBOSE_TIME && bsuccess)
1603  {
1605  }
1606 #endif
1607 
1608  if (VERBOSE_TIME && !bsuccess)
1609  {
1611  tranStats = saveLoopInfo();
1613  }
1614 
1615  return bsuccess;
1616 }
1617 
1618 //-----------------------------------------------------------------------------
1619 // Function : Transient::processFailedDCOP
1620 // Purpose :
1621 // Special Notes :
1622 // Scope : public
1623 // Creator : Rich Schiek, SNL
1624 // Creation Date : 3/11/06
1625 //-----------------------------------------------------------------------------
1627 {
1628  Stats::StatTop _processFailedDCOPStat("Failed DCOP Steps");
1629  Stats::TimeBlock _processFailedDCOPTimer(_processFailedDCOPStat);
1630 
1631  bool bsuccess = true;
1632 
1634 
1635  // DC Operating Point failed.
1638 
1639  lout() << "DC Operating Point Failed. Exiting transient loop" << std::endl;
1640 
1641  return bsuccess;
1642 }
1643 
1644 //-----------------------------------------------------------------------------
1645 // Function : Transient::finish
1646 // Purpose :
1647 // Special Notes :
1648 // Scope : public
1649 // Creator : Rich Schiek, SNL
1650 // Creation Date : 3/11/06
1651 //-----------------------------------------------------------------------------
1653 {
1654  bool bsuccess = true;
1655 
1657  {
1660  dsPtr_->timeStepsBreakpointFlag.push_back(beginningIntegration);
1661  dsPtr_->fastTimeSolutionVec.push_back(new Linear::Vector( *dsPtr_->currSolutionPtr));
1662  dsPtr_->fastTimeStateVec.push_back(new Linear::Vector( *dsPtr_->currStatePtr));
1663  dsPtr_->fastTimeQVec.push_back(new Linear::Vector( *dsPtr_->daeQVectorPtr));
1664  dsPtr_->fastTimeStoreVec.push_back(new Linear::Vector( *dsPtr_->currStorePtr));
1665  }
1666 
1667  if (!isPaused)
1668  {
1669  if (DEBUG_ANALYSIS)
1670  dout() << "Calling finishOutput" << std::endl;
1671 
1673 
1674  // This output call is for device-specific output (like from a PDE device,
1675  // outputting mesh-based tecplot files). It will only work in parallel if on
1676  // a machine where all processors have I/O capability, as devices are
1677  // local to a processor.
1679 
1681  }
1682 
1683  return bsuccess;
1684 }
1685 
1686 //-----------------------------------------------------------------------------
1687 // Function : Transient::doHandlePredictor
1688 // Purpose :
1689 // Special Notes :
1690 // Scope : private
1691 // Creator : Eric Keiter, SNL
1692 // Creation Date : 06/24/2013
1693 //-----------------------------------------------------------------------------
1695 {
1699 
1700  if (DEBUG_ANALYSIS & DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
1701  {
1702  dout() << " Transient::doHandlePredictor" << std::endl;
1705  }
1706 
1707  // Now, in case this is the upper level of a 2-level sim, tell the
1708  // inner solve to do its prediction:
1709  bool beginIntegrationFlag = analysisManager_.getBeginningIntegrationFlag(); // system_state.beginIntegrationFlag;
1710  double nextTimeStep = analysisManager_.getStepErrorControl().currentTimeStep; // system_state.nextTimeStep;
1711  double nextTime = analysisManager_.getStepErrorControl().nextTime; // system_state.nextTime;
1712  int currentOrder = analysisManager_.getWorkingIntegrationMethod().getOrder(); // system_state.currentOrder;
1713 
1714  loader_.startTimeStep(beginIntegrationFlag, nextTimeStep, nextTime, currentOrder);
1715 
1716  return true;
1717 }
1718 
1719 //-----------------------------------------------------------------------------
1720 // Function : Transient::resetForHB()
1721 // Purpose : When doing initial transient run, some analyses require
1722 // a reset function
1723 // they can fill this in if needed.
1724 // Special Notes :
1725 // Scope : public
1726 // Creator : T. Mei, SNL, Parallel Computational Sciences
1727 // Creation Date : 2/26/09
1728 //-----------------------------------------------------------------------------
1730 {
1731  dcopFlag_ = false;
1732  if (timeQueue_.get_size() != 0)
1733  {
1734  // these set_size calls will also "reset" the queue.
1735  timeQueue_.reset_queue();
1736  timeStepQueue_.reset_queue();
1737  stepStatusQueue_.reset_queue();
1738  estErrorOverTolQueue_.reset_queue();
1739  nonlinearSolverStatusQueue_.reset_queue();
1740  nonlinearSolverNumIterationsQueue_.reset_queue();
1741  nonlinearSolverMaxNormQueue_.reset_queue();
1742  nonlinearSolverMaxNormIndexQueue_.reset_queue();
1743  }
1744 
1745  return true;
1746 }
1747 
1748 
1749 //-----------------------------------------------------------------------------
1750 // Function : Transient::finalVerboseOutput
1751 // Purpose :
1752 // Special Notes :
1753 // Scope : public
1754 // Creator : Rich Schiek, SNL
1755 // Creation Date : 3/11/06
1756 //-----------------------------------------------------------------------------
1758 {
1759  bool bsuccess = true;
1760 
1761  lout() << "***** Problem read in and set up time: " << analysisManager_.getSolverStartTime() << " seconds" << std::endl;
1762 
1764  {
1765  double time;
1767  {
1768  time = startTRANtime_ - startDCOPtime;
1769  }
1770  else
1771  {
1772  time = endTRANtime_ - startDCOPtime;
1773  }
1774  lout() << " ***** DCOP time: " << time << " seconds. Breakdown follows:" << std::endl;
1775 
1776  printLoopInfo(0, dcStats);
1777  }
1778 
1780  {
1781  lout() << " ***** Transient Stepping time: " << endTRANtime_ - startTRANtime_ << " seconds. Breakdown follows:" << std::endl;
1782 
1784  }
1785 
1786  return bsuccess;
1787 }
1788 
1789 //-----------------------------------------------------------------------------
1790 // Function : Transient::logQueuedData
1791 // Purpose :
1792 // Special Notes :
1793 // Scope : public
1794 // Creator : Rich Schiek, SNL
1795 // Creation Date : 3/11/06
1796 //-----------------------------------------------------------------------------
1798 {
1799  if (timeQueue_.get_size() != 0)
1800  {
1801  // get the current non-linear solver return codes
1803 
1804  lout() << " *** Transient failure history: " << std::endl;
1806  {
1807  // truncation error is not used here so est err over tol is not useful in the output
1808  lout() << "Time Time Step Non-Linear Solver node node" << std::endl;
1809  lout() << "(sec) Step Status Status Iters ||F|| index name" << std::endl;
1810  }
1811  else
1812  {
1813  lout() << "Time Time Step EstErr Non-Linear Solver node node" << std::endl;
1814  lout() << "(sec) Step Status OverTol Status Iters ||F|| index name" << std::endl;
1815  }
1816 
1817  for (int i = 0; i < timeQueue_.get_size(); i++ )
1818  {
1819  int fieldWidth=10;
1820  lout() << std::scientific
1821  << std::setprecision(fieldWidth-7)
1822  << std::setfill(' ')
1823  << std::right
1824  << std::setw( fieldWidth )
1825  << timeQueue_.at_from_tail(i) << " "
1826  << timeStepQueue_.at_from_tail(i) << " ";
1827 
1828  if( stepStatusQueue_.at_from_tail(i) == 1 )
1829  {
1830  lout() << "pass ";
1831  }
1832  else
1833  {
1834  lout() << "fail ";
1835  }
1837  {
1838  }
1839  else
1840  {
1841  lout() << estErrorOverTolQueue_.at_from_tail(i) << " ";
1842  }
1843  int nlStatus = nonlinearSolverStatusQueue_.at_from_tail(i);
1844  lout() << std::setw(7) << std::right;
1845  if( nlStatus == nlReturnCodes.normTooSmall )
1846  {
1847  lout() << "P:s nrm";
1848  }
1849  else if( nlStatus == nlReturnCodes.normalConvergence)
1850  {
1851  lout() << "pass ";
1852  }
1853  else if( nlStatus == nlReturnCodes.nearConvergence )
1854  {
1855  lout() << "P:near ";
1856  }
1857  else if( nlStatus == nlReturnCodes.smallUpdate )
1858  {
1859  lout() << "P:s up ";
1860  }
1861  else if( nlStatus == nlReturnCodes.nanFail )
1862  {
1863  lout() << "F:NaN ";
1864  }
1865  else if( nlStatus == nlReturnCodes.tooManySteps )
1866  {
1867  lout() << "F:max s";
1868  }
1869  else if( nlStatus == nlReturnCodes.tooManyTranSteps )
1870  {
1871  lout() << "F:max s";
1872  }
1873  else if( nlStatus == nlReturnCodes.updateTooBig )
1874  {
1875  lout() << "F:big u";
1876  }
1877  else if( nlStatus == nlReturnCodes.stalled )
1878  {
1879  lout() << "F:stall";
1880  }
1881  else if( nlStatus == nlReturnCodes.wrmsExactZero )
1882  {
1883  lout() << "F:n zro";
1884  }
1885  else if( nlStatus == nlReturnCodes.innerSolveFailed )
1886  {
1887  lout() << "F:in Fl";
1888  }
1889  else
1890  {
1891  lout() << "code=" <<
1892  nonlinearSolverStatusQueue_.at_from_tail(i) << " ";
1893  }
1894 
1895  lout() << std::right << std::setw( 4 )
1896  << nonlinearSolverNumIterationsQueue_.at_from_tail(i) << " "
1897  << nonlinearSolverMaxNormQueue_.at_from_tail(i) ;
1898 
1899  int outIndex = nonlinearSolverMaxNormIndexQueue_.at_from_tail(i) ;
1900  lout() << std::right << std::fixed << std::setw( 7 ) << outIndex;
1901 
1902  const std::vector<const std::string *> &name_vec = topology_.getSolutionNodeNames();
1903 
1904  lout() << " " << std::left << ((outIndex < name_vec.size() && outIndex >= 0) ? *name_vec[outIndex] : "N/A") << std::endl;
1905  }
1906  }
1907 }
1908 
1909 
1910 //-----------------------------------------------------------------------------
1911 // Function : Transient::outputFailedStepData()
1912 // Purpose : outputs same information as logQueuedData, but only for
1913 // a single time step. Also different in that it is called
1914 // for any failed step, not just the final exit.
1915 // Special Notes :
1916 // Scope : public
1917 // Creator : Eric Keiter, SNL
1918 // Creation Date : 8/9/2015
1919 //-----------------------------------------------------------------------------
1921 {
1922  if (timeQueue_.get_size() != 0)
1923  {
1924  // get the current non-linear solver return codes
1926 
1927  lout() << "************\n*** Transient failure information: " << std::endl;
1929  {
1930  // truncation error is not used here so est err over tol is not useful in the output
1931  lout() << "Time Time Step Non-Linear Solver node node" << std::endl;
1932  lout() << "(sec) Step Status Status Iters ||F|| index name" << std::endl;
1933  }
1934  else
1935  {
1936  lout() << "Time Time Step EstErr Non-Linear Solver node node" << std::endl;
1937  lout() << "(sec) Step Status OverTol Status Iters ||F|| index name" << std::endl;
1938  }
1939 
1940  {
1941  int i=timeQueue_.get_size()-1;
1942  int fieldWidth=10;
1943  lout() << std::scientific
1944  << std::setprecision(fieldWidth-7)
1945  << std::setfill(' ')
1946  << std::right
1947  << std::setw( fieldWidth )
1948  << timeQueue_.at_from_tail(i) << " "
1949  << timeStepQueue_.at_from_tail(i) << " ";
1950 
1951  if( stepStatusQueue_.at_from_tail(i) == 1 )
1952  {
1953  lout() << "pass ";
1954  }
1955  else
1956  {
1957  lout() << "fail ";
1958  }
1960  {
1961  }
1962  else
1963  {
1964  lout() << estErrorOverTolQueue_.at_from_tail(i) << " ";
1965  }
1966  int nlStatus = nonlinearSolverStatusQueue_.at_from_tail(i);
1967  lout() << std::setw(7) << std::right;
1968  if( nlStatus == nlReturnCodes.normTooSmall )
1969  {
1970  lout() << "P:s nrm";
1971  }
1972  else if( nlStatus == nlReturnCodes.normalConvergence)
1973  {
1974  lout() << "pass ";
1975  }
1976  else if( nlStatus == nlReturnCodes.nearConvergence )
1977  {
1978  lout() << "P:near ";
1979  }
1980  else if( nlStatus == nlReturnCodes.smallUpdate )
1981  {
1982  lout() << "P:s up ";
1983  }
1984  else if( nlStatus == nlReturnCodes.nanFail )
1985  {
1986  lout() << "F:NaN ";
1987  }
1988  else if( nlStatus == nlReturnCodes.tooManySteps )
1989  {
1990  lout() << "F:max s";
1991  }
1992  else if( nlStatus == nlReturnCodes.tooManyTranSteps )
1993  {
1994  lout() << "F:max s";
1995  }
1996  else if( nlStatus == nlReturnCodes.updateTooBig )
1997  {
1998  lout() << "F:big u";
1999  }
2000  else if( nlStatus == nlReturnCodes.stalled )
2001  {
2002  lout() << "F:stall";
2003  }
2004  else if( nlStatus == nlReturnCodes.wrmsExactZero )
2005  {
2006  lout() << "F:n zro";
2007  }
2008  else if( nlStatus == nlReturnCodes.innerSolveFailed )
2009  {
2010  lout() << "F:in Fl";
2011  }
2012  else
2013  {
2014  lout() << "code=" <<
2015  nonlinearSolverStatusQueue_.at_from_tail(i) << " ";
2016  }
2017 
2018  lout() << std::right << std::setw( 4 )
2019  << nonlinearSolverNumIterationsQueue_.at_from_tail(i) << " "
2020  << nonlinearSolverMaxNormQueue_.at_from_tail(i) ;
2021 
2022  int outIndex = nonlinearSolverMaxNormIndexQueue_.at_from_tail(i) ;
2023  lout() << std::right << std::fixed << std::setw( 7 ) << outIndex;
2024 
2025  const std::vector<const std::string *> &name_vec = topology_.getSolutionNodeNames();
2026 
2027  lout() << " " << std::left << ((outIndex < name_vec.size() && outIndex >= 0) ? *name_vec[outIndex] : "N/A") << std::endl;
2028  }
2029  lout() << "************" << std::endl;
2030  }
2031 }
2032 
2033 //-----------------------------------------------------------------------------
2034 // Function : Transient::takeAnIntegrationStep_
2035 // Purpose : Take a transient integration step.
2036 // Special Notes :
2037 // Scope : private
2038 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
2039 // Creation Date : 01/24/08
2040 //-----------------------------------------------------------------------------
2041 void
2043 {
2044  { // Integration step predictor
2045  if (DEBUG_ANALYSIS)
2046  {
2047  Stats::StatTop _predictorStat("Predictor");
2048  Stats::TimeBlock _predictorTimer(_predictorStat);
2049  }
2050 
2052  }
2053 
2054  { // Load B/V source devices with time data
2055 
2056  if (DEBUG_ANALYSIS)
2057  {
2058  Stats::StatTop _updateDeviceSourceStat("Update Device Sources");
2059  Stats::TimeBlock _updateDeviceSourceTimer(_updateDeviceSourceStat);
2060  }
2061 
2063  }
2064 
2065  { // Nonlinear solve
2066  Stats::StatTop _nonlinearSolveStat("Nonlinear Solve");
2067  Stats::TimeBlock _nonlinearSolveTimer(_nonlinearSolveStat);
2068 
2070  }
2071 
2072  {
2073 // Stats::StatTop _errorStat("Error Estimation");
2074 // Stats::TimeBlock _errorTimer(_errorStat);
2075 
2076  // Add change to solution
2078 
2081 
2082  // Evaluate result
2083 
2084 
2086  }
2087 }
2088 
2089 //-----------------------------------------------------------------------------
2090 // Function : Transient::twoLevelStep
2091 //
2092 // Purpose : Take a transient integration step, for inner 2-level solve.
2093 //
2094 // Special Notes : Same as takeAnIntegrationStep, but does not do the
2095 // prediction. (that is in handlePredictor).
2096 //
2097 // The prediction is handled separately, as for a 2-level
2098 // solve, you only want to do the prediction on the first
2099 // solve of the attempted time step.
2100 //
2101 // Scope : public
2102 // Creator :
2103 // Creation Date : 3/11/06
2104 //-----------------------------------------------------------------------------
2106 {
2110 
2113 
2115  tranStats = saveLoopInfo();
2116 
2118 }
2119 
2120 //-----------------------------------------------------------------------------
2121 // Function : Transient::retakeAndAcceptTimeStep
2122 // Purpose : Do a requested time step and accept it
2123 // Special Notes :
2124 // Scope : public
2125 // Creator : Rich Schiek, Electrical and Microsystems Modeling
2126 // Creation Date : 01/23/09
2127 //-----------------------------------------------------------------------------
2128 bool Transient::retakeAndAcceptTimeStep( double aTimeStep )
2129 {
2130  bool bsuccess=true;
2131  // This function was put in place to handle the following situation.
2132  // If a series of time steps are rejected because the estimated error
2133  // over tol. is too high, Xyce may exit if the next time step falls under
2134  // the minTimeStep. A user could adjust the tolerances of a simulation
2135  // to try and get around this, but in UQ studies where there are 1,000s of
2136  // simulations, it can be difficult to get all of them to run. So,
2137  // if the user has set the netlist option timeint MINTIMESTEPRECOVERY=<int>
2138  // and we're about to exit because the time step has fallen under the minTimeStep
2139  // we will try and retake the time step that had the min. est. error over tol.
2140  // and accept that.
2141  //
2142  // At this point, Transient::processFailedStep() has already determined
2143  // that the preconditions outlined above are in place (i.e. the user requested
2144  // this and we're about to exit with a time step too small error), so lets
2145  // try the step that had the min. est error over tol.
2146 
2147  // set time step
2149 
2150  // take step
2152 
2153  // can't accept step if the non-linear solver failed
2155  {
2156  lout() << "Time step too small near step number: " << stepNumber << " Exiting transient loop.\n" << std::endl;
2157  bsuccess = false;
2158  }
2159  else
2160  {
2162  }
2163  return bsuccess;
2164 }
2165 
2166 //-----------------------------------------------------------------------------
2167 // Function : Transient::printStepHeader()
2168 // Purpose : Prints out time step information.
2169 // Special Notes :
2170 // Scope : public
2171 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
2172 // Creation Date : 6/26/00
2173 //-----------------------------------------------------------------------------
2174 void Transient::printStepHeader(std::ostream &os)
2175 {
2176  if (VERBOSE_TIME)
2177  {
2178  os << "***** " << (DEBUG_ANALYSIS ? analysisManager_.getCommandLine().getArgumentValue("netlist") : "") << " ";
2179 
2180  if (dcopFlag_)
2181  {
2182  os << "Start of DCOP STEP # ";
2183  }
2184  else
2185  {
2187  {
2189  {
2190  os << "Start of Time Step (INITIAL STEP) # ";
2191  }
2192  else
2193  {
2194  os << "Start of Time Step (DISCONTINUITY STEP) # ";
2195  }
2196  }
2197  else
2198  {
2200  {
2201  os << "Start of Time Step (AFTER FAILED STEP) # ";
2202  }
2203  else
2204  {
2205  os << "Start of Time Step (AFTER SUCCESS STEP) # ";
2206  }
2207  }
2208  }
2209 
2210  os << stats_.successStepsThisParameter_ + 1 << std::endl;
2211  }
2212 }
2213 
2214 //-----------------------------------------------------------------------------
2215 // Function : Transient::printProgress()
2216 // Purpose : Outputs run completion percentage and estimated
2217 // time-to-completion.
2218 //
2219 // Special Notes : This will need some fixing to work with .STEP.
2220 //
2221 // Scope : public
2222 // Creator : Scott A. Hutchinson, SNL, Computational Sciences
2223 // Creation Date : 06/07/2002
2224 //-----------------------------------------------------------------------------
2225 void Transient::printProgress(std::ostream &os)
2226 {
2228  {
2229  // Percent of the overall requested simulation time which is completed.
2230  double percentComplete;
2231  // Average CPU time per time step.
2232  double aveCPUTimePerStep;
2233  // Average clock time per time step.
2234  double aveSimTimePerStep;
2235  // Estimated CPU time to complete the simulation.
2236  double estCompletionTime = 0.0;
2237 
2238  // Report the beginning of the DC OP calculation. First call in OP.
2239  if (dcopFlag_)
2240  {
2242  if (gui_)
2243  {
2244  Report::signalProgress("Xyce in DC Operating Point Calculation");
2245  }
2246  os << "***** Beginning DC Operating Point Calculation...\n" << std::endl;
2247  }
2248  else if (firstTime && stats_.successStepsThisParameter_ == 1)
2249  {
2251  dcStats = saveLoopInfo();
2252  firstTime = false;
2253  if (gui_)
2254  {
2255  Report::signalProgress("Xyce in Transient Calculation");
2256  }
2257  os << "***** Beginning Transient Calculation...\n" << std::endl;
2258  }
2260  {
2261  if (startSimTime == -1.0)
2263 
2265  double diff2 = fabs(tiaParams_.finalTime - tiaParams_.initialTime);
2266 
2267  // 02/05/08 tscoffe: optimization differences after the TIA_REFACTOR
2268  // caused a floating point difference here and this resolves that
2269  // difference. After the refactor is merged back onto the main trunk, this
2270  // stuff should be removed.
2271  percentComplete = 100.0 * diff1/diff2;
2272 
2273  if (fabs(percentComplete - oldPercentComplete) > 1.0)
2274  {
2275  oldPercentComplete = percentComplete;
2276 
2277  aveCPUTimePerStep = analysisManager_.getXyceTranTimer().elapsedTime() /
2279  aveSimTimePerStep = (analysisManager_.getStepErrorControl().currentTime - startSimTime) /
2281 
2282  if (aveSimTimePerStep > Util::MachineDependentParams::MachineEpsilon())
2283  estCompletionTime = aveCPUTimePerStep *
2285  aveSimTimePerStep;
2286 
2287  if (!gui_)
2288  {
2289  os << "***** Percent complete: " << percentComplete << " %" << std::endl;
2290  }
2291 
2292  if (estCompletionTime > Util::MachineDependentParams::MachineEpsilon())
2293  {
2294  unsigned int days, hours, minutes, seconds;
2295  days = static_cast<int> (estCompletionTime / 86400);
2296  hours = static_cast<int> ((estCompletionTime - days * 86400) / 3600);
2297  minutes = static_cast<int> ((estCompletionTime - days * 86400 - hours * 3600) / 60);
2298  seconds = static_cast<int> (estCompletionTime - days * 86400 - hours * 3600 - minutes * 60);
2299 
2300  char timeStr[256];
2301  for (char *c = timeStr; c != timeStr + sizeof(timeStr); ++c)
2302  *c = 0;
2303 
2304  if (Parallel::rank(comm_) == 0)
2305  {
2306  // get current local system time
2307  time_t t = time( NULL );
2308  struct tm * now = localtime( &t );
2309 
2310  // format and display output
2311  if ( ( t != (time_t)-1 ) && ( strftime( timeStr, 255, "%c", now ) != 0 ) )
2312  {
2313  os << "***** Current system time: " << timeStr << std::endl;
2314  }
2315 
2316  else
2317  {
2318  os << "***** Current system time could not be determined." << std::endl;
2319  }
2320  }
2321 
2322  if (days > 0)
2323  sprintf(timeStr, "%3d days, %2d hrs., %2d min., %2d sec.", days, hours, minutes, seconds);
2324  else if (hours > 0)
2325  sprintf(timeStr, "%2d hrs., %2d min., %2d sec.", hours, minutes, seconds);
2326  else if (minutes > 0)
2327  sprintf(timeStr, "%2d min., %2d sec.", minutes, seconds);
2328  else
2329  sprintf(timeStr, "%2d sec.", seconds);
2330 
2331  if (gui_)
2332  {
2333  std::ostringstream ost;
2334  ost << "Xyce transient ";
2335  if (percentComplete < 10)
2336  ost.precision(2);
2337  else
2338  ost.precision(3);
2339  ost << percentComplete
2340  << "%% complete ... Estimated time to completion: "
2341  << timeStr << std::endl;
2342  Report::signalProgress(ost.str());
2343  }
2344  else
2345  {
2346  os << "***** Estimated time to completion: " << timeStr << std::endl << std::endl;
2347  }
2348  }
2349  }
2350  }
2351  }
2352 }
2353 
2354 //-----------------------------------------------------------------------------
2355 // Function : Transient::noopOutputs
2356 // Purpose :
2357 // Special Notes :
2358 // Scope : public
2359 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2360 // Creation Date : 8/31/2007
2361 //-----------------------------------------------------------------------------
2363 {
2365  {
2366  if ( !firstDoubleDCOPStep() )
2367  {
2376  objectiveVec_,
2378 
2379  if (outputAdapter_)
2383  }
2389  analysisManager_.setNextOutputTime(next_output_time);
2390  }
2391 }
2392 
2393 //-----------------------------------------------------------------------------
2394 // Function : Transient::tranopOutputs
2395 // Purpose :
2396 // Special Notes :
2397 // Scope : public
2398 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2399 // Creation Date : 8/31/2007
2400 //-----------------------------------------------------------------------------
2402 {
2403  //Test and output if necessary
2405  {
2406  // Make sure this isn't the NLP step of a PDE DCOP.
2407  if ( !firstDoubleDCOPStep() )
2408  {
2409  if (DEBUG_ANALYSIS)
2410  {
2411  dout() << "Transient::tranopOutputs:" << std::endl;
2412  dout() << "current lead current vector:" << std::endl;
2413 
2414  analysisManager_.getDataStore()->currLeadCurrentPtr->printPetraObject(dout());
2415 
2416  dout() << "current lead current deltaV vector:" << std::endl;
2417  analysisManager_.getDataStore()->currLeadDeltaVPtr->printPetraObject(dout());
2418  }
2419 
2427  objectiveVec_,
2429 
2430  if (outputAdapter_)
2431  {
2435  }
2436  }
2437 
2443  analysisManager_.setNextOutputTime(next_output_time);
2444  }
2445 
2446  // SAVE and DCOP restart:
2447  if (initialConditionsManager_.getDCOPRestartFlag()
2449  {
2451  }
2452 }
2453 
2454 //-----------------------------------------------------------------------------
2455 // Function : Transient::tranStepOutputs
2456 // Purpose :
2457 // Special Notes :
2458 // Scope : public
2459 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2460 // Creation Date : 8/31/2007
2461 //-----------------------------------------------------------------------------
2463 {
2464  // The printOutputSolution function will sometimes perform
2465  // interpolations between the current step and the previous step,
2466  // if the integrator is using a high order of integration during
2467  // a new-DAE simulation.
2468 
2469  // If the user has specified tstart, and this happens to be
2470  // the first output of the simulation (at t=tstart, instead of
2471  // t=0) the force the interpolator to *not* interpolate, even
2472  // if it is doing so normally.
2474 
2476  {
2477  if (outputAdapter_)
2478  {
2482 
2484  {
2485  // try normal new dae output
2486  std::vector<double> output_interpolation_times =
2492 
2495  tiaParams_,
2498  doNotInterpolate,
2499  output_interpolation_times,
2500  false) ;
2501  }
2502  }
2503  else
2504  {
2505  std::vector<double> output_interpolation_times =
2511 
2514  tiaParams_,
2517  doNotInterpolate,
2518  output_interpolation_times,
2519  false) ;
2520  }
2521 
2522  firstTranOutput_ = false;
2523 
2529  analysisManager_.setNextOutputTime(next_output_time);
2530  }
2531  else
2532  {
2533  std::vector<double> output_interpolation_times =
2539 
2543  doNotInterpolate,
2544  output_interpolation_times,
2545  true) ;
2546  }
2547 
2548  // .SAVE output
2550  {
2554  topology_.getSolutionNodeNameMap(),
2555  tiaParams_,
2557  initialConditionsManager_.getSaveTime(),
2558  doNotInterpolate);
2559  }
2560 }
2561 
2562 //-----------------------------------------------------------------------------
2563 // Function : testSaveOutputTime
2564 // Purpose : Similar to testOutputTime, except that this is for
2565 // .SAVE files.
2566 // Special Notes : Only outputs 1x.
2567 // Scope : public
2568 // Creator : Eric Keiter, SNL
2569 // Creation Date : 10/18/07
2570 //-----------------------------------------------------------------------------
2571 bool
2573  Analysis::AnalysisManager & analysis_manager,
2574  IO::InitialConditionsManager & initial_conditions_manager)
2575 {
2576  bool flag = true;
2577 
2578  if( !initial_conditions_manager.getSaveFlag())
2579  {
2580  flag = false;
2581  }
2582  else if (analysis_manager.getStepErrorControl().currentTime < initial_conditions_manager.getSaveTime())
2583  {
2584  flag = false;
2585  }
2586  else if (analysis_manager.getSavedAlready())
2587  {
2588  flag = false;
2589  }
2590 
2591  if (flag)
2592  {
2593  analysis_manager.setSavedAlready(true);
2594  Xyce::dout() << "Calling SAVE outputs!" <<std::endl;
2595  }
2596 
2597  return flag;
2598 }
2599 
2600 //-----------------------------------------------------------------------------
2601 // Function : testOutputTime
2602 // Purpose :
2603 // Special Notes :
2604 // Scope : public
2605 // Creator : Rob Hoekstra, SNL, Parallel ComputationalSciences.
2606 // Creation Date : 07/31/01
2607 //-----------------------------------------------------------------------------
2608 bool
2610  double current_time,
2611  double next_output_time,
2612  double start_time)
2613 {
2614  bool flag = true;
2615 
2616  if (current_time < start_time)
2617  {
2618  flag = false;
2619  }
2620  else if ((current_time < next_output_time)&& (fabs(current_time - next_output_time) >= 2 * Util::MachineDependentParams::MachinePrecision()))
2621  {
2622  flag = false;
2623  }
2624 
2625  return flag;
2626 }
2627 
2628 //-----------------------------------------------------------------------------
2629 // Function : updateOutputTime
2630 // Purpose : Advance output time so it is the next one after currTime
2631 // Special Notes : formerly part of testOutputTime
2632 // Scope : public
2633 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
2634 // Creation Date : 02/14/07
2635 //-----------------------------------------------------------------------------
2636 double
2638  double current_time,
2639  double next_output_time,
2640  double final_output_time,
2641  double initial_output_interval,
2642  const IO::IntervalVector & output_intervals)
2643 {
2644  // We only need to bother with this if the user has specified output control
2645  // options
2646  if (initial_output_interval > 0.0)
2647  {
2648  if (output_intervals.empty())
2649  {
2650  // Only an initial interval was specified
2651  while ((next_output_time < current_time)|| (fabs(current_time - next_output_time) < 2 * Util::MachineDependentParams::MachinePrecision()))
2652  next_output_time = next_output_time + initial_output_interval;
2653  }
2654  else if (current_time < output_intervals[0].first)
2655  {
2656  // Multiple intervals, but we're still in the first one
2657  while (next_output_time <= current_time)
2658  next_output_time = next_output_time + initial_output_interval;
2659  if (next_output_time > output_intervals[0].first)
2660  next_output_time = output_intervals[0].first;
2661  }
2662  else
2663  {
2664  // Multiple intervals specified, we're past the first one
2665  std::pair<double, double> currInterval, nextInterval;
2666  int size = output_intervals.size();
2667  for (int i = 0; i < size; ++i)
2668  if (output_intervals[i].first <= current_time)
2669  {
2670  currInterval = output_intervals[i];
2671  if ((i+1) < static_cast<int>(output_intervals.size()))
2672  nextInterval = output_intervals[i+1];
2673  }
2674  int step = static_cast<int> ((current_time-currInterval.first) /
2675  currInterval.second);
2676  next_output_time = currInterval.first + (step+1)*currInterval.second;
2677  if (nextInterval.first && (nextInterval.first!=currInterval.first) && (next_output_time>=nextInterval.first))
2678  next_output_time = nextInterval.first;
2679  }
2680 
2681  if (next_output_time >= final_output_time)
2682  next_output_time =final_output_time;
2683  }
2684 
2685  return next_output_time;
2686 }
2687 
2688 //-----------------------------------------------------------------------------
2689 // Function : AnalysisManager::testRestartSaveTime_
2690 // Purpose :
2691 // Special Notes :
2692 // Scope : public
2693 // Creator : Rob Hoekstra, SNL, Parallel ComputationalSciences.
2694 // Creation Date : 07/31/01
2695 //-----------------------------------------------------------------------------
2696 bool
2698  AnalysisManager & analysis_manager,
2699  IO::RestartMgr & restart_manager,
2700  double current_time,
2701  double & next_restart_save_time)
2702 {
2703  double initial_restart_interval = restart_manager.getInitialRestartInterval();
2704  const IO::IntervalVector &restart_intervals = restart_manager.getRestartIntervals();
2705 
2706  if (DEBUG_RESTART)
2707  {
2708  Xyce::dout() << "TESTING FOR RESTART SAVE" << std::endl
2709  << Xyce::subsection_divider << std::endl
2710  << "current_time: " << current_time << std::endl
2711  << "nextSaveTime: " << next_restart_save_time << std::endl
2712  << "initial_restart_interval: " << initial_restart_interval << std::endl;
2713  if (!restart_intervals.empty())
2714  {
2715  Xyce::dout() << "First restart interval: " << restart_intervals[0].first << std::endl;
2716  }
2717  else
2718  {
2719  Xyce::dout() << "restart_intervals is empty" << std::endl;
2720  }
2721  }
2722 
2723  bool flag = false;
2724  if (initial_restart_interval == 0.0)
2725  {
2726  flag = false;
2727  }
2728  else if (current_time < next_restart_save_time)
2729  {
2730  flag = false;
2731  }
2732  else if (restart_intervals.empty())
2733  {
2734  while (next_restart_save_time <= current_time)
2735  {
2736  next_restart_save_time += initial_restart_interval;
2737  }
2738  flag = true;
2739  }
2740  else if (current_time < restart_intervals[0].first)
2741  {
2742  while (next_restart_save_time <= current_time)
2743  {
2744  next_restart_save_time += initial_restart_interval;
2745  }
2746  if (next_restart_save_time > restart_intervals[0].first)
2747  {
2748  next_restart_save_time = restart_intervals[0].first;
2749  }
2750  flag = true;
2751  }
2752  else
2753  {
2754  std::pair<double, double> currInterval, nextInterval;
2755  int size = restart_intervals.size();
2756  for (int i = 0; i < size; ++i)
2757  {
2758  if (restart_intervals[i].first <= current_time)
2759  {
2760  currInterval = restart_intervals[i];
2761  if ((i+1) < (int)restart_intervals.size())
2762  {
2763  nextInterval = restart_intervals[i+1];
2764  }
2765  }
2766  }
2767  int step = static_cast <int> ((current_time - currInterval.first) /
2768  currInterval.second);
2769  next_restart_save_time = currInterval.first + (step+1)*currInterval.second;
2770 
2771  if (nextInterval.first && (nextInterval.first!=currInterval.first)
2772  && (next_restart_save_time >= nextInterval.first))
2773  {
2774  next_restart_save_time = nextInterval.first;
2775  }
2776  flag = true;
2777  }
2778 
2779  if (DEBUG_RESTART)
2780  Xyce::dout() << "new nextSaveTime: " << next_restart_save_time << std::endl
2781  << "restart flag: " << flag << std::endl
2782  << Xyce::subsection_divider << std::endl;
2783 
2784  return flag;
2785 }
2786 
2787 //-----------------------------------------------------------------------------
2788 // Function : computeOutputInterpolationTimes
2789 // Purpose : When we pass "nextOutputTime_", we might have skipped
2790 // over points where output was requested. Make a list of
2791 // those times so we can interpolate to them.
2792 // Special Notes :
2793 // Scope : public
2794 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling.
2795 // Creation Date : 02/14/07
2796 //-----------------------------------------------------------------------------
2797 std::vector<double>
2799  double current_time,
2800  double next_output_time,
2801  double final_output_time,
2802  double initial_output_interval,
2803  const IO::IntervalVector & output_intervals)
2804 {
2805  std::vector<double> output_interpolation_times;
2806 
2807  // if there are no output control options specified, we do nothing.
2808  if (initial_output_interval > 0.0)
2809  {
2810  if (output_intervals.empty() || current_time <= output_intervals[0].first)
2811  {
2812  // we're either in the first interval, or there only *is* one interval
2813  double t = next_output_time;
2814  while ((t < current_time) && ( current_time -t ) > 2 * Util::MachineDependentParams::MachinePrecision())
2815  {
2816  output_interpolation_times.push_back(t);
2817  t += initial_output_interval; // outputManagerAdapter_.getInitialOutputInterval();
2818  }
2819 
2820  if ((t - current_time) <= 2 * Util::MachineDependentParams::MachinePrecision() )
2821  {
2822  output_interpolation_times.push_back(current_time);
2823  }
2824 
2825  if ((t - final_output_time) > 2 * Util::MachineDependentParams::MachinePrecision())
2826  {
2827  // tack on finalTime or we'll miss it
2828  output_interpolation_times.push_back(final_output_time);
2829  }
2830  }
2831  else // we're out of the first interval, and there is more than one
2832  {
2833  int outInt,lastInt;
2834 
2835  lastInt=output_intervals.size()-1;
2836 
2837  // find which interval nextOutputTime_ is in
2838  for (outInt=0;
2839  outInt<lastInt&&output_intervals[outInt+1].first<=next_output_time;
2840  ++outInt) ;
2841 
2842  double t = next_output_time;
2843  while (t <= current_time)
2844  {
2845  output_interpolation_times.push_back(t);
2846  t += output_intervals[outInt].second;
2847  if (outInt != lastInt && t >= output_intervals[outInt+1].first)
2848  {
2849  ++outInt;
2850  t = output_intervals[outInt].first;
2851  }
2852  }
2853  }
2854  }
2855 
2856  return output_interpolation_times;
2857 }
2858 
2859 //-----------------------------------------------------------------------------
2860 // Function : writeConductanceFile
2861 // Purpose :
2862 // Special Notes :
2863 // Scope : public
2864 // Creator : Eric Keiter, SNL
2865 // Creation Date : 03/06/2006
2866 //-----------------------------------------------------------------------------
2867 void writeConductanceFile(const std::vector<std::string> &device_names, Nonlinear::ConductanceExtractor &conductance_extractor, const std::string &filename)
2868 {
2869  std::map<std::string,double> inputMap;
2870 
2871  // load inputMap from tiaParam.device_names option
2872  for (std::vector<std::string>::const_iterator it = device_names.begin(), end = device_names.end(); it != end; ++it)
2873  inputMap[*it] = 0.0;
2874 
2875  // if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
2876  // {
2877  // Xyce::dout() << "AnalysisManager::conductanceTest()" << std::endl;
2878  // for (std::list<std::string>::const_iterator it = tia_params.device_names.begin(), end = tia_params.device_names.end(); it != end; ++it)
2879  // Xyce::dout() << "current device name = \"" << *it
2880  // << "\" added to inputMap[ " << *it << " ] = " << inputMap[ *it ] << std::endl;
2881  // }
2882 
2883  int isize = inputMap.size();
2884  std::vector<double> outputVector(isize, 0.0);
2885  std::vector< std::vector<double> > jacobian(isize);
2886  for (int i = 0; i < isize; ++i)
2887  {
2888  jacobian[i].resize(isize, 0.0);
2889  }
2890 
2891  bool b1 = conductance_extractor.extract(inputMap, outputVector, jacobian);
2892 
2893  int iE1, iE2;
2894  int numElectrodes = isize;
2895 
2896  FILE *fp1;
2897  fp1 = fopen(filename.c_str(), "w");
2898 
2899  fprintf(fp1, "%s", "Conductance array: \n");
2900  fprintf(fp1,"%s", " ");
2901  if (b1)
2902  {
2903  std::map<std::string,double>::const_iterator iterM = inputMap.begin();
2904  std::map<std::string,double>::const_iterator endM = inputMap.end ();
2905  for (iE2 = 0; iE2 < numElectrodes; ++iE2, ++iterM)
2906  {
2907  std::string srcname = iterM->first;
2908  fprintf(fp1, "\t%14s", srcname.c_str());
2909  }
2910  fprintf(fp1, "%s", "\n");
2911 
2912  iterM = inputMap.begin();
2913  for (iE1 = 0; iE1 < numElectrodes; ++iE1, ++iterM)
2914  {
2915  std::string srcname = iterM->first;
2916  fprintf(fp1,"%14s",srcname.c_str());
2917  for (iE2 = 0; iE2 < numElectrodes; ++iE2)
2918  {
2919  fprintf(fp1,"\t%14.4e",jacobian[iE1][iE2]);
2920  }
2921  fprintf(fp1,"%s", "\n");
2922  }
2923  fprintf(fp1,"%s", "\n");
2924  }
2925  else
2926  {
2927  fprintf(fp1,"%s", "\nConductance calculation failed!\n");
2928  }
2929 
2930  fclose(fp1);
2931 }
2932 
2933 namespace {
2934 
2935 typedef Util::Factory<AnalysisBase, Transient> TransientFactoryBase;
2936 
2937 //-----------------------------------------------------------------------------
2938 // Class : TransientFactory
2939 // Purpose :
2940 // Special Notes :
2941 // Scope : public
2942 // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2943 // Creation Date : Thu Jan 29 12:53:02 2015
2944 //-----------------------------------------------------------------------------
2945 ///
2946 /// Factory for parsing Transient parameters from the netlist and creating Transient analysis.
2947 ///
2948 class TransientFactory: public TransientFactoryBase
2949 {
2950 public:
2951  //-----------------------------------------------------------------------------
2952  // Function : TransientFactory
2953  // Purpose :
2954  // Special Notes :
2955  // Scope : public
2956  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2957  // Creation Date : Thu Jan 29 12:54:09 2015
2958  //-----------------------------------------------------------------------------
2959  ///
2960  /// Constructs the Transient analysis factory
2961  ///
2962  /// @invariant Stores the results of parsing, so if more than one of the analysis and
2963  /// associated lines are parsed, the second options simply overwrite the previously parsed
2964  /// values.
2965  ///
2966  /// @invariant The existence of the parameters specified in the constructor cannot
2967  /// change.
2968  ///
2969  /// @param analysis_manager
2970  /// @param linear_system
2971  /// @param nonlinear_manager
2972  /// @param topology
2973  ///
2974  TransientFactory(
2975  Analysis::AnalysisManager & analysis_manager,
2976  Linear::System & linear_system,
2977  Nonlinear::Manager & nonlinear_manager,
2978  Loader::Loader & loader,
2979  Topo::Topology & topology,
2980  IO::InitialConditionsManager & initial_conditions_manager,
2981  IO::RestartMgr & restart_manager)
2982  : TransientFactoryBase(),
2983  analysisManager_(analysis_manager),
2984  linearSystem_(linear_system),
2985  nonlinearManager_(nonlinear_manager),
2986  loader_(loader),
2987  topology_(topology),
2988  initialConditionsManager_(initial_conditions_manager),
2989  restartManager_(restart_manager)
2990  {}
2991 
2992  virtual ~TransientFactory()
2993  {}
2994 
2995  //-----------------------------------------------------------------------------
2996  // Function : create
2997  // Purpose :
2998  // Special Notes :
2999  // Scope : public
3000  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
3001  // Creation Date : Thu Jan 29 12:59:00 2015
3002  //-----------------------------------------------------------------------------
3003  ///
3004  /// Create a new Transient analysis and applies the analysis and time integrator option blocks.
3005  ///
3006  /// @return new Transient analysis object
3007  ///
3008  Transient *create() const
3009  {
3010  analysisManager_.setAnalysisMode(ANP_MODE_TRANSIENT);
3012  transient->setAnalysisParams(transientAnalysisOptionBlock_);
3013  transient->setTimeIntegratorOptions(timeIntegratorOptionBlock_);
3014 
3015  return transient;
3016  }
3017 
3018  //-----------------------------------------------------------------------------
3019  // Function : setTransientAnalysisOptionBlock
3020  // Purpose :
3021  // Special Notes :
3022  // Scope : public
3023  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
3024  // Creation Date : Thu Jan 29 13:00:14 2015
3025  //-----------------------------------------------------------------------------
3026  ///
3027  /// Saves the analysis parsed options block in the factory.
3028  ///
3029  /// @invariant Overwrites any previously specified analysis option block.
3030  ///
3031  /// @param option_block parsed option block
3032  ///
3033  void setTransientAnalysisOptionBlock(const Util::OptionBlock &option_block)
3034  {
3035  transientAnalysisOptionBlock_ = option_block;
3036  }
3037 
3038  //-----------------------------------------------------------------------------
3039  // Function : setTimeIntegratorOptionBlock
3040  // Purpose :
3041  // Special Notes :
3042  // Scope : public
3043  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
3044  // Creation Date : Thu Jan 29 13:01:27 2015
3045  //-----------------------------------------------------------------------------
3046  ///
3047  /// Saves the time integrator parsed option block.
3048  ///
3049  /// @invariant Overwrites any previously specified time integrator option block.
3050  ///
3051  /// @param option_block parsed option block
3052  ///
3053  bool setTimeIntegratorOptionBlock(const Util::OptionBlock &option_block)
3054  {
3055  timeIntegratorOptionBlock_ = option_block;
3056 
3057  return true;
3058  }
3059 
3060 public:
3061  AnalysisManager & analysisManager_;
3062  Linear::System & linearSystem_;
3063  Nonlinear::Manager & nonlinearManager_;
3064  Loader::Loader & loader_;
3065  Topo::Topology & topology_;
3066  IO::InitialConditionsManager & initialConditionsManager_;
3067  IO::RestartMgr & restartManager_;
3068 
3069 private:
3071  Util::OptionBlock timeIntegratorOptionBlock_;
3072 };
3073 
3074 // .TRAN
3075 struct TransientAnalysisReg : public IO::PkgOptionsReg
3076 {
3077  TransientAnalysisReg(
3078  TransientFactory & factory)
3079  : factory_(factory)
3080  {}
3081 
3082  bool operator()(const Util::OptionBlock &option_block)
3083  {
3084  factory_.setTransientAnalysisOptionBlock(option_block);
3085 
3086  factory_.analysisManager_.addAnalysis(&factory_);
3087 
3088  return true;
3089  }
3090 
3091  TransientFactory & factory_;
3092 };
3093 
3094 
3095 //-----------------------------------------------------------------------------
3096 // Function : extractTRANData
3097 // Purpose : Extract the parameters from a netlist .DC line held in
3098 // parsedLine_.
3099 // Special Notes :
3100 // Scope : public
3101 // Creator : Lon Waters, SNL
3102 // Creation Date : 10/05/2001
3103 //-----------------------------------------------------------------------------
3104 bool
3105 extractTRANData(
3106  IO::PkgOptionsMgr & options_manager,
3107  IO::CircuitBlock & circuit_block,
3108  const std::string & netlist_filename,
3109  const IO::TokenVector & parsed_line)
3110 {
3111  Util::OptionBlock option_block("TRAN");
3112 
3113  int numFields = parsed_line.size();
3114 
3115  // Check that the minimum required number of fields are on the line.
3116  if ( numFields < 3 || numFields > 6 )
3117  {
3118  Report::UserError0().at(netlist_filename, parsed_line[0].lineNumber_)
3119  << ".TRAN line has an unexpected number of fields";
3120  return false;
3121  }
3122  else
3123  {
3124  int linePosition = 1; // Start of parameters on .param line.
3125  int endPosition = numFields;
3126 
3127  Util::Param parameter("", "");
3128 
3129  // TSTEP and TSTOP are required, get them now.
3130  parameter.setTag( "TSTEP" );
3131  parameter.setVal( parsed_line[linePosition].string_ );
3132  option_block.addParam( parameter );
3133  ++linePosition; // Advance to next parameter.
3134 
3135  parameter.setTag( "TSTOP" );
3136  parameter.setVal( parsed_line[linePosition].string_ );
3137  option_block.addParam( parameter );
3138  ++linePosition; // Advance to next parameter.
3139 
3140  // at this point we can have
3141  // [ <TSTART> [<DTMAX>] ] [NOOP|UIC] [{expression for time step schedule}]
3142  //
3143  // because these are optional, we'll need to test the type of each
3144  // parameter before deciding how to handle it
3145  //
3146  // need these flags to figure out what any untaged doubles are on the .tran line
3147  bool tstartFound=false;
3148  bool dtmaxFound=false;
3149  while( linePosition < endPosition )
3150  {
3151  // convert the next item to a parameter and set the
3152  // parameter's tag and value. We set both because
3153  // in some cases we need to change the tag and in
3154  // others we need to change the value
3155  parameter.setTag( parsed_line[linePosition].string_ );
3156  parameter.setVal( parsed_line[linePosition].string_ );
3157 
3158  if(parameter.hasExpressionValue())
3159  {
3160  // found a max time step schedule expression
3161  parameter.setTag("MAXTIMEEXPRESSION");
3162  option_block.addParam( parameter );
3163  }
3164  else
3165  {
3166  // could be TSTART DTMAX or NOOP|UIC
3167  if ( parameter.uTag() == "NOOP" || parameter.uTag() == "UIC" )
3168  {
3169  parameter.setVal( "1" );
3170  option_block.addParam( parameter );
3171  }
3172  else
3173  {
3174  if( !tstartFound )
3175  {
3176  parameter.setTag( "TSTART" );
3177  option_block.addParam( parameter );
3178  tstartFound=true;
3179  }
3180  else if( !dtmaxFound )
3181  {
3182  parameter.setTag( "DTMAX" );
3183  option_block.addParam( parameter );
3184  dtmaxFound=true;
3185  }
3186  else
3187  {
3188  Report::UserError0().at(netlist_filename, parsed_line[linePosition].lineNumber_)
3189  << "expected NOOP/UIC field on .TRAN line but found" << parameter.usVal();
3190  }
3191  }
3192  }
3193  linePosition++;
3194  }
3195 
3196  circuit_block.addOptions(option_block);
3197 
3198  return true; // Only get here on success.
3199  }
3200 }
3201 
3202 } // namespace <unnamed>
3203 
3204 
3205 bool
3207  FactoryBlock & factory_block)
3208 {
3209  TransientFactory *factory = new TransientFactory(factory_block.analysisManager_, factory_block.linearSystem_, factory_block.nonlinearManager_, factory_block.loader_, factory_block.topology_, factory_block.initialConditionsManager_, factory_block.restartManager_);
3210 
3211  addAnalysisFactory(factory_block, factory);
3212 
3213  factory_block.optionsManager_.addCommandParser(".TRAN", extractTRANData);
3214  factory_block.optionsManager_.addCommandParser(".TR", extractTRANData);
3215 
3216  factory_block.optionsManager_.addCommandProcessor("TRAN", new TransientAnalysisReg(*factory));
3217 
3218  factory_block.optionsManager_.addOptionsProcessor("TIMEINT", IO::createRegistrationOptions(*factory, &TransientFactory::setTimeIntegratorOptionBlock));
3219 
3220  return true;
3221 }
3222 
3223 } // namespace Analysis
3224 } // namespace Xyce
bool setAnalysisOption(const Util::Param &param)
bool enableSensitivity(TimeIntg::DataStore &data_store, Parallel::Manager &parallel_manager, Topo::Topology &topology)
Linear::Vector * lastSolutionPtr
std::vector< Linear::Vector * > fastTimeQVec
Util::FixedQueue< double > timeQueue_
TimeIntg::TIAParams tiaParams_
virtual int getMaxNormFindex() const =0
Topo::Topology & topology_
IO::InitialConditionsManager & initialConditionsManager_
void notify(const StepEvent &event)
std::vector< double > timeSteps
unsigned int successfulStepsTaken_
Number of consecutive successful time-integration steps.
bool icSensitivity(std::vector< double > &objectiveVec, std::vector< double > &dOdpVec, std::vector< double > &dOdpAdjVec, std::vector< double > &scaled_dOdpVec, std::vector< double > &scaled_dOdpAdjVec)
virtual bool setInitialGuess(Linear::Vector *solVectorPtr)
Definition: N_LOA_Loader.h:232
double initialTimeStep
User specified initial time step.
static const int type
Definition: N_TIA_OneStep.h:74
std::vector< bool > timeStepsBreakpointFlag
void setSavedAlready(bool saved_already)
void setNextOutputTime(double next_output_time)
bool testRestartSaveTime(AnalysisManager &analysis_manager, IO::RestartMgr &restart_manager, double current_time, double &next_restart_save_time)
bool setTimeIntegratorOption(const Util::Param &param)
bool testSaveOutputTime(Analysis::AnalysisManager &analysis_manager, IO::InitialConditionsManager &initial_conditions_manager)
bool calcSensitivity(std::vector< double > &objectiveVec, std::vector< double > &dOdpVec, std::vector< double > &dOdpAdjVec, std::vector< double > &scaled_dOdpVec, std::vector< double > &scaled_dOdpAdjVec)
void evaluateStepError(const Loader::Loader &loader, const TIAParams &tia_params)
Pure virtual class to augment a linear system.
int errorAnalysisOptionResetCount
Iteration count down to reset errorAnalysisOption to LOCAL_TRUNCATED_ESTIMATES.
std::vector< std::string > condTestDeviceNames
names for conductance test
int nIterations
Number of newton iterations.
virtual void outputMPDE(double time, const Linear::Vector *solution_vector)
std::vector< double > objectiveVec_
Topo::Topology & topology_
virtual void stepFailure(Analysis::TwoLevelMode analysis)
Definition: N_LOA_Loader.h:287
void dumpRestart(Parallel::Communicator &parallel_communicator, Topo::Topology &topology, Analysis::AnalysisManager &analysis_manager, const std::string &job_name, bool pack, double current_time) const
Util::OptionBlock timeIntegratorOptionBlock_
IO::RestartMgr & restartManager_
Util::FixedQueue< int > nonlinearSolverStatusQueue_
virtual bool outputPlotFiles() const
Definition: N_LOA_Loader.h:261
std::vector< double > dOdpAdjVec_
unsigned int stepNumber
Time-integration step number counter.
void outputSolDataArrays(std::ostream &os)
virtual double getMaxNormF() const =0
Linear::Vector * currStorePtr
Linear::Vector * lastStatePtr
void gatherStepStatistics(StatCounts &stats, Nonlinear::NonLinearSolver &nonlinear_solver, int newton_convergence_status)
int errorAnalysisOption
Error analysis option.
Util::ExpressionData * maxTimeStepExpression_
double finalTime
End time for simulation.
void createTimeIntegratorMethod(const TimeIntg::TIAParams &tia_params, const unsigned int integration_method)
bool extract(const std::map< std::string, double > &inputMap, std::vector< double > &outputVector, std::vector< std::vector< double > > &jacobian)
Linear::System & linearSystem_
ConductanceExtractor & getConductanceExtractor()
int exitStep
Exit after taking this many steps.
OutputMgrAdapter & outputManagerAdapter_
bool resetAll(const TIAParams &tia_params)
Util::FixedQueue< int > nonlinearSolverNumIterationsQueue_
std::vector< Linear::Vector * > fastTimeStateVec
Util::ListenerAutoSubscribe< StepEvent > StepEventListener
const Util::BreakPointLess & getBreakPointLess() const
void setAnalysisMode(AnalysisMode mode)
Linear::Vector * currStatePtr
unsigned int failedStepsAttempted_
Total number of failed time-integration steps.
Parallel::Manager * getPDSManager() const
bool setDCOPOption(const Util::Param &param)
Loader::Loader & loader_
TimeIntg::StepErrorControl & getStepErrorControl()
bool constantTimeStepFlag
Constant time step integration flag.
std::vector< Linear::Vector * > fastTimeSolutionVec
NonLinearSolver & getNonlinearSolver()
std::vector< TwoLevelError > innerErrorInfoVec
int minTimeStepsBP
User specified mininum number of steps between breakpoints.
Linear::Vector * daeQVectorPtr
std::vector< double > dOdpVec_
virtual bool initializeProblem(Linear::Vector *nextSolVectorPtr, Linear::Vector *currSolVectorPtr, Linear::Vector *lastSolVectorPtr, Linear::Vector *nextStaVectorPtr, Linear::Vector *currStaVectorPtr, Linear::Vector *lastStaVectorPtr, Linear::Vector *StateDerivVectorPtr, Linear::Vector *nextStoVectorPtr, Linear::Vector *currStoVectorPtr, Linear::Vector *lastStoVectorPtr, Linear::Vector *QVectorPtr, Linear::Vector *FVectorPtr, Linear::Vector *BVectorPtr, Linear::Vector *dFdxdVpVectorPtr, Linear::Vector *dQdxdVpVectorPtr) const =0
Linear::System & linearSystem_
void updateStopTime(Parallel::Machine comm, bool breakpoints_enabled, double initial_time, bool min_time_steps_breakpoint_given, double min_time_steps_breakpoint)
void resetAll(AnalysisMode mode)
virtual bool startTimeStep(bool beginIntegrationFlag, double nextTimeStep, double nextTime, int currentOrder)
Definition: N_LOA_Loader.h:305
void setErrorWtVector(const TIAParams &tia_params)
const ReturnCodes & getReturnCodes() const
bool saveTimeStepsFlag
flag to save timestpes in data store for later use
virtual bool isPDESystem() const
Definition: N_LOA_Loader.h:256
bool registerTransientFactory(FactoryBlock &factory_block)
Linear::Vector * daeFVectorPtr
bool mixedSignalStep(double maxTimeStepFromHabanero)
Util::OptionBlock transientAnalysisOptionBlock_
bool bpEnable
Enable breakpoints flag.
Nonlinear::Manager & nonlinearManager_
The FactoryBlock contains parameters needed by the analysis creation functions.
IO::InitialConditionsManager & initialConditionsManager_
Nonlinear::AnalysisMode nonlinearAnalysisMode(Mode mode)
Returns the nonlinear analysis mode given the analysis mode.
virtual void acceptStep()
Definition: N_LOA_Loader.h:292
OutputAdapter * outputAdapter_
void simulationPaused(double initial_time)
Util::FixedQueue< double > nonlinearSolverMaxNormQueue_
void printProgress(std::ostream &os)
virtual bool updateSources()
Definition: N_LOA_Loader.h:244
Linear::Vector * currLeadCurrentQDerivPtr
Linear::Vector * nextStatePtr
std::vector< Linear::Vector * > fastTimeStoreVec
void preMixedSignalStepDetails(double maxTimeStepFromHabanero)
AnalysisManager & analysisManager_
virtual bool printLoopInfo(int start, int finish)
Linear::Vector * dFdxdVpVectorPtr
IO::InitialConditionsManager & initialConditionsManager_
Loader::NonlinearEquationLoader & getNonlinearEquationLoader()
Linear::Vector * currLeadDeltaVPtr
TransientFactory & factory_
void setDoubleDCOPEnabled(bool enable)
void outputPredictedSolution(std::ostream &os)
bool retakeAndAcceptTimeStep(double aTimeStep)
double initialOutputTime
Time at which output starts (StepErrorControl)
N_MPDE_Manager * mpdeManager_
bool setTimeIntegratorOptions(const Util::OptionBlock &option_block)
Nonlinear::Manager & nonlinearManager_
void outputPredictedDerivative(std::ostream &os)
unsigned int initialIntegrationMethod_
Linear::Vector * nextSolutionPtr
unsigned int integrationMethod
Time-integration method.
Linear::Vector * nextStorePtr
void addAnalysisFactory(FactoryBlock &factory_block, Util::Factory< AnalysisBase, void > *factory)
double initialTime
Beginning time for the time integrator (StepErrorControl, integrators access from StepErrorControl) ...
Linear::Vector * dQdxdVpVectorPtr
bool setAnalysisParams(const Util::OptionBlock &paramsBlock)
Linear::Vector * currLeadCurrentPtr
Linear::Vector * lastStorePtr
void setInputOPFlag(bool initial_conditions_loaded)
TimeIntg::WorkingIntegrationMethod & getWorkingIntegrationMethod()
const IO::CmdParse & getCommandLine() const
std::vector< double > scaled_dOdpAdjVec_
std::string maxTimeStepExpressionString_
void setSwitchIntegrator(bool switch_itegrator)
void allocateTranSolver(Analysis::AnalysisManager &analysis_manager, Loader::NonlinearEquationLoader &nonlinear_equation_loader, Linear::System &linear_system, TimeIntg::DataStore &data_store, Parallel::Manager &parallel_manager, IO::OutputMgr &output_manager, Topo::Topology &topology)
bool saveOutputSolution(Parallel::Machine comm, IO::InitialConditionsManager &initial_conditions_manager, const NodeNameMap &node_name_map, const TIAParams &tia_params, Linear::Vector *solnVecPtr, const double saveTime, const bool doNotInterpolate)
Linear::Vector * currSolutionPtr
TimeIntg::DataStore * getDataStore()
unsigned int baseIntegrationMethod_
Current time-integration method flag.
IO::RestartMgr & restartManager_
bool updateMaxTimeStep(Parallel::Machine comm, Loader::Loader &loader, const TIAParams &tia_params, double suggestedMaxTimeStep=0.0)
double updateOutputTime(double current_time, double next_output_time, double final_output_time, double initial_output_interval, const IO::IntervalVector &output_intervals)
Util::FixedQueue< double > timeStepQueue_
const IO::IntervalVector & getOutputIntervals() const
bool updateBreakPoints(const Loader::Loader &loader, double initial_time)
std::vector< double > scaled_dOdpVec_
Linear::Vector * nextStateDerivPtr
virtual void stepSuccess(Analysis::TwoLevelMode analysis)
Definition: N_LOA_Loader.h:284
Util::FixedQueue< int > stepStatusQueue_
bool condTestFlag
flag for conductance test
virtual bool finishOutput() const
Definition: N_LOA_Loader.h:266
double exitTime
Exit when it exceeds this time.
Nonlinear::Manager & nonlinearManager_
virtual bool getInitialQnorm(std::vector< TimeIntg::TwoLevelError > &tleVec)
Definition: N_LOA_Loader.h:295
bool printOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const TIAParams &tia_params, const double time, Linear::Vector *solnVecPtr, const bool doNotInterpolate, const std::vector< double > &outputInterpolationTimes, bool skipPrintLineOutput)
void setTwoLevelMode(TwoLevelMode two_level_mode)
void writeConductanceFile(const std::vector< std::string > &device_names, Nonlinear::ConductanceExtractor &conductance_extractor, const std::string &filename)
Util::FixedQueue< double > nonlinearSolverMaxNormIndexQueue_
AnalysisManager & analysisManager_
void printStepHeader(std::ostream &os)
virtual int getNumIterations() const =0
bool passNLStall
option to pass some non-linear solver failures
Linear::Vector * flagSolutionPtr
void tranOutput(double time, Linear::Vector &currSolutionPtr, Linear::Vector &stateVecPtr, Linear::Vector &storeVecPtr, Linear::Vector &lead_current_vector, Linear::Vector &junction_voltage_vector, Linear::Vector &lead_current_dqdt_vector, std::vector< double > &objectiveVec_, std::vector< double > &dOdpVec_, std::vector< double > &dOdpAdjVec_, std::vector< double > &scaled_dOdpVec_, std::vector< double > &scaled_dOdpAdjVec_, bool skipPrintLineOutput=false)
Transient(AnalysisManager &analysis_manager, Linear::System &linear_system, Nonlinear::Manager &nonlinear_manager, Loader::Loader &loader, Topo::Topology &topology, IO::InitialConditionsManager &initial_conditions_manager, IO::RestartMgr &restart_manager, OutputAdapter *output_adapter=0, HB *hb_analysis=0, N_MPDE_Manager *mpde_manager=0)
Util::FixedQueue< double > estErrorOverTolQueue_
Linear::Vector * daeBVectorPtr
bool setReturnCodeOption(const Util::Param &param)
std::vector< double > computeOutputInterpolationTimes(double current_time, double next_output_time, double final_output_time, double initial_output_interval, const IO::IntervalVector &output_intervals)
bool testOutputTime(double current_time, double next_output_time, double start_time)