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>
22 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
23 std::string stepperType)
25 this->setTableau(stepperType);
26 this->setModel(appModel);
30 template<
class Scalar>
32 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
33 Teuchos::RCP<Teuchos::ParameterList> pList)
35 this->setTableau(pList);
36 this->setParameterList(pList);
37 this->setModel(appModel);
41 template<
class Scalar>
43 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel,
44 std::string stepperType,
45 Teuchos::RCP<Teuchos::ParameterList> pList)
47 this->setTableau(stepperType);
48 this->setParameterList(pList);
49 this->setModel(appModel);
53 template<
class Scalar>
55 const Teuchos::RCP<
const Thyra::ModelEvaluator<Scalar> >& appModel)
57 this->validExplicitODE(appModel);
60 inArgs_ = appModel_->getNominalValues();
61 outArgs_ = appModel_->createOutArgs();
64 template<
class Scalar>
66 const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& appModel)
68 this->setModel(appModel);
71 template<
class Scalar>
74 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
75 Teuchos::OSTab ostab(out,1,
"StepperExplicitRK::setSolver()");
76 *out <<
"Warning -- No solver to set for StepperExplicitRK "
77 <<
"(i.e., explicit method).\n" << std::endl;
81 template<
class Scalar>
83 Teuchos::RCP<Teuchos::ParameterList> solverPL)
85 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
86 Teuchos::OSTab ostab(out,1,
"StepperExplicitRK::setSolver()");
87 *out <<
"Warning -- No solver to set for StepperExplicitRK "
88 <<
"(i.e., explicit method).\n" << std::endl;
92 template<
class Scalar>
94 Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
96 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
97 Teuchos::OSTab ostab(out,1,
"StepperExplicitRK::setSolver()");
98 *out <<
"Warning -- No solver to set for StepperExplicitRK "
99 <<
"(i.e., explicit method).\n" << std::endl;
103 template<
class Scalar>
108 Scalar dt = std::numeric_limits<Scalar>::max();
109 if (!stepperPL_->get<
bool>(
"Use Embedded"))
return dt;
111 Teuchos::RCP<SolutionState<Scalar> > currentState=sh->getCurrentState();
112 Teuchos::RCP<SolutionStateMetaData<Scalar> > metaData = currentState->getMetaData();
113 const int order = metaData->getOrder();
114 const Scalar time = metaData->getTime();
115 const Scalar errorAbs = metaData->getTolRel();
116 const Scalar errorRel = metaData->getTolAbs();
118 Teuchos::RCP<Thyra::VectorBase<Scalar> > stageX_, scratchX;
119 stageX_ = Thyra::createMember(appModel_->get_f_space());
120 scratchX = Thyra::createMember(appModel_->get_f_space());
121 Thyra::assign(stageX_.ptr(), *(currentState->getX()));
123 std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar> > > stageXDot_(2);
124 for (
int i=0; i<2; ++i) {
125 stageXDot_[i] = Thyra::createMember(appModel_->get_f_space());
126 assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
130 typedef Thyra::ModelEvaluatorBase MEB;
131 Thyra::ModelEvaluatorBase::InArgs<Scalar> inArgs_ = appModel_->getNominalValues();
132 Thyra::ModelEvaluatorBase::OutArgs<Scalar> outArgs_ = appModel_->createOutArgs();
133 inArgs_.set_x(stageX_);
134 if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
135 if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
136 outArgs_.set_f(stageXDot_[0]);
137 appModel_->evalModel(inArgs_,outArgs_);
139 auto err_func = [] (Teuchos::RCP<Thyra::VectorBase<Scalar> > U,
140 const Scalar rtol,
const Scalar atol,
141 Teuchos::RCP<Thyra::VectorBase<Scalar> > absU)
144 Thyra::assign(absU.ptr(), *U);
145 Thyra::abs(*U, absU.ptr());
146 Thyra::Vt_S(absU.ptr(), rtol);
147 Thyra::Vp_S(absU.ptr(), atol);
148 Thyra::ele_wise_divide(Teuchos::as<Scalar>(1.0), *U, *absU, absU.ptr());
149 Scalar err = Thyra::norm_inf(*absU);
153 Scalar d0 = err_func(stageX_, errorRel, errorAbs, scratchX);
154 Scalar d1 = err_func(stageXDot_[0], errorRel, errorAbs, scratchX);
157 dt = Teuchos::as<Scalar>(0.01)*(d0/d1);
160 Thyra::Vp_StV(stageX_.ptr(), dt, *(stageXDot_[0]));
163 inArgs_.set_x(stageX_);
164 if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time + dt);
165 if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
166 outArgs_.set_f(stageXDot_[1]);
167 appModel_->evalModel(inArgs_,outArgs_);
171 Teuchos::RCP<Thyra::VectorBase<Scalar> > errX;
172 errX = Thyra::createMember(appModel_->get_f_space());
173 assign(errX.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
174 Thyra::V_VmV(errX.ptr(), *(stageXDot_[1]), *(stageXDot_[0]));
175 Scalar d2 = err_func(errX, errorRel, errorAbs, scratchX) / dt;
178 Scalar max_d1_d2 = std::max(d1, d2);
179 Scalar h1 = std::pow((0.01/max_d1_d2),(1.0/(order+1)));
182 dt = std::min(100*dt, h1);
186 template<
class Scalar>
189 if (stepperType ==
"") {
192 ERK_ButcherTableau_ = createRKBT<Scalar>(stepperType, this->stepperPL_);
195 TEUCHOS_TEST_FOR_EXCEPTION(ERK_ButcherTableau_->isImplicit() ==
true,
197 "Error - StepperExplicitRK received an implicit Butcher Tableau!\n"
198 <<
" Stepper Type = " << stepperType <<
"\n");
199 description_ = ERK_ButcherTableau_->description();
202 template<
class Scalar>
204 Teuchos::RCP<Teuchos::ParameterList> pList)
206 if (pList == Teuchos::null) {
208 if (this->stepperPL_ == Teuchos::null)
209 this->stepperPL_ = this->getDefaultParameters();
211 this->stepperPL_ = pList;
214 std::string stepperType =
215 this->stepperPL_->template get<std::string>(
"Stepper Type",
216 "RK Explicit 4 Stage");
217 ERK_ButcherTableau_ = createRKBT<Scalar>(stepperType, this->stepperPL_);
219 TEUCHOS_TEST_FOR_EXCEPTION(ERK_ButcherTableau_->isImplicit() ==
true,
221 "Error - StepperExplicitRK received an implicit Butcher Tableau!\n"
222 <<
" Stepper Type = " << stepperType <<
"\n");
223 description_ = ERK_ButcherTableau_->description();
227 template<
class Scalar>
231 if (obs == Teuchos::null) {
233 if (stepperObserver_ == Teuchos::null) {
234 stepperExplicitRKObserver_ =
238 (stepperExplicitRKObserver_);
241 stepperObserver_ = obs;
242 stepperExplicitRKObserver_ =
249 template<
class Scalar>
252 TEUCHOS_TEST_FOR_EXCEPTION( ERK_ButcherTableau_ == Teuchos::null,
254 "Error - Need to set the Butcher Tableau, setTableau(), before calling "
255 "StepperExplicitRK::initialize()\n");
257 TEUCHOS_TEST_FOR_EXCEPTION( appModel_ == Teuchos::null, std::logic_error,
258 "Error - Need to set the model, setModel(), before calling "
259 "StepperExplicitRK::initialize()\n");
261 this->setTableau(stepperPL_);
262 this->setParameterList(stepperPL_);
266 int numStages = ERK_ButcherTableau_->numStages();
267 stageX_ = Thyra::createMember(appModel_->get_f_space());
268 stageXDot_.resize(numStages);
269 for (
int i=0; i<numStages; ++i) {
270 stageXDot_[i] = Thyra::createMember(appModel_->get_f_space());
271 assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
274 if (ERK_ButcherTableau_->isEmbedded() and stepperPL_->get<
bool>(
"Use Embedded")){
275 ee_ = Thyra::createMember(appModel_->get_f_space());
276 abs_u0 = Thyra::createMember(appModel_->get_f_space());
277 abs_u = Thyra::createMember(appModel_->get_f_space());
278 sc = Thyra::createMember(appModel_->get_f_space());
282 template<
class Scalar>
288 TEMPUS_FUNC_TIME_MONITOR(
"Tempus::StepperExplicitRK::takeStep()");
292 "Error - StepperExplicitRK<Scalar>::takeStep(...)\n"
293 "Need at least two SolutionStates for ExplicitRK.\n"
295 "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
296 " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
299 RCP<SolutionState<Scalar> > currentState=
solutionHistory->getCurrentState();
300 RCP<SolutionState<Scalar> > workingState=
solutionHistory->getWorkingState();
301 const Scalar dt = workingState->getTimeStep();
302 const Scalar time = currentState->getTime();
304 const int numStages = ERK_ButcherTableau_->numStages();
305 Teuchos::SerialDenseMatrix<int,Scalar> A = ERK_ButcherTableau_->A();
306 Teuchos::SerialDenseVector<int,Scalar> b = ERK_ButcherTableau_->b();
307 Teuchos::SerialDenseVector<int,Scalar> c = ERK_ButcherTableau_->c();
310 for (
int i=0; i < numStages; ++i) {
311 if (!Teuchos::is_null(stepperExplicitRKObserver_))
313 Thyra::assign(stageX_.ptr(), *(currentState->getX()));
314 for (
int j=0; j < i; ++j) {
315 if (A(i,j) != Teuchos::ScalarTraits<Scalar>::zero()) {
316 Thyra::Vp_StV(stageX_.ptr(), dt*A(i,j), *stageXDot_[j]);
319 const Scalar ts = time + c(i)*dt;
322 typedef Thyra::ModelEvaluatorBase MEB;
323 inArgs_.set_x(stageX_);
324 if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(ts);
326 if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
327 outArgs_.set_f(stageXDot_[i]);
329 if (!Teuchos::is_null(stepperExplicitRKObserver_))
330 stepperExplicitRKObserver_->observeBeforeExplicit(
solutionHistory, *
this);
331 appModel_->evalModel(inArgs_,outArgs_);
333 if (!Teuchos::is_null(stepperExplicitRKObserver_))
338 Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
339 for (
int i=0; i < numStages; ++i) {
340 if (b(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
341 Thyra::Vp_StV((workingState->getX()).ptr(), dt*b(i), *(stageXDot_[i]));
350 if (ERK_ButcherTableau_->isEmbedded() and stepperPL_->get<
bool>(
"Use Embedded")){
352 RCP<SolutionStateMetaData<Scalar> > metaData = workingState->getMetaData();
353 const Scalar tolAbs = metaData->getTolRel();
354 const Scalar tolRel = metaData->getTolAbs();
358 Teuchos::SerialDenseVector<int,Scalar> errWght = b ;
359 errWght -= ERK_ButcherTableau_->bstar();
363 assign(ee_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
364 for (
int i=0; i < numStages; ++i) {
365 if (errWght(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
366 Thyra::Vp_StV(ee_.ptr(), dt*errWght(i), *(stageXDot_[i]));
371 Thyra::abs( *(currentState->getX()), abs_u0.ptr());
372 Thyra::abs( *(workingState->getX()), abs_u.ptr());
373 Thyra::pair_wise_max_update(tolRel, *abs_u0, abs_u.ptr());
374 Thyra::add_scalar(tolAbs, abs_u.ptr());
377 assign(sc.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
378 Thyra::ele_wise_divide(Teuchos::as<Scalar>(1.0), *ee_, *abs_u, sc.ptr());
379 Scalar err = Thyra::norm_inf(*sc);
380 metaData->setErrorRel(err);
386 workingState->setOrder(this->getOrder());
399 template<
class Scalar>
403 Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
409 template<
class Scalar>
412 return(description_);
416 template<
class Scalar>
418 Teuchos::FancyOStream &out,
419 const Teuchos::EVerbosityLevel verbLevel)
const
421 out << description() <<
"::describe:" << std::endl
422 <<
"appModel_ = " << appModel_->description() << std::endl;
426 template <
class Scalar>
428 const Teuchos::RCP<Teuchos::ParameterList> & pList)
430 if (pList == Teuchos::null) {
432 if (stepperPL_ == Teuchos::null) stepperPL_ = this->getDefaultParameters();
437 stepperPL_->validateParametersAndSetDefaults(*this->getValidParameters(),0);
441 template<
class Scalar>
442 Teuchos::RCP<const Teuchos::ParameterList>
460 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
461 pl->set<
bool>(
"Use Embedded",
false,
462 "'Whether to use Embedded Stepper (if available) or not\n"
463 " 'true' - Stepper will compute embedded solution and is adaptive.\n"
464 " 'false' - Stepper is not embedded(adaptive).\n");
465 pl->setParameters(*(ERK_ButcherTableau_->getValidParameters()));
470 template<
class Scalar>
471 Teuchos::RCP<Teuchos::ParameterList>
474 Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
475 pl->set<
bool>(
"Use Embedded",
false,
476 "'Whether to use Embedded Stepper (if available) or not\n"
477 " 'true' - Stepper will compute embedded solution and is adaptive.\n"
478 " 'false' - Stepper is not embedded(adaptive).\n");
479 if (ERK_ButcherTableau_ == Teuchos::null) {
480 auto ERK_ButcherTableau =
481 createRKBT<Scalar>(
"RK Explicit 4 Stage", Teuchos::null);
482 pl->setParameters(*(ERK_ButcherTableau->getValidParameters()));
484 pl->setParameters(*(ERK_ButcherTableau_->getValidParameters()));
490 template <
class Scalar>
491 Teuchos::RCP<Teuchos::ParameterList>
498 template <
class Scalar>
499 Teuchos::RCP<Teuchos::ParameterList>
502 Teuchos::RCP<Teuchos::ParameterList> temp_plist = stepperPL_;
503 stepperPL_ = Teuchos::null;
509 #endif // Tempus_StepperExplicitRK_impl_hpp