Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_StepperBackwardEuler_impl.hpp
Go to the documentation of this file.
1 //@HEADER
2 // *****************************************************************************
3 // Tempus: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef Tempus_StepperBackwardEuler_impl_hpp
11 #define Tempus_StepperBackwardEuler_impl_hpp
12 
14 #include "Tempus_WrapperModelEvaluatorBasic.hpp"
15 #include "Tempus_StepperFactory.hpp"
16 
17 namespace Tempus {
18 
19 template <class Scalar>
21 {
22  this->setStepperName("Backward Euler");
23  this->setStepperType("Backward Euler");
24  this->setUseFSAL(false);
25  this->setICConsistency("None");
26  this->setICConsistencyCheck(false);
27  this->setZeroInitialGuess(false);
28 
29  this->setAppAction(Teuchos::null);
30  this->setDefaultSolver();
31  this->setPredictor();
32 }
33 
34 template <class Scalar>
36  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
38  const Teuchos::RCP<Stepper<Scalar> >& predictorStepper, bool useFSAL,
39  std::string ICConsistency, bool ICConsistencyCheck, bool zeroInitialGuess,
41  stepperBEAppAction)
42 {
43  this->setStepperName("Backward Euler");
44  this->setStepperType("Backward Euler");
45  this->setUseFSAL(useFSAL);
46  this->setICConsistency(ICConsistency);
47  this->setICConsistencyCheck(ICConsistencyCheck);
48  this->setZeroInitialGuess(zeroInitialGuess);
49 
50  this->setAppAction(stepperBEAppAction);
51  this->setSolver(solver);
52  this->setPredictor(predictorStepper);
53 
54  if (appModel != Teuchos::null) {
55  this->setModel(appModel);
56  this->initialize();
57  }
58 }
59 
60 template <class Scalar>
61 void StepperBackwardEuler<Scalar>::setPredictor(std::string predictorType)
62 {
63  if (predictorType == "None") {
64  predictorStepper_ = Teuchos::null;
65  return;
66  }
67 
68  auto sf = Teuchos::rcp(new StepperFactory<Scalar>());
69  if (this->wrapperModel_ != Teuchos::null &&
70  this->wrapperModel_->getAppModel() != Teuchos::null) {
71  predictorStepper_ =
72  sf->createStepper(predictorType, this->wrapperModel_->getAppModel());
73  }
74  else {
75  predictorStepper_ = sf->createStepper(predictorType);
76  }
77 
78  this->isInitialized_ = false;
79 }
80 
82 template <class Scalar>
84  Teuchos::RCP<Stepper<Scalar> > predictorStepper)
85 {
86  predictorStepper_ = predictorStepper;
87  if (predictorStepper_ == Teuchos::null) return;
88 
90  predictorStepper_->getModel() == Teuchos::null &&
91  this->wrapperModel_->getAppModel() == Teuchos::null,
92  std::logic_error,
93  "Error - Need to set the model, setModel(), before calling "
94  "StepperBackwardEuler::setPredictor()\n");
95 
96  if (predictorStepper_->getModel() == Teuchos::null)
97  predictorStepper_->setModel(this->wrapperModel_->getAppModel());
98  predictorStepper_->initialize();
99 
100  this->isInitialized_ = false;
101 }
102 
103 template <class Scalar>
106 {
107  if (appAction == Teuchos::null) {
108  // Create default appAction
109  stepperBEAppAction_ =
111  }
112  else {
113  stepperBEAppAction_ = appAction;
114  }
115  this->isInitialized_ = false;
116 }
117 
118 template <class Scalar>
120  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
121 {
123 
124  if (predictorStepper_ != Teuchos::null) {
125  // If predictor's model is not set, set it to the stepper model.
126  if (predictorStepper_->getModel() == Teuchos::null) {
127  predictorStepper_->setModel(appModel);
128  predictorStepper_->initialize();
129  }
130  }
131 
132  this->isInitialized_ = false;
133 }
134 
135 template <class Scalar>
137  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
138 {
139  using Teuchos::RCP;
140 
141  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
142 
143  // Check if we need Stepper storage for xDot
144  if (initialState->getXDot() == Teuchos::null)
145  this->setStepperXDot(initialState->getX()->clone_v());
146  else
147  this->setStepperXDot(initialState->getXDot());
148 
150 }
151 
152 template <class Scalar>
154  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
155 {
156  this->checkInitialized();
157 
158  using Teuchos::RCP;
159 
160  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperBackwardEuler::takeStep()");
161  {
163  solutionHistory->getNumStates() < 2, std::logic_error,
164  "Error - StepperBackwardEuler<Scalar>::takeStep(...)\n"
165  << "Need at least two SolutionStates for Backward Euler.\n"
166  << " Number of States = " << solutionHistory->getNumStates()
167  << "\n Try setting in \"Solution History\" \"Storage Type\" = "
168  << "\"Undo\"\n or \"Storage Type\" = \"Static\" and \"Storage Limit\" = "
169  << "\"2\"\n");
170 
171  RCP<StepperBackwardEuler<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
172  stepperBEAppAction_->execute(
173  solutionHistory, thisStepper,
175 
176  RCP<SolutionState<Scalar> > workingState =
177  solutionHistory->getWorkingState();
178  RCP<SolutionState<Scalar> > currentState =
179  solutionHistory->getCurrentState();
180 
181  RCP<const Thyra::VectorBase<Scalar> > xOld = currentState->getX();
182  RCP<Thyra::VectorBase<Scalar> > x = workingState->getX();
183  if (workingState->getXDot() != Teuchos::null)
184  this->setStepperXDot(workingState->getXDot());
185  RCP<Thyra::VectorBase<Scalar> > xDot = this->getStepperXDot();
186 
187  computePredictor(solutionHistory);
188  if (workingState->getSolutionStatus() == Status::FAILED) return;
189 
190  const Scalar time = workingState->getTime();
191  const Scalar dt = workingState->getTimeStep();
192 
193  // Setup TimeDerivative
195  new StepperBackwardEulerTimeDerivative<Scalar>(Scalar(1.0) / dt, xOld));
196 
197  const Scalar alpha = Scalar(1.0) / dt;
198  const Scalar beta = Scalar(1.0);
199  auto p = Teuchos::rcp(
200  new ImplicitODEParameters<Scalar>(timeDer, dt, alpha, beta));
201 
202  stepperBEAppAction_->execute(
203  solutionHistory, thisStepper,
205 
206  const Thyra::SolveStatus<Scalar> sStatus =
207  this->solveImplicitODE(x, xDot, time, p);
208 
209  stepperBEAppAction_->execute(
210  solutionHistory, thisStepper,
212 
213  if (workingState->getXDot() != Teuchos::null) timeDer->compute(x, xDot);
214 
215  workingState->setSolutionStatus(sStatus); // Converged --> pass.
216  workingState->setOrder(this->getOrder());
217  workingState->computeNorms(currentState);
218  stepperBEAppAction_->execute(
219  solutionHistory, thisStepper,
221  }
222  return;
223 }
224 
225 template <class Scalar>
227  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
228 {
229  if (predictorStepper_ == Teuchos::null) return;
230  predictorStepper_->takeStep(solutionHistory);
231 
232  if (solutionHistory->getWorkingState()->getSolutionStatus() ==
233  Status::FAILED) {
234  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
235  Teuchos::OSTab ostab(out, 1, "StepperBackwardEuler::computePredictor");
236  *out << "Warning - predictorStepper has failed." << std::endl;
237  }
238  else {
239  // Reset status to WORKING since this is the predictor
240  solutionHistory->getWorkingState()->setSolutionStatus(Status::WORKING);
241  }
242 }
243 
250 template <class Scalar>
253 {
255  rcp(new StepperState<Scalar>(this->getStepperType()));
256  return stepperState;
257 }
258 
259 template <class Scalar>
261  Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
262 {
263  out.setOutputToRootOnly(0);
264  out << std::endl;
265  Stepper<Scalar>::describe(out, verbLevel);
266  StepperImplicit<Scalar>::describe(out, verbLevel);
267 
268  out << "--- StepperBackwardEuler ---\n";
269  out << " predictorStepper_ = " << predictorStepper_
270  << std::endl;
271  if (predictorStepper_ != Teuchos::null) {
272  out << " predictorStepper_->isInitialized() = "
273  << Teuchos::toString(predictorStepper_->isInitialized()) << std::endl;
274  out << " predictor stepper type = "
275  << predictorStepper_->description() << std::endl;
276  }
277  out << " stepperBEAppAction_ = " << stepperBEAppAction_
278  << std::endl;
279  out << "----------------------------" << std::endl;
280 }
281 
282 template <class Scalar>
284  Teuchos::FancyOStream& out) const
285 {
286  out.setOutputToRootOnly(0);
287  bool isValidSetup = true;
288 
289  if (!Stepper<Scalar>::isValidSetup(out)) isValidSetup = false;
290  if (!StepperImplicit<Scalar>::isValidSetup(out)) isValidSetup = false;
291 
292  if (predictorStepper_ != Teuchos::null) {
293  if (!predictorStepper_->isInitialized()) {
294  isValidSetup = false;
295  out << "The predictor stepper is not initialized!\n";
296  }
297  }
298 
299  if (stepperBEAppAction_ == Teuchos::null) {
300  isValidSetup = false;
301  out << "The Backward Euler AppAction is not set!\n";
302  }
303 
304  return isValidSetup;
305 }
306 
307 template <class Scalar>
310 {
311  auto pl = this->getValidParametersBasicImplicit();
312  if (predictorStepper_ == Teuchos::null)
313  pl->set("Predictor Stepper Type", "None");
314  else
315  pl->set("Predictor Stepper Type", predictorStepper_->getStepperType());
316  return pl;
317 }
318 
319 template <class Scalar>
321 {
322  return 2;
323 }
324 
325 template <class Scalar>
327  Thyra::VectorBase<Scalar>& residual,
330  const int param_index) const
331 {
332  typedef Thyra::ModelEvaluatorBase MEB;
333  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->createOutArgs();
334  outArgs.set_f(Teuchos::rcpFromRef(residual));
335  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
336 }
337 
338 template <class Scalar>
340  Thyra::LinearOpBase<Scalar>& jacobian,
343  const int param_index, const int deriv_index) const
344 {
345  typedef Thyra::ModelEvaluatorBase MEB;
346  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->createOutArgs();
347  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W_op));
348  outArgs.set_W_op(Teuchos::rcpFromRef(jacobian));
349  computeStepResidDerivImpl(outArgs, x, t, p, param_index, deriv_index);
350 }
351 
352 template <class Scalar>
357  const int param_index) const
358 {
359  typedef Thyra::ModelEvaluatorBase MEB;
360  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->createOutArgs();
361  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_DfDp, param_index)
362  .supports(MEB::DERIV_LINEAR_OP));
363  outArgs.set_DfDp(param_index,
364  MEB::Derivative<Scalar>(Teuchos::rcpFromRef(deriv)));
365  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
366 }
367 
368 template <class Scalar>
370  Thyra::LinearOpWithSolveBase<Scalar>& jacobian_solver,
373  const int param_index) const
374 {
375  typedef Thyra::ModelEvaluatorBase MEB;
376  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->createOutArgs();
377  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W));
378  outArgs.set_W(Teuchos::rcpFromRef(jacobian_solver));
379  computeStepResidDerivImpl(outArgs, x, t, p, param_index, 0);
380 }
381 
382 template <class Scalar>
387  const int param_index, const int deriv_index) const
388 {
389  using Teuchos::RCP;
390  typedef Thyra::ModelEvaluatorBase MEB;
391 
392  TEUCHOS_ASSERT(x.size() == 2);
393  TEUCHOS_ASSERT(t.size() == 2);
394  RCP<const Thyra::VectorBase<Scalar> > xn = x[0];
395  RCP<const Thyra::VectorBase<Scalar> > xo = x[1];
396  const Scalar tn = t[0];
397  const Scalar to = t[1];
398  const Scalar dt = tn - to;
399 
400  // compute x_dot
401  RCP<Thyra::VectorBase<Scalar> > x_dot = xn->clone_v();
403  new StepperBackwardEulerTimeDerivative<Scalar>(Scalar(1.0) / dt, xo));
404  timeDer->compute(xn, x_dot);
405 
406  // evaluate model
407  MEB::InArgs<Scalar> inArgs = this->wrapperModel_->createInArgs();
408  inArgs.set_x(xn);
409  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(x_dot);
410  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(tn);
411  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(dt);
412  inArgs.set_p(param_index, Teuchos::rcpFromRef(p));
413  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_alpha));
414  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_beta));
415  if (deriv_index == 0) {
416  // df/dx_n = df/dx_dot * dx_dot/dx_n + df/dx_n = 1/dt*df/dx_dot + df/dx_n
417  inArgs.set_alpha(Scalar(1.0) / dt);
418  inArgs.set_beta(Scalar(1.0));
419  }
420  else if (deriv_index == 1) {
421  // df/dx_{n-1} = df/dx_dot * dx_dot/dx_{n-1} = -1/dt*df/dx_dot
422  inArgs.set_alpha(Scalar(-1.0) / dt);
423  inArgs.set_beta(Scalar(0.0));
424  }
425  this->wrapperModel_->getAppModel()->evalModel(inArgs, outArgs);
426 }
427 
428 // Nonmember constructor - ModelEvaluator and ParameterList
429 // ------------------------------------------------------------------------
430 template <class Scalar>
432  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& model,
434 {
435  auto stepper = Teuchos::rcp(new StepperBackwardEuler<Scalar>());
436 
437  stepper->setStepperImplicitValues(pl);
438 
439  if (pl != Teuchos::null) {
440  std::string predictorName =
441  pl->get<std::string>("Predictor Stepper Type", "None");
442  stepper->setPredictor(predictorName);
443  }
444 
445  if (model != Teuchos::null) {
446  stepper->setModel(model);
447  stepper->initialize();
448  }
449 
450  return stepper;
451 }
452 
453 } // namespace Tempus
454 #endif // Tempus_StepperBackwardEuler_impl_hpp
void computeStepResidDerivImpl(const Thyra::ModelEvaluatorBase::OutArgs< Scalar > &outArgs, const Teuchos::Array< Teuchos::RCP< const Thyra::VectorBase< Scalar > > > &x, const Teuchos::Array< Scalar > &t, const Thyra::VectorBase< Scalar > &p, const int param_index, const int deriv_index=0) const
Implementation of computeStep*() methods.
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void computePredictor(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute predictor given the supplied stepper.
virtual void computeStepParamDeriv(Thyra::LinearOpBase< Scalar > &deriv, const Teuchos::Array< Teuchos::RCP< const Thyra::VectorBase< Scalar > > > &x, const Teuchos::Array< Scalar > &t, const Thyra::VectorBase< Scalar > &p, const int param_index) const override
Compute time step derivative w.r.t. model parameters.
virtual void computeStepResidual(Thyra::VectorBase< Scalar > &residual, const Teuchos::Array< Teuchos::RCP< const Thyra::VectorBase< Scalar > > > &x, const Teuchos::Array< Scalar > &t, const Thyra::VectorBase< Scalar > &p, const int param_index) const override
Compute time step residual.
Application Action for StepperBackwardEuler.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void computeStepSolver(Thyra::LinearOpWithSolveBase< Scalar > &jacobian_solver, const Teuchos::Array< Teuchos::RCP< const Thyra::VectorBase< Scalar > > > &x, const Teuchos::Array< Scalar > &t, const Thyra::VectorBase< Scalar > &p, const int param_index) const override
Compute time step Jacobian solver.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
Thyra Base interface for time steppers.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
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)
Thyra Base interface for implicit time steppers.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Take the specified timestep, dt, and return true if successful.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const override
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Return a valid ParameterList with current settings.
void setPredictor(std::string predictorType="None")
Set the predictor.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState() override
Get a default (initial) StepperState.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
virtual void setAppAction(Teuchos::RCP< StepperBackwardEulerAppAction< Scalar > > appAction)
virtual void computeStepJacobian(Thyra::LinearOpBase< Scalar > &jacobian, const Teuchos::Array< Teuchos::RCP< const Thyra::VectorBase< Scalar > > > &x, const Teuchos::Array< Scalar > &t, const Thyra::VectorBase< Scalar > &p, const int param_index, const int deriv_index) const override
Compute time step Jacobian.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
size_type size() const
Teuchos::RCP< StepperBackwardEuler< Scalar > > createStepperBackwardEuler(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, Teuchos::RCP< Teuchos::ParameterList > pl)
Nonmember constructor - ModelEvaluator and ParameterList.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
Time-derivative interface for Backward Euler.
#define TEUCHOS_ASSERT(assertion_test)
std::string toString(const T &t)
virtual int stencilLength() const override
Return the number of solution vectors in the time step stencil.