114 TEUCHOS_TEST_FOR_EXCEPTION(
116 "Error - Inconsistent time range.\n"
120 TEUCHOS_TEST_FOR_EXCEPTION(
123 "Error - Negative minimum time step. dtMin = " <<
getMinTimeStep() <<
")\n");
124 TEUCHOS_TEST_FOR_EXCEPTION(
127 "Error - Negative maximum time step. dtMax = " <<
getMaxTimeStep() <<
")\n");
128 TEUCHOS_TEST_FOR_EXCEPTION(
130 "Error - Inconsistent time step range.\n"
133 TEUCHOS_TEST_FOR_EXCEPTION(
136 "Error - Negative initial time step. dtInit = " <<
getInitTimeStep() <<
")\n");
140 "Error - Initial time step is out of range.\n"
146 TEUCHOS_TEST_FOR_EXCEPTION(
148 "Error - Inconsistent time index range.\n"
152 TEUCHOS_TEST_FOR_EXCEPTION(
155 "Error - Negative maximum time step. errorMaxAbs = " <<
getMaxAbsError() <<
")\n");
156 TEUCHOS_TEST_FOR_EXCEPTION(
159 "Error - Negative maximum time step. errorMaxRel = " <<
getMaxRelError() <<
")\n");
162 std::logic_error,
"Error - Strategy is unset!\n");
166 TEUCHOS_TEST_FOR_EXCEPTION(
169 "Error - 'Step Type' does not equal one of these:\n"
170 <<
" 'Constant' - Integrator will take constant time step sizes.\n"
171 <<
" 'Variable' - Integrator will allow changes to the time step "
217 TEMPUS_FUNC_TIME_MONITOR(
"Tempus::TimeStepControl::setNextTimeStep()");
219 RCP<SolutionState<Scalar>> workingState =
220 solutionHistory->getWorkingState();
221 const Scalar lastTime = solutionHistory->getCurrentState()->getTime();
222 const int iStep = workingState->getIndex();
223 Scalar dt = workingState->getTimeStep();
224 Scalar time = workingState->getTime();
226 RCP<StepperState<Scalar>> stepperState = workingState->getStepperState();
232 "Reset dt after time event.");
234 time = lastTime + dt;
242 time = lastTime + dt;
248 time = lastTime + dt;
253 workingState->setTimeStep(dt);
254 workingState->setTime(time);
261 dt = workingState->getTimeStep();
262 time = workingState->getTime();
267 "dt is too small. Resetting to minimum dt.");
269 time = lastTime + dt;
273 "dt is too large. Resetting to maximum dt.");
275 time = lastTime + dt;
280 bool outputDueToIndex =
false;
281 std::vector<Teuchos::RCP<TimeEventBase<Scalar>>> constrainingTEs;
282 if (
timeEvent_->isIndex(iStep, constrainingTEs)) {
283 for (
auto& e : constrainingTEs) {
284 if (e->getName() ==
"Output Index Interval" ||
285 e->getName() ==
"Output Index List") {
286 outputDueToIndex =
true;
292 Scalar endTime = lastTime + dt;
298 timeEvent_->eventInRange(lastTime, endTime, constrainingTEs);
300 bool outputDueToTime =
false;
301 Scalar tone = endTime;
302 bool landOnExactly =
false;
305 for (
auto& e : constrainingTEs) {
306 if (e->getLandOnExactly() ==
true) {
307 const Scalar te_time = e->timeOfNextEvent(lastTime);
308 if (!landOnExactly || te_time < tone) tone = te_time;
309 landOnExactly =
true;
314 for (
auto& e : constrainingTEs) {
315 if (e->getName() ==
"Output Time Interval" ||
316 e->getName() ==
"Output Time List") {
317 if (
getStepType() !=
"Variable" || !e->getLandOnExactly() ||
318 e->timeOfNextEvent(lastTime) <=
320 outputDueToTime =
true;
325 Scalar reltol = 1.0e-6;
327 if (landOnExactly ==
true) {
333 "Adjusting dt to hit the next TimeEvent.");
336 dt = tone - lastTime;
337 time = lastTime + dt;
339 else if (std::fabs(time - tone) < reltol * std::fabs(time)) {
343 iStep, dt, tone - lastTime,
344 "Adjusting dt for numerical roundoff to hit the next TimeEvent.");
347 dt = tone - lastTime;
348 time = lastTime + dt;
351 reltol * std::fabs(tone)) {
356 iStep, dt, (tone - lastTime) / 2.0,
357 "The next TimeEvent is within the minimum dt of the next time. "
358 "Adjusting dt to take two steps.");
359 dt = (tone - lastTime) / 2.0;
360 time = lastTime + dt;
362 outputDueToTime =
false;
372 reltol * std::fabs(lastTime + dt))) {
374 "Adjusting dt to hit final time.");
376 time = lastTime + dt;
381 TEUCHOS_TEST_FOR_EXCEPTION(
382 dt <= Scalar(0.0), std::out_of_range,
383 "Error - Time step is not positive. dt = " << dt <<
"\n");
386 TEUCHOS_TEST_FOR_EXCEPTION(
387 (lastTime + dt <
getInitTime()), std::out_of_range,
388 "Error - Time step does not move time INTO time range.\n"
389 <<
" [timeMin, timeMax] = ["
392 << lastTime <<
" + " << dt <<
" = " << lastTime + dt <<
"\n");
395 TEUCHOS_TEST_FOR_EXCEPTION(
397 "Error - Time step move time OUT OF time range.\n"
398 <<
" [timeMin, timeMax] = ["
401 << lastTime <<
" + " << dt <<
" = " << lastTime + dt <<
"\n");
404 workingState->setTimeStep(dt);
405 workingState->setTime(time);
406 workingState->setOutput(outputDueToIndex || outputDueToTime);
627 Teuchos::FancyOStream& out,
const Teuchos::EVerbosityLevel verbLevel)
const
629 auto l_out = Teuchos::fancyOStream(out.getOStream());
630 Teuchos::OSTab ostab(*l_out, 2, this->
description());
631 l_out->setOutputToRootOnly(0);
633 *l_out <<
"\n--- " << this->
description() <<
" ---" << std::endl;
635 if (Teuchos::as<int>(verbLevel) >= Teuchos::as<int>(Teuchos::VERB_MEDIUM)) {
637 std::ostringstream listIdx;
639 for (std::size_t i = 0; i < idx.size() - 1; ++i)
640 listIdx << idx[i] <<
", ";
641 listIdx << idx[idx.size() - 1];
645 std::ostringstream listTimes;
646 if (!times.empty()) {
647 for (std::size_t i = 0; i < times.size() - 1; ++i)
648 listTimes << times[i] <<
", ";
649 listTimes << times[times.size() - 1];
652 *l_out <<
" stepType = " <<
getStepType() << std::endl
667 <<
" outputIndices = " << listIdx.str() << std::endl
668 <<
" outputTimes = " << listTimes.str() << std::endl
676 *l_out << std::string(this->
description().length() + 8,
'-') << std::endl;
683 Teuchos::RCP<Teuchos::ParameterList> pl =
684 Teuchos::parameterList(
"Time Step Control");
686 pl->set<
double>(
"Initial Time",
getInitTime(),
"Initial time");
687 pl->set<
double>(
"Final Time",
getFinalTime(),
"Final time");
689 "Minimum time step size");
691 "Initial time step size");
693 "Maximum time step size");
694 pl->set<
int>(
"Initial Time Index",
getInitIndex(),
"Initial time index");
695 pl->set<
int>(
"Final Time Index",
getFinalIndex(),
"Final time index");
698 "The number of constant time steps. The actual step size gets computed\n"
699 "on the fly given the size of the time domain. Overides and resets\n"
700 " 'Final Time Index' = 'Initial Time Index' + 'Number of Time "
702 " 'Initial Time Step' = "
703 "('Final Time' - 'Initial Time')/'Number of Time Steps'\n");
705 "Maximum absolute error");
707 "Maximum relative error");
710 "Print timestep size when it changes");
712 auto event =
timeEvent_->find(
"Output Index Interval");
713 if (event != Teuchos::null) {
714 auto teri = Teuchos::rcp_dynamic_cast<TimeEventRangeIndex<Scalar>>(event);
715 pl->set<
int>(
"Output Index Interval", teri->getIndexStride(),
716 "Output Index Interval");
719 event =
timeEvent_->find(
"Output Time Interval");
720 if (event != Teuchos::null) {
721 auto ter = Teuchos::rcp_dynamic_cast<TimeEventRange<Scalar>>(event);
722 pl->set<
double>(
"Output Time Interval", ter->getTimeStride(),
723 "Output time interval");
728 "This determines if the timestep size will be adjusted to exactly land\n"
729 "on the output times for 'Variable' timestepping (default=true).\n"
730 "When set to 'false' or for 'Constant' time stepping, the timestep\n"
731 "following the output time will be flagged for output.\n");
734 event =
timeEvent_->find(
"Output Index List");
735 std::ostringstream list;
736 if (event != Teuchos::null) {
737 auto teli = Teuchos::rcp_dynamic_cast<TimeEventListIndex<Scalar>>(event);
738 std::vector<int> idx = teli->getIndexList();
740 for (std::size_t i = 0; i < idx.size() - 1; ++i) list << idx[i] <<
", ";
741 list << idx[idx.size() - 1];
744 pl->set<std::string>(
"Output Index List", list.str(),
745 "Comma deliminated list of output indices");
750 std::ostringstream list;
751 if (event != Teuchos::null) {
752 auto teli = Teuchos::rcp_dynamic_cast<TimeEventList<Scalar>>(event);
753 std::vector<Scalar> times = teli->getTimeList();
754 if (!times.empty()) {
755 for (std::size_t i = 0; i < times.size() - 1; ++i)
756 list << times[i] <<
", ";
757 list << times[times.size() - 1];
760 pl->set<std::string>(
"Output Time List", list.str(),
761 "Comma deliminated list of output times");
767 tecTmp->setTimeEvents(
timeEvent_->getTimeEvents());
768 tecTmp->remove(
"Output Index Interval");
769 tecTmp->remove(
"Output Time Interval");
770 tecTmp->remove(
"Output Index List");
771 tecTmp->remove(
"Output Time List");
772 if (tecTmp->getSize() > 0)
773 pl->set(
"Time Step Control Events", *tecTmp->getValidParameters());
776 pl->set<
int>(
"Maximum Number of Stepper Failures",
getMaxFailures(),
777 "Maximum number of Stepper failures");
778 pl->set<
int>(
"Maximum Number of Consecutive Stepper Failures",
780 "Maximum number of consecutive Stepper failures");
782 pl->set(
"Time Step Control Strategy",
792 Teuchos::RCP<Teuchos::ParameterList>
const& pList,
bool runInitialize)
794 using Teuchos::ParameterList;
799 if (pList == Teuchos::null || pList->numParams() == 0)
return tsc;
802 Teuchos::rcp_const_cast<ParameterList>(tsc->getValidParameters());
804 if (pList->isSublist(
"Time Step Control Events")) {
805 RCP<ParameterList> tsctePL =
806 Teuchos::sublist(pList,
"Time Step Control Events",
true);
807 tscValidPL->set(
"Time Step Control Events", *tsctePL);
810 pList->validateParametersAndSetDefaults(*tscValidPL, 0);
812 tsc->setInitTime(pList->get<
double>(
"Initial Time"));
813 tsc->setFinalTime(pList->get<
double>(
"Final Time"));
814 tsc->setMinTimeStep(pList->get<
double>(
"Minimum Time Step"));
815 tsc->setInitTimeStep(pList->get<
double>(
"Initial Time Step"));
816 tsc->setMaxTimeStep(pList->get<
double>(
"Maximum Time Step"));
817 tsc->setInitIndex(pList->get<
int>(
"Initial Time Index"));
818 tsc->setFinalIndex(pList->get<
int>(
"Final Time Index"));
819 tsc->setMaxAbsError(pList->get<
double>(
"Maximum Absolute Error"));
820 tsc->setMaxRelError(pList->get<
double>(
"Maximum Relative Error"));
821 tsc->setMaxFailures(pList->get<
int>(
"Maximum Number of Stepper Failures"));
822 tsc->setMaxConsecFailures(
823 pList->get<
int>(
"Maximum Number of Consecutive Stepper Failures"));
824 tsc->setPrintDtChanges(pList->get<
bool>(
"Print Time Step Changes"));
825 tsc->setNumTimeSteps(pList->get<
int>(
"Number of Time Steps"));
828 tec->setName(
"Time Step Control Events");
831 std::vector<int> outputIndices;
832 outputIndices.clear();
833 std::string str = pList->get<std::string>(
"Output Index List");
834 std::string delimiters(
",");
835 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
836 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
837 while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
838 std::string token = str.substr(lastPos, pos - lastPos);
839 outputIndices.push_back(
int(std::stoi(token)));
840 if (pos == std::string::npos)
break;
842 lastPos = str.find_first_not_of(delimiters, pos);
843 pos = str.find_first_of(delimiters, lastPos);
846 if (!outputIndices.empty()) {
848 std::sort(outputIndices.begin(), outputIndices.end());
850 std::unique(outputIndices.begin(), outputIndices.end()),
851 outputIndices.end());
854 outputIndices,
"Output Index List")));
860 tsc->getInitIndex(), tsc->getFinalIndex(),
861 pList->get<
int>(
"Output Index Interval"),
"Output Index Interval")));
863 auto outputExactly = pList->get<
bool>(
"Output Exactly On Output Times",
true);
866 std::vector<Scalar> outputTimes;
868 std::string str = pList->get<std::string>(
"Output Time List");
869 std::string delimiters(
",");
871 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
873 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
874 while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
876 std::string token = str.substr(lastPos, pos - lastPos);
877 outputTimes.push_back(Scalar(std::stod(token)));
878 if (pos == std::string::npos)
break;
880 lastPos = str.find_first_not_of(delimiters, pos);
881 pos = str.find_first_of(delimiters, lastPos);
884 if (!outputTimes.empty()) {
886 std::sort(outputTimes.begin(), outputTimes.end());
887 outputTimes.erase(std::unique(outputTimes.begin(), outputTimes.end()),
891 outputTimes,
"Output Time List", outputExactly)));
898 pList->get<
double>(
"Output Time Interval"),
899 "Output Time Interval", outputExactly)));
901 if (pList->isSublist(
"Time Step Control Events")) {
902 RCP<ParameterList> tsctePL =
903 Teuchos::sublist(pList,
"Time Step Control Events",
true);
905 auto timeEventType = tsctePL->get<std::string>(
"Type",
"Unknown");
906 if (timeEventType ==
"Range") {
909 else if (timeEventType ==
"Range Index") {
912 else if (timeEventType ==
"List") {
915 else if (timeEventType ==
"List Index") {
918 else if (timeEventType ==
"Composite") {
920 auto timeEvents = tecTmp->getTimeEvents();
921 for (
auto& e : timeEvents) tec->add(e);
924 RCP<Teuchos::FancyOStream> out =
925 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
926 out->setOutputToRootOnly(0);
927 Teuchos::OSTab ostab(out, 1,
"createTimeStepControl()");
928 *out <<
"Warning -- Unknown Time Event Type!\n"
929 <<
"'Type' = '" << timeEventType <<
"'\n"
930 <<
"Should call add() with this "
931 <<
"(app-specific?) Time Event.\n"
936 tsc->setTimeEvents(tec);
938 if (!pList->isParameter(
"Time Step Control Strategy")) {
939 tsc->setTimeStepControlStrategy();
943 RCP<ParameterList> tscsPL =
944 Teuchos::sublist(pList,
"Time Step Control Strategy",
true);
946 auto strategyType = tscsPL->get<std::string>(
"Strategy Type");
947 if (strategyType ==
"Constant") {
948 tsc->setTimeStepControlStrategy(
951 else if (strategyType ==
"Basic VS") {
952 tsc->setTimeStepControlStrategy(
955 else if (strategyType ==
"Integral Controller") {
956 tsc->setTimeStepControlStrategy(
959 else if (strategyType ==
"Composite") {
960 tsc->setTimeStepControlStrategy(
964 RCP<Teuchos::FancyOStream> out =
965 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
966 out->setOutputToRootOnly(0);
967 Teuchos::OSTab ostab(out, 1,
"createTimeStepControl()");
968 *out <<
"Warning -- Did not find a Tempus strategy to create!\n"
969 <<
"'Strategy Type' = '" << strategyType <<
"'\n"
970 <<
"Should call setTimeStepControlStrategy() with this\n"
971 <<
"(app-specific?) strategy, and initialize().\n"
976 if (runInitialize) tsc->initialize();
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...