Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperBackwardEuler_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_StepperBackwardEuler_impl_hpp
10 #define Tempus_StepperBackwardEuler_impl_hpp
11 
12 #include "Tempus_config.hpp"
14 #include "Tempus_WrapperModelEvaluatorBasic.hpp"
15 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
16 #include "NOX_Thyra.H"
17 
18 
19 namespace Tempus {
20 
21 // Forward Declaration for recursive includes (this Stepper <--> StepperFactory)
22 template<class Scalar> class StepperFactory;
23 
24 
25 template<class Scalar>
27 {
28  this->setStepperType( "Backward Euler");
29  this->setUseFSAL( this->getUseFSALDefault());
30  this->setICConsistency( this->getICConsistencyDefault());
31  this->setICConsistencyCheck( this->getICConsistencyCheckDefault());
32  this->setZeroInitialGuess( false);
33 
34  this->setObserver();
35 }
36 
37 
38 template<class Scalar>
40  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
41  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
42  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
43  bool useFSAL,
44  std::string ICConsistency,
45  bool ICConsistencyCheck,
46  bool zeroInitialGuess)
47 
48 {
49  this->setStepperType( "Backward Euler");
50  this->setUseFSAL( useFSAL);
51  this->setICConsistency( ICConsistency);
52  this->setICConsistencyCheck( ICConsistencyCheck);
53  this->setZeroInitialGuess( zeroInitialGuess);
54 
55  this->setObserver(obs);
56 
57  if (appModel != Teuchos::null) {
58 
59  this->setModel(appModel);
60  this->setSolver(solver);
61  this->initialize();
62  }
63 }
64 
65 
66 /// Set the predictor to a Stepper with default settings.
67 template<class Scalar>
68 void StepperBackwardEuler<Scalar>::setPredictor(std::string predictorType)
69 {
70  if (predictorType == "None") {
71  predictorStepper_ = Teuchos::null;
72  return;
73  }
74 
75  TEUCHOS_TEST_FOR_EXCEPTION(
76  this->wrapperModel_->getAppModel() == Teuchos::null, std::logic_error,
77  "Error - Need to set the model, setModel(), before calling "
78  "StepperBackwardEuler::setPredictor()\n");
79 
80  using Teuchos::RCP;
81  RCP<StepperFactory<Scalar> > sf = Teuchos::rcp(new StepperFactory<Scalar>());
82  predictorStepper_ =
83  sf->createStepper(predictorType, this->wrapperModel_->getAppModel());
84 }
85 
86 
87 /// Set the predictor.
88 template<class Scalar>
90  Teuchos::RCP<Stepper<Scalar> > predictorStepper)
91 {
92  TEUCHOS_TEST_FOR_EXCEPTION(
93  this->wrapperModel_->getAppModel() == Teuchos::null, std::logic_error,
94  "Error - Need to set the model, setModel(), before calling "
95  "StepperBackwardEuler::setPredictor()\n");
96 
97  predictorStepper_ = predictorStepper;
98  predictorStepper_->setModel(this->wrapperModel_->getAppModel());
99  predictorStepper_->initialize();
100 }
101 
102 
103 template<class Scalar>
105  Teuchos::RCP<StepperObserver<Scalar> > obs)
106 {
107  if (obs == Teuchos::null) {
108  // Create default observer, otherwise keep current observer.
109  if (this->stepperObserver_ == Teuchos::null) {
110  stepperBEObserver_ =
111  Teuchos::rcp(new StepperBackwardEulerObserver<Scalar>());
112  this->stepperObserver_ =
113  Teuchos::rcp_dynamic_cast<StepperObserver<Scalar> >(stepperBEObserver_,true);
114  }
115  } else {
116  this->stepperObserver_ = obs;
117  stepperBEObserver_ =
118  Teuchos::rcp_dynamic_cast<StepperBackwardEulerObserver<Scalar> >
119  (this->stepperObserver_,true);
120  }
121 }
122 
123 
124 template<class Scalar>
126 {
127  TEUCHOS_TEST_FOR_EXCEPTION(
128  this->wrapperModel_ == Teuchos::null, std::logic_error,
129  "Error - Need to set the model, setModel(), before calling "
130  "StepperBackwardEuler::initialize()\n");
131 }
132 
133 
134 template<class Scalar>
136  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
137 {
138  using Teuchos::RCP;
139 
140  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
141 
142  // Check if we need Stepper storage for xDot
143  if (initialState->getXDot() == Teuchos::null)
144  this->setStepperXDot(initialState->getX()->clone_v());
145 
147 
148  if (this->getUseFSAL()) {
149  RCP<Teuchos::FancyOStream> out = this->getOStream();
150  Teuchos::OSTab ostab(out,1,"StepperBackwardEuler::setInitialConditions()");
151  *out << "\nWarning -- The First-Step-As-Last (FSAL) principle is not "
152  << "needed with Backward Euler. The default is to set useFSAL=false, "
153  << "however useFSAL=true will also work but have no affect "
154  << "(i.e., no-op).\n" << std::endl;
155  }
156 }
157 
158 
159 template<class Scalar>
161  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
162 {
163  using Teuchos::RCP;
164 
165  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperBackwardEuler::takeStep()");
166  {
167  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
168  std::logic_error,
169  "Error - StepperBackwardEuler<Scalar>::takeStep(...)\n"
170  "Need at least two SolutionStates for Backward Euler.\n"
171  " Number of States = " << solutionHistory->getNumStates() << "\n"
172  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
173  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
174 
175  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
176  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
177  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
178 
179  RCP<const Thyra::VectorBase<Scalar> > xOld = currentState->getX();
180  RCP<Thyra::VectorBase<Scalar> > x = workingState->getX();
181 
182  RCP<Thyra::VectorBase<Scalar> > xDot = this->getStepperXDot(workingState);
183 
184  computePredictor(solutionHistory);
185  if (workingState->getSolutionStatus() == Status::FAILED)
186  return;
187 
188  const Scalar time = workingState->getTime();
189  const Scalar dt = workingState->getTimeStep();
190 
191  // Setup TimeDerivative
192  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
194  Scalar(1.0)/dt,xOld));
195 
196  const Scalar alpha = Scalar(1.0)/dt;
197  const Scalar beta = Scalar(1.0);
198  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
199  timeDer, dt, alpha, beta));
200 
201  if (!Teuchos::is_null(stepperBEObserver_))
202  stepperBEObserver_->observeBeforeSolve(solutionHistory, *this);
203 
204  const Thyra::SolveStatus<Scalar> sStatus =
205  this->solveImplicitODE(x, xDot, time, p);
206 
207  if (!Teuchos::is_null(stepperBEObserver_))
208  stepperBEObserver_->observeAfterSolve(solutionHistory, *this);
209 
210  if (workingState->getXDot() != Teuchos::null)
211  timeDer->compute(x, xDot);
212 
213  workingState->setSolutionStatus(sStatus); // Converged --> pass.
214  workingState->setOrder(this->getOrder());
215  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
216  }
217  return;
218 }
219 
220 template<class Scalar>
222  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
223 {
224  if (predictorStepper_ == Teuchos::null) return;
225  predictorStepper_->takeStep(solutionHistory);
226 
227  if (solutionHistory->getWorkingState()->getSolutionStatus()==Status::FAILED) {
228  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
229  Teuchos::OSTab ostab(out,1,"StepperBackwardEuler::computePredictor");
230  *out << "Warning - predictorStepper has failed." << std::endl;
231  } else {
232  // Reset status to WORKING since this is the predictor
233  solutionHistory->getWorkingState()->setSolutionStatus(Status::WORKING);
234  }
235 }
236 
237 
238 /** \brief Provide a StepperState to the SolutionState.
239  * This Stepper does not have any special state data,
240  * so just provide the base class StepperState with the
241  * Stepper description. This can be checked to ensure
242  * that the input StepperState can be used by this Stepper.
243  */
244 template<class Scalar>
245 Teuchos::RCP<Tempus::StepperState<Scalar> >
248 {
249  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
250  rcp(new StepperState<Scalar>(this->getStepperType()));
251  return stepperState;
252 }
253 
254 
255 template<class Scalar>
257  Teuchos::FancyOStream &out,
258  const Teuchos::EVerbosityLevel /* verbLevel */) const
259 {
260  out << this->getStepperType() << "::describe:" << std::endl
261  << "wrapperModel_ = " << this->wrapperModel_->description() << std::endl;
262 }
263 
264 
265 template<class Scalar>
266 Teuchos::RCP<const Teuchos::ParameterList>
268 {
269  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
270  getValidParametersBasic(pl, this->getStepperType());
271  pl->set<std::string>("Solver Name", "Default Solver");
272  pl->set<bool> ("Zero Initial Guess", false);
273  pl->set<std::string>("Predictor Stepper Type", "None");
274  Teuchos::RCP<Teuchos::ParameterList> solverPL = defaultSolverParameters();
275  pl->set("Default Solver", *solverPL);
276 
277  return pl;
278 }
279 
280 
281 template <class Scalar>
282 int
284 {
285  return 2;
286 }
287 
288 
289 template <class Scalar>
290 void
292  Thyra::VectorBase<Scalar>& residual,
293  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
294  const Teuchos::Array<Scalar>& t,
295  const Thyra::VectorBase<Scalar>& p,
296  const int param_index) const
297 {
298  typedef Thyra::ModelEvaluatorBase MEB;
299  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
300  outArgs.set_f(Teuchos::rcpFromRef(residual));
301  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
302 }
303 
304 template <class Scalar>
305 void
307  Thyra::LinearOpBase<Scalar>& jacobian,
308  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
309  const Teuchos::Array<Scalar>& t,
310  const Thyra::VectorBase<Scalar>& p,
311  const int param_index,
312  const int deriv_index) const
313 {
314  typedef Thyra::ModelEvaluatorBase MEB;
315  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
316  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W_op));
317  outArgs.set_W_op(Teuchos::rcpFromRef(jacobian));
318  computeStepResidDerivImpl(outArgs, x, t, p, param_index, deriv_index);
319 }
320 
321 template <class Scalar>
322 void
324  Thyra::LinearOpBase<Scalar>& deriv,
325  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
326  const Teuchos::Array<Scalar>& t,
327  const Thyra::VectorBase<Scalar>& p,
328  const int param_index) const
329 {
330  typedef Thyra::ModelEvaluatorBase MEB;
331  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
332  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_DfDp, param_index).supports(MEB::DERIV_LINEAR_OP));
333  outArgs.set_DfDp(param_index,
334  MEB::Derivative<Scalar>(Teuchos::rcpFromRef(deriv)));
335  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
336 }
337 
338 template <class Scalar>
339 void
341  Thyra::LinearOpWithSolveBase<Scalar>& jacobian_solver,
342  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
343  const Teuchos::Array<Scalar>& t,
344  const Thyra::VectorBase<Scalar>& p,
345  const int param_index) const
346 {
347  typedef Thyra::ModelEvaluatorBase MEB;
348  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
349  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W));
350  outArgs.set_W(Teuchos::rcpFromRef(jacobian_solver));
351  computeStepResidDerivImpl(outArgs, x, t, p, param_index, 0);
352 }
353 
354 template <class Scalar>
355 void
357  const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs,
358  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
359  const Teuchos::Array<Scalar>& t,
360  const Thyra::VectorBase<Scalar>& p,
361  const int param_index,
362  const int deriv_index) const
363 {
364  using Teuchos::RCP;
365  typedef Thyra::ModelEvaluatorBase MEB;
366 
367  TEUCHOS_ASSERT(x.size() == 2);
368  TEUCHOS_ASSERT(t.size() == 2);
369  RCP<const Thyra::VectorBase<Scalar> > xn = x[0];
370  RCP<const Thyra::VectorBase<Scalar> > xo = x[1];
371  const Scalar tn = t[0];
372  const Scalar to = t[1];
373  const Scalar dt = tn-to;
374 
375  // compute x_dot
376  RCP<Thyra::VectorBase<Scalar> > x_dot = xn->clone_v();
377  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
378  Teuchos::rcp(new StepperBackwardEulerTimeDerivative<Scalar>(Scalar(1.0)/dt,xo));
379  timeDer->compute(xn, x_dot);
380 
381  // evaluate model
382  MEB::InArgs<Scalar> inArgs = this->wrapperModel_->getInArgs();
383  inArgs.set_x(xn);
384  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (x_dot);
385  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (tn);
386  if (inArgs.supports(MEB::IN_ARG_step_size )) inArgs.set_step_size(dt);
387  inArgs.set_p(param_index, Teuchos::rcpFromRef(p));
388  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_alpha));
389  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_beta));
390  if (deriv_index == 0) {
391  // df/dx_n = df/dx_dot * dx_dot/dx_n + df/dx_n = 1/dt*df/dx_dot + df/dx_n
392  inArgs.set_alpha(Scalar(1.0)/dt);
393  inArgs.set_beta(Scalar(1.0));
394  }
395  else if (deriv_index == 1) {
396  // df/dx_{n-1} = df/dx_dot * dx_dot/dx_{n-1} = -1/dt*df/dx_dot
397  inArgs.set_alpha(Scalar(-1.0)/dt);
398  inArgs.set_beta(Scalar(0.0));
399  }
400  this->wrapperModel_->getAppModel()->evalModel(inArgs, outArgs);
401 }
402 
403 } // namespace Tempus
404 #endif // Tempus_StepperBackwardEuler_impl_hpp
StepperBackwardEulerObserver class for StepperBackwardEuler.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
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 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
Compute time step residual.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
virtual void computePredictor(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute predictor given the supplied stepper.
virtual int stencilLength() const
Return the number of solution vectors in the time step stencil.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
Thyra Base interface for time steppers.
StepperState is a simple class to hold state information about the stepper.
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
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
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
Compute time step derivative w.r.t. model parameters.
void setPredictor(std::string predictorType="None")
Set the predictor.
StepperObserver class for Stepper class.
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Time-derivative interface for Backward Euler.
virtual void initialize()
Initialize during construction and after changing input parameters.
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.