Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
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
17namespace Tempus {
18
19template <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
34template <class Scalar>
36 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
37 const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
38 const Teuchos::RCP<Stepper<Scalar> >& predictorStepper, bool useFSAL,
39 std::string ICConsistency, bool ICConsistencyCheck, bool zeroInitialGuess,
40 const Teuchos::RCP<StepperBackwardEulerAppAction<Scalar> >&
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
60template <class Scalar>
61void 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
82template <class Scalar>
84 Teuchos::RCP<Stepper<Scalar> > predictorStepper)
85{
86 predictorStepper_ = predictorStepper;
87 if (predictorStepper_ == Teuchos::null) return;
88
89 TEUCHOS_TEST_FOR_EXCEPTION(
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
103template <class Scalar>
105 Teuchos::RCP<StepperBackwardEulerAppAction<Scalar> > appAction)
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
118template <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
135template <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
152template <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 {
162 TEUCHOS_TEST_FOR_EXCEPTION(
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
194 Teuchos::RCP<TimeDerivative<Scalar> > timeDer = Teuchos::rcp(
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
225template <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() ==
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
250template <class Scalar>
251Teuchos::RCP<Tempus::StepperState<Scalar> >
253{
254 Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
255 rcp(new StepperState<Scalar>(this->getStepperType()));
256 return stepperState;
257}
258
259template <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
282template <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
307template <class Scalar>
308Teuchos::RCP<const Teuchos::ParameterList>
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
319template <class Scalar>
321{
322 return 2;
323}
324
325template <class Scalar>
328 const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
329 const Teuchos::Array<Scalar>& t, const Thyra::VectorBase<Scalar>& p,
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
338template <class Scalar>
341 const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
342 const Teuchos::Array<Scalar>& t, const Thyra::VectorBase<Scalar>& p,
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
352template <class Scalar>
355 const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
356 const Teuchos::Array<Scalar>& t, const Thyra::VectorBase<Scalar>& p,
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
368template <class Scalar>
371 const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
372 const Teuchos::Array<Scalar>& t, const Thyra::VectorBase<Scalar>& p,
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
382template <class Scalar>
384 const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs,
385 const Teuchos::Array<Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
386 const Teuchos::Array<Scalar>& t, const Thyra::VectorBase<Scalar>& p,
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();
402 Teuchos::RCP<TimeDerivative<Scalar> > timeDer = Teuchos::rcp(
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// ------------------------------------------------------------------------
430template <class Scalar>
431Teuchos::RCP<StepperBackwardEuler<Scalar> > createStepperBackwardEuler(
432 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& model,
433 Teuchos::RCP<Teuchos::ParameterList> pl)
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
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Application Action for StepperBackwardEuler.
Time-derivative interface for Backward Euler.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState() override
Get a default (initial) StepperState.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void setAppAction(Teuchos::RCP< StepperBackwardEulerAppAction< Scalar > > appAction)
virtual int stencilLength() const override
Return the number of solution vectors in the time step stencil.
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.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
virtual void computePredictor(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute predictor given the supplied stepper.
void setPredictor(std::string predictorType="None")
Set the predictor.
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 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 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 bool isValidSetup(Teuchos::FancyOStream &out) const override
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
Return a valid ParameterList with current settings.
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.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Take the specified timestep, dt, and return true if successful.
Thyra Base interface for implicit time steppers.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
StepperState is a simple class to hold state information about the stepper.
Thyra Base interface for time steppers.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Teuchos::RCP< StepperBackwardEuler< Scalar > > createStepperBackwardEuler(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, Teuchos::RCP< Teuchos::ParameterList > pl)
Nonmember constructor - ModelEvaluator and ParameterList.