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->setParameterList(Teuchos::null);
29  this->modelWarning();
30 }
31 
32 
33 template<class Scalar>
35  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
36  Teuchos::RCP<Teuchos::ParameterList> pList)
37 {
38  this->setParameterList(pList);
39 
40  if (appModel == Teuchos::null) {
41  this->modelWarning();
42  }
43  else {
44  this->setModel(appModel);
45  this->initialize();
46  }
47 }
48 
49 
50 /** \brief Set the predictor to a pre-defined predictor in the ParameterList.
51  * The predictor is set to predictorName sublist in the Stepper's
52  * ParameterList. The predictorName sublist should already be defined
53  * in the Stepper's ParameterList. Otherwise it will fail.
54  */
55 template<class Scalar>
56 void StepperBackwardEuler<Scalar>::setPredictor(std::string predictorName)
57 {
58  using Teuchos::RCP;
59  using Teuchos::ParameterList;
60 
61  RCP<ParameterList> predPL =
62  Teuchos::sublist(this->stepperPL_, predictorName, true);
63  this->stepperPL_->set("Predictor Name", predictorName);
64  if (predictorStepper_ != Teuchos::null) predictorStepper_ = Teuchos::null;
65  RCP<StepperFactory<Scalar> > sf = Teuchos::rcp(new StepperFactory<Scalar>());
66 }
67 
68 
69 /** \brief Set the predictor to the supplied Parameter sublist.
70  * This adds a new predictor Parameter sublist to the Stepper's ParameterList.
71  * If the predictor sublist is null, it tests if the predictor is set in
72  * the Stepper's ParameterList.
73  */
74 template<class Scalar>
76  Teuchos::RCP<Teuchos::ParameterList> predPL)
77 {
78  using Teuchos::RCP;
79  using Teuchos::ParameterList;
80 
81  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
82  std::string predictorName =
83  stepperPL->get<std::string>("Predictor Name","None");
84  if (is_null(predPL)) {
85  if (predictorName != "None") {
86  predPL = Teuchos::sublist(stepperPL, predictorName, true);
87  RCP<StepperFactory<Scalar> > sf =
88  Teuchos::rcp(new StepperFactory<Scalar>());
89  predictorStepper_ =
90  sf->createStepper(predPL, this->wrapperModel_->getAppModel());
91  }
92  } else {
93  TEUCHOS_TEST_FOR_EXCEPTION( predictorName == predPL->name(),
94  std::logic_error,
95  "Error - Trying to add a predictor that is already in ParameterList!\n"
96  << " Stepper Type = " << stepperPL->get<std::string>("Stepper Type")
97  << "\n" << " Predictor Name = "<<predictorName<<"\n");
98  predictorName = predPL->name();
99  stepperPL->set("Predictor Name", predictorName);
100  stepperPL->set(predictorName, *predPL); // Add sublist
101  if (predictorStepper_ != Teuchos::null) predictorStepper_ = Teuchos::null;
102  RCP<StepperFactory<Scalar> > sf =
103  Teuchos::rcp(new StepperFactory<Scalar>());
104  predictorStepper_ =
105  sf->createStepper(predPL, this->wrapperModel_->getAppModel());
106  }
107 }
108 
109 
110 template<class Scalar>
112  Teuchos::RCP<StepperObserver<Scalar> > obs)
113 {
114  if (obs == Teuchos::null) {
115  // Create default observer, otherwise keep current observer.
116  if (this->stepperObserver_ == Teuchos::null) {
117  stepperBEObserver_ =
118  Teuchos::rcp(new StepperBackwardEulerObserver<Scalar>());
119  this->stepperObserver_ =
120  Teuchos::rcp_dynamic_cast<StepperObserver<Scalar> >(stepperBEObserver_);
121  }
122  } else {
123  this->stepperObserver_ = obs;
124  stepperBEObserver_ =
125  Teuchos::rcp_dynamic_cast<StepperBackwardEulerObserver<Scalar> >
126  (this->stepperObserver_);
127  }
128 }
129 
130 
131 template<class Scalar>
133 {
134  TEUCHOS_TEST_FOR_EXCEPTION(
135  this->wrapperModel_ == Teuchos::null, std::logic_error,
136  "Error - Need to set the model, setModel(), before calling "
137  "StepperBackwardEuler::initialize()\n");
138 
139  this->setParameterList(this->stepperPL_);
140  this->setSolver();
141  this->setPredictor();
142  this->setObserver();
143 }
144 
145 
146 template<class Scalar>
148  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
149 {
150  using Teuchos::RCP;
151 
152  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
153 
154  // Check if we need Stepper storage for xDot
155  if (initialState->getXDot() == Teuchos::null)
156  this->setStepperXDot(initialState->getX()->clone_v());
157 
159 
160  if (this->getUseFSAL()) {
161  RCP<Teuchos::FancyOStream> out = this->getOStream();
162  Teuchos::OSTab ostab(out,1,"StepperBackwardEuler::setInitialConditions()");
163  *out << "\nWarning -- The First-Step-As-Last (FSAL) principle is not "
164  << "needed with Backward Euler. The default is to set useFSAL=false, "
165  << "however useFSAL=true will also work but have no affect "
166  << "(i.e., no-op).\n" << std::endl;
167  }
168 }
169 
170 
171 template<class Scalar>
173  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
174 {
175  using Teuchos::RCP;
176 
177  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperBackwardEuler::takeStep()");
178  {
179  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
180  std::logic_error,
181  "Error - StepperBackwardEuler<Scalar>::takeStep(...)\n"
182  "Need at least two SolutionStates for Backward Euler.\n"
183  " Number of States = " << solutionHistory->getNumStates() << "\n"
184  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
185  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
186 
187  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
188  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
189  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
190 
191  RCP<const Thyra::VectorBase<Scalar> > xOld = currentState->getX();
192  RCP<Thyra::VectorBase<Scalar> > x = workingState->getX();
193 
194  RCP<Thyra::VectorBase<Scalar> > xDot = this->getStepperXDot(workingState);
195 
196  computePredictor(solutionHistory);
197  if (workingState->getSolutionStatus() == Status::FAILED)
198  return;
199 
200  const Scalar time = workingState->getTime();
201  const Scalar dt = workingState->getTimeStep();
202 
203  // Setup TimeDerivative
204  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
206  Scalar(1.0)/dt,xOld));
207 
208  const Scalar alpha = Scalar(1.0)/dt;
209  const Scalar beta = Scalar(1.0);
210  Teuchos::RCP<ImplicitODEParameters<Scalar> > p =
211  Teuchos::rcp(new ImplicitODEParameters<Scalar>(timeDer,dt,alpha,beta,
212  SOLVE_FOR_X));
213 
214  if (!Teuchos::is_null(stepperBEObserver_))
215  stepperBEObserver_->observeBeforeSolve(solutionHistory, *this);
216 
217  const Thyra::SolveStatus<Scalar> sStatus =
218  this->solveImplicitODE(x, xDot, time, p);
219 
220  if (!Teuchos::is_null(stepperBEObserver_))
221  stepperBEObserver_->observeAfterSolve(solutionHistory, *this);
222 
223  if (workingState->getXDot() != Teuchos::null)
224  timeDer->compute(x, xDot);
225 
226  workingState->setSolutionStatus(sStatus); // Converged --> pass.
227  workingState->setOrder(this->getOrder());
228  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
229  }
230  return;
231 }
232 
233 template<class Scalar>
235  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
236 {
237  if (predictorStepper_ == Teuchos::null) return;
238  predictorStepper_->takeStep(solutionHistory);
239 
240  if (solutionHistory->getWorkingState()->getSolutionStatus()==Status::FAILED) {
241  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
242  Teuchos::OSTab ostab(out,1,"StepperBackwardEuler::computePredictor");
243  *out << "Warning - predictorStepper has failed." << std::endl;
244  } else {
245  // Reset status to WORKING since this is the predictor
246  solutionHistory->getWorkingState()->setSolutionStatus(Status::WORKING);
247  }
248 }
249 
250 
251 /** \brief Provide a StepperState to the SolutionState.
252  * This Stepper does not have any special state data,
253  * so just provide the base class StepperState with the
254  * Stepper description. This can be checked to ensure
255  * that the input StepperState can be used by this Stepper.
256  */
257 template<class Scalar>
258 Teuchos::RCP<Tempus::StepperState<Scalar> >
261 {
262  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
263  rcp(new StepperState<Scalar>(description()));
264  return stepperState;
265 }
266 
267 
268 template<class Scalar>
270 {
271  std::string name = "Backward Euler";
272  return(name);
273 }
274 
275 
276 template<class Scalar>
278  Teuchos::FancyOStream &out,
279  const Teuchos::EVerbosityLevel /* verbLevel */) const
280 {
281  out << description() << "::describe:" << std::endl
282  << "wrapperModel_ = " << this->wrapperModel_->description() << std::endl;
283 }
284 
285 
286 template <class Scalar>
288  Teuchos::RCP<Teuchos::ParameterList> const& pList)
289 {
290  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
291  if (pList == Teuchos::null) {
292  // Create default parameters if null, otherwise keep current parameters.
293  if (stepperPL == Teuchos::null) stepperPL = this->getDefaultParameters();
294  } else {
295  stepperPL = pList;
296  }
297  if (!(stepperPL->isParameter("Solver Name"))) {
298  stepperPL->set<std::string>("Solver Name", "Default Solver");
299  Teuchos::RCP<Teuchos::ParameterList> solverPL =
300  this->defaultSolverParameters();
301  stepperPL->set("Default Solver", *solverPL);
302  }
303  // Can not validate because of optional Parameters (e.g., Solver Name).
304  // stepperPL->validateParametersAndSetDefaults(*this->getValidParameters());
305 
306  std::string stepperType = stepperPL->get<std::string>("Stepper Type");
307  TEUCHOS_TEST_FOR_EXCEPTION( stepperType != "Backward Euler",
308  std::logic_error,
309  "Error - Stepper Type is not 'Backward Euler'!\n"
310  << " Stepper Type = "<<stepperPL->get<std::string>("Stepper Type")<<"\n");
311 
312  this->stepperPL_ = stepperPL;
313 }
314 
315 
316 template<class Scalar>
317 Teuchos::RCP<const Teuchos::ParameterList>
319 {
320  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
321  pl->setName("Default Stepper - " + this->description());
322  pl->set<std::string>("Stepper Type", this->description());
323  this->getValidParametersBasic(pl);
324  pl->set<bool> ("Zero Initial Guess", false);
325  pl->set<std::string>("Solver Name", "",
326  "Name of ParameterList containing the solver specifications.");
327 
328  return pl;
329 }
330 
331 
332 template<class Scalar>
333 Teuchos::RCP<Teuchos::ParameterList>
335 {
336  using Teuchos::RCP;
337  using Teuchos::ParameterList;
338  using Teuchos::rcp_const_cast;
339 
340  RCP<ParameterList> pl =
341  rcp_const_cast<ParameterList>(this->getValidParameters());
342 
343  pl->set<std::string>("Solver Name", "Default Solver");
344  RCP<ParameterList> solverPL = this->defaultSolverParameters();
345  pl->set("Default Solver", *solverPL);
346 
347  return pl;
348 }
349 
350 
351 template <class Scalar>
352 Teuchos::RCP<Teuchos::ParameterList>
354 {
355  return(this->stepperPL_);
356 }
357 
358 
359 template <class Scalar>
360 Teuchos::RCP<Teuchos::ParameterList>
362 {
363  Teuchos::RCP<Teuchos::ParameterList> temp_plist = this->stepperPL_;
364  this->stepperPL_ = Teuchos::null;
365  return(temp_plist);
366 }
367 
368 
369 template <class Scalar>
370 int
372 {
373  return 2;
374 }
375 
376 
377 template <class Scalar>
378 void
380  Thyra::VectorBase<Scalar>& residual,
381  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
382  const Teuchos::Array<Scalar>& t,
383  const Thyra::VectorBase<Scalar>& p,
384  const int param_index) const
385 {
386  typedef Thyra::ModelEvaluatorBase MEB;
387  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
388  outArgs.set_f(Teuchos::rcpFromRef(residual));
389  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
390 }
391 
392 template <class Scalar>
393 void
395  Thyra::LinearOpBase<Scalar>& jacobian,
396  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
397  const Teuchos::Array<Scalar>& t,
398  const Thyra::VectorBase<Scalar>& p,
399  const int param_index,
400  const int deriv_index) const
401 {
402  typedef Thyra::ModelEvaluatorBase MEB;
403  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
404  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W_op));
405  outArgs.set_W_op(Teuchos::rcpFromRef(jacobian));
406  computeStepResidDerivImpl(outArgs, x, t, p, param_index, deriv_index);
407 }
408 
409 template <class Scalar>
410 void
412  Thyra::LinearOpBase<Scalar>& deriv,
413  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
414  const Teuchos::Array<Scalar>& t,
415  const Thyra::VectorBase<Scalar>& p,
416  const int param_index) const
417 {
418  typedef Thyra::ModelEvaluatorBase MEB;
419  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
420  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_DfDp, param_index).supports(MEB::DERIV_LINEAR_OP));
421  outArgs.set_DfDp(param_index,
422  MEB::Derivative<Scalar>(Teuchos::rcpFromRef(deriv)));
423  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
424 }
425 
426 template <class Scalar>
427 void
429  Thyra::LinearOpWithSolveBase<Scalar>& jacobian_solver,
430  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
431  const Teuchos::Array<Scalar>& t,
432  const Thyra::VectorBase<Scalar>& p,
433  const int param_index) const
434 {
435  typedef Thyra::ModelEvaluatorBase MEB;
436  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
437  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W));
438  outArgs.set_W(Teuchos::rcpFromRef(jacobian_solver));
439  computeStepResidDerivImpl(outArgs, x, t, p, param_index, 0);
440 }
441 
442 template <class Scalar>
443 void
445  const Thyra::ModelEvaluatorBase::OutArgs<Scalar>& outArgs,
446  const Teuchos::Array< Teuchos::RCP<const Thyra::VectorBase<Scalar> > >& x,
447  const Teuchos::Array<Scalar>& t,
448  const Thyra::VectorBase<Scalar>& p,
449  const int param_index,
450  const int deriv_index) const
451 {
452  using Teuchos::RCP;
453  typedef Thyra::ModelEvaluatorBase MEB;
454 
455  TEUCHOS_ASSERT(x.size() == 2);
456  TEUCHOS_ASSERT(t.size() == 2);
457  RCP<const Thyra::VectorBase<Scalar> > xn = x[0];
458  RCP<const Thyra::VectorBase<Scalar> > xo = x[1];
459  const Scalar tn = t[0];
460  const Scalar to = t[1];
461  const Scalar dt = tn-to;
462 
463  // compute x_dot
464  RCP<Thyra::VectorBase<Scalar> > x_dot = xn->clone_v();
465  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
466  Teuchos::rcp(new StepperBackwardEulerTimeDerivative<Scalar>(Scalar(1.0)/dt,xo));
467  timeDer->compute(xn, x_dot);
468 
469  // evaluate model
470  MEB::InArgs<Scalar> inArgs = this->wrapperModel_->getInArgs();
471  inArgs.set_x(xn);
472  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (x_dot);
473  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (tn);
474  if (inArgs.supports(MEB::IN_ARG_step_size )) inArgs.set_step_size(dt);
475  inArgs.set_p(param_index, Teuchos::rcpFromRef(p));
476  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_alpha));
477  TEUCHOS_ASSERT(inArgs.supports(MEB::IN_ARG_beta));
478  if (deriv_index == 0) {
479  // df/dx_n = df/dx_dot * dx_dot/dx_n + df/dx_n = 1/dt*df/dx_dot + df/dx_n
480  inArgs.set_alpha(Scalar(1.0)/dt);
481  inArgs.set_beta(Scalar(1.0));
482  }
483  else if (deriv_index == 1) {
484  // df/dx_{n-1} = df/dx_dot * dx_dot/dx_{n-1} = -1/dt*df/dx_dot
485  inArgs.set_alpha(Scalar(-1.0)/dt);
486  inArgs.set_beta(Scalar(0.0));
487  }
488  this->wrapperModel_->getAppModel()->evalModel(inArgs, outArgs);
489 }
490 
491 } // namespace Tempus
492 #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.
Teuchos::RCP< Teuchos::ParameterList > getDefaultParameters() const
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
void setPredictor(std::string predictorName)
Set the predictor.
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
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.
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...
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
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
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)
Time-derivative interface for Backward Euler.
virtual void initialize()
Initialize during construction and after changing input parameters.
Solve for x and determine xDot from x.