Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_StepperExplicitRK_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_StepperExplicitRK_impl_hpp
10 #define Tempus_StepperExplicitRK_impl_hpp
11 
12 #include "Thyra_VectorStdOps.hpp"
13 
15 
16 namespace Tempus {
17 
18 template <class Scalar>
20 {
21  this->setUseEmbedded(false);
22  this->setStageNumber(-1);
23  this->setAppAction(Teuchos::null);
24 }
25 
26 template <class Scalar>
28  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
29  bool useFSAL, std::string ICConsistency, bool ICConsistencyCheck,
30  bool useEmbedded,
31  const Teuchos::RCP<StepperRKAppAction<Scalar> >& stepperRKAppAction)
32 {
33  this->setUseFSAL(useFSAL);
34  this->setICConsistency(ICConsistency);
35  this->setICConsistencyCheck(ICConsistencyCheck);
36  this->setUseEmbedded(useEmbedded);
37  this->setStageNumber(-1);
38  this->setErrorNorm();
39 
40  this->setAppAction(stepperRKAppAction);
41 
42  if (appModel != Teuchos::null) {
43  this->setModel(appModel);
44  this->initialize();
45  }
46 }
47 
48 template <class Scalar>
50  const Teuchos::RCP<SolutionHistory<Scalar> >& sh) const
51 {
52  Scalar dt = Scalar(1.0e+99);
53  if (!this->getUseEmbedded()) return dt;
54 
55  Teuchos::RCP<SolutionState<Scalar> > currentState = sh->getCurrentState();
56  const int order = currentState->getOrder();
57  const Scalar time = currentState->getTime();
58  const Scalar errorRel = currentState->getTolRel();
59  const Scalar errorAbs = currentState->getTolAbs();
60 
61  Teuchos::RCP<Thyra::VectorBase<Scalar> > stageX, scratchX;
62  stageX = Thyra::createMember(this->appModel_->get_f_space());
63  scratchX = Thyra::createMember(this->appModel_->get_f_space());
64  Thyra::assign(stageX.ptr(), *(currentState->getX()));
65 
66  std::vector<Teuchos::RCP<Thyra::VectorBase<Scalar> > > stageXDot(2);
67  for (int i = 0; i < 2; ++i) {
68  stageXDot[i] = Thyra::createMember(this->appModel_->get_f_space());
69  assign(stageXDot[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
70  }
71 
72  // A: one function evaluation at F(t_0, X_0)
73  typedef Thyra::ModelEvaluatorBase MEB;
74  MEB::InArgs<Scalar> inArgs = this->appModel_->getNominalValues();
75  MEB::OutArgs<Scalar> outArgs = this->appModel_->createOutArgs();
76  inArgs.set_x(stageX);
77  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
78  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
79  outArgs.set_f(stageXDot[0]); // K1
80  this->appModel_->evalModel(inArgs, outArgs);
81 
82  this->stepperErrorNormCalculator_->setRelativeTolerance(errorRel);
83  this->stepperErrorNormCalculator_->setAbsoluteTolerance(errorAbs);
84 
85  Scalar d0 = this->stepperErrorNormCalculator_->errorNorm(stageX);
86  Scalar d1 = this->stepperErrorNormCalculator_->errorNorm(stageXDot[0]);
87 
88  // b) first guess for the step size
89  dt = Teuchos::as<Scalar>(0.01) * (d0 / d1);
90 
91  // c) perform one explicit Euler step (X_1)
92  Thyra::Vp_StV(stageX.ptr(), dt, *(stageXDot[0]));
93 
94  // compute F(t_0 + dt, X_1)
95  inArgs.set_x(stageX);
96  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time + dt);
97  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
98  outArgs.set_f(stageXDot[1]); // K2
99  this->appModel_->evalModel(inArgs, outArgs);
100 
101  // d) compute estimate of the second derivative of the solution
102  // d2 = || f(t_0 + dt, X_1) - f(t_0, X_0) || / dt
104  errX = Thyra::createMember(this->appModel_->get_f_space());
105  assign(errX.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
106  Thyra::V_VmV(errX.ptr(), *(stageXDot[1]), *(stageXDot[0]));
107  Scalar d2 = this->stepperErrorNormCalculator_->errorNorm(errX) / dt;
108 
109  // e) compute step size h_1 (from m = 0 order Taylor series)
110  Scalar max_d1_d2 = std::max(d1, d2);
111  Scalar h1 = std::pow((0.01 / max_d1_d2), (1.0 / (order + 1)));
112 
113  // f) propose starting step size
114  dt = std::min(100 * dt, h1);
115  return dt;
116 }
117 
118 template <class Scalar>
121 {
122  return this->getValidParametersBasicERK();
123 }
124 
125 template <class Scalar>
128 {
129  auto pl = this->getValidParametersBasic();
130  pl->template set<bool>(
131  "Use Embedded", this->getUseEmbedded(),
132  "'Whether to use Embedded Stepper (if available) or not\n"
133  " 'true' - Stepper will compute embedded solution and is adaptive.\n"
134  " 'false' - Stepper is not embedded(adaptive).\n");
135  pl->template set<std::string>("Description", this->getDescription());
136 
137  return pl;
138 }
139 
140 template <class Scalar>
142 {
143  TEUCHOS_TEST_FOR_EXCEPTION(this->tableau_ == Teuchos::null, std::logic_error,
144  "Error - Need to set the tableau, before calling "
145  "StepperExplicitRK::initialize()\n");
146 
148  this->appModel_ == Teuchos::null, std::logic_error,
149  "Error - Need to set the model, setModel(), before calling "
150  "StepperExplicitRK::initialize()\n");
151 
153 }
154 
155 template <class Scalar>
157  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
158 {
160 
161  // Set the stage vectors
162  int numStages = this->tableau_->numStages();
163  stageXDot_.resize(numStages);
164  for (int i = 0; i < numStages; ++i) {
165  stageXDot_[i] = Thyra::createMember(this->appModel_->get_f_space());
166  assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
167  }
168 
169  this->setEmbeddedMemory();
170  this->setErrorNorm();
171 
172  this->isInitialized_ = false;
173 }
174 
175 template <class Scalar>
177 {
178  if (this->getModel() == Teuchos::null)
179  return; // Embedded memory will be set when setModel() is called.
180 
181  if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
182  this->ee_ = Thyra::createMember(this->appModel_->get_f_space());
183  this->abs_u0 = Thyra::createMember(this->appModel_->get_f_space());
184  this->abs_u = Thyra::createMember(this->appModel_->get_f_space());
185  this->sc = Thyra::createMember(this->appModel_->get_f_space());
186  }
187  else {
188  this->ee_ = Teuchos::null;
189  this->abs_u0 = Teuchos::null;
190  this->abs_u = Teuchos::null;
191  this->sc = Teuchos::null;
192  }
193 }
194 
195 template <class Scalar>
197  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
198 {
199  if (this->getUseFSAL())
200  this->setStepperXDot(stageXDot_.back());
201  else
202  this->setStepperXDot(stageXDot_[0]);
203 
205 
206  auto xDot = solutionHistory->getCurrentState()->getXDot();
207  if (xDot != Teuchos::null && this->getUseFSAL())
208  Thyra::assign(this->getStepperXDot().ptr(), *(xDot));
209 }
210 
211 template <class Scalar>
213  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
214 {
215  this->checkInitialized();
216 
217  using Teuchos::RCP;
218 
219  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperExplicitRK::takeStep()");
220  {
222  solutionHistory->getNumStates() < 2, std::logic_error,
223  "Error - StepperExplicitRK<Scalar>::takeStep(...)\n"
224  "Need at least two SolutionStates for ExplicitRK.\n"
225  " Number of States = "
226  << solutionHistory->getNumStates()
227  << "\n"
228  "Try setting in \"Solution History\" \"Storage Type\" = "
229  "\"Undo\"\n"
230  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = "
231  "\"2\"\n");
232 
233  RCP<SolutionState<Scalar> > currentState =
234  solutionHistory->getCurrentState();
235  RCP<SolutionState<Scalar> > workingState =
236  solutionHistory->getWorkingState();
237  const Scalar dt = workingState->getTimeStep();
238  const Scalar time = currentState->getTime();
239 
240  const int numStages = this->tableau_->numStages();
241  Teuchos::SerialDenseMatrix<int, Scalar> A = this->tableau_->A();
242  Teuchos::SerialDenseVector<int, Scalar> b = this->tableau_->b();
243  Teuchos::SerialDenseVector<int, Scalar> c = this->tableau_->c();
244 
245  Thyra::assign(workingState->getX().ptr(), *(currentState->getX()));
246 
247  RCP<StepperExplicitRK<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
248  this->stepperRKAppAction_->execute(
249  solutionHistory, thisStepper,
251 
252  // Compute stage solutions
253  for (int i = 0; i < numStages; ++i) {
254  this->setStageNumber(i);
255  Thyra::assign(workingState->getX().ptr(), *(currentState->getX()));
256  for (int j = 0; j < i; ++j) {
257  if (A(i, j) != Teuchos::ScalarTraits<Scalar>::zero()) {
258  Thyra::Vp_StV(workingState->getX().ptr(), dt * A(i, j),
259  *stageXDot_[j]);
260  }
261  }
262  this->setStepperXDot(stageXDot_[i]);
263 
264  this->stepperRKAppAction_->execute(
265  solutionHistory, thisStepper,
267  this->stepperRKAppAction_->execute(
268  solutionHistory, thisStepper,
270  this->stepperRKAppAction_->execute(
271  solutionHistory, thisStepper,
273  this->stepperRKAppAction_->execute(
274  solutionHistory, thisStepper,
276 
277  if (i == 0 && this->getUseFSAL() &&
278  workingState->getNConsecutiveFailures() == 0) {
279  RCP<Thyra::VectorBase<Scalar> > tmp = stageXDot_[0];
280  stageXDot_[0] = stageXDot_.back();
281  stageXDot_.back() = tmp;
282  this->setStepperXDot(stageXDot_[0]);
283  }
284  else {
285  const Scalar ts = time + c(i) * dt;
287 
288  // Evaluate xDot = f(x,t).
289  this->evaluateExplicitODE(stageXDot_[i], workingState->getX(), ts, p);
290  }
291 
292  this->stepperRKAppAction_->execute(
293  solutionHistory, thisStepper,
295  }
296  // reset the stage number
297  this->setStageNumber(-1);
298 
299  // Sum for solution: x_n = x_n-1 + Sum{ b(i) * dt*f(i) }
300  Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
301  for (int i = 0; i < numStages; ++i) {
302  if (b(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
303  Thyra::Vp_StV((workingState->getX()).ptr(), dt * b(i),
304  *(stageXDot_[i]));
305  }
306  }
307 
308  if (this->getUseFSAL()) {
309  if (numStages == 1) {
310  const Scalar ts = time + dt;
312  // Evaluate xDot = f(x,t).
313  this->evaluateExplicitODE(stageXDot_[0], workingState->getX(), ts, p);
314  }
315  if (workingState->getXDot() != Teuchos::null)
316  Thyra::assign((workingState->getXDot()).ptr(), *(stageXDot_.back()));
317  }
318 
319  // At this point, the stepper has passed.
320  // But when using adaptive time stepping, the embedded method
321  // can change the step status
322  workingState->setSolutionStatus(Status::PASSED);
323 
324  if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
325  const Scalar tolRel = workingState->getTolRel();
326  const Scalar tolAbs = workingState->getTolAbs();
327 
328  // update the tolerance
329  this->stepperErrorNormCalculator_->setRelativeTolerance(tolRel);
330  this->stepperErrorNormCalculator_->setAbsoluteTolerance(tolAbs);
331 
332  // just compute the error weight vector
333  // (all that is needed is the error, and not the embedded solution)
335  errWght -= this->tableau_->bstar();
336 
337  // Compute local truncation error estimate: | u^{n+1} - \hat{u}^{n+1} |
338  // Sum for solution: ee_n = Sum{ (b(i) - bstar(i)) * dt*f(i) }
339  assign(this->ee_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
340  for (int i = 0; i < numStages; ++i) {
341  if (errWght(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
342  Thyra::Vp_StV(this->ee_.ptr(), dt * errWght(i), *(stageXDot_[i]));
343  }
344  }
345 
346  Scalar err = this->stepperErrorNormCalculator_->computeWRMSNorm(
347  currentState->getX(), workingState->getX(), this->ee_);
348  workingState->setErrorRel(err);
349 
350  // Test if step should be rejected
351  if (std::isinf(err) || std::isnan(err) || err > Teuchos::as<Scalar>(1.0))
352  workingState->setSolutionStatus(Status::FAILED);
353  }
354 
355  workingState->setOrder(this->getOrder());
356  workingState->computeNorms(currentState);
357  this->stepperRKAppAction_->execute(
358  solutionHistory, thisStepper,
360  }
361  return;
362 }
363 
370 template <class Scalar>
373 {
375  rcp(new StepperState<Scalar>(this->getStepperType()));
376  return stepperState;
377 }
378 
379 template <class Scalar>
381  Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
382 {
383  out.setOutputToRootOnly(0);
384  out << std::endl;
385  Stepper<Scalar>::describe(out, verbLevel);
386  StepperExplicit<Scalar>::describe(out, verbLevel);
387 
388  out << "--- StepperExplicitRK ---\n";
389  if (this->tableau_ != Teuchos::null) this->tableau_->describe(out, verbLevel);
390  out << " tableau_ = " << this->tableau_ << std::endl;
391  out << " stepperRKAppAction_= " << this->stepperRKAppAction_ << std::endl;
392  out << " stageXDot_.size() = " << stageXDot_.size() << std::endl;
393  const int numStages = stageXDot_.size();
394  for (int i = 0; i < numStages; ++i)
395  out << " stageXDot_[" << i << "] = " << stageXDot_[i] << std::endl;
396  out << " useEmbedded_ = " << Teuchos::toString(this->useEmbedded_)
397  << std::endl;
398  out << " ee_ = " << this->ee_ << std::endl;
399  out << " abs_u0 = " << this->abs_u0 << std::endl;
400  out << " abs_u = " << this->abs_u << std::endl;
401  out << " sc = " << this->sc << std::endl;
402  out << "-------------------------" << std::endl;
403 }
404 
405 template <class Scalar>
407 {
408  out.setOutputToRootOnly(0);
409  bool isValidSetup = true;
410 
411  if (!Stepper<Scalar>::isValidSetup(out)) isValidSetup = false;
412  if (!StepperExplicit<Scalar>::isValidSetup(out)) isValidSetup = false;
413 
414  if (this->tableau_ == Teuchos::null) {
415  isValidSetup = false;
416  out << "The tableau is not set!\n";
417  }
418 
419  if (this->stepperRKAppAction_ == Teuchos::null) {
420  isValidSetup = false;
421  out << "The AppAction is not set!\n";
422  }
423 
424  return isValidSetup;
425 }
426 
427 } // namespace Tempus
428 #endif // Tempus_StepperExplicitRK_impl_hpp
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
Set model.
virtual void setupDefault()
Default setup for constructor.
virtual Scalar getInitTimeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void initialize()
Initialize after construction and changing input parameters.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Thyra Base interface for time steppers.
StepperState is a simple class to hold state information about the stepper.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Application Action for StepperRKBase.
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Ptr< T > ptr() const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions, make them consistent, and set needed memory.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
Set model.
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicERK() const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
virtual void initialize()
Initialize during construction and after changing input parameters.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
Thyra Base interface for implicit time steppers.
std::string toString(const T &t)
virtual void setup(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel, bool useFSAL, std::string ICConsistency, bool ICConsistencyCheck, bool useEmbedded, const Teuchos::RCP< StepperRKAppAction< Scalar > > &stepperRKAppAction)
Setup for constructor.