9 #ifndef Tempus_StepperExplicitRK_impl_hpp
10 #define Tempus_StepperExplicitRK_impl_hpp
12 #include "Tempus_RKButcherTableauBuilder.hpp"
14 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
15 #include "Thyra_VectorStdOps.hpp"
20 template<
class Scalar>
24 this->setParameterList(Teuchos::null);
28 template<
class Scalar>
30 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
31 Teuchos::RCP<Teuchos::ParameterList> pList)
33 this->setTableau(pList);
34 this->setParameterList(pList);
36 if (appModel == Teuchos::null) {
40 this->setModel(appModel);
45 template<
class Scalar>
47 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
48 std::string stepperType)
50 this->setTableau(stepperType);
52 if (appModel == Teuchos::null) {
56 this->setModel(appModel);
61 template<
class Scalar>
63 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
64 std::string stepperType,
65 Teuchos::RCP<Teuchos::ParameterList> pList)
67 this->setTableau(stepperType);
68 this->setParameterList(pList);
70 if (appModel == Teuchos::null) {
74 this->setModel(appModel);
79 template<
class Scalar>
84 Scalar dt = Scalar(1.0e+99);
85 if (!this->stepperPL_->template get<bool>(
"Use Embedded"))
return dt;
87 Teuchos::RCP<SolutionState<Scalar> > currentState=sh->getCurrentState();
88 Teuchos::RCP<SolutionStateMetaData<Scalar> > metaData = currentState->getMetaData();
89 const int order = metaData->getOrder();
90 const Scalar time = metaData->getTime();
91 const Scalar errorAbs = metaData->getTolRel();
92 const Scalar errorRel = metaData->getTolAbs();
94 Teuchos::RCP<Thyra::VectorBase<Scalar> > stageX, scratchX;
95 stageX = Thyra::createMember(this->appModel_->get_f_space());
96 scratchX = Thyra::createMember(this->appModel_->get_f_space());
97 Thyra::assign(stageX.ptr(), *(currentState->getX()));
99 std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar> > > stageXDot(2);
100 for (
int i=0; i<2; ++i) {
101 stageXDot[i] = Thyra::createMember(this->appModel_->get_f_space());
102 assign(stageXDot[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
106 typedef Thyra::ModelEvaluatorBase MEB;
107 MEB::InArgs<Scalar> inArgs = this->appModel_->getNominalValues();
108 MEB::OutArgs<Scalar> outArgs = this->appModel_->createOutArgs();
109 inArgs.set_x(stageX);
110 if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
111 if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
112 outArgs.set_f(stageXDot[0]);
113 this->appModel_->evalModel(inArgs, outArgs);
115 auto err_func = [] (Teuchos::RCP<Thyra::VectorBase<Scalar> > U,
116 const Scalar rtol,
const Scalar atol,
117 Teuchos::RCP<Thyra::VectorBase<Scalar> > absU)
120 Thyra::assign(absU.ptr(), *U);
121 Thyra::abs(*U, absU.ptr());
122 Thyra::Vt_S(absU.ptr(), rtol);
123 Thyra::Vp_S(absU.ptr(), atol);
124 Thyra::ele_wise_divide(Teuchos::as<Scalar>(1.0), *U, *absU, absU.ptr());
125 Scalar err = Thyra::norm_inf(*absU);
129 Scalar d0 = err_func(stageX, errorRel, errorAbs, scratchX);
130 Scalar d1 = err_func(stageXDot[0], errorRel, errorAbs, scratchX);
133 dt = Teuchos::as<Scalar>(0.01)*(d0/d1);
136 Thyra::Vp_StV(stageX.ptr(), dt, *(stageXDot[0]));
139 inArgs.set_x(stageX);
140 if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time + dt);
141 if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
142 outArgs.set_f(stageXDot[1]);
143 this->appModel_->evalModel(inArgs, outArgs);
147 Teuchos::RCP<Thyra::VectorBase<Scalar> > errX;
148 errX = Thyra::createMember(this->appModel_->get_f_space());
149 assign(errX.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
150 Thyra::V_VmV(errX.ptr(), *(stageXDot[1]), *(stageXDot[0]));
151 Scalar d2 = err_func(errX, errorRel, errorAbs, scratchX) / dt;
154 Scalar max_d1_d2 = std::max(d1, d2);
155 Scalar h1 = std::pow((0.01/max_d1_d2),(1.0/(order+1)));
158 dt = std::min(100*dt, h1);
162 template<
class Scalar>
165 if (stepperType ==
"") {
168 Teuchos::RCP<const RKButcherTableau<Scalar> > ERK_ButcherTableau =
169 createRKBT<Scalar>(stepperType, this->stepperPL_);
170 this->setTableau(ERK_ButcherTableau);
174 template<
class Scalar>
176 Teuchos::RCP<Teuchos::ParameterList> pList)
178 if (pList == Teuchos::null) {
180 if (this->stepperPL_ == Teuchos::null)
181 this->stepperPL_ = this->getDefaultParameters();
183 this->stepperPL_ = pList;
186 std::string stepperType =
187 this->stepperPL_->template get<std::string>(
"Stepper Type",
188 "RK Explicit 4 Stage");
189 Teuchos::RCP<const RKButcherTableau<Scalar> > ERK_ButcherTableau =
190 createRKBT<Scalar>(stepperType, this->stepperPL_);
191 this->setTableau(ERK_ButcherTableau);
194 template<
class Scalar>
198 ERK_ButcherTableau_ = ERK_ButcherTableau;
200 TEUCHOS_TEST_FOR_EXCEPTION(ERK_ButcherTableau_->isImplicit() ==
true,
202 "Error - StepperExplicitRK received an implicit Butcher Tableau!\n" <<
203 " Tableau = " << ERK_ButcherTableau_->description() <<
"\n");
207 template<
class Scalar>
211 if (obs == Teuchos::null) {
213 if (this->stepperObserver_ == Teuchos::null) {
214 stepperExplicitRKObserver_ =
216 this->stepperObserver_ =
218 (stepperExplicitRKObserver_);
221 this->stepperObserver_ = obs;
222 stepperExplicitRKObserver_ =
224 (this->stepperObserver_);
229 template<
class Scalar>
232 TEUCHOS_TEST_FOR_EXCEPTION( ERK_ButcherTableau_ == Teuchos::null,
234 "Error - Need to set the Butcher Tableau, setTableau(), before calling "
235 "StepperExplicitRK::initialize()\n");
237 TEUCHOS_TEST_FOR_EXCEPTION( this->appModel_==Teuchos::null, std::logic_error,
238 "Error - Need to set the model, setModel(), before calling "
239 "StepperExplicitRK::initialize()\n");
241 this->setTableau(this->stepperPL_);
242 this->setParameterList(this->stepperPL_);
246 int numStages = ERK_ButcherTableau_->numStages();
247 stageX_ = Thyra::createMember(this->appModel_->get_f_space());
248 stageXDot_.resize(numStages);
249 for (
int i=0; i<numStages; ++i) {
250 stageXDot_[i] = Thyra::createMember(this->appModel_->get_f_space());
251 assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
254 if ( ERK_ButcherTableau_->isEmbedded() and
255 this->stepperPL_->template get<bool>(
"Use Embedded") ){
256 ee_ = Thyra::createMember(this->appModel_->get_f_space());
257 abs_u0 = Thyra::createMember(this->appModel_->get_f_space());
258 abs_u = Thyra::createMember(this->appModel_->get_f_space());
259 sc = Thyra::createMember(this->appModel_->get_f_space());
264 template<
class Scalar>
270 RCP<SolutionState<Scalar> > initialState =
solutionHistory->getCurrentState();
273 if (initialState->getXDot() == Teuchos::null)
274 this->setStepperXDot(stageXDot_.back());
280 template<
class Scalar>
286 TEMPUS_FUNC_TIME_MONITOR(
"Tempus::StepperExplicitRK::takeStep()");
290 "Error - StepperExplicitRK<Scalar>::takeStep(...)\n"
291 "Need at least two SolutionStates for ExplicitRK.\n"
293 "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
294 " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
297 RCP<SolutionState<Scalar> > currentState=
solutionHistory->getCurrentState();
298 RCP<SolutionState<Scalar> > workingState=
solutionHistory->getWorkingState();
299 const Scalar dt = workingState->getTimeStep();
300 const Scalar time = currentState->getTime();
302 const int numStages = ERK_ButcherTableau_->numStages();
303 Teuchos::SerialDenseMatrix<int,Scalar> A = ERK_ButcherTableau_->A();
304 Teuchos::SerialDenseVector<int,Scalar> b = ERK_ButcherTableau_->b();
305 Teuchos::SerialDenseVector<int,Scalar> c = ERK_ButcherTableau_->c();
308 for (
int i=0; i < numStages; ++i) {
309 if (!Teuchos::is_null(stepperExplicitRKObserver_))
312 if ( i == 0 && this->getUseFSAL() &&
313 workingState->getNConsecutiveFailures() == 0 ) {
315 RCP<Thyra::VectorBase<Scalar> > tmp = stageXDot_[0];
316 stageXDot_[0] = stageXDot_.back();
317 stageXDot_.back() = tmp;
321 Thyra::assign(stageX_.ptr(), *(currentState->getX()));
322 for (
int j=0; j < i; ++j) {
323 if (A(i,j) != Teuchos::ScalarTraits<Scalar>::zero()) {
324 Thyra::Vp_StV(stageX_.ptr(), dt*A(i,j), *stageXDot_[j]);
327 const Scalar ts = time + c(i)*dt;
329 if (!Teuchos::is_null(stepperExplicitRKObserver_))
333 this->evaluateExplicitODE(stageXDot_[i], stageX_, ts);
336 if (!Teuchos::is_null(stepperExplicitRKObserver_))
341 Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
342 for (
int i=0; i < numStages; ++i) {
343 if (b(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
344 Thyra::Vp_StV((workingState->getX()).ptr(), dt*b(i), *(stageXDot_[i]));
354 if (ERK_ButcherTableau_->isEmbedded() and this->getEmbedded()) {
356 RCP<SolutionStateMetaData<Scalar> > metaData=workingState->getMetaData();
357 const Scalar tolAbs = metaData->getTolRel();
358 const Scalar tolRel = metaData->getTolAbs();
362 Teuchos::SerialDenseVector<int,Scalar> errWght = b ;
363 errWght -= ERK_ButcherTableau_->bstar();
367 assign(ee_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
368 for (
int i=0; i < numStages; ++i) {
369 if (errWght(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
370 Thyra::Vp_StV(ee_.ptr(), dt*errWght(i), *(stageXDot_[i]));
375 Thyra::abs( *(currentState->getX()), abs_u0.ptr());
376 Thyra::abs( *(workingState->getX()), abs_u.ptr());
377 Thyra::pair_wise_max_update(tolRel, *abs_u0, abs_u.ptr());
378 Thyra::add_scalar(tolAbs, abs_u.ptr());
381 assign(sc.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
382 Thyra::ele_wise_divide(Teuchos::as<Scalar>(1.0), *ee_, *abs_u, sc.ptr());
383 Scalar err = std::abs(Thyra::norm_inf(*sc));
384 metaData->setErrorRel(err);
387 if (std::isinf(err) || std::isnan(err) || err > Teuchos::as<Scalar>(1.0))
391 workingState->setOrder(this->getOrder());
404 template<
class Scalar>
408 Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
414 template<
class Scalar>
417 return(ERK_ButcherTableau_->description());
421 template<
class Scalar>
423 Teuchos::FancyOStream &out,
424 const Teuchos::EVerbosityLevel )
const
426 out << description() <<
"::describe:" << std::endl
427 <<
"appModel_ = " << this->appModel_->description() << std::endl;
431 template <
class Scalar>
433 const Teuchos::RCP<Teuchos::ParameterList> & pList)
435 if (pList == Teuchos::null) {
437 if (this->stepperPL_ == Teuchos::null)
438 this->stepperPL_ = this->getDefaultParameters();
440 this->stepperPL_ = pList;
443 this->stepperPL_->validateParametersAndSetDefaults(*this->getValidParameters(),0);
447 template<
class Scalar>
448 Teuchos::RCP<const Teuchos::ParameterList>
451 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
452 if (ERK_ButcherTableau_ == Teuchos::null) {
453 auto ERK_ButcherTableau =
454 createRKBT<Scalar>(
"RK Explicit 4 Stage", Teuchos::null);
455 pl->setParameters(*(ERK_ButcherTableau->getValidParameters()));
457 pl->setParameters(*(ERK_ButcherTableau_->getValidParameters()));
460 this->getValidParametersBasic(pl);
461 pl->set<std::string>(
"Initial Condition Consistency",
"Consistent");
462 pl->set<
bool>(
"Use Embedded",
false,
463 "'Whether to use Embedded Stepper (if available) or not\n"
464 " 'true' - Stepper will compute embedded solution and is adaptive.\n"
465 " 'false' - Stepper is not embedded(adaptive).\n");
470 template<
class Scalar>
471 Teuchos::RCP<Teuchos::ParameterList>
475 using Teuchos::ParameterList;
476 using Teuchos::rcp_const_cast;
478 RCP<ParameterList> pl =
479 rcp_const_cast<ParameterList>(this->getValidParameters());
485 template <
class Scalar>
486 Teuchos::RCP<Teuchos::ParameterList>
489 return(this->stepperPL_);
493 template <
class Scalar>
494 Teuchos::RCP<Teuchos::ParameterList>
497 Teuchos::RCP<Teuchos::ParameterList> temp_plist = this->stepperPL_;
498 this->stepperPL_ = Teuchos::null;
504 #endif // Tempus_StepperExplicitRK_impl_hpp
Teuchos::RCP< Teuchos::ParameterList > getDefaultParameters() const
virtual Scalar getInitTimeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual std::string description() const
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
StepperExplicitRKObserver class for StepperExplicitRK.
StepperState is a simple class to hold state information about the stepper.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions, make them consistent, and set needed memory.
StepperObserver class for Stepper class.
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
StepperExplicitRK()
Default constructor.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)
virtual void initialize()
Initialize during construction and after changing input parameters.
virtual void setTableau(std::string stepperType)
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.