Tempus  Version of the Day
Time Integration
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 {
103  TEUCHOS_TEST_FOR_EXCEPTION(
104  (getInitTime() > getFinalTime() ), std::logic_error,
105  "Error - Inconsistent time range.\n"
106  " (timeMin = "<<getInitTime()<<") > (timeMax = "<<getFinalTime()<<")\n");
107 
108  TEUCHOS_TEST_FOR_EXCEPTION(
109  (getMinTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
110  std::logic_error,
111  "Error - Negative minimum time step. dtMin = "<<getMinTimeStep()<<")\n");
112  TEUCHOS_TEST_FOR_EXCEPTION(
113  (getMaxTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
114  std::logic_error,
115  "Error - Negative maximum time step. dtMax = "<<getMaxTimeStep()<<")\n");
116  TEUCHOS_TEST_FOR_EXCEPTION(
117  (getMinTimeStep() > getMaxTimeStep() ), std::logic_error,
118  "Error - Inconsistent time step range.\n"
119  " (dtMin = "<<getMinTimeStep()<<") > (dtMax = "<<getMaxTimeStep()<<")\n");
120  TEUCHOS_TEST_FOR_EXCEPTION(
121  (getInitTimeStep() < Teuchos::ScalarTraits<Scalar>::zero() ),
122  std::logic_error,
123  "Error - Negative initial time step. dtInit = "<<getInitTimeStep()<<")\n");
124  TEUCHOS_TEST_FOR_EXCEPTION(
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 
133  TEUCHOS_TEST_FOR_EXCEPTION(
134  (getInitIndex() > getFinalIndex() ), std::logic_error,
135  "Error - Inconsistent time index range.\n"
136  " (iStepMin = "<<getInitIndex()<<") > (iStepMax = "
137  <<getFinalIndex()<<")\n");
138 
139  TEUCHOS_TEST_FOR_EXCEPTION(
140  (getMaxAbsError() < Teuchos::ScalarTraits<Scalar>::zero() ),
141  std::logic_error,
142  "Error - Negative maximum time step. errorMaxAbs = "
143  <<getMaxAbsError()<<")\n");
144  TEUCHOS_TEST_FOR_EXCEPTION(
145  (getMaxRelError() < Teuchos::ScalarTraits<Scalar>::zero() ),
146  std::logic_error,
147  "Error - Negative maximum time step. errorMaxRel = "
148  <<getMaxRelError()<<")\n");
149 
150  TEUCHOS_TEST_FOR_EXCEPTION(
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 
158  TEUCHOS_TEST_FOR_EXCEPTION(
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.
366  TEUCHOS_TEST_FOR_EXCEPTION(
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") {
374  TEUCHOS_TEST_FOR_EXCEPTION(
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>
460  Teuchos::FancyOStream &out,
461  const Teuchos::EVerbosityLevel verbLevel) const
462 {
463  auto l_out = Teuchos::fancyOStream( out.getOStream() );
464  Teuchos::OSTab ostab(*l_out, 2, this->description());
465  l_out->setOutputToRootOnly(0);
466 
467  *l_out << "\n--- " << this->description() << " ---" <<std::endl;
468 
469  if (Teuchos::as<int>(verbLevel) >= Teuchos::as<int>(Teuchos::VERB_MEDIUM)) {
470  std::vector<int> idx = getOutputIndices();
471  std::ostringstream listIdx;
472  if (!idx.empty()) {
473  for(std::size_t i = 0; i < idx.size()-1; ++i) listIdx << idx[i] << ", ";
474  listIdx << idx[idx.size()-1];
475  }
476 
477  std::vector<Scalar> times = getOutputTimes();
478  std::ostringstream listTimes;
479  if (!times.empty()) {
480  for(std::size_t i = 0; i < times.size()-1; ++i)
481  listTimes << times[i] << ", ";
482  listTimes << times[times.size()-1];
483  }
484 
485  *l_out << " stepType = " << getStepType() << std::endl
486  << " initTime = " << getInitTime() << std::endl
487  << " finalTime = " << getFinalTime() << std::endl
488  << " minTimeStep = " << getMinTimeStep() << std::endl
489  << " initTimeStep = " << getInitTimeStep() << std::endl
490  << " maxTimeStep = " << getMaxTimeStep() << std::endl
491  << " initIndex = " << getInitIndex() << std::endl
492  << " finalIndex = " << getFinalIndex() << std::endl
493  << " maxAbsError = " << getMaxAbsError() << std::endl
494  << " maxRelError = " << getMaxRelError() << std::endl
495  << " maxFailures = " << getMaxFailures() << std::endl
496  << " maxConsecFailures = " << getMaxConsecFailures() << std::endl
497  << " numTimeSteps = " << getNumTimeSteps() << std::endl
498  << " printDtChanges = " << getPrintDtChanges() << std::endl
499  << " outputExactly = " << getOutputExactly() << std::endl
500  << " outputIndices = " << listIdx.str() << std::endl
501  << " outputTimes = " << listTimes.str() << std::endl
502  << " outputIndexInterval= " << getOutputIndexInterval() << std::endl
503  << " outputTimeInterval = " << getOutputTimeInterval() << std::endl
504  << " outputAdjustedDt = " << outputAdjustedDt_ << std::endl
505  << " dtAfterOutput = " << dtAfterOutput_ <<std::endl;
506  stepControlStrategy_->describe(*l_out, verbLevel);
507  }
508  *l_out << std::string(this->description().length()+8, '-') <<std::endl;
509 
510 }
511 
512 
513 template<class Scalar>
515  Teuchos::RCP<TimeStepControlStrategy<Scalar> > tscs)
516 {
517  using Teuchos::rcp;
518 
519  if ( tscs != Teuchos::null ) {
520  stepControlStrategy_ = tscs;
521  } else {
522  stepControlStrategy_ =
523  rcp(new TimeStepControlStrategyConstant<Scalar>(getInitTimeStep()));
524  }
525  isInitialized_ = false;
526 }
527 
528 
529 template<class Scalar>
530 Teuchos::RCP<const Teuchos::ParameterList>
532 {
533  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList("Time Step Control");
534 
535  pl->set<double>("Initial Time" , getInitTime() , "Initial time");
536  pl->set<double>("Final Time" , getFinalTime() , "Final time");
537  pl->set<double>("Minimum Time Step" , getMinTimeStep() , "Minimum time step size");
538  pl->set<double>("Initial Time Step" , getInitTimeStep(), "Initial time step size");
539  pl->set<double>("Maximum Time Step" , getMaxTimeStep() , "Maximum time step size");
540  pl->set<int> ("Initial Time Index" , getInitIndex() , "Initial time index");
541  pl->set<int> ("Final Time Index" , getFinalIndex() , "Final time index");
542  pl->set<int> ("Number of Time Steps", getNumTimeSteps(),
543  "The number of constant time steps. The actual step size gets computed\n"
544  "on the fly given the size of the time domain. Overides and resets\n"
545  " 'Final Time Index' = 'Initial Time Index' + 'Number of Time Steps'\n"
546  " 'Initial Time Step' = "
547  "('Final Time' - 'Initial Time')/'Number of Time Steps'\n");
548  pl->set<double>("Maximum Absolute Error", getMaxAbsError() , "Maximum absolute error");
549  pl->set<double>("Maximum Relative Error", getMaxRelError() , "Maximum relative error");
550 
551  pl->set<bool> ("Print Time Step Changes", getPrintDtChanges(),
552  "Print timestep size when it changes");
553 
554  pl->set<bool>("Output Exactly On Output Times", getOutputExactly(),
555  "This determines if the timestep size will be adjusted to exactly land\n"
556  "on the output times for 'Variable' timestepping (default=true).\n"
557  "When set to 'false' or for 'Constant' time stepping, the timestep\n"
558  "following the output time will be flagged for output.\n");
559 
560  pl->set<int> ("Output Index Interval", getOutputIndexInterval(), "Output index interval");
561  pl->set<double>("Output Time Interval", getOutputTimeInterval(), "Output time interval");
562 
563  {
564  std::vector<int> idx = getOutputIndices();
565  std::ostringstream list;
566  if (!idx.empty()) {
567  for(std::size_t i = 0; i < idx.size()-1; ++i) list << idx[i] << ", ";
568  list << idx[idx.size()-1];
569  }
570  pl->set<std::string>("Output Index List", list.str(),
571  "Comma deliminated list of output indices");
572  }
573  {
574  std::vector<Scalar> times = getOutputTimes();
575  std::ostringstream list;
576  if (!times.empty()) {
577  for(std::size_t i = 0; i < times.size()-1; ++i) list << times[i] << ", ";
578  list << times[times.size()-1];
579  }
580  pl->set<std::string>("Output Time List", list.str(),
581  "Comma deliminated list of output times");
582  }
583 
584  pl->set<int> ("Maximum Number of Stepper Failures", getMaxFailures(),
585  "Maximum number of Stepper failures");
586  pl->set<int> ("Maximum Number of Consecutive Stepper Failures", getMaxConsecFailures(),
587  "Maximum number of consecutive Stepper failures");
588 
589  pl->set("Time Step Control Strategy", *stepControlStrategy_->getValidParameters());
590 
591  return pl;
592 }
593 
594 
595 // Nonmember constructor - ParameterList
596 // ------------------------------------------------------------------------
597 template <class Scalar>
598 Teuchos::RCP<TimeStepControl<Scalar> > createTimeStepControl(
599  Teuchos::RCP<Teuchos::ParameterList> const& pList, bool runInitialize)
600 {
601  using Teuchos::RCP;
602  using Teuchos::ParameterList;
603 
604  auto tsc = Teuchos::rcp(new TimeStepControl<Scalar>());
605  if (pList == Teuchos::null) return tsc;
606 
607  pList->validateParametersAndSetDefaults(*tsc->getValidParameters(), 0);
608 
609  tsc->setInitTime( pList->get<double>("Initial Time"));
610  tsc->setFinalTime( pList->get<double>("Final Time"));
611  tsc->setMinTimeStep( pList->get<double>("Minimum Time Step"));
612  tsc->setInitTimeStep( pList->get<double>("Initial Time Step"));
613  tsc->setMaxTimeStep( pList->get<double>("Maximum Time Step"));
614  tsc->setInitIndex( pList->get<int> ("Initial Time Index"));
615  tsc->setFinalIndex( pList->get<int> ("Final Time Index"));
616  tsc->setMaxAbsError( pList->get<double>("Maximum Absolute Error"));
617  tsc->setMaxRelError( pList->get<double>("Maximum Relative Error"));
618  tsc->setMaxFailures( pList->get<int> ("Maximum Number of Stepper Failures"));
619  tsc->setMaxConsecFailures(pList->get<int> ("Maximum Number of Consecutive Stepper Failures"));
620  tsc->setPrintDtChanges( pList->get<bool> ("Print Time Step Changes"));
621  tsc->setNumTimeSteps( pList->get<int> ("Number of Time Steps"));
622 
623  tsc->setOutputExactly( pList->get<bool> ("Output Exactly On Output Times"));
624 
625  // Parse output indices
626  {
627  std::vector<int> outputIndices;
628  outputIndices.clear();
629  std::string str = pList->get<std::string>("Output Index List");
630  std::string delimiters(",");
631  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
632  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
633  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
634  std::string token = str.substr(lastPos,pos-lastPos);
635  outputIndices.push_back(int(std::stoi(token)));
636  if(pos==std::string::npos) break;
637 
638  lastPos = str.find_first_not_of(delimiters, pos);
639  pos = str.find_first_of(delimiters, lastPos);
640  }
641 
642  // order output indices
643  std::sort(outputIndices.begin(),outputIndices.end());
644  tsc->setOutputIndices(outputIndices);
645  }
646 
647  tsc->setOutputIndexInterval(pList->get<int>("Output Index Interval"));
648 
649  // Parse output times
650  {
651  std::vector<Scalar> outputTimes;
652  outputTimes.clear();
653  std::string str = pList->get<std::string>("Output Time List");
654  std::string delimiters(",");
655  // Skip delimiters at the beginning
656  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
657  // Find the first delimiter
658  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
659  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
660  // Found a token, add it to the vector
661  std::string token = str.substr(lastPos,pos-lastPos);
662  outputTimes.push_back(Scalar(std::stod(token)));
663  if(pos==std::string::npos) break;
664 
665  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
666  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
667  }
668 
669  // order output times
670  std::sort(outputTimes.begin(),outputTimes.end());
671  outputTimes.erase(std::unique(outputTimes.begin(),
672  outputTimes.end() ),
673  outputTimes.end() );
674  tsc->setOutputTimes(outputTimes);
675  }
676 
677  tsc->setOutputTimeInterval(pList->get<double>("Output Time Interval"));
678 
679 
680  if ( !pList->isParameter("Time Step Control Strategy") ) {
681 
682  tsc->setTimeStepControlStrategy(); // i.e, set default Constant timestep strategy.
683 
684  } else {
685 
686  RCP<ParameterList> tscsPL =
687  Teuchos::sublist(pList, "Time Step Control Strategy", true);
688 
689  auto strategyType = tscsPL->get<std::string>("Strategy Type");
690  if (strategyType == "Constant") {
691  tsc->setTimeStepControlStrategy(
692  createTimeStepControlStrategyConstant<Scalar>(tscsPL));
693  } else if (strategyType == "Basic VS") {
694  tsc->setTimeStepControlStrategy(
695  createTimeStepControlStrategyBasicVS<Scalar>(tscsPL));
696  } else if (strategyType == "Integral Controller") {
697  tsc->setTimeStepControlStrategy(
698  createTimeStepControlStrategyIntegralController<Scalar>(tscsPL));
699  } else if (strategyType == "Composite") {
700  tsc->setTimeStepControlStrategy(
701  createTimeStepControlStrategyComposite<Scalar>(tscsPL));
702  } else {
703  RCP<Teuchos::FancyOStream> out =
704  Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
705  out->setOutputToRootOnly(0);
706  Teuchos::OSTab ostab(out,1, "createTimeStepControl()");
707  *out << "Warning -- Did not find a Tempus strategy to create!\n"
708  << "'Strategy Type' = '" << strategyType << "'\n"
709  << "Should call setTimeStepControlStrategy() with this\n"
710  << "(app-specific?) strategy, and initialize().\n" << std::endl;
711  }
712  }
713 
714  if (runInitialize) tsc->initialize();
715  return tsc;
716 }
717 
718 
719 } // namespace Tempus
720 #endif // Tempus_TimeStepControl_impl_hpp
Teuchos::RCP< TimeStepControl< Scalar > > createTimeStepControl(Teuchos::RCP< Teuchos::ParameterList > const &pList, bool runInitialize=true)
Nonmember constructor from ParameterList.
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
virtual void setNumTimeSteps(int numTimeSteps)
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return ParameterList with current values.
virtual void setTimeStepControlStrategy(Teuchos::RCP< TimeStepControlStrategy< Scalar > > tscs=Teuchos::null)
Status
Status for the Integrator, the Stepper and the SolutionState.
virtual void printDtChanges(int istep, Scalar dt_old, Scalar dt_new, std::string reason) const
TimeStepControl manages the time step size. There several mechanisms that effect the time step size a...
TimeStepControl()
Default Constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
StepControlStrategy class for TimeStepControl.
virtual void setNextTimeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory, Status &integratorStatus)
Determine the time step size.
TimeStepControlStrategy class for TimeStepControl.
virtual bool indexInRange(const int iStep) const
Check if time step index is within minimum and maximum index.