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: 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 
13 #include "Tempus_WrapperModelEvaluatorBasic.hpp"
14 #include "Tempus_StepperFactory.hpp"
15 
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22 {
23  this->setStepperName( "Backward Euler");
24  this->setStepperType( "Backward Euler");
25  this->setUseFSAL( false);
26  this->setICConsistency( "None");
27  this->setICConsistencyCheck( false);
28  this->setZeroInitialGuess( false);
29 
30  this->setAppAction(Teuchos::null);
31  this->setDefaultSolver();
32  this->setPredictor();
33 }
34 
35 
36 template<class Scalar>
38  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
40  const Teuchos::RCP<Stepper<Scalar> >& predictorStepper,
41  bool useFSAL,
42  std::string ICConsistency,
43  bool ICConsistencyCheck,
44  bool zeroInitialGuess,
45  const Teuchos::RCP<StepperBackwardEulerAppAction<Scalar> >& stepperBEAppAction)
46 {
47  this->setStepperName( "Backward Euler");
48  this->setStepperType( "Backward Euler");
49  this->setUseFSAL( useFSAL);
50  this->setICConsistency( ICConsistency);
51  this->setICConsistencyCheck( ICConsistencyCheck);
52  this->setZeroInitialGuess( zeroInitialGuess);
53 
54  this->setAppAction(stepperBEAppAction);
55  this->setSolver(solver);
56  this->setPredictor(predictorStepper);
57 
58  if (appModel != Teuchos::null) {
59  this->setModel(appModel);
60  this->initialize();
61  }
62 }
63 
64 
65 template<class Scalar>
66 void StepperBackwardEuler<Scalar>::setPredictor(std::string predictorType)
67 {
68  if (predictorType == "None") {
69  predictorStepper_ = Teuchos::null;
70  return;
71  }
72 
73  auto sf = Teuchos::rcp(new StepperFactory<Scalar>());
74  if (this->wrapperModel_ != Teuchos::null &&
75  this->wrapperModel_->getAppModel() != Teuchos::null) {
76  predictorStepper_ = sf->createStepper(predictorType,
77  this->wrapperModel_->getAppModel());
78  } else {
79  predictorStepper_ = sf->createStepper(predictorType);
80  }
81 
82  this->isInitialized_ = false;
83 }
84 
85 
87 template<class Scalar>
89  Teuchos::RCP<Stepper<Scalar> > predictorStepper)
90 {
91  predictorStepper_ = predictorStepper;
92  if (predictorStepper_ == Teuchos::null) return;
93 
95  predictorStepper_->getModel() == Teuchos::null &&
96  this->wrapperModel_->getAppModel() == Teuchos::null, std::logic_error,
97  "Error - Need to set the model, setModel(), before calling "
98  "StepperBackwardEuler::setPredictor()\n");
99 
100  if (predictorStepper_->getModel() == Teuchos::null)
101  predictorStepper_->setModel(this->wrapperModel_->getAppModel());
102  predictorStepper_->initialize();
103 
104  this->isInitialized_ = false;
105 }
106 
107 
108 template<class Scalar>
111 {
112  if (appAction == Teuchos::null) {
113  // Create default appAction
114  stepperBEAppAction_ =
116  } else {
117  stepperBEAppAction_ = appAction;
118  }
119  this->isInitialized_ = false;
120 }
121 
122 
123 template<class Scalar>
125  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
126 {
127  using Teuchos::RCP;
128 
129  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
130 
131  // Check if we need Stepper storage for xDot
132  if (initialState->getXDot() == Teuchos::null)
133  this->setStepperXDot(initialState->getX()->clone_v());
134  else
135  this->setStepperXDot(initialState->getXDot());
136 
138 }
139 
140 
141 template<class Scalar>
143  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
144 {
145  this->checkInitialized();
146 
147  using Teuchos::RCP;
148 
149  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperBackwardEuler::takeStep()");
150  {
151  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
152  std::logic_error,
153  "Error - StepperBackwardEuler<Scalar>::takeStep(...)\n"
154  "Need at least two SolutionStates for Backward Euler.\n"
155  " Number of States = " << solutionHistory->getNumStates() << "\n"
156  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
157  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
158 
159  RCP<StepperBackwardEuler<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
160  stepperBEAppAction_->execute(solutionHistory, thisStepper,
162 
163  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
164  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
165 
166  RCP<const Thyra::VectorBase<Scalar> > xOld = currentState->getX();
167  RCP<Thyra::VectorBase<Scalar> > x = workingState->getX();
168  if (workingState->getXDot() != Teuchos::null)
169  this->setStepperXDot(workingState->getXDot());
170  RCP<Thyra::VectorBase<Scalar> > xDot = this->getStepperXDot();
171 
172  computePredictor(solutionHistory);
173  if (workingState->getSolutionStatus() == Status::FAILED)
174  return;
175 
176  const Scalar time = workingState->getTime();
177  const Scalar dt = workingState->getTimeStep();
178 
179  // Setup TimeDerivative
182  Scalar(1.0)/dt,xOld));
183 
184  const Scalar alpha = Scalar(1.0)/dt;
185  const Scalar beta = Scalar(1.0);
187  timeDer, dt, alpha, beta));
188 
189  stepperBEAppAction_->execute(solutionHistory, thisStepper,
191 
192  const Thyra::SolveStatus<Scalar> sStatus =
193  this->solveImplicitODE(x, xDot, time, p);
194 
195  stepperBEAppAction_->execute(solutionHistory, thisStepper,
197 
198  if (workingState->getXDot() != Teuchos::null)
199  timeDer->compute(x, xDot);
200 
201  workingState->setSolutionStatus(sStatus); // Converged --> pass.
202  workingState->setOrder(this->getOrder());
203  workingState->computeNorms(currentState);
204  stepperBEAppAction_->execute(solutionHistory, thisStepper,
206  }
207  return;
208 }
209 
210 template<class Scalar>
212  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
213 {
214  if (predictorStepper_ == Teuchos::null) return;
215  predictorStepper_->takeStep(solutionHistory);
216 
217  if (solutionHistory->getWorkingState()->getSolutionStatus()==Status::FAILED) {
218  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
219  Teuchos::OSTab ostab(out,1,"StepperBackwardEuler::computePredictor");
220  *out << "Warning - predictorStepper has failed." << std::endl;
221  } else {
222  // Reset status to WORKING since this is the predictor
223  solutionHistory->getWorkingState()->setSolutionStatus(Status::WORKING);
224  }
225 }
226 
227 
234 template<class Scalar>
238 {
240  rcp(new StepperState<Scalar>(this->getStepperType()));
241  return stepperState;
242 }
243 
244 
245 template<class Scalar>
248  const Teuchos::EVerbosityLevel verbLevel) const
249 {
250  out << std::endl;
251  Stepper<Scalar>::describe(out, verbLevel);
252  StepperImplicit<Scalar>::describe(out, verbLevel);
253 
254  out << "--- StepperBackwardEuler ---\n";
255  out << " predictorStepper_ = "
256  << predictorStepper_ << std::endl;
257  if (predictorStepper_ != Teuchos::null) {
258  out << " predictorStepper_->isInitialized() = "
259  << Teuchos::toString(predictorStepper_->isInitialized()) << std::endl;
260  out << " predictor stepper type = "
261  << predictorStepper_->description() << std::endl;
262  }
263  out << " stepperBEAppAction_ = "
264  << stepperBEAppAction_ << std::endl;
265  out << "----------------------------" << std::endl;
266 }
267 
268 
269 template<class Scalar>
271 {
272  bool isValidSetup = true;
273 
274  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
275  if ( !StepperImplicit<Scalar>::isValidSetup(out) ) isValidSetup = false;
276 
277  if (predictorStepper_ != Teuchos::null) {
278  if ( !predictorStepper_->isInitialized() ) {
279  isValidSetup = false;
280  out << "The predictor stepper is not initialized!\n";
281  }
282  }
283 
284  if (stepperBEAppAction_ == Teuchos::null) {
285  isValidSetup = false;
286  out << "The Backward Euler AppAction is not set!\n";
287  }
288 
289  return isValidSetup;
290 }
291 
292 
293 template<class Scalar>
296 {
297  auto pl = this->getValidParametersBasicImplicit();
298  if (predictorStepper_ == Teuchos::null)
299  pl->set("Predictor Stepper Type", "None");
300  else
301  pl->set("Predictor Stepper Type", predictorStepper_->getStepperType());
302  return pl;
303 }
304 
305 
306 template <class Scalar>
307 int
309 {
310  return 2;
311 }
312 
313 
314 template <class Scalar>
315 void
317  Thyra::VectorBase<Scalar>& residual,
319  const Teuchos::Array<Scalar>& t,
320  const Thyra::VectorBase<Scalar>& p,
321  const int param_index) const
322 {
323  typedef Thyra::ModelEvaluatorBase MEB;
324  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
325  outArgs.set_f(Teuchos::rcpFromRef(residual));
326  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
327 }
328 
329 template <class Scalar>
330 void
332  Thyra::LinearOpBase<Scalar>& jacobian,
334  const Teuchos::Array<Scalar>& t,
335  const Thyra::VectorBase<Scalar>& p,
336  const int param_index,
337  const int deriv_index) const
338 {
339  typedef Thyra::ModelEvaluatorBase MEB;
340  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
341  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W_op));
342  outArgs.set_W_op(Teuchos::rcpFromRef(jacobian));
343  computeStepResidDerivImpl(outArgs, x, t, p, param_index, deriv_index);
344 }
345 
346 template <class Scalar>
347 void
351  const Teuchos::Array<Scalar>& t,
352  const Thyra::VectorBase<Scalar>& p,
353  const int param_index) const
354 {
355  typedef Thyra::ModelEvaluatorBase MEB;
356  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
357  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_DfDp, param_index).supports(MEB::DERIV_LINEAR_OP));
358  outArgs.set_DfDp(param_index,
359  MEB::Derivative<Scalar>(Teuchos::rcpFromRef(deriv)));
360  computeStepResidDerivImpl(outArgs, x, t, p, param_index);
361 }
362 
363 template <class Scalar>
364 void
366  Thyra::LinearOpWithSolveBase<Scalar>& jacobian_solver,
368  const Teuchos::Array<Scalar>& t,
369  const Thyra::VectorBase<Scalar>& p,
370  const int param_index) const
371 {
372  typedef Thyra::ModelEvaluatorBase MEB;
373  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
374  TEUCHOS_ASSERT(outArgs.supports(MEB::OUT_ARG_W));
375  outArgs.set_W(Teuchos::rcpFromRef(jacobian_solver));
376  computeStepResidDerivImpl(outArgs, x, t, p, param_index, 0);
377 }
378 
379 template <class Scalar>
380 void
384  const Teuchos::Array<Scalar>& t,
385  const Thyra::VectorBase<Scalar>& p,
386  const int param_index,
387  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();
404  timeDer->compute(xn, x_dot);
405 
406  // evaluate model
407  MEB::InArgs<Scalar> inArgs = this->wrapperModel_->getInArgs();
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 
429 // Nonmember constructor - ModelEvaluator and ParameterList
430 // ------------------------------------------------------------------------
431 template<class Scalar>
434  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& model,
436 {
437  auto stepper = Teuchos::rcp(new StepperBackwardEuler<Scalar>());
438 
439  stepper->setStepperImplicitValues(pl);
440 
441  if (model != Teuchos::null) {
442  stepper->setModel(model);
443 
444  if (pl != Teuchos::null) {
445  std::string predictorName =
446  pl->get<std::string>("Predictor Stepper Type", "None");
447  stepper->setPredictor(predictorName);
448  }
449  stepper->initialize();
450  }
451 
452  return stepper;
453 }
454 
455 
456 } // namespace Tempus
457 #endif // Tempus_StepperBackwardEuler_impl_hpp
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.
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
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.
Application Action for StepperBackwardEuler.
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.
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 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.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setAppAction(Teuchos::RCP< StepperBackwardEulerAppAction< Scalar > > appAction)
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
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
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.
Time-derivative interface for Backward Euler.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
#define TEUCHOS_ASSERT(assertion_test)
std::string toString(const T &t)