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) {
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
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
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.
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.
Teuchos::RCP< StepperBackwardEulerAppAction< Scalar > > stepperBEAppAction_
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.
Teuchos::RCP< Stepper< Scalar > > predictorStepper_
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.
Time-derivative interface for Backward Euler.
Thyra Base interface for time steppers.
bool isInitialized_
True if stepper's member data is initialized.
void setICConsistencyCheck(bool c)
virtual void setStepperXDot(Teuchos::RCP< Thyra::VectorBase< Scalar > > xDot)
Set xDot for Stepper storage.
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDot()
Get Stepper xDot.
void setStepperName(std::string s)
Set the stepper name.
virtual void initialize()
Initialize after construction and changing input parameters.
std::string getStepperType() const
Get the stepper type. The stepper type is used as an identifier for the stepper, and can only be set ...
virtual void setUseFSAL(bool a)
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void checkInitialized()
Check initialization, and error out on failure.
void setStepperType(std::string s)
Set the stepper type.
void setICConsistency(std::string s)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
Teuchos::RCP< WrapperModelEvaluator< Scalar > > wrapperModel_
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicImplicit() const
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver) override
Set solver.
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.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const override
const Thyra::SolveStatus< Scalar > solveImplicitODE(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xDot, const Scalar time, const Teuchos::RCP< ImplicitODEParameters< Scalar > > &p, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &y=Teuchos::null, const int index=-1)
Solve implicit ODE, f(x, xDot, t, p) = 0.
virtual void setZeroInitialGuess(bool zIG)
StepperState is a simple class to hold state information about the stepper.
Teuchos::RCP< StepperBackwardEuler< Scalar > > createStepperBackwardEuler(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, Teuchos::RCP< Teuchos::ParameterList > pl)
Nonmember constructor - ModelEvaluator and ParameterList.