Xyce  6.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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-2014 Sandia Corporation
10 //
11 // This program is free software: you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation, either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see <http://www.gnu.org/licenses/>.
23 //-----------------------------------------------------------------------------
24 
25 //-----------------------------------------------------------------------------
26 // Filename : $RCSfile: N_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.112.2.1 $
35 // Revision Date : $Date: 2014/03/04 23:50:53 $
36 // Current Owner : $Author: tvrusso $
37 //-----------------------------------------------------------------------------
38 
39 #include <Xyce_config.h>
40 
41 
42 // ---------- Standard Includes ----------
43 #include <sstream>
44 #include <iomanip>
45 
46 
47 // ---------- Xyce Includes ----------
48 #include <N_ANP_AnalysisManager.h>
49 #include <N_TIA_Assembler.h>
50 #include <N_TIA_DataStore.h>
51 #include <N_LOA_Loader.h>
52 #include <N_LAS_System.h>
53 #include <N_MPDE_Manager.h>
54 #include <N_IO_OutputMgr.h>
55 #include <N_IO_RestartMgr.h>
56 #include <N_TIA_StepErrorControl.h>
57 #include <N_UTL_Timer.h>
58 #include <N_UTL_NoCase.h>
59 #include <N_ERH_Progress.h>
60 
61 #include <N_IO_CmdParse.h>
62 
63 #include<N_ANP_Transient.h>
64 
65 #include<N_UTL_ExpressionData.h>
66 #include<N_NLS_ReturnCodes.h>
67 
68 namespace Xyce {
69 namespace Analysis {
70 
71 //-----------------------------------------------------------------------------
72 // Function : Transient::Transient( AnalysisManager * )
73 // Purpose : constructor
74 // Special Notes :
75 // Scope : public
76 // Creator : Rich Schiek, SNL
77 // Creation Date : 3/11/06
78 //-----------------------------------------------------------------------------
80  AnalysisBase(anaManagerPtr),
81  initialIntegrationMethod_(TIAMethod_ONESTEP),
82  firstTranOutput_(true),
83  isPaused(false),
84  dcopFlag_(true),
85  startDCOPtime(0.0),
86  endTRANtime(0.0),
87  gui_(false),
88  historyTrackingOn_(true),
89  maxTimeStepExpressionGiven_(false),
90  maxTimeStepExpressionAsString_(""),
91  firstTime(true),
92  oldPercentComplete(0.0),
93  startSimTime(-1.0),
94  dcStats(0),
95  tranStats(0)
96 {
97  gui_ = commandLine_.argExists("-gui");
98  restartMgrRCPtr_ = anaManagerPtr->restartPtr;
99 
100  // initialize this to an empty vector
102 }
103 
104 //-----------------------------------------------------------------------------
105 // Function : Transient::setAnalysisParams
106 // Purpose :
107 // Special Notes : These are from the .TRAN statement.
108 // Scope : public
109 // Creator : Eric Keiter, SNL
110 // Creation Date : 6/21/10
111 //-----------------------------------------------------------------------------
112 bool Transient::setAnalysisParams(const N_UTL_OptionBlock & paramsBlock)
113 {
114  std::list<N_UTL_Param>::const_iterator it_tp;
115  std::list<N_UTL_Param>::const_iterator first = paramsBlock.getParams().begin();
116  std::list<N_UTL_Param>::const_iterator last = paramsBlock.getParams().end();
117  for (it_tp = first; it_tp != last; ++it_tp)
118  {
119  if (it_tp->uTag() == "TSTART")
120  {
121  tiaParams.tStart = it_tp->getImmutableValue<double>();
122  tiaParams.tStartGiven = true;
123  }
124  else if (it_tp->uTag() == "TSTOP")
125  {
126  tiaParams.finalTime = it_tp->getImmutableValue<double>();
127  }
128  else if (it_tp->uTag() == "TSTEP")
129  {
130  tiaParams.userSpecified_startingTimeStep = it_tp->getImmutableValue<double>();
131  }
132  else if (it_tp->uTag() == "NOOP" ||
133  it_tp->uTag() == "UIC")
134  {
135  tiaParams.NOOP = 1;
136  }
137  else if (it_tp->uTag() == "DTMAX")
138  {
139  tiaParams.maxTimeStep = it_tp->getImmutableValue<double>();
141 #ifdef Xyce_DEBUG_ANALYSIS
142  if (tiaParams.debugLevel > 0)
143  {
144  dout() << "setting maxTimeStep = " << tiaParams.maxTimeStep << std::endl;
145  }
146 #endif
147  }
148  else if (it_tp->uTag() == "MAXTIMEEXPRESSION")
149  {
150  // an expression was given which should specify what
151  // max time step to use based on the current simulation
152  // time. The expected format of this is
153  // {schedule( t0, max_del_t0, t1, max_del_t1, ...)}
154  // we'll just store the expression as a string for now
155  // as we need to make sure other classes are up and running
156  // before we can create the actual expression. That will
157  // happen in Transient class as it will ultimately use this
159  maxTimeStepExpressionAsString_ = it_tp->stringValue();
160  }
161  }
162 
164  {
165  std::ostringstream ost;
166  ost << " In N_TIA_StepErrorControl::setTranAnalysisParams: " << std::endl;
167  ost << "Final time of " << tiaParams.finalTime
168  << " is earlier or same as start time of "
169  << tiaParams.tStart << std::endl;
170  ost << " Check netlist for invalid .TRAN specification " << std::endl;
171  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_FATAL_0, ost.str());
172  }
173 
174  // if starting time steps is baloney, set then to a default value.
175  // ERK. This trap is redudant with an identical one in step error
176  // control.
178  {
180  }
181 
182 #ifdef Xyce_DEBUG_ANALYSIS
183  if (tiaParams.debugLevel > 0)
184  {
185  dout() << std::endl
186  << section_divider << std::endl
187  << " Transient simulation parameters" << std::endl
188  << " initial time = " << tiaParams.initialTime << std::endl
189  << " final time = " << tiaParams.finalTime << std::endl
190  << " starting time step = " << tiaParams.userSpecified_startingTimeStep << std::endl
191  << " tStart (time of first output) = " << tiaParams.tStart << std::endl;
192 
193  if (!(tiaParams.NOOP))
194  {
195  dout() << " NOOP/UIC is NOT set" << std::endl;
196  }
197  else
198  {
199  dout() << " NOOP/UIC is set" << std::endl;
200  }
201 
202  dout() << section_divider << std::endl;
203  }
204 #endif
205 
207  {
208  // set-up expression object for getting a user specified, time dependent
209  // max time step value
211  maxTimeStepExpressionRCPtr_ = rcp( new N_UTL_ExpressionData( maxTimeStepExpressionAsString_, *outputMgrAdapterRCPtr_->getOutputMgrPtr() ) );
212  }
213 
214  // queueSize_ should can be set from the .options timeint line. Use default in tiaParams
215  // as that will be overwritten if the user set it via .options. Also, if it's less than
216  // or equal to zero assume that the user wants this turned off.
217  // We'll store the attempted time step, time step status,
218  // estimated error over tolerance, non-linear solver status and non-linear solver norm
219  // for each step, up to the last queueSize_ steps.
220 
222  {
223  historyTrackingOn_ = true;
225  timeQueue_.set_size( queueSize_ );
226  timeStepQueue_.set_size( queueSize_ );
227  stepStatusQueue_.set_size( queueSize_ );
228  estErrorOverTolQueue_.set_size( queueSize_ );
233  }
234  else
235  {
236  historyTrackingOn_ = false;
237  }
238 
239  return true;
240 }
241 
242 //-----------------------------------------------------------------------------
243 // Function : Transient::run()
244 // Purpose :
245 // Special Notes :
246 // Scope : public
247 // Creator : Rich Schiek, SNL
248 // Creation Date : 3/11/06
249 //-----------------------------------------------------------------------------
251 {
252  bool bsuccess = true;
253  isPaused = false;
254 
255  if (anaManagerRCPtr_->getHBFlag() && !anaManagerRCPtr_->getMPDEStartupFlag())
256  resetForHB();
257 
258  bsuccess = bsuccess & init();
259  bsuccess = bsuccess & loopProcess();
260 
261  // if processing the loop failed,
262  // then skip finish step
263  if( bsuccess )
264  {
265  bsuccess = bsuccess & finish();
266  }
267 
268  return bsuccess;
269 }
270 
271 //-----------------------------------------------------------------------------
272 // Function : Transient::init()
273 // Purpose :
274 // Special Notes :
275 // Scope : public
276 // Creator : Rich Schiek, SNL
277 // Creation Date : 3/11/06
278 //-----------------------------------------------------------------------------
280 {
281  bool bsuccess = true;
282 
285  {
287  }
288 
289  if (!tiaParams.resume)
290  {
292  if(dcopFlag_)
293  {
294  anaManagerRCPtr_->currentMode_ = 0;
295  }
296  else
297  {
298  anaManagerRCPtr_->currentMode_ = 1;
299  }
300 
301  doubleDCOPFlag_ = loaderRCPtr_->getDoubleDCOPFlag();
303 
304  if (restartMgrRCPtr_->isRestart())
305  {
306  loaderRCPtr_->getInitialQnorm(anaManagerRCPtr_->getTIADataStore()->innerErrorInfoVec);
307 
308 // secRCPtr_->initialTime = secRCPtr_->currentTime;
309  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
310  wimRCPtr_->initialize();
311 
312  dcopFlag_ = false;
313  anaManagerRCPtr_->currentMode_ = 1;
314 
315 #ifdef Xyce_PARALLEL_MPI
316  // Update vectors with off proc values.
317  lasSystemRCPtr_->updateExternValsSolnVector(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr);
318  lasSystemRCPtr_->updateExternValsSolnVector(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr);
319  lasSystemRCPtr_->updateExternValsStateVector(anaManagerRCPtr_->getTIADataStore()->nextStatePtr);
320  lasSystemRCPtr_->updateExternValsStateVector(anaManagerRCPtr_->getTIADataStore()->currStatePtr);
321  lasSystemRCPtr_->updateExternValsStoreVector(anaManagerRCPtr_->getTIADataStore()->nextStorePtr);
322  lasSystemRCPtr_->updateExternValsStoreVector(anaManagerRCPtr_->getTIADataStore()->currStorePtr);
323 #endif
324 
325  // Set the nonlinear solver parameters to those appropriate for the
326  // transient solution. If starting from here, we're not doing a DCOP
327  // calculation first - we're jumping right into the transient.
329  }
330  else
331  {
332  if (dcopFlag_)
333  {
334  // Get set to do the operating point.
336  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
337  }
338  else // otherwise NOOP/UIC
339  {
341  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
342  }
343 
344  // This setInitialGuess call is to up an initial guess in the
345  // devices that have them (usually PDE devices). This is DIFFERENT
346  // than an initial condition.
347  loaderRCPtr_->setInitialGuess (anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr);
348 
349  if (anaManagerRCPtr_->getBlockAnalysisFlag())
350  {
351  beginningIntegration = true;
352  }
353 
354  // 12/13/07 tscoffe/tmei: .ic should not be applied to MPDE currently.
355  // A new mechanism must be set up for this, e.g. .mpde_ic
356  if (!anaManagerRCPtr_->getMPDEFlag() && !anaManagerRCPtr_->getMPDEStartupFlag())
357  {
358  // If available, set initial solution. This may be from a DCOP restart,
359  // a .IC, or a .NODESET line. These can be used in both the UIC/NOOP
360  // case, as well as the DCOP case, so they need to be outside the if-statement.
361  inputOPFlag_ = outputMgrAdapterRCPtr_->setupInitialConditions
362  ( *(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr),*(anaManagerRCPtr_->getTIADataStore()->flagSolutionPtr));
363  }
364 
365  if (!dcopFlag_ && !anaManagerRCPtr_->getMPDEFlag())
366  {
367  // this "initializeProblem" call is to set the IC's in devices that
368  // have them. This is done IN PLACE of the operating point.
369  loaderRCPtr_->initializeProblem
370  ((anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr),
371  (anaManagerRCPtr_->getTIADataStore()->currSolutionPtr),
372  (anaManagerRCPtr_->getTIADataStore()->lastSolutionPtr),
373  (anaManagerRCPtr_->getTIADataStore()->nextStatePtr),
374  (anaManagerRCPtr_->getTIADataStore()->currStatePtr),
375  (anaManagerRCPtr_->getTIADataStore()->lastStatePtr),
376  (anaManagerRCPtr_->getTIADataStore()->nextStateDerivPtr),
377  (anaManagerRCPtr_->getTIADataStore()->nextStorePtr),
378  (anaManagerRCPtr_->getTIADataStore()->currStorePtr),
379  (anaManagerRCPtr_->getTIADataStore()->lastStorePtr),
380  (anaManagerRCPtr_->getTIADataStore()->daeQVectorPtr),
381  (anaManagerRCPtr_->getTIADataStore()->daeFVectorPtr),
382  (anaManagerRCPtr_->getTIADataStore()->dFdxdVpVectorPtr),
383  (anaManagerRCPtr_->getTIADataStore()->dQdxdVpVectorPtr) );
384 
385  // Do this to populate the q-vector:
386  // since we're also skipping the DC OP, this call will
387  // also force the loader to propagate the state vector to the
388  // device manager which updates state vector seen by the devices.
389  assemblerRCPtr_->loadRHS();
390  }
391 
392  // Set a constant history.
393  anaManagerRCPtr_->getTIADataStore()->setConstantHistory();
394  anaManagerRCPtr_->getTIADataStore()->computeDividedDifferences();
395  wimRCPtr_->obtainCorrectorDeriv();
396 
397 #ifdef Xyce_PARALLEL_MPI
398  // Update vectors with off proc values.
399  lasSystemRCPtr_->updateExternValsSolnVector(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr);
400  lasSystemRCPtr_->updateExternValsSolnVector(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr);
401  lasSystemRCPtr_->updateExternValsStateVector(anaManagerRCPtr_->getTIADataStore()->nextStatePtr);
402  lasSystemRCPtr_->updateExternValsStateVector(anaManagerRCPtr_->getTIADataStore()->currStatePtr);
403  lasSystemRCPtr_->updateExternValsStoreVector(anaManagerRCPtr_->getTIADataStore()->nextStorePtr);
404  lasSystemRCPtr_->updateExternValsStoreVector(anaManagerRCPtr_->getTIADataStore()->currStorePtr);
405 #endif
406 
407  if (!dcopFlag_ && !tiaParams.resume)
408  {
409  // Now do a NOOP output. ERK: 08/30/2007 This isn't the best place to
410  // put this, but it will have to do for now. If this isn't here, then
411  // NOOP/UIC simulations don't output at t=0.0 in the *prn file.
412  noopOutputs ();
413  }
414 
415  stepNumber = 0;
416  tranStepNumber = 0;
417  anaManagerRCPtr_->breakPointRestartStep = 0;
418  }
419  }
420  else
421  {
422  if(anaManagerRCPtr_->currentMode_ == 1)
423  {
424  // we're resuming from a previous transient simulation
425  // this is an ugly side effect of the analysis manager's deleting
426  // the transient object after it retured in a paused state
427  // need to fix this in Xyce 6.0 . RLS 12/22/2009
428  dcopFlag_=false;
429 
430  // we default firstTranOutput_ to true to force the first time point to be output
431  // however, if we're resuming, then we need this to be false
432  // this is really a defect of a paused simulation's Transient object
433  // being deleted by the AnalysisManager and then a new one being created
434  // when the simulation is resumed. Need to fully fix this. RLS 12/22/2009
435  firstTranOutput_ = false;
436  }
437 
438  // in a 2 level problem, we can be asked to resume
439  // without first making the integration method. So
440  // catch that.
441  if (wimRCPtr_->getIntegMethodPtr() == NULL)
442  {
444  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
445  }
446 
447 #ifdef Xyce_DEBUG_ANALYSIS
448  if (tiaParams.debugLevel > 0)
449  dout() << " transient loop called with resume true " << std::endl;
450 #endif
451  }
452 
453  anaManagerRCPtr_->switchIntegrator_ = false;
454 
455  if (!tiaParams.resume)
456  {
457  // if we're resuming, this was already done prior to pausing, and doing
458  // it again screws us up
459  double suggestedMaxTime=0.0;
461  {
462  suggestedMaxTime = maxTimeStepExpressionRCPtr_->evaluate(
463  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr, anaManagerRCPtr_->getTIADataStore()->currStatePtr, anaManagerRCPtr_->getTIADataStore()->currStorePtr);
464  }
465  secRCPtr_->updateMaxTimeStep( suggestedMaxTime );
466  secRCPtr_->updateMinTimeStep();
467  secRCPtr_->updateBreakPoints();
468  }
469 
470  // reset min error tracking variables
471  // if the step number is less than zero we'll assume there is no valid
472  // min. estimated error over tol or an associated time step. This frees us
473  // from putting Machine::Big here and trying to do something with that.
475  minEstErrorOverTol = 0.0;
477 
478  return bsuccess;
479 }
480 
481 //-----------------------------------------------------------------------------
482 // Function : Transient::loopProcess()
483 // Purpose : Conduct the time stepping loop.
484 // Special Notes :
485 // Scope : public
486 // Creator : Rich Schiek, SNL
487 // Creation Date : 3/11/06
488 //-----------------------------------------------------------------------------
490 {
491  bool bsuccess = true;
492 
493  // Transient time stepping loop:
494  while (!(secRCPtr_->finished()))
495  {
496 #ifdef Xyce_VERBOSE_TIME
497  printStepHeader(Xyce::lout());
498 #endif
499  printProgress(Xyce::lout());
500 
501  // ------------------------------------------------------------------------
502  // If the flag is set to switch integration methods, do that here.
503  // For example, switch from operating point to transient backward euler.
504 
505  if (anaManagerRCPtr_->switchIntegrator_)
506  {
507  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
508  }
509 
510  // ------------------------------------------------------------------------
511  // Set the step size, current time and next time.
512 
513  secRCPtr_->updateStopTime();
514 
515 #ifdef Xyce_DEBUG_ANALYSIS
516  if (tiaParams.debugLevel > 0)
517  {
518  dout() << std::endl;
519  dout() << "Transient::loopProcess()" << std::endl;
520  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
521  dout() << "secRCPtr_->stepAttemptStatus = " << secRCPtr_->stepAttemptStatus << std::endl;
522  }
523 #endif
524 
525  if (beginningIntegration &&
526  secRCPtr_->stepAttemptStatus)
527  {
528  // ------------------------------------------------------------------------
529  // 07/29/04 TSC: initial step-size selection is now done in the
530  // integration method initialize call under the DAE formulation. This
531  // segregates codes changes better and makes sense to do as an
532  // initialization step even if its changed later.
533  loaderRCPtr_->getInitialQnorm(anaManagerRCPtr_->getTIADataStore()->innerErrorInfoVec);
534  double suggestedMaxTime=0.0;
536  {
537  suggestedMaxTime = maxTimeStepExpressionRCPtr_->evaluate(
538  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr, anaManagerRCPtr_->getTIADataStore()->currStatePtr, anaManagerRCPtr_->getTIADataStore()->currStorePtr);
539  }
540  secRCPtr_->updateMaxTimeStep( suggestedMaxTime );
541  wimRCPtr_->initialize();
542  }
543 
544  // ------------------------------------------------------------------------
545  // If we've switched the integration method, we need to obtain the
546  // corrector derivative only after we've updated the TimeInfo.
547  if (anaManagerRCPtr_->switchIntegrator_)
548  {
549  anaManagerRCPtr_->switchIntegrator_ = false;
550  wimRCPtr_->obtainCorrectorDeriv();
551  }
552 
553 #ifdef Xyce_VERBOSE_TIME
554  if (!dcopFlag_)
555  secRCPtr_->outputTimeInfo(lout());
556 #endif
557 
558  // ------------------------------------------------------------------------
559  // Set the nonlinear solver parameters to those appropriate for the
560  // transient solution, if neccessary.
561  if (!dcopFlag_)
562  {
564  }
565 
566  // Ask the method to update its coefficients
567  wimRCPtr_->updateCoeffs();
568 
569  // ------------------------------------------------------------------------
570  // Perform the time step:
572 
573  // ------------------------------------------------------------------------
574 
575  if (dcopFlag_ && secRCPtr_->stepAttemptStatus)
576  {
578  }
579  else if (dcopFlag_ && !secRCPtr_->stepAttemptStatus)
580  {
582  bsuccess = false;
583  break;
584  }
585 
586  // Transient
587  else
588  {
589  if (secRCPtr_->stepAttemptStatus)
590  {
592  }
593  else if( (tiaParams.passNLStall == true) &&
594  !(secRCPtr_->stepAttemptStatus) &&
595  (secRCPtr_->currentTimeStep < (4*secRCPtr_->minTimeStep)) )
596  {
597  // potentially a VERY dangerous options.
598  // if the non-linear solver is stalling, and we're very close to a min
599  // time step, then calls this failure a pass
600  if( secRCPtr_->newtonConvergenceStatus == -3)
601  {
602  std::string msg = "Transient::loopProcess() Nonlinear solver stalled. Calling this a pass";
603  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
605  }
606  // another VERY dangerous options.
607  // if the non-linear solver is reporting too big of an update, and we're very close to a min
608  // time step, then calls this failure a pass
609  if( secRCPtr_->newtonConvergenceStatus == -2)
610  {
611  std::string msg = "Transient::loopProcess() Update too big. Calling this a pass";
612  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
614  }
615  // another VERY dangerous options.
616  // if the non-linear solver is not converging in the max number of steps,
617  // and we're very close to a min time step, then calls this failure a pass
618  //
619  // if( secRCPtr_->newtonConvergenceStatus == -1)
620  // {
621  // std::string msg = "Transient::loopProcess() Too many steps. Calling this a pass";
622  // N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
623  // processSuccessfulStep();
624  // }
625  else
626  {
627  // process this failed step as we would have by default.
628  bool b1 = processFailedStep();
629  if (!b1)
630  {
631  bsuccess = false;
632  break;
633  }
634  }
635  }
636  else // stepAttemptStatus (ie do this if the step FAILED)
637  {
638  bool b1 = processFailedStep();
639  if (!b1)
640  {
641  bsuccess = false;
642  break;
643  }
644  } // stepAttemptStatus
645 
646  } // transient
647 
648 #ifdef Xyce_DEBUG_ANALYSIS
649  if (tiaParams.debugLevel > 0)
650  {
651  dout() << std::endl;
652  dout() << " Here we are, just before checking whether to pause. " << std::endl;
653  dout() << " minTimeStep = " << secRCPtr_->minTimeStep << std::endl;
654  dout() << " final time = " << tiaParams.finalTime << std::endl;
655  dout() << " pause time = " << anaManagerRCPtr_->getPauseTime() << std::endl;
656  dout() << " initial time = " << secRCPtr_->initialTime << std::endl;
657  dout() << " current time = " << secRCPtr_->currentTime << std::endl;
658  if (anaManagerRCPtr_->getPauseTime() == secRCPtr_->currentTime)
659  {
660  dout() << " Pause time and current time equal " << std::endl;
661  }
662  else
663  {
664  dout() << " difference between current and pause times is "
665  << anaManagerRCPtr_->getPauseTime() - secRCPtr_->currentTime << std::endl;
666  }
667  if (anaManagerRCPtr_->getPauseTime() == secRCPtr_->initialTime)
668  {
669  dout() << " Pause time and initial time equal " << std::endl;
670  }
671  }
672 #endif
673 
674  if (secRCPtr_->isPauseTime())
675  {
676  // Failure at this point only indicates that the simulation
677  // is paused and may be resumed.
678 #ifdef Xyce_DEBUG_ANALYSIS
679  if (tiaParams.debugLevel > 0)
680  {
681  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
682  }
683 #endif
684  secRCPtr_->simulationPaused();
685  isPaused = true;
686  bsuccess = true;
687  break;
688  }
689 
690  // If the exit time has been exceeded, exit.
691  if (tiaParams.exitTime != 0.0 &&
692  secRCPtr_->currentTime > tiaParams.exitTime)
693  {
694  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
695  bsuccess = true;
696  break;
697  }
698 
699  if (tiaParams.exitStep != -1 &&
700  static_cast<int>(stepNumber) == tiaParams.exitStep)
701  {
702  lout() << "Exit step. Exiting transient loop\n" << std::endl;
703  bsuccess = true;
704  break;
705  }
706 
707  } // end of time loop
708  endTRANtime = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime();
710 
711  return bsuccess;
712 }
713 
714 
715 //-----------------------------------------------------------------------------
716 // Function : Transient::mixedSignalStep
717 // Purpose :
718 // Special Notes : Habanero API function
719 // Scope : public
720 // Creator : Eric Keiter, SNL
721 // Creation Date : 3/04/09
722 //-----------------------------------------------------------------------------
724 {
726  return true;
727 }
728 
729 //-----------------------------------------------------------------------------
730 // Function : Transient::preStepDetails
731 // Purpose :
732 // Special Notes : Habanero API function
733 // Scope : private_
734 // Creator : Eric Keiter, SNL
735 // Creation Date : 3/04/09
736 //-----------------------------------------------------------------------------
737 void Transient::preStepDetails (double maxTimeStepFromHabanero)
738 {
739 #ifdef Xyce_VERBOSE_TIME
740  printStepHeader(Xyce::lout());
741 #endif
742  printProgress(Xyce::lout());
743 
744  // ------------------------------------------------------------------------
745  // If the flag is set to switch integration methods, do that here.
746  // For example, switch from operating point to transient backward euler.
747 
748  if (anaManagerRCPtr_->switchIntegrator_)
749  {
750  wimRCPtr_->createTimeIntegMethod(integrationMethod_);
751  }
752 
753  // ------------------------------------------------------------------------
754  // Set the step size, current time and next time.
755  secRCPtr_->updateStopTime();
756 
757  // ------------------------------------------------------------------------
758  // If a max time is set from Habanero, impose it now that stopTime is updated.
759  if (maxTimeStepFromHabanero > 0)
760  {
761  double currentTimeStep = Xycemin(maxTimeStepFromHabanero, secRCPtr_->currentTimeStep);
762  secRCPtr_->setTimeStep(currentTimeStep);
763  }
764 
765 #ifdef Xyce_DEBUG_ANALYSIS
766  if (tiaParams.debugLevel > 0)
767  {
768  dout() << std::endl;
769  dout() << "Transient::loopProcess()" << std::endl;
770  dout() << "beginningIntegration = " << beginningIntegration << std::endl;
771  dout() << "secRCPtr_->stepAttemptStatus = " << secRCPtr_->stepAttemptStatus << std::endl;
772  }
773 #endif
774 
775 
776  if (beginningIntegration &&
777  secRCPtr_->stepAttemptStatus)
778  {
779  // ------------------------------------------------------------------------
780  // 07/29/04 TSC: initial step-size selection is now done in the
781  // integration method initialize call under the DAE formulation. This
782  // segregates codes changes better and makes sense to do as an
783  // initialization step even if its changed later.
784  loaderRCPtr_->getInitialQnorm(anaManagerRCPtr_->getTIADataStore()->innerErrorInfoVec);
785  double suggestedMaxTime=0.0;
787  {
788  suggestedMaxTime = maxTimeStepExpressionRCPtr_->evaluate(
789  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr, anaManagerRCPtr_->getTIADataStore()->currStatePtr, anaManagerRCPtr_->getTIADataStore()->currStorePtr);
790  }
791  secRCPtr_->updateMaxTimeStep( suggestedMaxTime );
792  wimRCPtr_->initialize();
793  }
794 
795  // ------------------------------------------------------------------------
796  // If we've switched the integration method, we need to obtain the
797  // corrector derivative only after we've updated the TimeInfo.
798  if (anaManagerRCPtr_->switchIntegrator_)
799  {
800  anaManagerRCPtr_->switchIntegrator_ = false;
801  wimRCPtr_->obtainCorrectorDeriv();
802  }
803 
804 #ifdef Xyce_VERBOSE_TIME
805  if (!dcopFlag_)
806  {
807  secRCPtr_->outputTimeInfo(lout());
808  }
809 #endif
810 
811  // ------------------------------------------------------------------------
812  // Set the nonlinear solver parameters to those appropriate for the
813  // transient solution, if neccessary.
814  if (!dcopFlag_)
815  {
817  }
818 
819  // Ask the method to update its coefficients
820  wimRCPtr_->updateCoeffs();
821 }
822 
823 //-----------------------------------------------------------------------------
824 // Function : Transient::finalizeStep
825 // Purpose :
826 // Special Notes : Habanero API function
827 // Scope : public
828 // Creator : Eric Keiter, SNL
829 // Creation Date : 3/04/09
830 //-----------------------------------------------------------------------------
832 {
833  bool recoverableFailureFlag = true;
834 
835  if (dcopFlag_ && secRCPtr_->stepAttemptStatus)
836  {
838  }
839  else if (dcopFlag_ && !secRCPtr_->stepAttemptStatus)
840  {
842  recoverableFailureFlag = false;
843  }
844  // Transient
845  else
846  {
847  if (secRCPtr_->stepAttemptStatus)
848  {
850  }
851  else if( (tiaParams.passNLStall == true) &&
852  !(secRCPtr_->stepAttemptStatus) &&
853  (secRCPtr_->currentTimeStep < (4*secRCPtr_->minTimeStep)) )
854  {
855  // potentially a VERY dangerous options.
856  // if the non-linear solver is stalling, and we're very close to a min
857  // time step, then calls this failure a pass
858 
859  if( secRCPtr_->newtonConvergenceStatus == -3)
860  {
861  std::string msg = "Transient::loopProcess() Nonlinear solver stalled. Calling this a pass";
862  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
864  }
865  // another VERY dangerous options.
866  // if the non-linear solver is reporting too big of an update, and we're very close to a min
867  // time step, then calls this failure a pass
868  if( secRCPtr_->newtonConvergenceStatus == -2)
869  {
870  std::string msg = "Transient::loopProcess() Update too big. Calling this a pass";
871  N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
873  }
874  // another VERY dangerous options.
875  // if the non-linear solver is not converging in the max number of steps,
876  // and we're very close to a min time step, then calls this failure a pass
877  //
878  // if( secRCPtr_->newtonConvergenceStatus == -1)
879  // {
880  // std::string msg = "Transient::loopProcess() Too many steps. Calling this a pass";
881  // N_ERH_ErrorMgr::report(N_ERH_ErrorMgr::DEV_WARNING_0, msg);
882  // processSuccessfulStep();
883  // }
884  else
885  {
886  // process this failed step as we would have by default.
887  recoverableFailureFlag = processFailedStep();
888  }
889  }
890  else // stepAttemptStatus (ie do this if the step FAILED)
891  {
892  recoverableFailureFlag = processFailedStep();
893  }
894  } // transient
895 
896 #ifdef Xyce_DEBUG_ANALYSIS
897  if (tiaParams.debugLevel > 0)
898  {
899  dout() << std::endl;
900  dout() << " Here we are, just before checking whether to pause. " << std::endl;
901  dout() << " minTimeStep = " << secRCPtr_->minTimeStep << std::endl;
902  dout() << " final time = " << tiaParams.finalTime << std::endl;
903  dout() << " pause time = " << anaManagerRCPtr_->getPauseTime() << std::endl;
904  dout() << " initial time = " << secRCPtr_->initialTime << std::endl;
905  dout() << " current time = " << secRCPtr_->currentTime << std::endl;
906  if (anaManagerRCPtr_->getPauseTime() == secRCPtr_->currentTime)
907  {
908  dout() << " Pause time and current time equal " << std::endl;
909  }
910  else
911  {
912  dout() << " difference between current and pause times is " << anaManagerRCPtr_->getPauseTime() - secRCPtr_->currentTime << std::endl;
913  }
914  if (anaManagerRCPtr_->getPauseTime() == secRCPtr_->initialTime)
915  {
916  dout() << " Pause time and initial time equal " << std::endl;
917  }
918  }
919 #endif
920 
921  if (secRCPtr_->isPauseTime())
922  {
923  // Failure at this point only indicates that the simulation
924  // is paused and may be resumed.
925 #ifdef Xyce_DEBUG_ANALYSIS
926  if (tiaParams.debugLevel > 0)
927  {
928  dout() << "Transient::loopProcess(): pausing simulation " << std::endl;
929  }
930 #endif
931  secRCPtr_->simulationPaused();
932  isPaused = true;
933  recoverableFailureFlag = false;
934  }
935 
936  // If the exit time has been exceeded, exit.
937  if (tiaParams.exitTime != 0.0 &&
938  secRCPtr_->currentTime > tiaParams.exitTime)
939  {
940 
941  lout() << "Exit time exceeded. Exiting transient loop\n" << std::endl;
942  recoverableFailureFlag = false;
943  }
944 
945  if (tiaParams.exitStep != -1 &&
946  static_cast<int>(stepNumber) == tiaParams.exitStep)
947  {
948  lout() <<"Exit step. Exiting transient loop\n" << std::endl;
949  recoverableFailureFlag = false;
950  }
951 
952  return recoverableFailureFlag;
953 }
954 
955 //-----------------------------------------------------------------------------
956 // Function : Transient::processSuccessfulDCOP()
957 // Purpose :
958 // Special Notes :
959 // Scope : public
960 // Creator : Rich Schiek, SNL
961 // Creation Date : 3/11/06
962 //-----------------------------------------------------------------------------
964 {
965  bool bsuccess = true;
966 
967  loaderRCPtr_->stepSuccess (anaManagerRCPtr_->currentMode_);
968 
970 
971  // Communicate down to the device level that the step has been accepted.
972  // This must be done before the "times" get rotated, and certainly before
973  // the vectors get rotated. The primary target for this call is the
974  // transmission line device, which needs to know when it has a valid
975  // solution so it can save history. (And now the ADC/DAC devices too)
976  // needs to happen before dcopFlag_ is set to false.
977  loaderRCPtr_->acceptStep();
978 
979  // Reset some settings (to switch from DCOP to transient, if not the
980  // first step of a "double" DCOP.
981  if ( firstDoubleDCOPStep_ () ) // (pde-only)
982  {
983  dcopFlag_ = true;
984  anaManagerRCPtr_->currentMode_ = 0;
986  }
987  else
988  {
989  dcopFlag_ = false;
990  anaManagerRCPtr_->currentMode_ = 1;
991  anaManagerRCPtr_->switchIntegrator_ = true;
993  beginningIntegration = true;
994  }
995 
996  anaManagerRCPtr_->getTIADataStore()->setConstantHistory();
997  anaManagerRCPtr_->getTIADataStore()->computeDividedDifferences();
998  wimRCPtr_->obtainCorrectorDeriv();
999 
1000  anaManagerRCPtr_->getTIADataStore()->updateSolDataArrays ();
1001 
1002  tranopOutputs ();
1003 
1004  // Now that output has been called, update the doubleDCOP step
1005  // if neccessary. (Only matters for pde problems)
1007 
1008  //Test and save restart if necessary
1009  if( anaManagerRCPtr_->testRestartSaveTime_() )
1010  {
1011  if (DEBUG_RESTART)
1012  dout() << "\n " << commandLine_.getArgumentValue("netlist")
1013  << " Calling dumpRestartData" << std::endl;
1014 
1015  restartMgrRCPtr_->dumpRestartData( secRCPtr_->currentTime );
1016 
1017  if (DEBUG_RESTART)
1018  dout() << " Done Calling dumpRestartData" << std::endl;
1019  }
1020 
1021  // This output call is for device-specific output, such as .OP,
1022  // or internal plot output from PDE(TCAD) devices.
1023  loaderRCPtr_->output();
1024 
1025  nlsMgrRCPtr_->allocateTranSolver();
1026  secRCPtr_->previousCallStepSuccessful = true;
1027 
1028  return bsuccess;
1029 }
1030 
1031 //-----------------------------------------------------------------------------
1032 // Function : Transient::processSuccessfulStep()
1033 // Purpose :
1034 // Special Notes :
1035 // Scope : public
1036 // Creator : Rich Schiek, SNL
1037 // Creation Date : 3/11/06
1038 //-----------------------------------------------------------------------------
1040 {
1041  bool bsuccess = true;
1042  loaderRCPtr_->stepSuccess (anaManagerRCPtr_->currentMode_);
1043 
1044  if( historyTrackingOn_ )
1045  {
1046  // store status of this step
1047  timeQueue_.push_back( secRCPtr_->currentTime );
1048  timeStepQueue_.push_back( secRCPtr_->currentTimeStep );
1049  stepStatusQueue_.push_back( 1 );
1050  estErrorOverTolQueue_.push_back( secRCPtr_->estOverTol_);
1051  nonlinearSolverStatusQueue_.push_back( secRCPtr_->newtonConvergenceStatus );
1052  nonlinearSolverNumIterationsQueue_.push_back( secRCPtr_->nIterations);
1053  nonlinearSolverMaxNormQueue_.push_back( nlsMgrRCPtr_->getMaxNormF() );
1054  nonlinearSolverMaxNormIndexQueue_.push_back( nlsMgrRCPtr_->getMaxNormFindex () );
1055  }
1056 
1057 #ifdef Xyce_DEBUG_ANALYSIS
1058  if (tiaParams.debugLevel > 0)
1059  {
1060  dout() << " Transient::processSuccessfulStep()" << std::endl
1061  << "Newton step succeeded:" << std::endl
1062  << "nextSolutionPtr: " << std::endl;
1063 
1064  anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr->printPetraObject(dout());
1065  dout() << std::endl;
1066  }
1067 #endif
1068  // Set things up for the next time step, based on if this one was
1069  // successful.
1070 
1071  // This output call is for device-specific output (like from a PDE device,
1072  // outputting mesh-based tecplot files). It will only work in parallel if on
1073  // a machine where all processors have I/O capability.
1074  // Note: this output needs to happen before the "times" get rotated.
1075  loaderRCPtr_->output();
1076 
1077  // Communicate down to the device level that the step has been accepted.
1078  // This must be done before the "times" get rotated, and certainly before
1079  // the vectors get rotated. The primary target for this call is the
1080  // transmission line device, which needs to know when it has a valid
1081  // solution so it can save history.
1082  loaderRCPtr_->acceptStep();
1083 
1084  // current time will get updated in completeStep(). We'll save its value
1085  // for the moment so it can be saved if needed with the rest of the
1086  // solution if tiaParams.saveTimeStepsFlag is set.
1087  // This fixes an off by one bug in getting the right time value and
1088  // keeps the real solutions associated with that value too.
1089  double currentTime = secRCPtr_->currentTime;
1090  double suggestedMaxTime=0.0;
1092  {
1093  suggestedMaxTime = maxTimeStepExpressionRCPtr_->evaluate(
1094  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr, anaManagerRCPtr_->getTIADataStore()->currStatePtr, anaManagerRCPtr_->getTIADataStore()->currStorePtr);
1095  }
1096  secRCPtr_->updateMaxTimeStep( suggestedMaxTime );
1097  secRCPtr_->updateMinTimeStep();
1098  secRCPtr_->updateBreakPoints();
1099 
1100 #ifdef Xyce_VERBOSE_TIME
1101  if (tiaParams.debugLevel > 0)
1102  {
1103  dout() << "Transient Analysis: accepting time step" << std::endl;
1104  }
1105 #endif // Xyce_VERBOSE_TIME
1106 
1107  wimRCPtr_->completeStep();
1108 
1109 #ifdef Xyce_VERBOSE_TIME
1110  if (tiaParams.errorAnalysisOption == 1)
1111  {
1112  dout().precision(15);
1113  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = " << tiaParams.TimeStepLimitedbyBP << "\n" << std::endl;
1114  dout() << "ERROROPTION=1: NL Its = " << secRCPtr_->nIterations << "\n" << std::endl;
1115  dout() << "ERROROPTION=1: New DeltaT = " << secRCPtr_->currentTimeStep << "\n" << std::endl;
1116  }
1117 #endif // Xyce_VERBOSE_TIME
1118 
1119  stepNumber += 1;
1120  tranStepNumber += 1;
1123 
1124  secRCPtr_->numberSuccessiveFailures -= 1;
1125  if (secRCPtr_->numberSuccessiveFailures < 0)
1126  secRCPtr_->numberSuccessiveFailures = 0;
1127 
1128  // --------------------------------------------------------------------
1129  // Check to see if we have hit the end or a discontinuity point. The
1130  // next discontinuity point is represented by the stopTime variable.
1131 
1132  // Note: make sure that when we check for discontinuity point, we take
1133  // into account the possibility of roundoff error. Use the same bpTol
1134  // as is used in function updateBreakPoints.
1135  double bpTol = anaManagerRCPtr_->getBreakpointTol();
1136 
1137  if (tiaParams.bpEnable)
1138  {
1139  double timeDiff1 = secRCPtr_->currentTime - secRCPtr_->stopTime;
1140  double timeDiff2 = secRCPtr_->currentTime - tiaParams.finalTime;
1141  timeDiff1 = fabs(timeDiff1);
1142  timeDiff2 = fabs(timeDiff2);
1143 
1144 #ifdef Xyce_DEBUG_ANALYSIS
1145  if (tiaParams.debugLevel > 0)
1146  {
1147  dout() << " Checking whether to set breakpointrestartstep" << std::endl;
1148  dout() << " current - stop = " << timeDiff1 << std::endl;
1149  dout() << " current - final = " << timeDiff2 << std::endl;
1150  dout() << " bpTol = " << bpTol << std::endl;
1151  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1152  dout() << " setting breakPointRestartStep to " << tranStepNumber;
1153  }
1154 #endif
1155  if (timeDiff1 <= bpTol && timeDiff2 > bpTol)
1156  {
1157  anaManagerRCPtr_->breakPointRestartStep = tranStepNumber;
1158  }
1159  }
1160 
1161  if (anaManagerRCPtr_->breakPointRestartStep == tranStepNumber)
1162  {
1163  beginningIntegration = true;
1164  }
1165  else
1166  {
1167  beginningIntegration = false;
1168  }
1169 
1171  {
1173  }
1175  {
1178  }
1179 
1181  {
1182  anaManagerRCPtr_->getTIADataStore()->timeSteps.push_back(currentTime);
1183  anaManagerRCPtr_->getTIADataStore()->timeStepsBreakpointFlag.push_back(beginningIntegration);
1184  N_LAS_Vector * aVecPtr = new N_LAS_Vector( *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr) );
1185  anaManagerRCPtr_->getTIADataStore()->fastTimeSolutionVec.push_back( aVecPtr );
1186  aVecPtr = new N_LAS_Vector( *(anaManagerRCPtr_->getTIADataStore()->currStatePtr) );
1187  anaManagerRCPtr_->getTIADataStore()->fastTimeStateVec.push_back( aVecPtr );
1188  aVecPtr = new N_LAS_Vector( *(anaManagerRCPtr_->getTIADataStore()->daeQVectorPtr) );
1189  anaManagerRCPtr_->getTIADataStore()->fastTimeQVec.push_back( aVecPtr );
1190  aVecPtr = new N_LAS_Vector( *(anaManagerRCPtr_->getTIADataStore()->currStorePtr) );
1191  anaManagerRCPtr_->getTIADataStore()->fastTimeStoreVec.push_back( aVecPtr );
1192  }
1193 
1194  // 03/16/04 tscoffe: This is where the solution pointers are rotated.
1195  anaManagerRCPtr_->getTIADataStore()->updateSolDataArrays();
1196 
1197 #ifdef Xyce_DEBUG_ANALYSIS
1198 #ifdef Xyce_DEBUG_TIME
1199  if (tiaParams.debugLevel > 1)
1200  anaManagerRCPtr_->getTIADataStore()->outputSolDataArrays(Xyce::dout());
1201 #endif
1202 #endif
1203 
1204  tranStepOutputs ();
1205 
1206  // Test and save restart if necessary
1207  if (anaManagerRCPtr_->testRestartSaveTime_())
1208  restartMgrRCPtr_->dumpRestartData(secRCPtr_->currentTime);
1209 
1210  secRCPtr_->previousCallStepSuccessful = true;
1211 
1212  // reset min error tracking variables
1213  // if the step number is less than zero we'll assume there is no valid
1214  // min. estimated error over tol or an associated time step. This frees us
1215  // from putting Machine::Big here and trying to do something with that.
1217 
1218  return bsuccess;
1219 }
1220 
1221 
1222 //-----------------------------------------------------------------------------
1223 // Function : Transient::processFailedStep
1224 // Purpose :
1225 // Special Notes :
1226 // Scope : public
1227 // Creator : Rich Schiek, SNL
1228 // Creation Date : 3/11/06
1229 //-----------------------------------------------------------------------------
1231 {
1232  bool bsuccess = true;
1233 
1234  if( historyTrackingOn_ )
1235  {
1236  // store status of this step
1237  timeQueue_.push_back( secRCPtr_->currentTime );
1238  timeStepQueue_.push_back( secRCPtr_->currentTimeStep );
1239  stepStatusQueue_.push_back( 0 );
1240  estErrorOverTolQueue_.push_back( secRCPtr_->estOverTol_);
1241  nonlinearSolverStatusQueue_.push_back( secRCPtr_->newtonConvergenceStatus );
1242  nonlinearSolverNumIterationsQueue_.push_back( secRCPtr_->nIterations);
1243  nonlinearSolverMaxNormQueue_.push_back( nlsMgrRCPtr_->getMaxNormF() );
1244  nonlinearSolverMaxNormIndexQueue_.push_back( nlsMgrRCPtr_->getMaxNormFindex() );
1245  }
1246 
1247  // save some info about this step
1248  double estOverTol = secRCPtr_->getEstOverTol();
1249  if( (stepNumberAtMinEstErrorOverTol < 0) || ( estOverTol < minEstErrorOverTol ) )
1250  {
1251  // our first failed step, so automatically save info
1253  minEstErrorOverTol = secRCPtr_->getEstOverTol();
1254  timeStepAtMinEstErrorOverTol = secRCPtr_->currentTimeStep;
1255  }
1256 
1257  loaderRCPtr_->stepFailure (anaManagerRCPtr_->currentMode_);
1258 
1259 #ifdef Xyce_VERBOSE_TIME
1260  // DO NOT REMOVE THIS OUTPUT LINE. It is depended upon by the TIA/ERROROPTION
1261  // test case, which will fail if this output doesn't happen.
1262  dout() << "Transient Analysis: rejecting time step" << std::endl;
1263 #endif // Xyce_VERBOSE_TIME
1264 
1265  wimRCPtr_->rejectStep();
1266 
1267 #ifdef Xyce_VERBOSE_TIME
1268  if (tiaParams.errorAnalysisOption == 1)
1269  {
1270  dout().precision(15);
1271  dout() << "ERROROPTION=1: TimeStepLimitedbyBP = " << tiaParams.TimeStepLimitedbyBP << "\n" << std::endl;
1272  dout() << "ERROROPTION=1: NL Its = " << secRCPtr_->nIterations << "\n" << std::endl;
1273  dout() << "ERROROPTION=1: New DeltaT = " << secRCPtr_->currentTimeStep << "\n" << std::endl;
1274  }
1275 #endif // Xyce_VERBOSE_TIME
1276 
1277 #ifdef Xyce_DEBUG_ANALYSIS
1278  if (tiaParams.debugLevel > 0)
1279  {
1280  dout() << " Transient::processFailedStep" << std::endl
1281  << "Newton step failed:" << std::endl
1282  << "nextSolutionPtr: " << std::endl;
1283  anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr->printPetraObject(dout());
1284  dout() << std::endl;
1285  }
1286 #endif
1288  secRCPtr_->numberSuccessiveFailures += 1;
1289 
1290  if (secRCPtr_->currentTimeStep <= secRCPtr_->minTimeStep)
1291  {
1292 #ifdef Xyce_DEBUG_ANALYSIS
1293  if (tiaParams.debugLevel > 0)
1294  {
1295  dout() << "currTimeStep: " << secRCPtr_->currentTimeStep << std::endl;
1296  dout() << "minTimeStep: " << secRCPtr_->minTimeStep << std::endl;
1297  }
1298 #endif
1299 
1300  // before we exit with a time step too small error, check if minTimeStepRecoveryCounter is greater than zero
1301  // if it is, then the user wants us to try to accept the step that had the minimum
1302  // estimated error over tol.
1304  {
1305  lout() << "Attempting to retake and accept step where estimated error over tolerance was: " << minEstErrorOverTol
1306  << " and time step was: " << timeStepAtMinEstErrorOverTol << std::endl;
1307 
1310  }
1311  else
1312  {
1313  outputQueuedData();
1314  lout() << "Time step too small near step number: " << stepNumber << " Exiting transient loop.\n" << std::endl;
1315 
1316  bsuccess = false;
1317  }
1318  }
1319 
1321  {
1322  outputQueuedData();
1323  lout() << "Newton solver failed in constant time step mode. Exiting transient loop.\n" << std::endl;
1324 
1325  bsuccess = false;
1326  }
1327 
1328  if (tiaParams.exitStep != -1 &&
1329  static_cast<int>(totalNumberSuccessStepsThisParameter_) == (tiaParams.exitStep-1))
1330  {
1331  outputQueuedData();
1332  lout() << "Exit Step. Exiting transient loop\n" << std::endl;
1333  bsuccess = false;
1334  }
1335 #ifdef Xyce_VERBOSE_TIME
1336  if (!bsuccess)
1337  {
1338  endTRANtime = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime();
1339  tranStats = saveLoopInfo();
1341  }
1342 #endif
1343 
1344  return bsuccess;
1345 }
1346 
1347 //-----------------------------------------------------------------------------
1348 // Function : Transient::processFailedDCOP
1349 // Purpose :
1350 // Special Notes :
1351 // Scope : public
1352 // Creator : Rich Schiek, SNL
1353 // Creation Date : 3/11/06
1354 //-----------------------------------------------------------------------------
1356 {
1357  bool bsuccess = true;
1358 
1359  loaderRCPtr_->stepFailure (anaManagerRCPtr_->currentMode_);
1360 
1361  // DC Operating Point failed.
1363  (secRCPtr_->numberSuccessiveFailures)++;
1364 
1365  lout() << "DC Operating Point Failed. Exiting transient loop" << std::endl;
1366 
1367  return bsuccess;
1368 }
1369 
1370 //-----------------------------------------------------------------------------
1371 // Function : Transient::finish
1372 // Purpose :
1373 // Special Notes :
1374 // Scope : public
1375 // Creator : Rich Schiek, SNL
1376 // Creation Date : 3/11/06
1377 //-----------------------------------------------------------------------------
1379 {
1380  bool bsuccess = true;
1381 
1382  if (tiaParams.saveTimeStepsFlag && anaManagerRCPtr_->getHBFlag())
1383  {
1384  RefCountPtr<N_TIA_DataStore> dsPtr_ = anaManagerRCPtr_->getTIADataStore();
1385  dsPtr_->timeSteps.push_back(secRCPtr_->currentTime);
1386  dsPtr_->timeStepsBreakpointFlag.push_back(beginningIntegration);
1387  N_LAS_Vector * aVecPtr = new N_LAS_Vector( *(dsPtr_->currSolutionPtr) );
1388  dsPtr_->fastTimeSolutionVec.push_back( aVecPtr );
1389  aVecPtr = new N_LAS_Vector( *(dsPtr_->currStatePtr) );
1390  dsPtr_->fastTimeStateVec.push_back( aVecPtr );
1391  aVecPtr = new N_LAS_Vector( *(dsPtr_->daeQVectorPtr) );
1392  dsPtr_->fastTimeQVec.push_back( aVecPtr );
1393  aVecPtr = new N_LAS_Vector( *(dsPtr_->currStorePtr) );
1394  dsPtr_->fastTimeStoreVec.push_back( aVecPtr );
1395  }
1396 
1397  if (!isPaused)
1398  {
1399 #ifdef Xyce_DEBUG_ANALYSIS
1400  dout() << "Calling finishOutput" << std::endl;
1401 #endif
1402  outputMgrAdapterRCPtr_->finishOutput();
1403 
1404  // This output call is for device-specific output (like from a PDE device,
1405  // outputting mesh-based tecplot files). It will only work in parallel if on
1406  // a machine where all processors have I/O capability, as devices are
1407  // local to a processor.
1408  loaderRCPtr_->finishOutput();
1409 
1411  }
1412 
1413  return bsuccess;
1414 }
1415 
1416 //-----------------------------------------------------------------------------
1417 // Function : Transient::handlePredictor
1418 // Purpose :
1419 // Special Notes :
1420 // Scope : private
1421 // Creator : Eric Keiter, SNL
1422 // Creation Date : 06/24/2013
1423 //-----------------------------------------------------------------------------
1425 {
1426  anaManagerRCPtr_->getTIADataStore()->setErrorWtVector();
1427  wimRCPtr_->obtainPredictor();
1428  wimRCPtr_->obtainPredictorDeriv();
1429 
1430 #ifdef Xyce_DEBUG_ANALYSIS
1431 #ifdef Xyce_DEBUG_TIME
1432  if (tiaParams.debugLevel > 1)
1433  {
1434  dout() << " Transient::handlePredictor" << std::endl;
1435  anaManagerRCPtr_->getTIADataStore()->outputPredictedSolution(Xyce::dout());
1436  anaManagerRCPtr_->getTIADataStore()->outputPredictedDerivative(Xyce::dout());
1437  }
1438 #endif
1439 #endif
1440 
1441  // Now, in case this is the upper level of a 2-level sim, tell the
1442  // inner solve to do its prediction:
1443  loaderRCPtr_->startTimeStep ();
1444 
1445  return true;
1446 }
1447 
1448 //-----------------------------------------------------------------------------
1449 // Function : Transient::resetForStepAnalysis()
1450 // Purpose : When doing a .STEP sweep, some data must be reset to its
1451 // initial state.
1452 // Special Notes :
1453 // Scope : public
1454 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1455 // Creation Date : 8/26/04
1456 //-----------------------------------------------------------------------------
1458 {
1460  stepNumber = 0;
1461  beginningIntegration = true;
1462 
1463  nlsMgrRCPtr_->resetAll(DC_OP);
1464  secRCPtr_->resetAll();
1465  dcopFlag_ = false;
1466  anaManagerRCPtr_->nextOutputTime_ = 0.0;
1467 
1468  if (historyTrackingOn_)
1469  {
1470  // these set_size calls will also "reset" the queue.
1471  timeQueue_.set_size( queueSize_ );
1472  timeStepQueue_.set_size( queueSize_ );
1473  stepStatusQueue_.set_size( queueSize_ );
1474  estErrorOverTolQueue_.set_size( queueSize_ );
1479  }
1480 
1481  return true;
1482 }
1483 
1484 //-----------------------------------------------------------------------------
1485 // Function : Transient::resetForHB()
1486 // Purpose : When doing initial transient run, some analyses require
1487 // a reset function
1488 // they can fill this in if needed.
1489 // Special Notes :
1490 // Scope : public
1491 // Creator : T. Mei, SNL, Parallel Computational Sciences
1492 // Creation Date : 2/26/09
1493 //-----------------------------------------------------------------------------
1495 {
1496  nlsMgrRCPtr_->resetAll(DC_OP);
1497  secRCPtr_->resetAll();
1498  anaManagerRCPtr_->getTIADataStore()->resetAll();
1499  dcopFlag_ = false;
1500  anaManagerRCPtr_->nextOutputTime_ = 0.0;
1501 
1502  if (historyTrackingOn_)
1503  {
1504  // these set_size calls will also "reset" the queue.
1505  timeQueue_.set_size( queueSize_ );
1506  timeStepQueue_.set_size( queueSize_ );
1507  stepStatusQueue_.set_size( queueSize_ );
1508  estErrorOverTolQueue_.set_size( queueSize_ );
1513  }
1514 
1515  return true;
1516 }
1517 
1518 
1519 //-----------------------------------------------------------------------------
1520 // Function : Transient::finalVerboseOutput
1521 // Purpose :
1522 // Special Notes :
1523 // Scope : public
1524 // Creator : Rich Schiek, SNL
1525 // Creation Date : 3/11/06
1526 //-----------------------------------------------------------------------------
1528 {
1529  bool bsuccess = true;
1530 
1531  lout() << "***** Problem read in and set up time: " << anaManagerRCPtr_->solverStartTime_ << " seconds" << std::endl;
1532 
1533  if (anaManagerRCPtr_->analysis == ANP_MODE_TRANSIENT)
1534  {
1535  double time;
1536  if (anaManagerRCPtr_->startTRANtime > startDCOPtime)
1537  {
1538  time = anaManagerRCPtr_->startTRANtime - startDCOPtime;
1539  }
1540  else
1541  {
1542  time = endTRANtime - startDCOPtime;
1543  }
1544  lout() << " ***** DCOP time: " << time << " seconds. Breakdown follows:" << std::endl;
1545 
1546  printLoopInfo(0, dcStats);
1547  }
1548 
1549  if (anaManagerRCPtr_->analysis == ANP_MODE_TRANSIENT &&
1550  endTRANtime >= anaManagerRCPtr_->startTRANtime)
1551  {
1552  lout() << " ***** Transient Stepping time: " << endTRANtime-anaManagerRCPtr_->startTRANtime << " seconds. Breakdown follows:" << std::endl;
1553 
1555  }
1556 
1557  return bsuccess;
1558 }
1559 
1560 //-----------------------------------------------------------------------------
1561 // Function : Transient::outputQueuedData
1562 // Purpose :
1563 // Special Notes :
1564 // Scope : public
1565 // Creator : Rich Schiek, SNL
1566 // Creation Date : 3/11/06
1567 //-----------------------------------------------------------------------------
1569 {
1570  if( historyTrackingOn_ )
1571  {
1572 #ifndef Xyce_PARALLEL_MPI
1573  // if necessary set up the names map.
1574  Xyce::NodeNamePairMap & nodeNames = outputMgrAdapterRCPtr_->getAllNodes();
1575  int nodeNameSize = nodeNames.size();
1576  nameVec_.resize(nodeNameSize+1,"gnd");
1577  Xyce::NodeNamePairMap::iterator mapI, mapEnd;
1578  mapEnd = nodeNames.end();
1579  mapI = nodeNames.begin();
1580  for ( ; mapI != mapEnd ; ++mapI)
1581  {
1582  nameVec_[(*mapI).second.first] = (*mapI).first;
1583  }
1584 #endif
1585 
1586  // get the current non-linear solver return codes
1587  N_NLS_ReturnCodes nlReturnCodes = nlsMgrRCPtr_->getReturnCodes();
1588 
1589  lout() << " *** Transient failure history: " << std::endl;
1590  if (tiaParams.errorAnalysisOption == 1)
1591  {
1592  // truncation error is not used here so est err over tol is not useful in the output
1593  lout() << "Time Time Step Non-Linear Solver node node" << std::endl;
1594  lout() << "(sec) Step Status Status Iters ||F|| index name" << std::endl;
1595  }
1596  else
1597  {
1598  lout() << "Time Time Step EstErr Non-Linear Solver node node" << std::endl;
1599  lout() << "(sec) Step Status OverTol Status Iters ||F|| index name" << std::endl;
1600  }
1601 
1602  for( int i=0; i<queueSize_; i++ )
1603  {
1604  int fieldWidth=10;
1605  lout() << std::scientific << std::setprecision(fieldWidth-7) << std::setfill(' ') << std::right << std::setw( fieldWidth )
1606  << timeQueue_.at_from_tail(i) << " "
1607  << timeStepQueue_.at_from_tail(i) << " ";
1608  if( stepStatusQueue_.at_from_tail(i) == 1 )
1609  {
1610  lout() << "pass ";
1611  }
1612  else
1613  {
1614  lout() << "fail ";
1615  }
1616  if (tiaParams.errorAnalysisOption == 1)
1617  {
1618  }
1619  else
1620  {
1621  lout() << estErrorOverTolQueue_.at_from_tail(i) << " ";
1622  }
1623  int nlStatus = nonlinearSolverStatusQueue_.at_from_tail(i);
1624  lout() << std::setw(7) << std::right;
1625  if( nlStatus == nlReturnCodes.normTooSmall )
1626  {
1627  lout() << "P:s nrm";
1628  }
1629  else if( nlStatus == nlReturnCodes.normalConvergence)
1630  {
1631  lout() << "pass ";
1632  }
1633  else if( nlStatus == nlReturnCodes.nearConvergence )
1634  {
1635  lout() << "P:near ";
1636  }
1637  else if( nlStatus == nlReturnCodes.smallUpdate )
1638  {
1639  lout() << "P:s up ";
1640  }
1641  else if( nlStatus == nlReturnCodes.nanFail )
1642  {
1643  lout() << "F:NaN ";
1644  }
1645  else if( nlStatus == nlReturnCodes.tooManySteps )
1646  {
1647  lout() << "F:max s";
1648  }
1649  else if( nlStatus == nlReturnCodes.tooManyTranSteps )
1650  {
1651  lout() << "F:max s";
1652  }
1653  else if( nlStatus == nlReturnCodes.updateTooBig )
1654  {
1655  lout() << "F:big u";
1656  }
1657  else if( nlStatus == nlReturnCodes.stalled )
1658  {
1659  lout() << "F:stall";
1660  }
1661  else if( nlStatus == nlReturnCodes.wrmsExactZero )
1662  {
1663  lout() << "F:n zro";
1664  }
1665  else if( nlStatus == nlReturnCodes.innerSolveFailed )
1666  {
1667  lout() << "F:in Fl";
1668  }
1669  else
1670  {
1671  lout() << "code=" <<
1672  nonlinearSolverStatusQueue_.at_from_tail(i) << " ";
1673  }
1674 
1675  lout() << std::right << std::setw( 4 )
1676  << nonlinearSolverNumIterationsQueue_.at_from_tail(i) << " "
1677  << nonlinearSolverMaxNormQueue_.at_from_tail(i) ;
1678 
1679  int outIndex = nonlinearSolverMaxNormIndexQueue_.at_from_tail(i) ;
1680  lout() << std::right << std::fixed << std::setw( 7 ) << outIndex;
1681 
1682  std::string outIndexName("");
1683  if (!(nameVec_.empty()))
1684  {
1685  int nsize = nameVec_.size();
1686  if (nsize > outIndex && outIndex >=0)
1687  {
1688  outIndexName = nameVec_[outIndex];
1689  }
1690  }
1691  else
1692  {
1693  outIndexName = "N/A";
1694  }
1695  lout() << std::left << " " << outIndexName;
1696  lout() << std::endl;
1697  }
1698  }
1699 }
1700 
1701 //-----------------------------------------------------------------------------
1702 // Function : Transient::takeAnIntegrationStep_
1703 // Purpose : Take a transient integration step.
1704 // Special Notes :
1705 // Scope : private
1706 // Creator : Richard Schiek, SNL, Electrical and Microsystem Modeling
1707 // Creation Date : 01/24/08
1708 //-----------------------------------------------------------------------------
1710 {
1711  handlePredictor();
1712  loaderRCPtr_->updateSources();
1713  secRCPtr_->newtonConvergenceStatus = nlsMgrRCPtr_->solve();
1714 
1715 #ifdef Xyce_DEBUG_ANALYSIS
1716  dout() << "Transient::takeAnIntegrationStep_: newtonConvergenceStatus = " << secRCPtr_->newtonConvergenceStatus << std::endl;
1717 #endif
1718 
1719  anaManagerRCPtr_->getTIADataStore()->stepLinearCombo ();
1721  secRCPtr_->nIterations = nlsMgrRCPtr_->getNumIterations();
1722  secRCPtr_->evaluateStepError ();
1723 
1724  return;
1725 }
1726 
1727 
1728 //-----------------------------------------------------------------------------
1729 // Function : Transient::twoLevelStep
1730 //
1731 // Purpose : Take a transient integration step, for inner 2-level solve.
1732 //
1733 // Special Notes : Same as takeAnIntegrationStep, but does not do the
1734 // prediction. (that is in handlePredictor_).
1735 //
1736 // The prediction is handled separately, as for a 2-level
1737 // solve, you only want to do the prediction on the first
1738 // solve of the attempted time step.
1739 //
1740 // Scope : public
1741 // Creator :
1742 // Creation Date : 3/11/06
1743 //-----------------------------------------------------------------------------
1745 {
1746  loaderRCPtr_->updateSources();
1747  secRCPtr_->newtonConvergenceStatus = nlsMgrRCPtr_->solve();
1748  anaManagerRCPtr_->getTIADataStore()->stepLinearCombo ();
1749 
1751  secRCPtr_->evaluateStepError ();
1752 
1753  endTRANtime = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime();
1754  tranStats = saveLoopInfo();
1755 
1756  return (secRCPtr_->stepAttemptStatus);
1757 }
1758 
1759 //-----------------------------------------------------------------------------
1760 // Function : Transient::retakeAndAcceptTimeStep
1761 // Purpose : Do a requested time step and accept it
1762 // Special Notes :
1763 // Scope : public
1764 // Creator : Rich Schiek, Electrical and Microsystems Modeling
1765 // Creation Date : 01/23/09
1766 //-----------------------------------------------------------------------------
1767 bool Transient::retakeAndAcceptTimeStep( double aTimeStep )
1768 {
1769  bool bsuccess=true;
1770  // This function was put in place to handle the following situation.
1771  // If a series of time steps are rejected because the estimated error
1772  // over tol. is too high, Xyce may exit if the next time step falls under
1773  // the minTimeStep. A user could adjust the tolerances of a simulation
1774  // to try and get around this, but in UQ studies where there are 1,000s of
1775  // simulations, it can be difficult to get all of them to run. So,
1776  // if the user has set the netlist option timeint MINTIMESTEPRECOVERY=<int>
1777  // and we're about to exit because the time step has fallen under the minTimeStep
1778  // we will try and retake the time step that had the min. est. error over tol.
1779  // and accept that.
1780  //
1781  // At this point, Transient::processFailedStep() has already determined
1782  // that the preconditions outlined above are in place (i.e. the user requested
1783  // this and we're about to exit with a time step too small error), so lets
1784  // try the step that had the min. est error over tol.
1785 
1786  // set time step
1787  secRCPtr_->currentTimeStep = timeStepAtMinEstErrorOverTol;
1788 
1789  // take step
1791 
1792  // can't accept step if the non-linear solver failed
1793  if(secRCPtr_->nIterations==0)
1794  {
1795  lout() << "Time step too small near step number: " << stepNumber << " Exiting transient loop.\n" << std::endl;
1796  bsuccess = false;
1797  }
1798  else
1799  {
1801  }
1802  return bsuccess;
1803 }
1804 
1805 //-----------------------------------------------------------------------------
1806 // Function : Transient::printStepHeader()
1807 // Purpose : Prints out time step information.
1808 // Special Notes :
1809 // Scope : public
1810 // Creator : Eric Keiter, SNL, Parallel Computational Sciences
1811 // Creation Date : 6/26/00
1812 //-----------------------------------------------------------------------------
1813 void Transient::printStepHeader(std::ostream &os)
1814 {
1815  if (VERBOSE_TIME) {
1816  os << "***** " << (DEBUG_ANALYSIS ? commandLine_.getArgumentValue("netlist") : "") << " ";
1817 
1818  if (dcopFlag_)
1819  {
1820  os << "Start of DCOP STEP # ";
1821  }
1822  else
1823  {
1825  {
1826  if (secRCPtr_->currentTime == tiaParams.initialTime)
1827  {
1828  os << "Start of Time Step (INITIAL STEP) # ";
1829  }
1830  else
1831  {
1832  os << "Start of Time Step (DISCONTINUITY STEP) # ";
1833  }
1834  }
1835  else
1836  {
1837  if (!secRCPtr_->stepAttemptStatus)
1838  {
1839  os << "Start of Time Step (AFTER FAILED STEP) # ";
1840  }
1841  else
1842  {
1843  os << "Start of Time Step (AFTER SUCCESS STEP) # ";
1844  }
1845  }
1846  }
1847 
1848  os << totalNumberSuccessStepsThisParameter_ + 1 << std::endl;
1849  }
1850 }
1851 
1852 //-----------------------------------------------------------------------------
1853 // Function : Transient::printProgress()
1854 // Purpose : Outputs run completion percentage and estimated
1855 // time-to-completion.
1856 //
1857 // Special Notes : This will need some fixing to work with .STEP.
1858 //
1859 // Scope : public
1860 // Creator : Scott A. Hutchinson, SNL, Computational Sciences
1861 // Creation Date : 06/07/2002
1862 //-----------------------------------------------------------------------------
1863 void Transient::printProgress(std::ostream &os)
1864 {
1865  if (anaManagerRCPtr_->progressFlag_)
1866  {
1867  // Percent of the overall requested simulation time which is completed.
1868  double percentComplete;
1869  // Average CPU time per time step.
1870  double aveCPUTimePerStep;
1871  // Average clock time per time step.
1872  double aveSimTimePerStep;
1873  // Estimated CPU time to complete the simulation.
1874  double estCompletionTime = 0.0;
1875 
1876  // Report the beginning of the DC OP calculation. First call in OP.
1877  if (dcopFlag_)
1878  {
1879  startDCOPtime = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime();
1880  if (gui_)
1881  {
1882  Report::signalProgress("Xyce in DC Operating Point Calculation");
1883  }
1884  os << "***** Beginning DC Operating Point Calculation...\n" << std::endl;
1885  }
1887  {
1888  anaManagerRCPtr_->startTRANtime = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime();
1889  dcStats = saveLoopInfo();
1890  firstTime = false;
1891  if (gui_)
1892  {
1893  Report::signalProgress("Xyce in Transient Calculation");
1894  }
1895  os << "***** Beginning Transient Calculation...\n" << std::endl;
1896  }
1898  {
1899  if (startSimTime == -1.0)
1900  startSimTime = secRCPtr_->currentTime;
1901 
1902  double diff1 = fabs(secRCPtr_->currentTime - tiaParams.initialTime);
1903  double diff2 = fabs(tiaParams.finalTime - tiaParams.initialTime);
1904 
1905  // 02/05/08 tscoffe: optimization differences after the TIA_REFACTOR
1906  // caused a floating point difference here and this resolves that
1907  // difference. After the refactor is merged back onto the main trunk, this
1908  // stuff should be removed.
1909  percentComplete = 100.0 * diff1/diff2;
1910 
1911  if (fabs(percentComplete - oldPercentComplete) > 1.0)
1912  {
1913  oldPercentComplete = percentComplete;
1914 
1915  aveCPUTimePerStep = anaManagerRCPtr_->xyceTranTimerPtr_->elapsedTime() /
1917  aveSimTimePerStep = (secRCPtr_->currentTime - startSimTime) /
1919 
1920  if (aveSimTimePerStep > N_UTL_MachineDependentParams::MachineEpsilon())
1921  estCompletionTime = aveCPUTimePerStep *
1922  fabs(tiaParams.finalTime - secRCPtr_->currentTime) /
1923  aveSimTimePerStep;
1924 
1925  if (!gui_)
1926  {
1927  os << "***** Percent complete: " << percentComplete << " %" << std::endl;
1928  }
1929 
1930  if (estCompletionTime > N_UTL_MachineDependentParams::MachineEpsilon())
1931  {
1932  unsigned int days, hours, minutes, seconds;
1933  days = static_cast<int> (estCompletionTime / 86400);
1934  hours = static_cast<int> ((estCompletionTime - days * 86400) / 3600);
1935  minutes = static_cast<int> ((estCompletionTime - days * 86400 - hours * 3600) / 60);
1936  seconds = static_cast<int> (estCompletionTime - days * 86400 - hours * 3600 - minutes * 60);
1937 
1938  char timeStr[256];
1939  for (char *c = timeStr; c != timeStr + sizeof(timeStr); ++c)
1940  *c = 0;
1941 
1942 #ifdef Xyce_PARALLEL_MPI
1943  // get current local system time
1944  time_t t = time( NULL );
1945  struct tm * now = localtime( &t );
1946 
1947  // format and display output
1948  if ( ( t != (time_t)-1 ) && ( strftime( timeStr, 255, "%c", now ) != 0 ) )
1949  {
1950  os << "***** Current system time: " << timeStr << std::endl;
1951  }
1952 
1953  else
1954  {
1955  os << "***** Current system time could not be determined." << std::endl;
1956  }
1957 #endif
1958 
1959  if (days > 0)
1960  sprintf(timeStr, "%3d days, %2d hrs., %2d min., %2d sec.", days, hours, minutes, seconds);
1961  else if (hours > 0)
1962  sprintf(timeStr, "%2d hrs., %2d min., %2d sec.", hours, minutes, seconds);
1963  else if (minutes > 0)
1964  sprintf(timeStr, "%2d min., %2d sec.", minutes, seconds);
1965  else
1966  sprintf(timeStr, "%2d sec.", seconds);
1967 
1968  if (gui_)
1969  {
1970  std::ostringstream ost;
1971  ost << "Xyce transient ";
1972  if (percentComplete < 10)
1973  ost.precision(2);
1974  else
1975  ost.precision(3);
1976  ost << percentComplete
1977  << "%% complete ... Estimated time to completion: "
1978  << timeStr << std::endl;
1979  Report::signalProgress(ost.str());
1980  }
1981  else
1982  {
1983  os << "***** Estimated time to completion: " << timeStr << std::endl << std::endl;
1984  }
1985  }
1986  }
1987  }
1988  }
1989 }
1990 
1991 //-----------------------------------------------------------------------------
1992 // Function : Transient::noopOutputs
1993 // Purpose :
1994 // Special Notes :
1995 // Scope : public
1996 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
1997 // Creation Date : 8/31/2007
1998 //-----------------------------------------------------------------------------
2000 {
2001  if( testOutputTime_() )
2002  {
2003  if ( !firstDoubleDCOPStep_ () )
2004  {
2005  bool printIC = true;
2006  if (printIC)
2007  {
2008  outputMgrAdapterRCPtr_->tranOutput(
2009  secRCPtr_->currentTime,
2010  *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr),
2011  *(anaManagerRCPtr_->getTIADataStore()->currStatePtr),
2012  *(anaManagerRCPtr_->getTIADataStore()->currStorePtr),
2013  objectiveVec_,
2015  }
2016  if ( ( !Teuchos::is_null(anaManagerRCPtr_->mpdeMgrPtr_) ) &&
2017  ( anaManagerRCPtr_->mpdeMgrPtr_->getMPDEFlag() ) &&
2018  ( !(anaManagerRCPtr_->mpdeMgrPtr_->getMPDEIcFlag()) )
2019  )
2020  {
2021  // output the operating point if we can in MPDE mode
2022  outputMgrAdapterRCPtr_->outputMPDE(secRCPtr_->currentTime,
2023  *(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr));
2024  }
2025  }
2026  updateOutputTime_(secRCPtr_->currentTime);
2027  }
2028 }
2029 
2030 //-----------------------------------------------------------------------------
2031 // Function : Transient::tranopOutputs
2032 // Purpose :
2033 // Special Notes :
2034 // Scope : public
2035 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2036 // Creation Date : 8/31/2007
2037 //-----------------------------------------------------------------------------
2039 {
2040  //Test and output if necessary
2041  if( testOutputTime_() )
2042  {
2043  // Make sure this isn't the NLP step of a PDE DCOP.
2044  if ( !firstDoubleDCOPStep_ () )
2045  {
2046 #ifdef Xyce_DEBUG_ANALYSIS
2047  dout() << "Calling conventional TRANOP outputs!" << std::endl;
2048 #endif
2049  outputMgrAdapterRCPtr_->tranOutput(secRCPtr_->currentTime,
2050  *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr),
2051  *(anaManagerRCPtr_->getTIADataStore()->currStatePtr),
2052  *(anaManagerRCPtr_->getTIADataStore()->currStorePtr),
2053  objectiveVec_,
2055 
2056  outputMgrAdapterRCPtr_->outputMPDE(secRCPtr_->currentTime,
2057  *(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr));
2058  // check this - may be a mistake.
2059  }
2060  updateOutputTime_(secRCPtr_->currentTime);
2061  }
2062 
2063  // SAVE and DCOP restart:
2064  if ( anaManagerRCPtr_->testDCOPOutputTime_() || anaManagerRCPtr_->testSaveOutputTime_() )
2065  {
2066  outputMgrAdapterRCPtr_->outputDCOP( *(anaManagerRCPtr_->getTIADataStore()->currSolutionPtr) );
2067  }
2068 }
2069 
2070 //-----------------------------------------------------------------------------
2071 // Function : Transient::tranStepOutputs
2072 // Purpose :
2073 // Special Notes :
2074 // Scope : public
2075 // Creator : Eric Keiter, SNL, Electrical and Microsystems Modeling
2076 // Creation Date : 8/31/2007
2077 //-----------------------------------------------------------------------------
2079 {
2080  // The printOutputSolution function will sometimes perform
2081  // interpolations between the current step and the previous step,
2082  // if the integrator is using a high order of integration during
2083  // a new-DAE simulation.
2084 
2085  // If the user has specified tstart, and this happens to be
2086  // the first output of the simulation (at t=tstart, instead of
2087  // t=0) the force the interpolator to *not* interpolate, even
2088  // if it is doing so normally.
2089  bool doNotInterpolate=
2091 
2092 #ifdef Xyce_DEBUG_ANALYSIS
2093  if (tiaParams.debugLevel > 0)
2094  {
2095  if (doNotInterpolate)
2096  {
2097  dout() << "doNotInterpolate is TRUE!" << std::endl;
2098  }
2099  else
2100  {
2101  dout() << "doNotInterpolate is FALSE!" << std::endl;
2102  }
2103  }
2104 #endif
2105 
2106  if (testOutputTime_())
2107  {
2108  if ((!Teuchos::is_null(anaManagerRCPtr_->mpdeMgrPtr_)) && (anaManagerRCPtr_->mpdeMgrPtr_->blockAnalysisFlag()==true))
2109  {
2110 #ifdef Xyce_DEBUG_ANALYSIS
2111  if (tiaParams.debugLevel > 0)
2112  {
2113  dout() << "Calling MPDE outputs!" << std::endl;
2114  }
2115 #endif
2116  outputMgrAdapterRCPtr_->outputMPDE(secRCPtr_->currentTime, *(anaManagerRCPtr_->getTIADataStore()->nextSolutionPtr));
2117 
2118  // If we are actually in the MPDE phase, rather than the initial
2119  // condition, then output here.
2120  if (anaManagerRCPtr_->mpdeMgrPtr_->getMPDEFlag()==true && tiaParams.outputInterpMPDE)
2121  {
2122  if (anaManagerRCPtr_->mpdeMgrPtr_->getWaMPDEFlag()==false)
2123  {
2124  std::vector<double> fastTimes = anaManagerRCPtr_->mpdeMgrPtr_->getFastTimePoints();
2125  wimRCPtr_->printMPDEOutputSolution(
2126  outputMgrAdapterRCPtr_, secRCPtr_->currentTime,
2127  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2128  fastTimes );
2129  }
2130  else
2131  {
2132  std::vector<double> fastTimes = anaManagerRCPtr_->mpdeMgrPtr_->getFastTimePoints();
2133  int phiGID = anaManagerRCPtr_->mpdeMgrPtr_->getPhiGID();
2134  wimRCPtr_->printWaMPDEOutputSolution(
2135  outputMgrAdapterRCPtr_, secRCPtr_->currentTime,
2136  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2137  fastTimes, phiGID );
2138  }
2139  }
2140  // uncomment the following else block to get mpde initial
2141  // condition calculations printed out
2142  else
2143  {
2144  // try normal new dae output
2146  wimRCPtr_->printOutputSolution(
2147  outputMgrAdapterRCPtr_, secRCPtr_->currentTime,
2148  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2149  doNotInterpolate,
2151  false) ;
2152  }
2153  }
2154  else
2155  {
2157  wimRCPtr_->printOutputSolution(
2158  outputMgrAdapterRCPtr_, secRCPtr_->currentTime,
2159  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2160  doNotInterpolate,
2162  false) ;
2163  }
2164 
2165  firstTranOutput_ = false;
2166 
2167  updateOutputTime_(secRCPtr_->currentTime);
2168  }
2169  else
2170  {
2171  // just call the output manager to udpate non print line elements
2173  wimRCPtr_->printOutputSolution(
2174  outputMgrAdapterRCPtr_, secRCPtr_->currentTime,
2175  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2176  doNotInterpolate,
2178  true) ;
2179  }
2180 
2181  // SAVE output:
2182  if ( anaManagerRCPtr_->testSaveOutputTime_() )
2183  {
2184  wimRCPtr_->saveOutputSolution(
2186  anaManagerRCPtr_->getTIADataStore()->currSolutionPtr,
2187  anaManagerRCPtr_->saveTime_, doNotInterpolate);
2188  }
2189 }
2190 
2191 //-----------------------------------------------------------------------------
2192 // Function : Transient::testOutputTime_
2193 // Purpose :
2194 // Special Notes :
2195 // Scope : public
2196 // Creator : Rob Hoekstra, SNL, Parallel ComputationalSciences.
2197 // Creation Date : 07/31/01
2198 //-----------------------------------------------------------------------------
2200 {
2201  bool flag;
2202 
2203 #ifdef Xyce_DEBUG_ANALYSIS
2204  if (tiaParams.debugLevel > 0)
2205  {
2206  dout().width(21); dout().precision(13); dout().setf(std::ios::scientific);
2207  dout() << "Transient::testOutputTime. secPtr_->currentTime = " << secRCPtr_->currentTime << std::endl;
2208  dout() << "Transient::testOutputTime. tStart = " << tiaParams.tStart << std::endl;
2209  dout() << "Transient::testOutputTime. nextOutputTime_ = " << anaManagerRCPtr_->nextOutputTime_ << std::endl;
2210  for (int i=0;i<anaManagerRCPtr_->outputIntervals_.size();++i)
2211  {
2212  dout() << "outputIntervals_["<<i<<"].first = " << anaManagerRCPtr_->outputIntervals_[i].first;
2213  dout() << std::endl;
2214  }
2215  dout() << std::endl;
2216  }
2217 #endif
2218 
2219  if (secRCPtr_->currentTime < tiaParams.tStart)
2220  {
2221  flag = false;
2222  }
2223  else if (secRCPtr_->currentTime >= tiaParams.finalTime)
2224  {
2225  flag = true;
2226  }
2227  else if (anaManagerRCPtr_->initialOutputInterval_ == 0.0)
2228  {
2229  flag = true;
2230  }
2231  else if (secRCPtr_->currentTime < anaManagerRCPtr_->nextOutputTime_)
2232  {
2233  flag = false;
2234  }
2235  else
2236  {
2237  flag = true;
2238  }
2239 
2240  return flag;
2241 }
2242 
2243 //-----------------------------------------------------------------------------
2244 // Function : Transient::updateOutputTime_
2245 // Purpose : Advance output time so it is the next one after currTime
2246 // Special Notes : formerly part of testOutputTime_
2247 // Scope : public
2248 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling
2249 // Creation Date : 02/14/07
2250 //-----------------------------------------------------------------------------
2251 void Transient::updateOutputTime_(double currTime)
2252 {
2253  // We only need to bother with this if the user has specified output control
2254  // options
2255  if (anaManagerRCPtr_->outputIntervalSpecified_())
2256  {
2257  if (anaManagerRCPtr_->outputIntervals_.empty())
2258  {
2259  // Only an initial interval was specified
2260  while (anaManagerRCPtr_->nextOutputTime_ <= currTime)
2261  anaManagerRCPtr_->nextOutputTime_ += anaManagerRCPtr_->initialOutputInterval_;
2262  }
2263  else if (currTime < anaManagerRCPtr_->outputIntervals_[0].first)
2264  {
2265  // Multiple intervals, but we're still in the first one
2266  while (anaManagerRCPtr_->nextOutputTime_ <= currTime)
2267  anaManagerRCPtr_->nextOutputTime_ += anaManagerRCPtr_->initialOutputInterval_;
2268  if (anaManagerRCPtr_->nextOutputTime_ > anaManagerRCPtr_->outputIntervals_[0].first)
2269  anaManagerRCPtr_->nextOutputTime_ = anaManagerRCPtr_->outputIntervals_[0].first;
2270  }
2271  else
2272  {
2273  // Multiple intervals specified, we're past the first one
2274  std::pair<double, double> currInterval, nextInterval;
2275  int size = anaManagerRCPtr_->outputIntervals_.size();
2276  for (int i = 0; i < size; ++i)
2277  if (anaManagerRCPtr_->outputIntervals_[i].first <= currTime)
2278  {
2279  currInterval = anaManagerRCPtr_->outputIntervals_[i];
2280  if ((i+1) < static_cast<int>(anaManagerRCPtr_->outputIntervals_.size()))
2281  nextInterval = anaManagerRCPtr_->outputIntervals_[i+1];
2282  }
2283  int step = static_cast<int> ((currTime-currInterval.first) /
2284  currInterval.second);
2285  anaManagerRCPtr_->nextOutputTime_ = currInterval.first + (step+1)*currInterval.second;
2286  if (nextInterval.first && (nextInterval.first!=currInterval.first)
2287  && (anaManagerRCPtr_->nextOutputTime_>=nextInterval.first))
2288  anaManagerRCPtr_->nextOutputTime_ = nextInterval.first;
2289  }
2290 
2291  if (anaManagerRCPtr_->nextOutputTime_ >= tiaParams.finalTime)
2292  anaManagerRCPtr_->nextOutputTime_ = tiaParams.finalTime;
2293  }
2294 }
2295 
2296 //-----------------------------------------------------------------------------
2297 // Function : Transient::computeOutputInterpolationTimes_
2298 // Purpose : When we pass "nextOutputTime_", we might have skipped
2299 // over points where output was requested. Make a list of
2300 // those times so we can interpolate to them.
2301 // Special Notes :
2302 // Scope : public
2303 // Creator : Tom Russo, SNL, Electrical and Microsystems Modeling.
2304 // Creation Date : 02/14/07
2305 //-----------------------------------------------------------------------------
2307 {
2308  double t;
2309  outputInterpolationTimes_.clear();
2310  // if there are no output control options specified, we do nothing.
2311  if (anaManagerRCPtr_->outputIntervalSpecified_())
2312  {
2313  if (anaManagerRCPtr_->outputIntervals_.empty() || currTime <= anaManagerRCPtr_->outputIntervals_[0].first)
2314  {
2315  // we're either in the first interval, or there only *is* one interval
2316  t=anaManagerRCPtr_->nextOutputTime_;
2317  while (t < currTime)
2318  {
2319  outputInterpolationTimes_.push_back(t);
2320  t += anaManagerRCPtr_->initialOutputInterval_;
2321  }
2322 
2323  if( (t - currTime) <= 100 * N_UTL_MachineDependentParams::MachinePrecision() )
2324  {
2325  outputInterpolationTimes_.push_back(currTime);
2326  }
2327 
2328  if( (t - tiaParams.finalTime) > 100 * N_UTL_MachineDependentParams::MachinePrecision() )
2329  {
2330  // tack on finalTime or we'll miss it
2332  }
2333  }
2334  else // we're out of the first interval, and there is more than one
2335  {
2336  int outInt,lastInt;
2337 
2338  lastInt=anaManagerRCPtr_->outputIntervals_.size()-1;
2339 
2340  // find which interval nextOutputTime_ is in
2341  for (outInt=0;
2342  outInt<lastInt&&anaManagerRCPtr_->outputIntervals_[outInt+1].first<=anaManagerRCPtr_->nextOutputTime_;
2343  ++outInt) ;
2344 
2345  t=anaManagerRCPtr_->nextOutputTime_;
2346  while (t <= currTime)
2347  {
2348  outputInterpolationTimes_.push_back(t);
2349  t += anaManagerRCPtr_->outputIntervals_[outInt].second;
2350  if (outInt != lastInt && t >= anaManagerRCPtr_->outputIntervals_[outInt+1].first)
2351  {
2352  ++outInt;
2353  t = anaManagerRCPtr_->outputIntervals_[outInt].first;
2354  }
2355  }
2356  }
2357  }
2358 }
2359 
2360 } // namespace Analysis
2361 } // namespace Xyce