Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_TimeStepControl_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ****************************************************************************
3 // Tempus: Copyright (2017) Sandia Corporation
4 //
5 // Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6 // ****************************************************************************
7 // @HEADER
8 
9 #ifndef Tempus_TimeStepControl_impl_hpp
10 #define Tempus_TimeStepControl_impl_hpp
11 
12 #include "Teuchos_TimeMonitor.hpp"
13 
18 
19 
20 namespace Tempus {
21 
22 template<class Scalar>
24  : isInitialized_ (false),
25  initTime_ (0.0),
26  finalTime_ (1.0e+99),
27  minTimeStep_ (0.0),
28  initTimeStep_ (1.0),
29  maxTimeStep_ (1.0e+99),
30  initIndex_ (0),
31  finalIndex_ (1000000),
32  maxAbsError_ (1.0e-08),
33  maxRelError_ (1.0e-08),
34  maxFailures_ (10),
35  maxConsecFailures_ (5),
36  numTimeSteps_ (-1),
37  printDtChanges_ (true),
38  outputExactly_ (true),
39  //outputIndices_ (),
40  //outputTimes_ (),
41  outputIndexInterval_(1000000),
42  outputTimeInterval_ (1.0e+99),
43  outputAdjustedDt_(false),
44  dtAfterOutput_(0.0)
45 {
47  this->initialize();
48 }
49 
50 
51 template<class Scalar>
53  Scalar initTime,
54  Scalar finalTime,
55  Scalar minTimeStep,
56  Scalar initTimeStep,
57  Scalar maxTimeStep,
58  int initIndex,
59  int finalIndex,
60  Scalar maxAbsError,
61  Scalar maxRelError,
62  int maxFailures,
63  int maxConsecFailures,
64  int numTimeSteps,
65  bool printDtChanges,
66  bool outputExactly,
67  std::vector<int> outputIndices,
68  std::vector<Scalar> outputTimes,
69  int outputIndexInterval,
70  Scalar outputTimeInterval,
71  Teuchos::RCP<TimeStepControlStrategy<Scalar>> stepControlStrategy)
72  : isInitialized_ (false ),
73  initTime_ (initTime ),
74  finalTime_ (finalTime ),
75  minTimeStep_ (minTimeStep ),
76  initTimeStep_ (initTimeStep ),
77  maxTimeStep_ (maxTimeStep ),
78  initIndex_ (initIndex ),
79  finalIndex_ (finalIndex ),
80  maxAbsError_ (maxAbsError ),
81  maxRelError_ (maxRelError ),
82  maxFailures_ (maxFailures ),
83  maxConsecFailures_ (maxConsecFailures ),
84  numTimeSteps_ (numTimeSteps ),
85  printDtChanges_ (printDtChanges ),
86  outputExactly_ (outputExactly ),
87  outputIndices_ (outputIndices ),
88  outputTimes_ (outputTimes ),
89  outputIndexInterval_(outputIndexInterval),
90  outputTimeInterval_ (outputTimeInterval ),
91  outputAdjustedDt_ (false ),
92  dtAfterOutput_ (0.0 ),
93  stepControlStrategy_(stepControlStrategy)
94 {
96  this->initialize();
97 }
98 
99 
100 template<class Scalar>
102 {
104  (getInitTime() > getFinalTime() ), std::logic_error,
105  "Error - Inconsistent time range.\n"
106  " (timeMin = "<<getInitTime()<<") > (timeMax = "<<getFinalTime()<<")\n");
107 
109  (getMinTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
110  std::logic_error,
111  "Error - Negative minimum time step. dtMin = "<<getMinTimeStep()<<")\n");
113  (getMaxTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
114  std::logic_error,
115  "Error - Negative maximum time step. dtMax = "<<getMaxTimeStep()<<")\n");
117  (getMinTimeStep() > getMaxTimeStep() ), std::logic_error,
118  "Error - Inconsistent time step range.\n"
119  " (dtMin = "<<getMinTimeStep()<<") > (dtMax = "<<getMaxTimeStep()<<")\n");
121  (getInitTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
122  std::logic_error,
123  "Error - Negative initial time step. dtInit = "<<getInitTimeStep()<<")\n");
125  (getInitTimeStep() < getMinTimeStep() ||
126  getInitTimeStep() > getMaxTimeStep() ),
127  std::out_of_range,
128  "Error - Initial time step is out of range.\n"
129  << " [dtMin, dtMax] = [" << getMinTimeStep() << ", "
130  << getMaxTimeStep() << "]\n"
131  << " dtInit = " << getInitTimeStep() << "\n");
132 
134  (getInitIndex() > getFinalIndex() ), std::logic_error,
135  "Error - Inconsistent time index range.\n"
136  " (iStepMin = "<<getInitIndex()<<") > (iStepMax = "
137  <<getFinalIndex()<<")\n");
138 
140  (getMaxAbsError() < Teuchos::ScalarTraits<Scalar>::zero() ),
141  std::logic_error,
142  "Error - Negative maximum time step. errorMaxAbs = "
143  <<getMaxAbsError()<<")\n");
145  (getMaxRelError() < Teuchos::ScalarTraits<Scalar>::zero() ),
146  std::logic_error,
147  "Error - Negative maximum time step. errorMaxRel = "
148  <<getMaxRelError()<<")\n");
149 
151  (getStepType() != "Constant" && getStepType() != "Variable"),
152  std::out_of_range,
153  "Error - 'Step Type' does not equal one of these:\n"
154  << " 'Constant' - Integrator will take constant time step sizes.\n"
155  << " 'Variable' - Integrator will allow changes to the time step size.\n"
156  << " stepType = " << getStepType() << "\n");
157 
159  (stepControlStrategy_ == Teuchos::null), std::logic_error,
160  "Error - Strategy is unset!\n");
161 
162  stepControlStrategy_->initialize();
163 
164  isInitialized_ = true; // Only place where this is set to true!
165 }
166 
167 
168 template<class Scalar>
170 printDtChanges(int istep, Scalar dt_old, Scalar dt_new, std::string reason) const
171 {
172  if (!getPrintDtChanges()) return;
173 
174  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
175  out->setOutputToRootOnly(0);
176  Teuchos::OSTab ostab(out,0,"printDtChanges");
177 
178  std::stringstream message;
179  message << std::scientific
180  <<std::setw(6)<<std::setprecision(3)<<istep
181  << " * (dt = "<<std::setw(9)<<std::setprecision(3)<<dt_old
182  << ", new = "<<std::setw(9)<<std::setprecision(3)<<dt_new
183  << ") " << reason << std::endl;
184  *out << message.str();
185 }
186 
187 
188 template<class Scalar>
190 {
191  if ( !isInitialized_ ) {
192  this->describe( *(this->getOStream()), Teuchos::VERB_MEDIUM);
193  TEUCHOS_TEST_FOR_EXCEPTION( !isInitialized_, std::logic_error,
194  "Error - " << this->description() << " is not initialized!");
195  }
196 }
197 
198 
199 template<class Scalar>
201  const Teuchos::RCP<SolutionHistory<Scalar> > & solutionHistory,
202  Status & integratorStatus)
203 {
204  using Teuchos::RCP;
205 
206  checkInitialized();
207 
208  TEMPUS_FUNC_TIME_MONITOR("Tempus::TimeStepControl::setNextTimeStep()");
209  {
210  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
211  const Scalar lastTime = solutionHistory->getCurrentState()->getTime();
212  const int iStep = workingState->getIndex();
213  Scalar dt = workingState->getTimeStep();
214  Scalar time = workingState->getTime();
215  bool output = false;
216 
217  RCP<StepperState<Scalar> > stepperState = workingState->getStepperState();
218 
219  // If last time step was adjusted for output, reinstate previous dt.
220  if (getStepType() == "Variable") {
221  if (outputAdjustedDt_ == true) {
222  printDtChanges(iStep, dt, dtAfterOutput_, "Reset dt after output.");
223  dt = dtAfterOutput_;
224  time = lastTime + dt;
225  outputAdjustedDt_ = false;
226  dtAfterOutput_ = 0.0;
227  }
228 
229  if (dt <= 0.0) {
230  printDtChanges(iStep, dt, getInitTimeStep(), "Reset dt to initial dt.");
231  dt = getInitTimeStep();
232  time = lastTime + dt;
233  }
234 
235  if (dt < getMinTimeStep()) {
236  printDtChanges(iStep, dt, getMinTimeStep(), "Reset dt to minimum dt.");
237  dt = getMinTimeStep();
238  time = lastTime + dt;
239  }
240  }
241 
242  // Update dt for the step control strategy to be informed
243  workingState->setTimeStep(dt);
244  workingState->setTime(time);
245 
246  // Call the step control strategy (to update dt if needed)
247  stepControlStrategy_->setNextTimeStep(*this, solutionHistory,
248  integratorStatus);
249 
250  // Get the dt (probably have changed by stepControlStrategy_)
251  dt = workingState->getTimeStep();
252  time = workingState->getTime();
253 
254  if (getStepType() == "Variable") {
255  if (dt < getMinTimeStep()) { // decreased below minimum dt
256  printDtChanges(iStep, dt, getMinTimeStep(),
257  "dt is too small. Resetting to minimum dt.");
258  dt = getMinTimeStep();
259  time = lastTime + dt;
260  }
261  if (dt > getMaxTimeStep()) { // increased above maximum dt
262  printDtChanges(iStep, dt, getMaxTimeStep(),
263  "dt is too large. Resetting to maximum dt.");
264  dt = getMaxTimeStep();
265  time = lastTime + dt;
266  }
267  }
268 
269 
270  // Check if we need to output this step index
271  std::vector<int>::const_iterator it =
272  std::find(getOutputIndices().begin(), getOutputIndices().end(), iStep);
273  if (it != getOutputIndices().end()) output = true;
274 
275  const int iInterval = getOutputIndexInterval();
276  if ( (iStep - getInitIndex()) % iInterval == 0) output = true;
277 
278  // Check if we need to output in the next timestep based on
279  // outputTimes_ or "Output Time Interval".
280  Scalar reltol = 1.0e-6;
281  Scalar endTime = lastTime+dt+getMinTimeStep();
282  // getMinTimeStep() = dt for constant time step
283  // so we can't add it on here
284  if (getStepType() == "Constant") endTime = lastTime+dt;
285  bool checkOutput = false;
286  Scalar oTime = getInitTime();
287  for (size_t i=0; i < outputTimes_.size(); ++i) {
288  oTime = outputTimes_[i];
289  if (lastTime < oTime && oTime <= endTime) {
290  checkOutput = true;
291  break;
292  }
293  }
294  const Scalar tInterval = getOutputTimeInterval();
295  Scalar oTime2 = ceil((lastTime-getInitTime())/tInterval)*tInterval
296  + getInitTime();
297  if (lastTime < oTime2 && oTime2 <= endTime) {
298  if (checkOutput == true) {
299  if (oTime2 < oTime) oTime = oTime2; // Use the first output time.
300  } else {
301  checkOutput = true;
302  oTime = oTime2;
303  }
304  }
305 
306  if (checkOutput == true) {
307  const bool outputExactly = getOutputExactly();
308  if (getStepType() == "Variable" && outputExactly == true) {
309  // Adjust time step to hit output times.
310  if ( time > oTime ) {
311  output = true;
312  printDtChanges(iStep, dt, oTime - lastTime,
313  "Adjusting dt to hit the next output time.");
314  // Next output time is not near next time
315  // (>getMinTimeStep() away from it).
316  // Take time step to hit output time.
317  outputAdjustedDt_ = true;
318  dtAfterOutput_ = dt;
319  dt = oTime - lastTime;
320  time = lastTime + dt;
321  } else if (std::fabs((time-oTime)/(time)) < reltol) {
322  output = true;
323  printDtChanges(iStep, dt, oTime - lastTime,
324  "Adjusting dt for numerical roundoff to hit the next output time.");
325  // Next output time IS VERY near next time (<reltol away from it),
326  // e.g., adjust for numerical roundoff.
327  outputAdjustedDt_ = true;
328  dtAfterOutput_ = dt;
329  dt = oTime - lastTime;
330  time = lastTime + dt;
331  } else if (std::fabs((time + getMinTimeStep() - oTime)/oTime) < reltol ) {
332  printDtChanges(iStep, dt, (oTime - lastTime)/2.0,
333  "The next output time is within the minimum dt of the next time. "
334  "Adjusting dt to take two steps.");
335  // Next output time IS near next time
336  // (<getMinTimeStep() away from it).
337  // Take two time steps to get to next output time.
338  dt = (oTime - lastTime)/2.0;
339  time = lastTime + dt;
340  }
341  } else {
342  // Stepping over output time and want this time step for output,
343  // but do not want to change dt. Either because of 'Constant' time
344  // step or user specification, "Output Exactly On Output Times"=false.
345  output = true;
346  }
347  }
348 
349  // Adjust time step to hit final time or correct for small
350  // numerical differences.
351  if (getStepType() == "Variable") {
352  if ((lastTime + dt > getFinalTime() ) ||
353  (std::fabs((lastTime+dt-getFinalTime())/(lastTime+dt)) < reltol)) {
354  printDtChanges(iStep, dt, getFinalTime() - lastTime,
355  "Adjusting dt to hit final time.");
356  dt = getFinalTime() - lastTime;
357  time = lastTime + dt;
358  }
359  }
360 
361  // Check for negative time step.
362  TEUCHOS_TEST_FOR_EXCEPTION( dt <= Scalar(0.0), std::out_of_range,
363  "Error - Time step is not positive. dt = " << dt <<"\n");
364 
365  // Time step always needs to keep time within range.
367  (lastTime + dt < getInitTime()), std::out_of_range,
368  "Error - Time step does not move time INTO time range.\n"
369  " [timeMin, timeMax] = [" << getInitTime() << ", "
370  << getFinalTime() << "]\n"
371  " T + dt = " << lastTime <<" + "<< dt <<" = " << lastTime + dt <<"\n");
372 
373  if (getStepType() == "Variable") {
375  (lastTime + dt > getFinalTime()), std::out_of_range,
376  "Error - Time step move time OUT OF time range.\n"
377  " [timeMin, timeMax] = [" << getInitTime() << ", "
378  << getFinalTime() << "]\n"
379  " T + dt = " << lastTime <<" + "<< dt <<" = " << lastTime + dt <<"\n");
380  }
381 
382  workingState->setTimeStep(dt);
383  workingState->setTime(time);
384  workingState->setOutput(output);
385  }
386  return;
387 }
388 
389 
391 template<class Scalar>
392 bool TimeStepControl<Scalar>::timeInRange(const Scalar time) const
393 {
394  // Get absolute tolerance 1.0e-(i+14), i.e., 14 digits of accuracy.
395  const int relTol = 14;
396  const int i =
397  (getInitTime() == 0) ? 0 : 1 + (int)std::floor(std::log10(std::fabs(getInitTime()) ) );
398  const Scalar absTolInit = std::pow(10, i-relTol);
399  const int j =
400  (getFinalTime() == 0) ? 0 : 1 + (int)std::floor(std::log10(std::fabs(getFinalTime()) ) );
401  const Scalar absTolFinal = std::pow(10, j-relTol);
402 
403  const bool test1 = getInitTime() - absTolInit <= time;
404  const bool test2 = time < getFinalTime() - absTolFinal;
405 
406  return (test1 && test2);
407 }
408 
409 
411 template<class Scalar>
412 bool TimeStepControl<Scalar>::indexInRange(const int iStep) const{
413  bool iir = (getInitIndex() <= iStep && iStep < getFinalIndex());
414  return iir;
415 }
416 
417 
418 template<class Scalar>
420 {
421  TEUCHOS_TEST_FOR_EXCEPTION( getStepType() != "Constant", std::out_of_range,
422  "Error - Can only use setNumTimeSteps() when 'Step Type' == 'Constant'.\n");
423 
424  if (numTimeSteps >= 0) {
425  numTimeSteps_ = numTimeSteps;
426  setFinalIndex(getInitIndex() + numTimeSteps_);
427  Scalar initTimeStep;
428  if (numTimeSteps_ == 0)
429  initTimeStep = Scalar(0.0);
430  else
431  initTimeStep = (getFinalTime() - getInitTime())/numTimeSteps_;
432  setInitTimeStep(initTimeStep);
433  setMinTimeStep (initTimeStep);
434  setMaxTimeStep (initTimeStep);
435 
436  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
437  out->setOutputToRootOnly(0);
438  Teuchos::OSTab ostab(out,1,"setNumTimeSteps");
439  *out << "Warning - setNumTimeSteps() Setting 'Number of Time Steps' = " << getNumTimeSteps()
440  << " Set the following parameters: \n"
441  << " 'Final Time Index' = " << getFinalIndex() << "\n"
442  << " 'Initial Time Step' = " << getInitTimeStep() << "\n"
443  << " 'Step Type' = " << getStepType() << std::endl;
444 
445  isInitialized_ = false;
446  }
447 }
448 
449 
450 template<class Scalar>
452 {
453  std::string name = "Tempus::TimeStepControl";
454  return(name);
455 }
456 
457 
458 template<class Scalar>
461  const Teuchos::EVerbosityLevel verbLevel) const
462 {
463  if (verbLevel == Teuchos::VERB_EXTREME) {
464 
465  std::vector<int> idx = getOutputIndices();
466  std::ostringstream listIdx;
467  if (!idx.empty()) {
468  for(std::size_t i = 0; i < idx.size()-1; ++i) listIdx << idx[i] << ", ";
469  listIdx << idx[idx.size()-1];
470  }
471 
472  std::vector<Scalar> times = getOutputTimes();
473  std::ostringstream listTimes;
474  if (!times.empty()) {
475  for(std::size_t i = 0; i < times.size()-1; ++i) listTimes << times[i] << ", ";
476  listTimes << times[times.size()-1];
477  }
478 
479  auto l_out = Teuchos::fancyOStream( out.getOStream() );
480  l_out->setOutputToRootOnly(0);
481  *l_out << description() << "::describe:" << std::endl
482  << "stepType = " << getStepType() << std::endl
483  << "initTime = " << getInitTime() << std::endl
484  << "finalTime = " << getFinalTime() << std::endl
485  << "minTimeStep = " << getMinTimeStep() << std::endl
486  << "initTimeStep = " << getInitTimeStep() << std::endl
487  << "maxTimeStep = " << getMaxTimeStep() << std::endl
488  << "initIndex = " << getInitIndex() << std::endl
489  << "finalIndex = " << getFinalIndex() << std::endl
490  << "maxAbsError = " << getMaxAbsError() << std::endl
491  << "maxRelError = " << getMaxRelError() << std::endl
492  << "maxFailures = " << getMaxFailures() << std::endl
493  << "maxConsecFailures = " << getMaxConsecFailures() << std::endl
494  << "numTimeSteps = " << getNumTimeSteps() << std::endl
495  << "printDtChanges = " << getPrintDtChanges() << std::endl
496  << "outputExactly = " << getOutputExactly() << std::endl
497  << "outputIndices = " << listIdx.str() << std::endl
498  << "outputTimes = " << listTimes.str() << std::endl
499  << "outputIndexInterval= " << getOutputIndexInterval() << std::endl
500  << "outputTimeInterval = " << getOutputTimeInterval() << std::endl
501  << "outputAdjustedDt = " << outputAdjustedDt_ << std::endl
502  << "dtAfterOutput = " << dtAfterOutput_ << std::endl
503  << "stepControlSrategy = " << std::endl;
504  stepControlStrategy_->describe(out, verbLevel);
505  }
506 }
507 
508 
509 template<class Scalar>
512 {
513  using Teuchos::rcp;
514 
515  if ( tscs != Teuchos::null ) {
516  stepControlStrategy_ = tscs;
517  } else {
518  stepControlStrategy_ =
519  rcp(new TimeStepControlStrategyConstant<Scalar>(getInitTimeStep()));
520  }
521  isInitialized_ = false;
522 }
523 
524 
525 template<class Scalar>
528 {
529  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList("Time Step Control");
530 
531  pl->set<double>("Initial Time" , getInitTime() , "Initial time");
532  pl->set<double>("Final Time" , getFinalTime() , "Final time");
533  pl->set<double>("Minimum Time Step" , getMinTimeStep() , "Minimum time step size");
534  pl->set<double>("Initial Time Step" , getInitTimeStep(), "Initial time step size");
535  pl->set<double>("Maximum Time Step" , getMaxTimeStep() , "Maximum time step size");
536  pl->set<int> ("Initial Time Index" , getInitIndex() , "Initial time index");
537  pl->set<int> ("Final Time Index" , getFinalIndex() , "Final time index");
538  pl->set<int> ("Number of Time Steps", getNumTimeSteps(),
539  "The number of constant time steps. The actual step size gets computed\n"
540  "on the fly given the size of the time domain. Overides and resets\n"
541  " 'Final Time Index' = 'Initial Time Index' + 'Number of Time Steps'\n"
542  " 'Initial Time Step' = "
543  "('Final Time' - 'Initial Time')/'Number of Time Steps'\n");
544  pl->set<double>("Maximum Absolute Error", getMaxAbsError() , "Maximum absolute error");
545  pl->set<double>("Maximum Relative Error", getMaxRelError() , "Maximum relative error");
546 
547  pl->set<bool> ("Print Time Step Changes", getPrintDtChanges(),
548  "Print timestep size when it changes");
549 
550  pl->set<bool>("Output Exactly On Output Times", getOutputExactly(),
551  "This determines if the timestep size will be adjusted to exactly land\n"
552  "on the output times for 'Variable' timestepping (default=true).\n"
553  "When set to 'false' or for 'Constant' time stepping, the timestep\n"
554  "following the output time will be flagged for output.\n");
555 
556  pl->set<int> ("Output Index Interval", getOutputIndexInterval(), "Output index interval");
557  pl->set<double>("Output Time Interval", getOutputTimeInterval(), "Output time interval");
558 
559  {
560  std::vector<int> idx = getOutputIndices();
561  std::ostringstream list;
562  if (!idx.empty()) {
563  for(std::size_t i = 0; i < idx.size()-1; ++i) list << idx[i] << ", ";
564  list << idx[idx.size()-1];
565  }
566  pl->set<std::string>("Output Index List", list.str(),
567  "Comma deliminated list of output indices");
568  }
569  {
570  std::vector<Scalar> times = getOutputTimes();
571  std::ostringstream list;
572  if (!times.empty()) {
573  for(std::size_t i = 0; i < times.size()-1; ++i) list << times[i] << ", ";
574  list << times[times.size()-1];
575  }
576  pl->set<std::string>("Output Time List", list.str(),
577  "Comma deliminated list of output times");
578  }
579 
580  pl->set<int> ("Maximum Number of Stepper Failures", getMaxFailures(),
581  "Maximum number of Stepper failures");
582  pl->set<int> ("Maximum Number of Consecutive Stepper Failures", getMaxConsecFailures(),
583  "Maximum number of consecutive Stepper failures");
584 
585  pl->set("Time Step Control Strategy", *stepControlStrategy_->getValidParameters());
586 
587  return pl;
588 }
589 
590 
591 // Nonmember constructor - ParameterList
592 // ------------------------------------------------------------------------
593 template <class Scalar>
595  Teuchos::RCP<Teuchos::ParameterList> const& pList, bool runInitialize)
596 {
597  using Teuchos::RCP;
599 
600  auto tsc = Teuchos::rcp(new TimeStepControl<Scalar>());
601  if (pList == Teuchos::null) return tsc;
602 
603  pList->validateParametersAndSetDefaults(*tsc->getValidParameters(), 0);
604 
605  tsc->setInitTime( pList->get<double>("Initial Time"));
606  tsc->setFinalTime( pList->get<double>("Final Time"));
607  tsc->setMinTimeStep( pList->get<double>("Minimum Time Step"));
608  tsc->setInitTimeStep( pList->get<double>("Initial Time Step"));
609  tsc->setMaxTimeStep( pList->get<double>("Maximum Time Step"));
610  tsc->setInitIndex( pList->get<int> ("Initial Time Index"));
611  tsc->setFinalIndex( pList->get<int> ("Final Time Index"));
612  tsc->setMaxAbsError( pList->get<double>("Maximum Absolute Error"));
613  tsc->setMaxRelError( pList->get<double>("Maximum Relative Error"));
614  tsc->setMaxFailures( pList->get<int> ("Maximum Number of Stepper Failures"));
615  tsc->setMaxConsecFailures(pList->get<int> ("Maximum Number of Consecutive Stepper Failures"));
616  tsc->setPrintDtChanges( pList->get<bool> ("Print Time Step Changes"));
617  tsc->setNumTimeSteps( pList->get<int> ("Number of Time Steps"));
618 
619  tsc->setOutputExactly( pList->get<bool> ("Output Exactly On Output Times"));
620 
621  // Parse output indices
622  {
623  std::vector<int> outputIndices;
624  outputIndices.clear();
625  std::string str = pList->get<std::string>("Output Index List");
626  std::string delimiters(",");
627  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
628  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
629  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
630  std::string token = str.substr(lastPos,pos-lastPos);
631  outputIndices.push_back(int(std::stoi(token)));
632  if(pos==std::string::npos) break;
633 
634  lastPos = str.find_first_not_of(delimiters, pos);
635  pos = str.find_first_of(delimiters, lastPos);
636  }
637 
638  // order output indices
639  std::sort(outputIndices.begin(),outputIndices.end());
640  tsc->setOutputIndices(outputIndices);
641  }
642 
643  tsc->setOutputIndexInterval(pList->get<int>("Output Index Interval"));
644 
645  // Parse output times
646  {
647  std::vector<Scalar> outputTimes;
648  outputTimes.clear();
649  std::string str = pList->get<std::string>("Output Time List");
650  std::string delimiters(",");
651  // Skip delimiters at the beginning
652  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
653  // Find the first delimiter
654  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
655  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
656  // Found a token, add it to the vector
657  std::string token = str.substr(lastPos,pos-lastPos);
658  outputTimes.push_back(Scalar(std::stod(token)));
659  if(pos==std::string::npos) break;
660 
661  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
662  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
663  }
664 
665  // order output times
666  std::sort(outputTimes.begin(),outputTimes.end());
667  outputTimes.erase(std::unique(outputTimes.begin(),
668  outputTimes.end() ),
669  outputTimes.end() );
670  tsc->setOutputTimes(outputTimes);
671  }
672 
673  tsc->setOutputTimeInterval(pList->get<double>("Output Time Interval"));
674 
675 
676  if ( !pList->isParameter("Time Step Control Strategy") ) {
677 
678  tsc->setTimeStepControlStrategy(); // i.e, set default Constant timestep strategy.
679 
680  } else {
681 
682  RCP<ParameterList> tscsPL =
683  Teuchos::sublist(pList, "Time Step Control Strategy", true);
684 
685  auto strategyType = tscsPL->get<std::string>("Strategy Type");
686  if (strategyType == "Constant") {
687  tsc->setTimeStepControlStrategy(
688  createTimeStepControlStrategyConstant<Scalar>(tscsPL));
689  } else if (strategyType == "Basic VS") {
690  tsc->setTimeStepControlStrategy(
691  createTimeStepControlStrategyBasicVS<Scalar>(tscsPL));
692  } else if (strategyType == "Integral Controller") {
693  tsc->setTimeStepControlStrategy(
694  createTimeStepControlStrategyIntegralController<Scalar>(tscsPL));
695  } else if (strategyType == "Composite") {
696  tsc->setTimeStepControlStrategy(
697  createTimeStepControlStrategyComposite<Scalar>(tscsPL));
698  } else {
699  RCP<Teuchos::FancyOStream> out =
700  Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
701  out->setOutputToRootOnly(0);
702  Teuchos::OSTab ostab(out,1, "createTimeStepControl()");
703  *out << "Warning -- Did not find a Tempus strategy to create!\n"
704  << "'Strategy Type' = '" << strategyType << "'\n"
705  << "Should call setTimeStepControlStrategy() with this\n"
706  << "(app-specific?) strategy, and initialize().\n" << std::endl;
707  }
708  }
709 
710  if (runInitialize) tsc->initialize();
711  return tsc;
712 }
713 
714 
715 } // namespace Tempus
716 #endif // Tempus_TimeStepControl_impl_hpp
Teuchos::RCP< TimeStepControl< Scalar > > createTimeStepControl(Teuchos::RCP< Teuchos::ParameterList > const &pList, bool runInitialize=true)
Nonmember constructor from ParameterList.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
virtual void setNumTimeSteps(int numTimeSteps)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void printDtChanges(int istep, Scalar dt_old, Scalar dt_new, std::string reason) const
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void setTimeStepControlStrategy(Teuchos::RCP< TimeStepControlStrategy< Scalar > > tscs=Teuchos::null)
Status
Status for the Integrator, the Stepper and the SolutionState.
virtual bool indexInRange(const int iStep) const
Check if time step index is within minimum and maximum index.
TimeStepControl manages the time step size. There several mechanisms that effect the time step size a...
TimeStepControl()
Default Constructor.
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
StepControlStrategy class for TimeStepControl.
RCP< std::basic_ostream< char_type, traits_type > > getOStream()
virtual void setNextTimeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory, Status &integratorStatus)
Determine the time step size.
virtual bool timeInRange(const Scalar time) const
Check if time is within minimum and maximum time.
void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
TimeStepControlStrategy class for TimeStepControl.
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return ParameterList with current values.