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.212.2.1 $
35 // Revision Date : $Date: 2015/04/02 18:20:07 $
36 // Current Owner : $Author: tvrusso $
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_OutputMgr.h>
52 #include <N_IO_PkgOptionsMgr.h>
53 #include <N_IO_RestartMgr.h>
54 #include <N_LAS_System.h>
55 #include <N_LOA_Loader.h>
57 #include <N_MPDE_Manager.h>
58 #include <N_NLS_ReturnCodes.h>
59 #include <N_PDS_Comm.h>
60 #include <N_PDS_Serial.h>
61 #include <N_PDS_MPI.h>
62 #include <N_TIA_DataStore.h>
63 #include <N_TIA_OneStep.h>
65 #include <N_TIA_StepErrorControl.h>
67 #include <N_TOP_Topology.h>
68 #include <N_UTL_Diagnostic.h>
69 #include <N_UTL_ExpressionData.h>
70 #include <N_UTL_ExtendedString.h>
71 #include <N_UTL_FeatureTest.h>
72 #include <N_UTL_MachDepParams.h>
73 #include <N_UTL_NoCase.h>
74 #include <N_UTL_Param.h>
75 #include <N_UTL_Timer.h>
76 
77 
78 namespace Xyce {
79 namespace Analysis {
80 
81 //-----------------------------------------------------------------------------
82 // Function : Transient::Transient(AnalysisManager &manager)
83 // Purpose : constructor
84 // Special Notes :
85 // Scope : public
86 // Creator : Rich Schiek, SNL
87 // Creation Date : 3/11/06
88 //-----------------------------------------------------------------------------
90  AnalysisManager & analysis_manager,
91  Linear::System & linear_system,
92  Nonlinear::Manager & nonlinear_manager,
93  Topo::Topology & topology,
94  OutputAdapter * output_adapter,
95  HB * hb_analysis,
96  N_MPDE_Manager * mpde_manager)
97  : AnalysisBase(analysis_manager, "Transient"),
98  StepEventListener(&analysis_manager),
99  comm_(analysis_manager.getPDSManager()->getPDSComm()->comm()),
100  analysisManager_(analysis_manager),
101  loader_(analysis_manager.getLoader()),
102  linearSystem_(linear_system),
103  nonlinearManager_(nonlinear_manager),
104  topology_(topology),
105  outputManagerAdapter_(analysis_manager.getOutputManagerAdapter()),
106  outputAdapter_(output_adapter),
107  tiaParams_(),
108  sensFlag_(analysis_manager.getSensFlag()),
109  initialIntegrationMethod_(TimeIntg::OneStep::type),
110  firstTranOutput_(true),
111  isPaused(false),
112  dcopFlag_(true),
113  startDCOPtime(0.0),
114  startTRANtime_(0.0),
115  endTRANtime_(0.0),
116  gui_(analysisManager_.getCommandLine().argExists("-gui")),
117  maxTimeStepExpressionString_(),
118  maxTimeStepExpression_(0),
119  firstTime(true),
120  oldPercentComplete(0.0),
121  startSimTime(-1.0),
122  dcStats(0),
123  tranStats(0),
124  exitTime(0.0),
125  exitStep(-1),
126  integrationMethod(7),
127  historyTrackingDepth(25),
128  passNLStall(false),
129  saveTimeStepsFlag(false),
130  condTestFlag(false),
131  condTestDeviceNames(),
132  outputInterpMPDE(true),
133  hbAnalysis_(hb_analysis),
134  mpdeManager_(mpde_manager)
135 {}
136 
137 void Transient::notify(const StepEvent &event)
138 {
139  if (event.state_ == StepEvent::STEP_STARTED)
140  {
142 
145  dcopFlag_ = false;
147 
148  if (timeQueue_.get_size() != 0)
149  {
150  // these set_size calls will also "reset" the queue.
151  timeQueue_.reset_queue();
152  timeStepQueue_.reset_queue();
153  stepStatusQueue_.reset_queue();
154  estErrorOverTolQueue_.reset_queue();
155  nonlinearSolverStatusQueue_.reset_queue();
157  nonlinearSolverMaxNormQueue_.reset_queue();
158  nonlinearSolverMaxNormIndexQueue_.reset_queue();
159  }
160  }
161 }
162 
163 //-----------------------------------------------------------------------------
164 // Function : Transient::setAnalysisParams
165 // Purpose :
166 // Special Notes : These are from the .TRAN statement.
167 // Scope : public
168 // Creator : Eric Keiter, SNL
169 // Creation Date : 6/21/10
170 //-----------------------------------------------------------------------------
171 bool Transient::setAnalysisParams(const Util::OptionBlock & paramsBlock)
172 {
173  for (Util::ParamList::const_iterator it = paramsBlock.begin(), end = paramsBlock.end(); it != end; ++it)
174  {
175  const Util::Param &param = *it;
176 
177  if (tiaParams_.setAnalysisOption(param))
178  ;
179  else if (param.uTag() == "NOOP" ||
180  param.uTag() == "UIC")
181  {
182  setNOOP(true);
183  }
184  else if (param.uTag() == "MAXTIMEEXPRESSION")
185  {
186  // an expression was given which should specify what
187  // max time step to use based on the current simulation
188  // time. The expected format of this is
189  // {schedule( t0, max_del_t0, t1, max_del_t1, ...)}
190  // we'll just store the expression as a string for now
191  // as we need to make sure other classes are up and running
192  // before we can create the actual expression. That will
193  // happen in Transient class as it will ultimately use this
194  maxTimeStepExpressionString_ = param.stringValue();
195  }
196  else
197  Report::UserError() << param.uTag() << " is not a recognized analysis option";
198  }
199 
201  {
202  UserFatal(*this) << "Final time of " << tiaParams_.finalTime
203  << " is earlier or same as start time of " << tiaParams_.initialOutputTime << std::endl
204  << " Check netlist for invalid .TRAN specification";
205  }
206 
207  // if starting time steps is baloney, set then to a default value.
208  // ERK. This trap is redudant with an identical one in step error
209  // control.
210  if ( tiaParams_.initialTimeStep <= 0.0 )
211  {
212  tiaParams_.initialTimeStep = 1.0e-10;
213  }
214 
215  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
216  {
217  dout() << std::endl
218  << section_divider << std::endl
219  << " Transient simulation parameters" << std::endl
220  << " initial time = " << tiaParams_.initialTime << std::endl
221  << " final time = " << tiaParams_.finalTime << std::endl
222  << " starting time step = " << tiaParams_.initialTimeStep << std::endl
223  << " initialOutputTime (time of first output) = " << tiaParams_.initialOutputTime << std::endl;
224 
225  if (!getNOOP())
226  {
227  dout() << " NOOP/UIC is NOT set" << std::endl;
228  }
229  else
230  {
231  dout() << " NOOP/UIC is set" << std::endl;
232  }
233 
234  dout() << section_divider << std::endl;
235  }
236 
237  if (!maxTimeStepExpressionString_.empty())
238  {
239  // set-up expression object for getting a user specified, time dependent max time step value
240  delete maxTimeStepExpression_;
241 
242  maxTimeStepExpression_ = new Util::ExpressionData(maxTimeStepExpressionString_);
243  }
244 
245  // historySize_ should can be set from the .options timeint line. Use default in tiaParams
246  // as that will be overwritten if the user set it via .options. Also, if it's less than
247  // or equal to zero assume that the user wants this turned off.
248  // We'll store the attempted time step, time step status,
249  // estimated error over tolerance, non-linear solver status and non-linear solver norm
250  // for each step, up to the last historySize_ steps.
251 
252  if (historyTrackingDepth > 0 )
253  {
254  int size = historyTrackingDepth;
255  timeQueue_.set_size( size );
256  timeStepQueue_.set_size( size );
257  stepStatusQueue_.set_size( size );
258  estErrorOverTolQueue_.set_size( size );
259  nonlinearSolverStatusQueue_.set_size( size );
260  nonlinearSolverNumIterationsQueue_.set_size( size );
261  nonlinearSolverMaxNormQueue_.set_size( size );
262  nonlinearSolverMaxNormIndexQueue_.set_size( size );
263  }
264 
265  return true;
266 }
267 
268 //-----------------------------------------------------------------------------
269 // Function : AnalysisManager::setTranOptions
270 // Purpose :
271 // Special Notes : These are from '.options timeint'
272 // Scope : public
273 // Creator : Eric R. Keiter, SNL, Parallel Computational Sciences
274 // Creation Date : 04/18/02
275 //-----------------------------------------------------------------------------
276 bool
278  const Util::OptionBlock & option_block)
279 {
280  for (Util::ParamList::const_iterator it = option_block.begin(), end = option_block.end(); it != end; ++it)
281  {
282  const Util::Param &param = (*it);
283 
284  if (param.uTag() == "METHOD")
285  {
286  if (param.isInteger())
287  integrationMethod = param.getImmutableValue<int>();
288  else
289  {
290  ExtendedString stringVal ( param.stringValue() );
291  stringVal.toUpper();
292 
293  if (stringVal == "TRAP" || stringVal == "TRAPEZOIDAL")
294  integrationMethod = 7;
295  else if (stringVal == "BDF")
296  integrationMethod = 6;
297  else if (stringVal == "GEAR")
298  integrationMethod = 8;
299  else
300  {
301  Report::UserError0() << "Unsupported transient method type";
302  }
303  }
304 
305  }
306  else if (param.uTag()=="EXITTIME" )
307  exitTime = param.getImmutableValue<double>();
308  else if (param.uTag()=="EXITSTEP" )
309  exitStep = param.getImmutableValue<int>();
310  else if (param.uTag() == "HISTORYTRACKINGDEPTH" )
311  historyTrackingDepth = param.getImmutableValue<int>();
312  else if (param.uTag() == "PASSNLSTALL")
313  passNLStall = param.getImmutableValue<bool>();
314  else if (param.uTag() == "CONDTEST")
315  condTestFlag = static_cast<bool> (param.getImmutableValue<int>());
316  else if (param.uTag() == "CONDTESTDEVICENAME")
317  condTestDeviceNames.push_back(param.stringValue() );
318  else if (param.uTag() == "OUTPUTINTERPMPDE")
319  outputInterpMPDE = static_cast<bool> (param.getImmutableValue<int>());
320  else if (param.uTag() == "DAESTATEDERIV" )
321  analysisManager_.setDAEStateDerivFlag(static_cast<bool> (param.getImmutableValue<int>()));
322  else if (param.uTag() == "DEBUGLEVEL" )
323  IO::setTimeIntegratorDebugLevel(analysisManager_.getCommandLine(), param.getImmutableValue<int>());
324  else if (nonlinearManager_.setReturnCodeOption(param))
325  ;
326  else if (tiaParams_.setTimeIntegratorOption(param))
327  ;
328  else if (setDCOPOption(param))
329  ;
330  else
331  Report::UserError() << param.uTag() << " is not a recognized time integration option";
332  }
333 
334  return true;
335 }
336 
337 //-----------------------------------------------------------------------------
338 // Function : Transient::run()
339 // Purpose :
340 // Special Notes :
341 // Scope : public
342 // Creator : Rich Schiek, SNL
343 // Creation Date : 3/11/06
344 //-----------------------------------------------------------------------------
346 {
347  isPaused = false;
348 
349  bool bsuccess = doInit() && doLoopProcess() && doFinish();
350 
351  if (condTestFlag)
353 
354  return bsuccess;
355 }
356 
357 //-----------------------------------------------------------------------------
358 // Function : Transient::init()
359 // Purpose :
360 // Special Notes :
361 // Scope : public
362 // Creator : Rich Schiek, SNL
363 // Creation Date : 3/11/06
364 //-----------------------------------------------------------------------------
366 {
367  bool bsuccess = true;
368 
369  if (sensFlag_)
370  {
371  Stats::StatTop _sensitivityStat("Sensitivity");
372 
374  }
375 
378  {
380  }
381 
383  {
385  {
386  // we're resuming from a previous transient simulation
387  // this is an ugly side effect of the analysis manager's deleting
388  // the transient object after it returned in a paused state
389  // need to fix this in Xyce 6.0 . RLS 12/22/2009
390  dcopFlag_ = false;
391 
392  // we default firstTranOutput_ to true to force the first time point to be output
393  // however, if we're resuming, then we need this to be false
394  // this is really a defect of a paused simulation's Transient object
395  // being deleted by the AnalysisManager and then a new one being created
396  // when the simulation is resumed. Need to fully fix this. RLS 12/22/2009
397  firstTranOutput_ = false;
398  }
399 
400  // in a 2 level problem, we can be asked to resume
401  // without first making the integration method. So
402  // catch that.
404  {
407  }
408 
409  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
410  dout() << " transient init called with resume true " << std::endl;
411  }
412  else
413  {
414  dcopFlag_ = !getNOOP();
415 
417 
420 
422  {
424 
427 
428  dcopFlag_ = false;
429  analysisManager_.setTwoLevelMode(Analysis::TWO_LEVEL_MODE_TRANSIENT);
430 
431  // Update vectors with off proc values.
432  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->nextSolutionPtr);
433  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->currSolutionPtr);
434  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->nextStatePtr);
435  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->currStatePtr);
436  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->nextStorePtr);
437  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->currStorePtr);
438 
439  // Set the nonlinear solver parameters to those appropriate for the
440  // transient solution. If starting from here, we're not doing a DCOP
441  // calculation first - we're jumping right into the transient.
443  }
444  else // not restart
445  {
446  if (dcopFlag_)
447  {
448  // Get set to do the operating point.
451  }
452  else // otherwise NOOP/UIC
453  {
456  }
457 
458  // This setInitialGuess call is to up an initial guess in the
459  // devices that have them (usually PDE devices). This is DIFFERENT
460  // than an initial condition.
462 
463  // 12/13/07 tscoffe/tmei: .ic should not be applied to MPDE currently.
464  // A new mechanism must be set up for this, e.g. .mpde_ic
465  if (!mpdeManager_ || mpdeManager_->getTransientNeedsToLoadInitialConditionsAndInitializeProblem())
466  {
467  // If available, set initial solution. This may be from a DCOP restart,
468  // a .IC, or a .NODESET line. These can be used in both the UIC/NOOP
469  // case, as well as the DCOP case, so they need to be outside the if-statement.
474  }
475 
476  if (!dcopFlag_ && (!mpdeManager_ || mpdeManager_->getTransientNeedsToLoadInitialConditionsAndInitializeProblem()))
477  {
478  // this "initializeProblem" call is to set the IC's in devices that
479  // have them. This is done IN PLACE of the operating point.
496 
497  // Do this to populate the q-vector:
498  // since we're also skipping the DC OP, this call will
499  // also force the loader to propagate the state vector to the
500  // device manager which updates state vector seen by the devices.
502  }
503 
504  // Set a constant history.
508 
509  // Update vectors with off proc values.
510  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->nextSolutionPtr);
511  linearSystem_.updateExternValsSolnVector(analysisManager_.getDataStore()->currSolutionPtr);
512  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->nextStatePtr);
513  linearSystem_.updateExternValsStateVector(analysisManager_.getDataStore()->currStatePtr);
514  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->nextStorePtr);
515  linearSystem_.updateExternValsStoreVector(analysisManager_.getDataStore()->currStorePtr);
516 
517  // if we are skipping the DCOP, but .sens was requested, then call this here.
518  if (!dcopFlag_ && !mpdeManager_ && sensFlag_)
519  {
521 
523  }
524 
525  if (!dcopFlag_)
526  {
527  // Now do a NOOP output. ERK: 08/30/2007 This isn't the best place to
528  // put this, but it will have to do for now. If this isn't here, then
529  // NOOP/UIC simulations don't output at t=0.0 in the *prn file.
530  noopOutputs ();
531  }
532 
533  stepNumber = 0;
534  tranStepNumber = 0;
536  }
537  }
538 
540 
542  {
543  // if we're resuming, this was already done prior to pausing, and doing
544  // it again screws us up
545  double suggestedMaxTime=0.0;
547  {
549 
550  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
552  }
556  }
557 
558  // reset min error tracking variables
559  // if the step number is less than zero we'll assume there is no valid
560  // min. estimated error over tol or an associated time step. This frees us
561  // from putting Machine::Big here and trying to do something with that.
563  minEstErrorOverTol = 0.0;
565 
566  return bsuccess;
567 }
568 
569 //-----------------------------------------------------------------------------
570 // Function : Transient::loopProcess()
571 // Purpose : Conduct the time stepping loop.
572 // Special Notes :
573 // Scope : public
574 // Creator : Rich Schiek, SNL
575 // Creation Date : 3/11/06
576 //-----------------------------------------------------------------------------
578 {
579  bool bsuccess = true;
580 
581  Stats::Stat _transientStat(Stats::StatTop::getTop());
582  Stats::TimeBlock _transientTimer(_transientStat);
583 
584  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::INITIALIZE, AnalysisEvent::TRAN));
585 
586  // Transient time stepping loop:
588  {
589  if (VERBOSE_TIME)
590  printStepHeader(Xyce::lout());
591 
592  printProgress(Xyce::lout());
593 
594  // ------------------------------------------------------------------------
595  // If the flag is set to switch integration methods, do that here.
596  // For example, switch from operating point to transient backward euler.
597 
599  {
601  }
602 
603  // ------------------------------------------------------------------------
604  // Set the step size, current time and next time.
605 
607  comm_,
612 
613  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
614  {
615  dout() << std::endl;
616  dout() << "Transient::loopProcess()" << std::endl;
617  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
618  dout() << "analysisManager_.getStepErrorControl().stepAttemptStatus = " << analysisManager_.getStepErrorControl().stepAttemptStatus << std::endl;
619  }
620 
621  if (beginningIntegration &&
623  {
624  // ------------------------------------------------------------------------
625  // 07/29/04 TSC: initial step-size selection is now done in the
626  // integration method initialize call under the DAE formulation. This
627  // segregates codes changes better and makes sense to do as an
628  // initialization step even if its changed later.
630  double suggestedMaxTime=0.0;
632  {
633  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
635  }
638  }
639 
640  // ------------------------------------------------------------------------
641  // If we've switched the integration method, we need to obtain the
642  // corrector derivative only after we've updated the TimeInfo.
644  {
647  }
648 
649  if (VERBOSE_TIME && !dcopFlag_)
651 
652  // ------------------------------------------------------------------------
653  // Set the nonlinear solver parameters to those appropriate for the
654  // transient solution, if neccessary.
655  if (!dcopFlag_)
656  {
658  }
659 
660  // Ask the method to update its coefficients
662 
664 
665  // ------------------------------------------------------------------------
666  // Perform the time step:
668 
669  // ------------------------------------------------------------------------
671  {
673  }
675  {
677  bsuccess = false;
678  break;
679  }
680  // Transient
681  else
682  {
684  {
686  }
687  else if (passNLStall
690  {
691  // potentially a VERY dangerous options.
692  // if the non-linear solver is stalling, and we're very close to a min
693  // time step, then calls this failure a pass
695  {
696  {
697  UserWarning(*this) << "Nonlinear solver stalled. Calling this a pass";
698  }
699 
701  }
702  // another VERY dangerous options.
703  // if the non-linear solver is reporting too big of an update, and we're very close to a min
704  // time step, then calls this failure a pass
706  {
707  {
708  UserWarning(*this) << "Update too big. Calling this a pass";
709  }
710 
712  }
713  // another VERY dangerous options.
714  // if the non-linear solver is not converging in the max number of steps,
715  // and we're very close to a min time step, then calls this failure a pass
716  //
717  // if( analysisManager_.getStepErrorControl().newtonConvergenceStatus == -1)
718  // {
719  // Report::UserWarning0() << "Too many steps, calling this a pass";
720  // processSuccessfulStep();
721  // }
722  else
723  {
724  // process this failed step as we would have by default.
725  bool b1 = processFailedStep();
726  if (!b1)
727  {
728  bsuccess = false;
729  break;
730  }
731  }
732  }
733  else // stepAttemptStatus (ie do this if the step FAILED)
734  {
735  bool b1 = processFailedStep();
736  if (!b1)
737  {
738  bsuccess = false;
739  break;
740  }
741  } // stepAttemptStatus
742  } // transient
743 
744  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
745  {
746  dout() << std::endl;
747  dout() << " Here we are, just before checking whether to pause. " << std::endl;
748  dout() << " minTimeStep = " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
749  dout() << " final time = " << tiaParams_.finalTime << std::endl;
750  dout() << " pause time = " << analysisManager_.getPauseTime() << std::endl;
751  dout() << " initial time = " << analysisManager_.getStepErrorControl().initialTime << std::endl;
752  dout() << " current time = " << analysisManager_.getStepErrorControl().currentTime << std::endl;
754  {
755  dout() << " Pause time and current time equal " << std::endl;
756  }
757  else
758  {
759  dout() << " difference between current and pause times is "
761  }
763  {
764  dout() << " Pause time and initial time equal " << std::endl;
765  }
766  }
767 
769  {
770  // Failure at this point only indicates that the simulation
771  // is paused and may be resumed.
772  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
773  {
774  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
775  }
776 
778  isPaused = true;
779  bsuccess = true;
780  break;
781  }
782 
783  // If the exit time has been exceeded, exit.
785  {
786  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
787  bsuccess = true;
788  break;
789  }
790 
791  if (exitStep != -1 && static_cast<int>(stepNumber) == exitStep)
792  {
793  lout() << "Exit step. Exiting transient loop\n" << std::endl;
794  bsuccess = true;
795  break;
796  }
797 
798  } // end of time loop
799 
802 
803  static_cast<Xyce::Util::Notifier<AnalysisEvent> &>(analysisManager_).publish(AnalysisEvent(AnalysisEvent::FINISH, AnalysisEvent::TRAN));
804 
805  return bsuccess;
806 }
807 
808 
809 //-----------------------------------------------------------------------------
810 // Function : Transient::mixedSignalStep
811 // Purpose :
812 // Special Notes : Habanero API function
813 // Scope : public
814 // Creator : Eric Keiter, SNL
815 // Creation Date : 3/04/09
816 //-----------------------------------------------------------------------------
817 bool Transient::mixedSignalStep(double maxTimeStepFromHabanero)
818 {
819  preMixedSignalStepDetails(maxTimeStepFromHabanero);
820 
822 
823  return true;
824 }
825 
826 //-----------------------------------------------------------------------------
827 // Function : Transient::preStepDetails
828 // Purpose :
829 // Special Notes : Habanero API function
830 // Scope : private_
831 // Creator : Eric Keiter, SNL
832 // Creation Date : 3/04/09
833 //-----------------------------------------------------------------------------
834 void
836  double maxTimeStepFromHabanero)
837 {
838  if (VERBOSE_TIME)
839  printStepHeader(Xyce::lout());
840 
841  printProgress(Xyce::lout());
842 
843  // ------------------------------------------------------------------------
844  // If the flag is set to switch integration methods, do that here.
845  // For example, switch from operating point to transient backward euler.
846 
848  {
850  }
851 
852  // ------------------------------------------------------------------------
853  // Set the step size, current time and next time.
855  comm_,
860 
861  // ------------------------------------------------------------------------
862  // If a max time is set from Habanero, impose it now that stopTime is updated.
863  if (maxTimeStepFromHabanero > 0)
864  {
865  double currentTimeStep = std::min(maxTimeStepFromHabanero, analysisManager_.getStepErrorControl().currentTimeStep);
867  }
868 
869  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
870  {
871  dout() << std::endl;
872  dout() << "Transient::loopProcess()" << std::endl;
873  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
874  dout() << "analysisManager_.getStepErrorControl().stepAttemptStatus = " << analysisManager_.getStepErrorControl().stepAttemptStatus << std::endl;
875  }
876 
877  if (beginningIntegration &&
879  {
880  // ------------------------------------------------------------------------
881  // 07/29/04 TSC: initial step-size selection is now done in the
882  // integration method initialize call under the DAE formulation. This
883  // segregates codes changes better and makes sense to do as an
884  // initialization step even if its changed later.
886  double suggestedMaxTime=0.0;
888  {
889  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
891  }
894  }
895 
896  // ------------------------------------------------------------------------
897  // If we've switched the integration method, we need to obtain the
898  // corrector derivative only after we've updated the TimeInfo.
900  {
903  }
904 
905  if (VERBOSE_TIME &&!dcopFlag_)
907 
908  // ------------------------------------------------------------------------
909  // Set the nonlinear solver parameters to those appropriate for the
910  // transient solution, if neccessary.
911  if (!dcopFlag_)
912  {
914  }
915 
916  // Ask the method to update its coefficients
918 }
919 
920 //-----------------------------------------------------------------------------
921 // Function : Transient::finalizeMixedSignalStep
922 // Purpose :
923 // Special Notes : Habanero API function
924 // Scope : public
925 // Creator : Eric Keiter, SNL
926 // Creation Date : 3/04/09
927 //-----------------------------------------------------------------------------
928 bool
930 {
931  bool recoverableFailureFlag = true;
932 
934  {
936  }
938  {
940  recoverableFailureFlag = false;
941  }
942  // Transient
943  else
944  {
946  {
948  }
949  else if (passNLStall
952  {
953  // potentially a VERY dangerous options.
954  // if the non-linear solver is stalling, and we're very close to a min
955  // time step, then calls this failure a pass
956 
958  {
959  Report::UserWarning0() << "Nonlinear solver stalled, calling this a pass";
961  }
962  // another VERY dangerous options.
963  // if the non-linear solver is reporting too big of an update, and we're very close to a min
964  // time step, then calls this failure a pass
966  {
967  Report::UserWarning0() << "Update too big, calling this a pass";
969  }
970  // another VERY dangerous options.
971  // if the non-linear solver is not converging in the max number of steps,
972  // and we're very close to a min time step, then calls this failure a pass
973  //
974  // if( analysisManager_.getStepErrorControl().newtonConvergenceStatus == -1)
975  // {
976  // Report::UserWarning0() << "?Too many steps, calling this a pass";
977  // processSuccessfulStep();
978  // }
979  else
980  {
981  // process this failed step as we would have by default.
982  recoverableFailureFlag = processFailedStep();
983  }
984  }
985  else // stepAttemptStatus (ie do this if the step FAILED)
986  {
987  recoverableFailureFlag = processFailedStep();
988  }
989  } // transient
990 
991  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
992  {
993  dout() << std::endl;
994  dout() << " Here we are, just before checking whether to pause. " << std::endl;
995  dout() << " minTimeStep = " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
996  dout() << " final time = " << tiaParams_.finalTime << std::endl;
997  dout() << " pause time = " << analysisManager_.getPauseTime() << std::endl;
998  dout() << " initial time = " << analysisManager_.getStepErrorControl().initialTime << std::endl;
999  dout() << " current time = " << analysisManager_.getStepErrorControl().currentTime << std::endl;
1001  {
1002  dout() << " Pause time and current time equal " << std::endl;
1003  }
1004  else
1005  {
1006  dout() << " difference between current and pause times is " << analysisManager_.getPauseTime() - analysisManager_.getStepErrorControl().currentTime << std::endl;
1007  }
1009  {
1010  dout() << " Pause time and initial time equal " << std::endl;
1011  }
1012  }
1013 
1015  {
1016  // Failure at this point only indicates that the simulation
1017  // is paused and may be resumed.
1018  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1019  {
1020  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
1021  }
1022 
1024  isPaused = true;
1025  recoverableFailureFlag = false;
1026  }
1027 
1028  // If the exit time has been exceeded, exit.
1030  {
1031 
1032  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
1033  recoverableFailureFlag = false;
1034  }
1035 
1036  if (exitStep != -1 && static_cast<int>(stepNumber) == exitStep)
1037  {
1038  lout() <<"Exit step. Exiting transient loop\n" << std::endl;
1039  recoverableFailureFlag = false;
1040  }
1041 
1042  return recoverableFailureFlag;
1043 }
1044 
1045 //-----------------------------------------------------------------------------
1046 // Function : Transient::processSuccessfulDCOP()
1047 // Purpose :
1048 // Special Notes :
1049 // Scope : public
1050 // Creator : Rich Schiek, SNL
1051 // Creation Date : 3/11/06
1052 //-----------------------------------------------------------------------------
1054 {
1055  Stats::StatTop _processSuccessfulDCOPStat("Successful DCOP Steps");
1056  Stats::TimeBlock _processSuccessfulDCOPTimer(_processSuccessfulDCOPStat);
1057 
1058  bool bsuccess = true;
1059 
1061 
1062  if (sensFlag_ && !firstDoubleDCOPStep() )
1063  {
1065  }
1066 
1068 
1069  // Communicate down to the device level that the step has been accepted.
1070  // This must be done before the "times" get rotated, and certainly before
1071  // the vectors get rotated. The primary target for this call is the
1072  // transmission line device, which needs to know when it has a valid
1073  // solution so it can save history. (And now the ADC/DAC devices too)
1074  // needs to happen before dcopFlag_ is set to false.
1075  loader_.acceptStep();
1076 
1077  // Reset some settings (to switch from DCOP to transient, if not the
1078  // first step of a "double" DCOP.
1079  if ( firstDoubleDCOPStep() ) // (pde-only)
1080  {
1081  dcopFlag_ = true;
1084  }
1085  else
1086  {
1087  dcopFlag_ = false;
1091  beginningIntegration = true;
1092  }
1093 
1097 
1099 
1100  tranopOutputs ();
1101  // Now that output has been called, update the doubleDCOP step
1102  // if neccessary. (Only matters for pde problems)
1104 
1105  //Test and save restart if necessary
1107  {
1108  if (DEBUG_RESTART)
1109  dout() << "\n " << analysisManager_.getCommandLine().getArgumentValue("netlist")
1110  << " Calling dumpRestartData" << std::endl;
1111 
1113 
1114  if (DEBUG_RESTART)
1115  dout() << " Done Calling dumpRestartData" << std::endl;
1116  }
1117 
1118  // This output call is for device-specific output, such as .OP,
1119  // or internal plot output from PDE(TCAD) devices.
1120  loader_.output();
1121 
1123 
1125 
1126  return bsuccess;
1127 }
1128 
1129 //-----------------------------------------------------------------------------
1130 // Function : Transient::processSuccessfulStep()
1131 // Purpose :
1132 // Special Notes :
1133 // Scope : public
1134 // Creator : Rich Schiek, SNL
1135 // Creation Date : 3/11/06
1136 //-----------------------------------------------------------------------------
1138 {
1139  Stats::StatTop _processSuccessfulStepStat("Successful Step");
1140  Stats::TimeBlock _processSuccessfulStepTimer(_processSuccessfulStepStat);
1141 
1143 
1145 
1146  if (timeQueue_.get_size() != 0)
1147  {
1148  // store status of this step
1151  stepStatusQueue_.push_back( 1 );
1157  }
1158 
1159  if (sensFlag_)
1160  {
1163  }
1164 
1165  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1166  {
1167  dout() << " Transient::processSuccessfulStep()" << std::endl
1168  << "Newton step succeeded:" << std::endl
1169  << "nextSolutionPtr: " << std::endl;
1170 
1171  analysisManager_.getDataStore()->nextSolutionPtr->printPetraObject(dout());
1172  dout() << std::endl;
1173  }
1174 
1175  // Set things up for the next time step, based on if this one was
1176  // successful.
1177 
1178  // This output call is for device-specific output (like from a PDE device,
1179  // outputting mesh-based tecplot files). It will only work in parallel if on
1180  // a machine where all processors have I/O capability.
1181  // Note: this output needs to happen before the "times" get rotated.
1182  loader_.output();
1183 
1184  // Communicate down to the device level that the step has been accepted.
1185  // This must be done before the "times" get rotated, and certainly before
1186  // the vectors get rotated. The primary target for this call is the
1187  // transmission line device, which needs to know when it has a valid
1188  // solution so it can save history.
1189  loader_.acceptStep();
1190 
1191  // current time will get updated in completeStep(). We'll save its value
1192  // for the moment so it can be saved if needed with the rest of the
1193  // solution if tiaParams_.saveTimeStepsFlag is set.
1194  // This fixes an off by one bug in getting the right time value and
1195  // keeps the real solutions associated with that value too.
1196  double currentTime = analysisManager_.getStepErrorControl().currentTime;
1197  double suggestedMaxTime = 0.0;
1199  {
1200  suggestedMaxTime = maxTimeStepExpression_->evaluate(comm_, outputManagerAdapter_.getOutputManager().getCircuitTime(),
1202  }
1206 
1207  if (VERBOSE_TIME && isActive(Diag::TIME_PARAMETERS))
1208  dout() << "Transient Analysis: accepting time step" << std::endl;
1209 
1211 
1213  {
1214  dout().precision(15);
1215  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = " << analysisManager_.getStepErrorControl().TimeStepLimitedbyBP << "\n" << std::endl;
1216  dout() << "ERROROPTION=1: NL Its = " << analysisManager_.getStepErrorControl().nIterations << "\n" << std::endl;
1217  dout() << "ERROROPTION=1: New DeltaT = " << analysisManager_.getStepErrorControl().currentTimeStep << "\n" << std::endl;
1218  }
1219 
1220  stepNumber += 1;
1221  tranStepNumber += 1;
1224 
1228 
1229  // --------------------------------------------------------------------
1230  // Check to see if we have hit the end or a discontinuity point. The
1231  // next discontinuity point is represented by the stopTime variable.
1232 
1233  // Note: make sure that when we check for discontinuity point, we take
1234  // into account the possibility of roundoff error. Use the same bpTol
1235  // as is used in function updateBreakPoints.
1236  double bpTol = analysisManager_.getStepErrorControl().getBreakPointLess().tolerance_;
1237 
1238  if (tiaParams_.bpEnable)
1239  {
1242  timeDiff1 = fabs(timeDiff1);
1243  timeDiff2 = fabs(timeDiff2);
1244 
1245  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1246  {
1247  dout() << " Checking whether to set breakpointrestartstep" << std::endl;
1248  dout() << " current - stop = " << timeDiff1 << std::endl;
1249  dout() << " current - final = " << timeDiff2 << std::endl;
1250  dout() << " bpTol = " << bpTol << std::endl;
1251  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1252  dout() << " setting breakPointRestartStep to " << tranStepNumber;
1253  }
1254 
1255  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1256  {
1258  }
1259  }
1260 
1262  {
1263  beginningIntegration = true;
1264  }
1265  else
1266  {
1267  beginningIntegration = false;
1268  }
1269 
1271  {
1273  }
1275  {
1278  }
1279 
1280  if (saveTimeStepsFlag)
1281  {
1282  analysisManager_.getDataStore()->timeSteps.push_back(currentTime);
1284  Linear::Vector * aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currSolutionPtr) );
1285  analysisManager_.getDataStore()->fastTimeSolutionVec.push_back( aVecPtr );
1286  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currStatePtr) );
1287  analysisManager_.getDataStore()->fastTimeStateVec.push_back( aVecPtr );
1288  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->daeQVectorPtr) );
1289  analysisManager_.getDataStore()->fastTimeQVec.push_back( aVecPtr );
1290  aVecPtr = new Linear::Vector( *(analysisManager_.getDataStore()->currStorePtr) );
1291  analysisManager_.getDataStore()->fastTimeStoreVec.push_back( aVecPtr );
1292  }
1293 
1294  // 03/16/04 tscoffe: This is where the solution pointers are rotated.
1296 
1297  if (DEBUG_ANALYSIS & DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
1299 
1300  {
1301  Stats::StatTop _outputStat("Output");
1302  Stats::TimeBlock _outputTimer(_outputStat);
1303 
1304  tranStepOutputs ();
1305  }
1306 
1307  // Test and save restart if necessary
1310 
1312 
1313  // reset min error tracking variables
1314  // if the step number is less than zero we'll assume there is no valid
1315  // min. estimated error over tol or an associated time step. This frees us
1316  // from putting Machine::Big here and trying to do something with that.
1318 
1319  return true;
1320 }
1321 
1322 
1323 //-----------------------------------------------------------------------------
1324 // Function : Transient::processFailedStep
1325 // Purpose :
1326 // Special Notes :
1327 // Scope : public
1328 // Creator : Rich Schiek, SNL
1329 // Creation Date : 3/11/06
1330 //-----------------------------------------------------------------------------
1332 {
1333  Stats::StatTop _processFailedStat("Failed Steps");
1334  Stats::TimeBlock _processFailedTimer(_processFailedStat);
1335 
1337  Stats::StatTop _nonlinearConvergenceFailureStat("Nonlinear Failure");
1338  Stats::TimeBlock _nonlinearConvergenceFailureTimer(_nonlinearConvergenceFailureStat);
1339  }
1340 
1341  bool bsuccess = true;
1342 
1344 
1345  if (timeQueue_.get_size() != 0)
1346  {
1347  // store status of this step
1350  stepStatusQueue_.push_back( 0 );
1356  }
1357 
1358  // save some info about this step
1359  double estOverTol = analysisManager_.getStepErrorControl().getEstOverTol();
1360  if( (stepNumberAtMinEstErrorOverTol < 0) || ( estOverTol < minEstErrorOverTol ) )
1361  {
1362  // our first failed step, so automatically save info
1366  }
1367 
1369 
1370  // DO NOT REMOVE THIS OUTPUT LINE. It is depended upon by the TIA/ERROROPTION
1371  // test case, which will fail if this output doesn't happen.
1372  if (VERBOSE_TIME)
1373  dout() << "Transient Analysis: rejecting time step" << std::endl;
1374 
1376 
1378  {
1379  dout().precision(15);
1380  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = " << analysisManager_.getStepErrorControl().TimeStepLimitedbyBP << "\n" << std::endl;
1381  dout() << "ERROROPTION=1: NL Its = " << analysisManager_.getStepErrorControl().nIterations << "\n" << std::endl;
1382  dout() << "ERROROPTION=1: New DeltaT = " << analysisManager_.getStepErrorControl().currentTimeStep << "\n" << std::endl;
1383  }
1384 
1385  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1386  {
1387  dout() << " Transient::processFailedStep" << std::endl
1388  << "Newton step failed:" << std::endl
1389  << "nextSolutionPtr: " << std::endl;
1390  analysisManager_.getDataStore()->nextSolutionPtr->printPetraObject(dout());
1391  dout() << std::endl;
1392  }
1393 
1396 
1398  {
1399  if (DEBUG_ANALYSIS && isActive(Diag::TIME_PARAMETERS))
1400  {
1401  dout() << "currTimeStep: " << analysisManager_.getStepErrorControl().currentTimeStep << std::endl;
1402  dout() << "minTimeStep: " << analysisManager_.getStepErrorControl().minTimeStep << std::endl;
1403  }
1404 
1405  // before we exit with a time step too small error, check if minTimeStepRecoveryCounter is greater than zero
1406  // if it is, then the user wants us to try to accept the step that had the minimum
1407  // estimated error over tol.
1409  {
1410  lout() << "Attempting to retake and accept step where estimated error over tolerance was: " << minEstErrorOverTol
1411  << " and time step was: " << timeStepAtMinEstErrorOverTol << std::endl;
1412 
1415  }
1416  else
1417  {
1418  logQueuedData();
1419  lout() << "Time step too small near step number: " << stepNumber << " Exiting transient loop.\n" << std::endl;
1420 
1421  bsuccess = false;
1422  }
1423  }
1424 
1426  {
1427  logQueuedData();
1428  lout() << "Newton solver failed in constant time step mode. Exiting transient loop.\n" << std::endl;
1429 
1430  bsuccess = false;
1431  }
1432 
1433  if (exitStep != -1 && static_cast<int>(stats_.successStepsThisParameter_) == exitStep - 1)
1434  {
1435  logQueuedData();
1436  lout() << "Exit Step. Exiting transient loop\n" << std::endl;
1437  bsuccess = false;
1438  }
1439 
1440  if (VERBOSE_TIME && !bsuccess)
1441  {
1443  tranStats = saveLoopInfo();
1445  }
1446 
1447  return bsuccess;
1448 }
1449 
1450 //-----------------------------------------------------------------------------
1451 // Function : Transient::processFailedDCOP
1452 // Purpose :
1453 // Special Notes :
1454 // Scope : public
1455 // Creator : Rich Schiek, SNL
1456 // Creation Date : 3/11/06
1457 //-----------------------------------------------------------------------------
1459 {
1460  Stats::StatTop _processFailedDCOPStat("Failed DCOP Steps");
1461  Stats::TimeBlock _processFailedDCOPTimer(_processFailedDCOPStat);
1462 
1463  bool bsuccess = true;
1464 
1466 
1467  // DC Operating Point failed.
1470 
1471  lout() << "DC Operating Point Failed. Exiting transient loop" << std::endl;
1472 
1473  return bsuccess;
1474 }
1475 
1476 //-----------------------------------------------------------------------------
1477 // Function : Transient::finish
1478 // Purpose :
1479 // Special Notes :
1480 // Scope : public
1481 // Creator : Rich Schiek, SNL
1482 // Creation Date : 3/11/06
1483 //-----------------------------------------------------------------------------
1485 {
1486  bool bsuccess = true;
1487 
1489  {
1492  dsPtr_->timeStepsBreakpointFlag.push_back(beginningIntegration);
1493  Linear::Vector * aVecPtr = new Linear::Vector( *(dsPtr_->currSolutionPtr) );
1494  dsPtr_->fastTimeSolutionVec.push_back( aVecPtr );
1495  aVecPtr = new Linear::Vector( *(dsPtr_->currStatePtr) );
1496  dsPtr_->fastTimeStateVec.push_back( aVecPtr );
1497  aVecPtr = new Linear::Vector( *(dsPtr_->daeQVectorPtr) );
1498  dsPtr_->fastTimeQVec.push_back( aVecPtr );
1499  aVecPtr = new Linear::Vector( *(dsPtr_->currStorePtr) );
1500  dsPtr_->fastTimeStoreVec.push_back( aVecPtr );
1501  }
1502 
1503  if (!isPaused)
1504  {
1505  if (DEBUG_ANALYSIS)
1506  dout() << "Calling finishOutput" << std::endl;
1507 
1509 
1510  // This output call is for device-specific output (like from a PDE device,
1511  // outputting mesh-based tecplot files). It will only work in parallel if on
1512  // a machine where all processors have I/O capability, as devices are
1513  // local to a processor.
1515 
1517  }
1518 
1519  return bsuccess;
1520 }
1521 
1522 //-----------------------------------------------------------------------------
1523 // Function : Transient::doHandlePredictor
1524 // Purpose :
1525 // Special Notes :
1526 // Scope : private
1527 // Creator : Eric Keiter, SNL
1528 // Creation Date : 06/24/2013
1529 //-----------------------------------------------------------------------------
1531 {
1535 
1536  if (DEBUG_ANALYSIS & DEBUG_TIME && isActive(Diag::TIME_DUMP_SOLUTION_ARRAYS))
1537  {
1538  dout() << " Transient::doHandlePredictor" << std::endl;
1541  }
1542 
1543  // Now, in case this is the upper level of a 2-level sim, tell the
1544  // inner solve to do its prediction:
1546 
1547  return true;
1548 }
1549 
1550 //-----------------------------------------------------------------------------
1551 // Function : Transient::resetForHB()
1552 // Purpose : When doing initial transient run, some analyses require
1553 // a reset function
1554 // they can fill this in if needed.
1555 // Special Notes :
1556 // Scope : public
1557 // Creator : T. Mei, SNL, Parallel Computational Sciences
1558 // Creation Date : 2/26/09
1559 //-----------------------------------------------------------------------------
1561 {
1562  dcopFlag_ = false;
1563  if (timeQueue_.get_size() != 0)
1564  {
1565  // these set_size calls will also "reset" the queue.
1566  timeQueue_.reset_queue();
1567  timeStepQueue_.reset_queue();
1568  stepStatusQueue_.reset_queue();
1569  estErrorOverTolQueue_.reset_queue();
1570  nonlinearSolverStatusQueue_.reset_queue();
1571  nonlinearSolverNumIterationsQueue_.reset_queue();
1572  nonlinearSolverMaxNormQueue_.reset_queue();
1573  nonlinearSolverMaxNormIndexQueue_.reset_queue();
1574  }
1575 
1576  return true;
1577 }
1578 
1579 
1580 //-----------------------------------------------------------------------------
1581 // Function : Transient::finalVerboseOutput
1582 // Purpose :
1583 // Special Notes :
1584 // Scope : public
1585 // Creator : Rich Schiek, SNL
1586 // Creation Date : 3/11/06
1587 //-----------------------------------------------------------------------------
1589 {
1590  bool bsuccess = true;
1591 
1592  lout() << "***** Problem read in and set up time: " << analysisManager_.getSolverStartTime() << " seconds" << std::endl;
1593 
1595  {
1596  double time;
1598  {
1599  time = startTRANtime_ - startDCOPtime;
1600  }
1601  else
1602  {
1603  time = endTRANtime_ - startDCOPtime;
1604  }
1605  lout() << " ***** DCOP time: " << time << " seconds. Breakdown follows:" << std::endl;
1606 
1607  printLoopInfo(0, dcStats);
1608  }
1609 
1611  {
1612  lout() << " ***** Transient Stepping time: " << endTRANtime_ - startTRANtime_ << " seconds. Breakdown follows:" << std::endl;
1613 
1615  }
1616 
1617  return bsuccess;
1618 }
1619 
1620 //-----------------------------------------------------------------------------
1621 // Function : Transient::logQueuedData
1622 // Purpose :
1623 // Special Notes :
1624 // Scope : public
1625 // Creator : Rich Schiek, SNL
1626 // Creation Date : 3/11/06
1627 //-----------------------------------------------------------------------------
1629 {
1630  if (timeQueue_.get_size() != 0)
1631  {
1632  // get the current non-linear solver return codes
1634 
1635  lout() << " *** Transient failure history: " << std::endl;
1637  {
1638  // truncation error is not used here so est err over tol is not useful in the output
1639  lout() << "Time Time Step Non-Linear Solver node node" << std::endl;
1640  lout() << "(sec) Step Status Status Iters ||F|| index name" << std::endl;
1641  }
1642  else
1643  {
1644  lout() << "Time Time Step EstErr Non-Linear Solver node node" << std::endl;
1645  lout() << "(sec) Step Status OverTol Status Iters ||F|| index name" << std::endl;
1646  }
1647 
1648  for (int i = 0; i < timeQueue_.get_size(); i++ )
1649  {
1650  int fieldWidth=10;
1651  lout() << std::scientific << std::setprecision(fieldWidth-7) << std::setfill(' ') << std::right << std::setw( fieldWidth )
1652  << timeQueue_.at_from_tail(i) << " "
1653  << timeStepQueue_.at_from_tail(i) << " ";
1654  if( stepStatusQueue_.at_from_tail(i) == 1 )
1655  {
1656  lout() << "pass ";
1657  }
1658  else
1659  {
1660  lout() << "fail ";
1661  }
1663  {
1664  }
1665  else
1666  {
1667  lout() << estErrorOverTolQueue_.at_from_tail(i) << " ";
1668  }
1669  int nlStatus = nonlinearSolverStatusQueue_.at_from_tail(i);
1670  lout() << std::setw(7) << std::right;
1671  if( nlStatus == nlReturnCodes.normTooSmall )
1672  {
1673  lout() << "P:s nrm";
1674  }
1675  else if( nlStatus == nlReturnCodes.normalConvergence)
1676  {
1677  lout() << "pass ";
1678  }
1679  else if( nlStatus == nlReturnCodes.nearConvergence )
1680  {
1681  lout() << "P:near ";
1682  }
1683  else if( nlStatus == nlReturnCodes.smallUpdate )
1684  {
1685  lout() << "P:s up ";
1686  }
1687  else if( nlStatus == nlReturnCodes.nanFail )
1688  {
1689  lout() << "F:NaN ";
1690  }
1691  else if( nlStatus == nlReturnCodes.tooManySteps )
1692  {
1693  lout() << "F:max s";
1694  }
1695  else if( nlStatus == nlReturnCodes.tooManyTranSteps )
1696  {
1697  lout() << "F:max s";
1698  }
1699  else if( nlStatus == nlReturnCodes.updateTooBig )
1700  {
1701  lout() << "F:big u";
1702  }
1703  else if( nlStatus == nlReturnCodes.stalled )
1704  {
1705  lout() << "F:stall";
1706  }
1707  else if( nlStatus == nlReturnCodes.wrmsExactZero )
1708  {
1709  lout() << "F:n zro";
1710  }
1711  else if( nlStatus == nlReturnCodes.innerSolveFailed )
1712  {
1713  lout() << "F:in Fl";
1714  }
1715  else
1716  {
1717  lout() << "code=" <<
1718  nonlinearSolverStatusQueue_.at_from_tail(i) << " ";
1719  }
1720 
1721  lout() << std::right << std::setw( 4 )
1722  << nonlinearSolverNumIterationsQueue_.at_from_tail(i) << " "
1723  << nonlinearSolverMaxNormQueue_.at_from_tail(i) ;
1724 
1725  int outIndex = nonlinearSolverMaxNormIndexQueue_.at_from_tail(i) ;
1726  lout() << std::right << std::fixed << std::setw( 7 ) << outIndex;
1727 
1728  const std::vector<const std::string *> &name_vec = topology_.getSolutionNodeNames();
1729 
1730  lout() << " " << std::left << ((outIndex < name_vec.size() && outIndex >= 0) ? *name_vec[outIndex] : "N/A") << std::endl;
1731  }
1732  }
1733 }
1734 
1735 //-----------------------------------------------------------------------------
1736 // Function : Transient::takeAnIntegrationStep_
1737 // Purpose : Take a transient integration step.
1738 // Special Notes :
1739 // Scope : private
1740 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
1741 // Creation Date : 01/24/08
1742 //-----------------------------------------------------------------------------
1743 void
1745 {
1746  { // Integration step predictor
1747  Stats::StatTop _predictorStat("Predictor");
1748  Stats::TimeBlock _predictorTimer(_predictorStat);
1749 
1751  }
1752 
1753  { // Load B/V source devices with time data
1754  Stats::StatTop _updateDeviceSourceStat("Update Device Sources");
1755  Stats::TimeBlock _updateDeviceSourceTimer(_updateDeviceSourceStat);
1756 
1758  }
1759 
1760  { // Nonlinear solve
1761  Stats::StatTop _nonlinearSolveStat("Nonlinear Solve");
1762  Stats::TimeBlock _nonlinearSolveTimer(_nonlinearSolveStat);
1763 
1765  }
1766 
1767  if (DEBUG_ANALYSIS)
1768  dout() << "Transient::takeAnIntegrationStep_: newtonConvergenceStatus = " << analysisManager_.getStepErrorControl().newtonConvergenceStatus << std::endl;
1769 
1770  {
1771  Stats::StatTop _errorStat("Error Estimation");
1772  Stats::TimeBlock _errorTimer(_errorStat);
1773 
1774  // Add change to solution
1776 
1779 
1780  // Evaluate result
1782  }
1783 }
1784 
1785 //-----------------------------------------------------------------------------
1786 // Function : Transient::twoLevelStep
1787 //
1788 // Purpose : Take a transient integration step, for inner 2-level solve.
1789 //
1790 // Special Notes : Same as takeAnIntegrationStep, but does not do the
1791 // prediction. (that is in handlePredictor).
1792 //
1793 // The prediction is handled separately, as for a 2-level
1794 // solve, you only want to do the prediction on the first
1795 // solve of the attempted time step.
1796 //
1797 // Scope : public
1798 // Creator :
1799 // Creation Date : 3/11/06
1800 //-----------------------------------------------------------------------------
1802 {
1806 
1809 
1811  tranStats = saveLoopInfo();
1812 
1814 }
1815 
1816 //-----------------------------------------------------------------------------
1817 // Function : Transient::retakeAndAcceptTimeStep
1818 // Purpose : Do a requested time step and accept it
1819 // Special Notes :
1820 // Scope : public
1821 // Creator : Rich Schiek, Electrical and Microsystems Modeling
1822 // Creation Date : 01/23/09
1823 //-----------------------------------------------------------------------------
1824 bool Transient::retakeAndAcceptTimeStep( double aTimeStep )
1825 {
1826  bool bsuccess=true;
1827  // This function was put in place to handle the following situation.
1828  // If a series of time steps are rejected because the estimated error
1829  // over tol. is too high, Xyce may exit if the next time step falls under
1830  // the minTimeStep. A user could adjust the tolerances of a simulation
1831  // to try and get around this, but in UQ studies where there are 1,000s of
1832  // simulations, it can be difficult to get all of them to run. So,
1833  // if the user has set the netlist option timeint MINTIMESTEPRECOVERY=<int>
1834  // and we're about to exit because the time step has fallen under the minTimeStep
1835  // we will try and retake the time step that had the min. est. error over tol.
1836  // and accept that.
1837  //
1838  // At this point, Transient::processFailedStep() has already determined
1839  // that the preconditions outlined above are in place (i.e. the user requested
1840  // this and we're about to exit with a time step too small error), so lets
1841  // try the step that had the min. est error over tol.
1842 
1843  // set time step
1845 
1846  // take step
1848 
1849  // can't accept step if the non-linear solver failed
1851  {
1852  lout() << "Time step too small near step number: " << stepNumber << " Exiting transient loop.\n" << std::endl;
1853  bsuccess = false;
1854  }
1855  else
1856  {
1858  }
1859  return bsuccess;
1860 }
1861 
1862 //-----------------------------------------------------------------------------
1863 // Function : Transient::printStepHeader()
1864 // Purpose : Prints out time step information.
1865 // Special Notes :
1866 // Scope : public
1867 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1868 // Creation Date : 6/26/00
1869 //-----------------------------------------------------------------------------
1870 void Transient::printStepHeader(std::ostream &os)
1871 {
1872  if (VERBOSE_TIME) {
1873  os << "***** " << (DEBUG_ANALYSIS ? analysisManager_.getCommandLine().getArgumentValue("netlist") : "") << " ";
1874 
1875  if (dcopFlag_)
1876  {
1877  os << "Start of DCOP STEP # ";
1878  }
1879  else
1880  {
1882  {
1884  {
1885  os << "Start of Time Step (INITIAL STEP) # ";
1886  }
1887  else
1888  {
1889  os << "Start of Time Step (DISCONTINUITY STEP) # ";
1890  }
1891  }
1892  else
1893  {
1895  {
1896  os << "Start of Time Step (AFTER FAILED STEP) # ";
1897  }
1898  else
1899  {
1900  os << "Start of Time Step (AFTER SUCCESS STEP) # ";
1901  }
1902  }
1903  }
1904 
1905  os << stats_.successStepsThisParameter_ + 1 << std::endl;
1906  }
1907 }
1908 
1909 //-----------------------------------------------------------------------------
1910 // Function : Transient::printProgress()
1911 // Purpose : Outputs run completion percentage and estimated
1912 // time-to-completion.
1913 //
1914 // Special Notes : This will need some fixing to work with .STEP.
1915 //
1916 // Scope : public
1917 // Creator : Scott A. Hutchinson, SNL, Computational Sciences
1918 // Creation Date : 06/07/2002
1919 //-----------------------------------------------------------------------------
1920 void Transient::printProgress(std::ostream &os)
1921 {
1923  {
1924  // Percent of the overall requested simulation time which is completed.
1925  double percentComplete;
1926  // Average CPU time per time step.
1927  double aveCPUTimePerStep;
1928  // Average clock time per time step.
1929  double aveSimTimePerStep;
1930  // Estimated CPU time to complete the simulation.
1931  double estCompletionTime = 0.0;
1932 
1933  // Report the beginning of the DC OP calculation. First call in OP.
1934  if (dcopFlag_)
1935  {
1937  if (gui_)
1938  {
1939  Report::signalProgress("Xyce in DC Operating Point Calculation");
1940  }
1941  os << "***** Beginning DC Operating Point Calculation...\n" << std::endl;
1942  }
1943  else if (firstTime && stats_.successStepsThisParameter_ == 1)
1944  {
1946  dcStats = saveLoopInfo();
1947  firstTime = false;
1948  if (gui_)
1949  {
1950  Report::signalProgress("Xyce in Transient Calculation");
1951  }
1952  os << "***** Beginning Transient Calculation...\n" << std::endl;
1953  }
1955  {
1956  if (startSimTime == -1.0)
1958 
1960  double diff2 = fabs(tiaParams_.finalTime - tiaParams_.initialTime);
1961 
1962  // 02/05/08 tscoffe: optimization differences after the TIA_REFACTOR
1963  // caused a floating point difference here and this resolves that
1964  // difference. After the refactor is merged back onto the main trunk, this
1965  // stuff should be removed.
1966  percentComplete = 100.0 * diff1/diff2;
1967 
1968  if (fabs(percentComplete - oldPercentComplete) > 1.0)
1969  {
1970  oldPercentComplete = percentComplete;
1971 
1972  aveCPUTimePerStep = analysisManager_.getXyceTranTimer().elapsedTime() /
1974  aveSimTimePerStep = (analysisManager_.getStepErrorControl().currentTime - startSimTime) /
1976 
1977  if (aveSimTimePerStep > Util::MachineDependentParams::MachineEpsilon())
1978  estCompletionTime = aveCPUTimePerStep *
1980  aveSimTimePerStep;
1981 
1982  if (!gui_)
1983  {
1984  os << "***** Percent complete: " << percentComplete << " %" << std::endl;
1985  }
1986 
1987  if (estCompletionTime > Util::MachineDependentParams::MachineEpsilon())
1988  {
1989  unsigned int days, hours, minutes, seconds;
1990  days = static_cast<int> (estCompletionTime / 86400);
1991  hours = static_cast<int> ((estCompletionTime - days * 86400) / 3600);
1992  minutes = static_cast<int> ((estCompletionTime - days * 86400 - hours * 3600) / 60);
1993  seconds = static_cast<int> (estCompletionTime - days * 86400 - hours * 3600 - minutes * 60);
1994 
1995  char timeStr[256];
1996  for (char *c = timeStr; c != timeStr + sizeof(timeStr); ++c)
1997  *c = 0;
1998 
1999  if (Parallel::rank(comm_) == 0) {
2000  // get current local system time
2001  time_t t = time( NULL );
2002  struct tm * now = localtime( &t );
2003 
2004  // format and display output
2005  if ( ( t != (time_t)-1 ) && ( strftime( timeStr, 255, "%c", now ) != 0 ) )
2006  {
2007  os << "***** Current system time: " << timeStr << std::endl;
2008  }
2009 
2010  else
2011  {
2012  os << "***** Current system time could not be determined." << std::endl;
2013  }
2014  }
2015 
2016  if (days > 0)
2017  sprintf(timeStr, "%3d days, %2d hrs., %2d min., %2d sec.", days, hours, minutes, seconds);
2018  else if (hours > 0)
2019  sprintf(timeStr, "%2d hrs., %2d min., %2d sec.", hours, minutes, seconds);
2020  else if (minutes > 0)
2021  sprintf(timeStr, "%2d min., %2d sec.", minutes, seconds);
2022  else
2023  sprintf(timeStr, "%2d sec.", seconds);
2024 
2025  if (gui_)
2026  {
2027  std::ostringstream ost;
2028  ost << "Xyce transient ";
2029  if (percentComplete < 10)
2030  ost.precision(2);
2031  else
2032  ost.precision(3);
2033  ost << percentComplete
2034  << "%% complete ... Estimated time to completion: "
2035  << timeStr << std::endl;
2036  Report::signalProgress(ost.str());
2037  }
2038  else
2039  {
2040  os << "***** Estimated time to completion: " << timeStr << std::endl << std::endl;
2041  }
2042  }
2043  }
2044  }
2045  }
2046 }
2047 
2048 //-----------------------------------------------------------------------------
2049 // Function : Transient::noopOutputs
2050 // Purpose :
2051 // Special Notes :
2052 // Scope : public
2053 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2054 // Creation Date : 8/31/2007
2055 //-----------------------------------------------------------------------------
2057 {
2059  {
2060  if ( !firstDoubleDCOPStep() )
2061  {
2069  objectiveVec_,
2071 
2072  // if (mpdeManager_ && !mpdeManager_->getMPDEIcFlag())
2073  // {
2074  // // output the operating point if we can in MPDE mode
2075  // outputManagerAdapter_.outputMPDE(
2076  // analysisManager_.getStepErrorControl().currentTime,
2077  // mpdeManager_->getFastTimePoints(),
2078  // dynamic_cast<const Linear::BlockVector &>(*analysisManager_.getDataStore()->nextSolutionPtr));
2079  // }
2080  if (outputAdapter_)
2083  mpdeManager_->getFastTimePoints(),
2085  }
2087  analysisManager_.setNextOutputTime(next_output_time);
2088  }
2089 }
2090 
2091 //-----------------------------------------------------------------------------
2092 // Function : Transient::tranopOutputs
2093 // Purpose :
2094 // Special Notes :
2095 // Scope : public
2096 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2097 // Creation Date : 8/31/2007
2098 //-----------------------------------------------------------------------------
2100 {
2101  //Test and output if necessary
2103  {
2104  // Make sure this isn't the NLP step of a PDE DCOP.
2105  if ( !firstDoubleDCOPStep() )
2106  {
2107  if (DEBUG_ANALYSIS)
2108  dout() << "Calling conventional TRANOP outputs!" << std::endl;
2109 
2116  objectiveVec_,
2118 
2119  // if (mpdeManager_)
2120  // outputManagerAdapter_.outputMPDE(
2121  // analysisManager_.getStepErrorControl().currentTime,
2122  // mpdeManager_->getFastTimePoints(),
2123  // dynamic_cast<const Linear::BlockVector &>(*analysisManager_.getDataStore()->nextSolutionPtr));
2124  if (outputAdapter_)
2127  mpdeManager_->getFastTimePoints(),
2129  }
2130 
2132  analysisManager_.setNextOutputTime(next_output_time);
2133  }
2134 
2135  // SAVE and DCOP restart:
2137  {
2139  }
2140 }
2141 
2142 //-----------------------------------------------------------------------------
2143 // Function : Transient::tranStepOutputs
2144 // Purpose :
2145 // Special Notes :
2146 // Scope : public
2147 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2148 // Creation Date : 8/31/2007
2149 //-----------------------------------------------------------------------------
2151 {
2152  // The printOutputSolution function will sometimes perform
2153  // interpolations between the current step and the previous step,
2154  // if the integrator is using a high order of integration during
2155  // a new-DAE simulation.
2156 
2157  // If the user has specified tstart, and this happens to be
2158  // the first output of the simulation (at t=tstart, instead of
2159  // t=0) the force the interpolator to *not* interpolate, even
2160  // if it is doing so normally.
2162 
2164  {
2165  // if (mpdeManager_)
2166  // {
2167 
2168  // outputManagerAdapter_.outputMPDE(
2169  // analysisManager_.getStepErrorControl().currentTime,
2170  // mpdeManager_->getFastTimePoints(),
2171  // dynamic_cast<const Linear::BlockVector &>(*analysisManager_.getDataStore()->nextSolutionPtr));
2172 
2173  if (outputAdapter_)
2174  {
2177  mpdeManager_->getFastTimePoints(),
2179 
2180  // If we are actually in the MPDE phase, rather than the initial
2181  // condition, then output here.
2182  if (outputInterpMPDE && mpdeManager_ && mpdeManager_->getTransientNowCanOutputTrueMPDEResults())
2183  {
2184  if (!mpdeManager_->getWaMPDEFlag())
2185  {
2186  const std::vector<double> &fastTimes = mpdeManager_->getFastTimePoints();
2190  fastTimes );
2191  }
2192  else
2193  {
2194  const std::vector<double> &fastTimes = mpdeManager_->getFastTimePoints();
2195  int phiGID = mpdeManager_->getPhiGID();
2199  fastTimes, phiGID );
2200  }
2201  }
2202  // uncomment the following else block to get mpde initial
2203  // condition calculations printed out
2204  else
2205  {
2206  // try normal new dae output
2207  std::vector<double> output_interpolation_times =
2209 
2212  tiaParams_,
2215  doNotInterpolate,
2216  output_interpolation_times,
2217  false) ;
2218  }
2219  }
2220  else
2221  {
2222  std::vector<double> output_interpolation_times =
2224 
2227  tiaParams_,
2230  doNotInterpolate,
2231  output_interpolation_times,
2232  false) ;
2233  }
2234 
2235  firstTranOutput_ = false;
2236 
2238  analysisManager_.setNextOutputTime(next_output_time);
2239  }
2240  else
2241  {
2243 
2247  doNotInterpolate,
2248  output_interpolation_times,
2249  true) ;
2250  }
2251 
2252  // SAVE output:
2254  {
2257  tiaParams_,
2259  analysisManager_.getSaveTime(), doNotInterpolate);
2260  }
2261 }
2262 
2263 //-----------------------------------------------------------------------------
2264 // Function : testOutputTime
2265 // Purpose :
2266 // Special Notes :
2267 // Scope : public
2268 // Creator : Rob Hoekstra, SNL, Parallel ComputationalSciences.
2269 // Creation Date : 07/31/01
2270 //-----------------------------------------------------------------------------
2271 bool
2273  double current_time,
2274  double next_output_time,
2275  double start_time)
2276 {
2277  bool flag = true;
2278 
2279  if (current_time < start_time)
2280  {
2281  flag = false;
2282  }
2283  else if ((current_time < next_output_time)&& (fabs(current_time - next_output_time) >= 2 * Util::MachineDependentParams::MachinePrecision()))
2284  {
2285  flag = false;
2286  }
2287 
2288  return flag;
2289 }
2290 
2291 //-----------------------------------------------------------------------------
2292 // Function : updateOutputTime
2293 // Purpose : Advance output time so it is the next one after currTime
2294 // Special Notes : formerly part of testOutputTime
2295 // Scope : public
2296 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
2297 // Creation Date : 02/14/07
2298 //-----------------------------------------------------------------------------
2299 double
2301  double current_time,
2302  double next_output_time,
2303  double final_output_time,
2304  double initial_output_interval,
2305  const IO::IntervalVector & output_intervals)
2306 {
2307  // We only need to bother with this if the user has specified output control
2308  // options
2309  if (initial_output_interval > 0.0)
2310  {
2311  if (output_intervals.empty())
2312  {
2313  // Only an initial interval was specified
2314  while ((next_output_time < current_time)|| (fabs(current_time - next_output_time) < 2 * Util::MachineDependentParams::MachinePrecision()))
2315  next_output_time = next_output_time + initial_output_interval;
2316  }
2317  else if (current_time < output_intervals[0].first)
2318  {
2319  // Multiple intervals, but we're still in the first one
2320  while (next_output_time <= current_time)
2321  next_output_time = next_output_time + initial_output_interval;
2322  if (next_output_time > output_intervals[0].first)
2323  next_output_time = output_intervals[0].first;
2324  }
2325  else
2326  {
2327  // Multiple intervals specified, we're past the first one
2328  std::pair<double, double> currInterval, nextInterval;
2329  int size = output_intervals.size();
2330  for (int i = 0; i < size; ++i)
2331  if (output_intervals[i].first <= current_time)
2332  {
2333  currInterval = output_intervals[i];
2334  if ((i+1) < static_cast<int>(output_intervals.size()))
2335  nextInterval = output_intervals[i+1];
2336  }
2337  int step = static_cast<int> ((current_time-currInterval.first) /
2338  currInterval.second);
2339  next_output_time = currInterval.first + (step+1)*currInterval.second;
2340  if (nextInterval.first && (nextInterval.first!=currInterval.first) && (next_output_time>=nextInterval.first))
2341  next_output_time = nextInterval.first;
2342  }
2343 
2344  if (next_output_time >= final_output_time)
2345  next_output_time =final_output_time;
2346  }
2347 
2348  return next_output_time;
2349 }
2350 
2351 //-----------------------------------------------------------------------------
2352 // Function : computeOutputInterpolationTimes
2353 // Purpose : When we pass "nextOutputTime_", we might have skipped
2354 // over points where output was requested. Make a list of
2355 // those times so we can interpolate to them.
2356 // Special Notes :
2357 // Scope : public
2358 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling.
2359 // Creation Date : 02/14/07
2360 //-----------------------------------------------------------------------------
2361 std::vector<double>
2363  double current_time,
2364  double next_output_time,
2365  double final_output_time,
2366  double initial_output_interval,
2367  const IO::IntervalVector & output_intervals)
2368 {
2369  std::vector<double> output_interpolation_times;
2370 
2371  // if there are no output control options specified, we do nothing.
2372  if (initial_output_interval > 0.0)
2373  {
2374  if (output_intervals.empty() || current_time <= output_intervals[0].first)
2375  {
2376  // we're either in the first interval, or there only *is* one interval
2377  double t = next_output_time;
2378  while ((t < current_time) && ( current_time -t ) > 2 * Util::MachineDependentParams::MachinePrecision())
2379  {
2380  output_interpolation_times.push_back(t);
2381  t += initial_output_interval; // outputManagerAdapter_.getInitialOutputInterval();
2382  }
2383 
2384  if ((t - current_time) <= 2 * Util::MachineDependentParams::MachinePrecision() )
2385  {
2386  output_interpolation_times.push_back(current_time);
2387  }
2388 
2389  if ((t - final_output_time) > 2 * Util::MachineDependentParams::MachinePrecision())
2390  {
2391  // tack on finalTime or we'll miss it
2392  output_interpolation_times.push_back(final_output_time);
2393  }
2394  }
2395  else // we're out of the first interval, and there is more than one
2396  {
2397  int outInt,lastInt;
2398 
2399  lastInt=output_intervals.size()-1;
2400 
2401  // find which interval nextOutputTime_ is in
2402  for (outInt=0;
2403  outInt<lastInt&&output_intervals[outInt+1].first<=next_output_time;
2404  ++outInt) ;
2405 
2406  double t = next_output_time;
2407  while (t <= current_time)
2408  {
2409  output_interpolation_times.push_back(t);
2410  t += output_intervals[outInt].second;
2411  if (outInt != lastInt && t >= output_intervals[outInt+1].first)
2412  {
2413  ++outInt;
2414  t = output_intervals[outInt].first;
2415  }
2416  }
2417  }
2418  }
2419 
2420  return output_interpolation_times;
2421 }
2422 
2423 namespace {
2424 
2425 //-----------------------------------------------------------------------------
2426 // Class : TransientFactory
2427 // Purpose :
2428 // Special Notes :
2429 // Scope : public
2430 // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2431 // Creation Date : Thu Jan 29 12:53:02 2015
2432 //-----------------------------------------------------------------------------
2433 ///
2434 /// Factory for parsing Transient parameters from the netlist and creating Transient analysis.
2435 ///
2436 class TransientFactory: public Factory<Transient>
2437 {
2438 public:
2439  //-----------------------------------------------------------------------------
2440  // Function : TransientFactory
2441  // Purpose :
2442  // Special Notes :
2443  // Scope : public
2444  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2445  // Creation Date : Thu Jan 29 12:54:09 2015
2446  //-----------------------------------------------------------------------------
2447  ///
2448  /// Constructs the Transient analysis factory
2449  ///
2450  /// @invariant Stores the results of parsing, so if more than one of the analysis and
2451  /// associated lines are parsed, the second options simply overwrite the previously parsed
2452  /// values.
2453  ///
2454  /// @invariant The existence of the parameters specified in the constructor cannot
2455  /// change.
2456  ///
2457  /// @param analysis_manager
2458  /// @param linear_system
2459  /// @param nonlinear_manager
2460  /// @param topology
2461  ///
2462  TransientFactory(
2463  Analysis::AnalysisManager & analysis_manager,
2464  Linear::System & linear_system,
2465  Nonlinear::Manager & nonlinear_manager,
2466  Topo::Topology & topology)
2467  : Factory<Transient>(),
2468  analysisManager_(analysis_manager),
2469  linearSystem_(linear_system),
2470  nonlinearManager_(nonlinear_manager),
2471  topology_(topology)
2472  {}
2473 
2474  virtual ~TransientFactory()
2475  {}
2476 
2477  //-----------------------------------------------------------------------------
2478  // Function : create
2479  // Purpose :
2480  // Special Notes :
2481  // Scope : public
2482  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2483  // Creation Date : Thu Jan 29 12:59:00 2015
2484  //-----------------------------------------------------------------------------
2485  ///
2486  /// Create a new Transient analysis and applies the analysis and time integrator option blocks.
2487  ///
2488  /// @return new Transient analysis object
2489  ///
2490  Transient *create() const
2491  {
2492  analysisManager_.setAnalysisMode(ANP_MODE_TRANSIENT);
2493  Transient *transient = new Transient(analysisManager_, linearSystem_, nonlinearManager_, topology_);
2494  transient->setAnalysisParams(transientAnalysisOptionBlock_);
2495  transient->setTimeIntegratorOptions(timeIntegratorOptionBlock_);
2496 
2497  return transient;
2498  }
2499 
2500  //-----------------------------------------------------------------------------
2501  // Function : setTransientAnalysisOptionBlock
2502  // Purpose :
2503  // Special Notes :
2504  // Scope : public
2505  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2506  // Creation Date : Thu Jan 29 13:00:14 2015
2507  //-----------------------------------------------------------------------------
2508  ///
2509  /// Saves the analysis parsed options block in the factory.
2510  ///
2511  /// @invariant Overwrites any previously specified analysis option block.
2512  ///
2513  /// @param option_block parsed option block
2514  ///
2515  void setTransientAnalysisOptionBlock(const Util::OptionBlock &option_block)
2516  {
2517  transientAnalysisOptionBlock_ = option_block;
2518  }
2519 
2520  //-----------------------------------------------------------------------------
2521  // Function : setTimeIntegratorOptionBlock
2522  // Purpose :
2523  // Special Notes :
2524  // Scope : public
2525  // Creator : David G. Baur Raytheon Sandia National Laboratories 1355
2526  // Creation Date : Thu Jan 29 13:01:27 2015
2527  //-----------------------------------------------------------------------------
2528  ///
2529  /// Saves the time integrator parsed option block.
2530  ///
2531  /// @invariant Overwrites any previously specified time integrator option block.
2532  ///
2533  /// @param option_block parsed option block
2534  ///
2535  void setTimeIntegratorOptionBlock(const Util::OptionBlock &option_block)
2536  {
2537  timeIntegratorOptionBlock_ = option_block;
2538  }
2539 
2540 public:
2541  AnalysisManager & analysisManager_;
2542  Linear::System & linearSystem_;
2543  Nonlinear::Manager & nonlinearManager_;
2544  Topo::Topology & topology_;
2545 
2546 private:
2548  Util::OptionBlock timeIntegratorOptionBlock_;
2549 };
2550 
2551 // .options TIMEINT
2552 struct TimeIntegratorOptionsReg : public IO::PkgOptionsReg
2553 {
2554  TimeIntegratorOptionsReg(
2555  TransientFactory & factory )
2556  : factory_(factory)
2557  {}
2558 
2559  bool operator()(const Util::OptionBlock &option_block)
2560  {
2561  factory_.setTimeIntegratorOptionBlock(option_block);
2562 
2563  return true;
2564  }
2565 
2566  TransientFactory & factory_;
2567 };
2568 
2569 // .TRAN
2570 struct TransientAnalysisReg : public IO::PkgOptionsReg
2571 {
2572  TransientAnalysisReg(
2573  TransientFactory & factory)
2574  : factory_(factory)
2575  {}
2576 
2577  bool operator()(const Util::OptionBlock &option_block)
2578  {
2579  factory_.setTransientAnalysisOptionBlock(option_block);
2580 
2581  factory_.analysisManager_.addAnalysis(&factory_);
2582 
2583  return true;
2584  }
2585 
2586  TransientFactory & factory_;
2587 };
2588 
2589 } // namespace <unnamed>
2590 
2591 
2592 bool
2594  const std::string & netlist_filename,
2595  IO::PkgOptionsMgr & options_manager,
2596  AnalysisManager & analysis_manager,
2597  Linear::System & linear_system,
2598  Nonlinear::Manager & nonlinear_manager,
2599  Topo::Topology & topology)
2600 {
2601  TransientFactory *factory = new TransientFactory(analysis_manager, linear_system, nonlinear_manager, topology);
2602 
2603  analysis_manager.addAnalysisFactory(factory);
2604 
2605  options_manager.submitRegistration("TRAN", netlist_filename, new TransientAnalysisReg(*factory));
2606  options_manager.submitRegistration("TIMEINT", netlist_filename, new TimeIntegratorOptionsReg(*factory));
2607 
2608  return true;
2609 }
2610 
2611 } // namespace Analysis
2612 } // 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
Transient(AnalysisManager &analysis_manager, Linear::System &linear_system, Nonlinear::Manager &nonlinear_manager, Topo::Topology &topology, OutputAdapter *output_adapter=0, HB *hb_analysis=0, N_MPDE_Manager *mpde_manager=0)
Util::FixedQueue< double > timeQueue_
virtual int getMaxNormFindex() const =0
TimeIntg::TIAParams tiaParams_
Topo::Topology & topology_
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:231
double initialTimeStep
User specified initial time step.
static const int type
Definition: N_TIA_OneStep.h:74
std::vector< bool > timeStepsBreakpointFlag
void setNextOutputTime(double next_output_time)
bool setTimeIntegratorOption(const Util::Param &param)
bool calcSensitivity(std::vector< double > &objectiveVec, std::vector< double > &dOdpVec, std::vector< double > &dOdpAdjVec, std::vector< double > &scaled_dOdpVec, std::vector< double > &scaled_dOdpAdjVec)
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.
std::vector< double > objectiveVec_
int doubleDCOPStep_
current step in the DCOP loop.
Topo::Topology & topology_
virtual void stepFailure(Analysis::TwoLevelMode analysis)
Definition: N_LOA_Loader.h:286
Util::OptionBlock timeIntegratorOptionBlock_
bool registerTransientFactory(const std::string &netlist_filename, IO::PkgOptionsMgr &options_manager, AnalysisManager &analysis_manager, Linear::System &linear_system, Nonlinear::Manager &nonlinear_manager, Topo::Topology &topology)
Util::FixedQueue< int > nonlinearSolverStatusQueue_
std::vector< double > dOdpAdjVec_
unsigned int stepNumber
Time-integration step number counter.
virtual int getNumIterations() const =0
void outputSolDataArrays(std::ostream &os)
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.
bool updateMaxTimeStep(Parallel::Machine comm, const TIAParams &tia_params, double suggestedMaxTimeStep=0.0)
void createTimeIntegratorMethod(const TimeIntg::TIAParams &tia_params, const unsigned int integration_method)
bool setupInitialConditions(Linear::Vector &solnVec, Linear::Vector &flagVec)
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
void dumpRestart(Parallel::Communicator &parallel_communicator, Analysis::AnalysisManager &analysis_manager, double current_time) const
bool saveOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const TIAParams &tia_params, Linear::Vector *solnVecPtr, const double saveTime, const bool doNotInterpolate)
bool setDCOPOption(const Util::Param &param)
TimeIntg::StepErrorControl & getStepErrorControl()
bool constantTimeStepFlag
Constant time step integration flag.
std::vector< Linear::Vector * > fastTimeSolutionVec
NonLinearSolver & getNonlinearSolver()
bool testDCOPOutputTime()
Returns true if the DCOP Restart parameters have been set.
std::vector< TwoLevelError > innerErrorInfoVec
int minTimeStepsBP
User specified mininum number of steps between breakpoints.
Linear::Vector * daeQVectorPtr
std::vector< double > dOdpVec_
virtual void outputMPDE(double time, const std::vector< double > &fast_time_points, const Linear::Vector *solution_vector)
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)
bool printMPDEOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const double time, Linear::Vector *solnVecPtr, const std::vector< double > &fastTimes)
void resetAll(AnalysisMode mode)
virtual bool startTimeStep()
Definition: N_LOA_Loader.h:304
void setErrorWtVector(const TIAParams &tia_params)
const ReturnCodes & getReturnCodes() const
bool saveTimeStepsFlag
flag to save timestpes in data store for later use
Linear::Vector * daeFVectorPtr
bool mixedSignalStep(double maxTimeStepFromHabanero)
Util::OptionBlock transientAnalysisOptionBlock_
bool bpEnable
Enable breakpoints flag.
Nonlinear::Manager & nonlinearManager_
Nonlinear::AnalysisMode nonlinearAnalysisMode(Mode mode)
Returns the nonlinear analysis mode given the analysis mode.
virtual void acceptStep()
Definition: N_LOA_Loader.h:291
OutputAdapter * outputAdapter_
void simulationPaused(double initial_time)
void setTwoLevelMode(TwoLevelMode current_mode)
Util::FixedQueue< double > nonlinearSolverMaxNormQueue_
void printProgress(std::ostream &os)
virtual bool updateSources()
Definition: N_LOA_Loader.h:243
Linear::Vector * nextStatePtr
std::vector< Linear::Vector * > fastTimeStoreVec
void tranOutput(double time, Linear::Vector &currSolutionPtr, Linear::Vector &stateVecPtr, Linear::Vector &storeVecPtr, Linear::Vector &lead_current_vector, Linear::Vector &junction_voltage_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)
void preMixedSignalStepDetails(double maxTimeStepFromHabanero)
AnalysisManager & analysisManager_
virtual bool printLoopInfo(int start, int finish)
Linear::Vector * dFdxdVpVectorPtr
Loader::NonlinearEquationLoader & getNonlinearEquationLoader()
Linear::Vector * currLeadDeltaVPtr
TransientFactory & factory_
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)
void addAnalysisFactory(Factory< void > *factory)
void outputPredictedDerivative(std::ostream &os)
unsigned int initialIntegrationMethod_
TimeIntegrationMethod *(* Factory)(const TIAParams &tia_params, StepErrorControl &step_error_control, DataStore &data_store)
Linear::Vector * nextSolutionPtr
unsigned int integrationMethod
Time-integration method.
virtual bool getDoubleDCOPFlag() const
Definition: N_LOA_Loader.h:255
Linear::Vector * nextStorePtr
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_
bool updateBreakPoints(double initial_time)
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)
Linear::Vector * currSolutionPtr
TimeIntg::DataStore * getDataStore()
void evaluateStepError(const TIAParams &tia_params)
bool doubleDCOPFlag_
true if doing a double-DCOP is possible.
unsigned int baseIntegrationMethod_
Current time-integration method flag.
bool printWaMPDEOutputSolution(Analysis::OutputMgrAdapter &outputManagerAdapter, const double time, Linear::Vector *solnVecPtr, const std::vector< double > &fastTimes, const int phiGID)
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
std::vector< double > scaled_dOdpVec_
Linear::Vector * nextStateDerivPtr
virtual void stepSuccess(Analysis::TwoLevelMode analysis)
Definition: N_LOA_Loader.h:283
Util::FixedQueue< int > stepStatusQueue_
bool condTestFlag
flag for conductance test
virtual bool finishOutput() const
Definition: N_LOA_Loader.h:265
void outputDCOP(const Linear::Vector &solution)
double exitTime
Exit when it exceeds this time.
bool outputInterpMPDE
flag for interpolating the MPDE output. Sometimes, the interpolation is the hard part.
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
Nonlinear::Manager & nonlinearManager_
virtual bool getInitialQnorm(std::vector< TimeIntg::TwoLevelError > &tleVec)
Definition: N_LOA_Loader.h:294
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 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)
bool passNLStall
option to pass some non-linear solver failures
Linear::Vector * flagSolutionPtr
Util::FixedQueue< double > estErrorOverTolQueue_
Linear::Vector * daeBVectorPtr
bool setReturnCodeOption(const Util::Param &param)
virtual double getMaxNormF() const =0
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)
virtual bool output() const
Definition: N_LOA_Loader.h:260