Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperBDF2_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_StepperBDF2_impl_hpp
10 #define Tempus_StepperBDF2_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 startup stepper to a pre-defined stepper in the ParameterList
51  *
52  * The startup stepper is set to stepperName sublist in the Stepper's
53  * ParameterList. The stepperName sublist should already be defined
54  * in the Stepper's ParameterList. Otherwise it will fail.
55  */
56 template<class Scalar>
57 void StepperBDF2<Scalar>::setStartUpStepper(std::string startupStepperName)
58 {
59  using Teuchos::RCP;
60  using Teuchos::ParameterList;
61 
62  RCP<ParameterList> startupStepperPL =
63  Teuchos::sublist(this->stepperPL_, startupStepperName, true);
64  this->stepperPL_->set("Start Up Stepper Name", startupStepperName);
65  RCP<StepperFactory<Scalar> > sf = Teuchos::rcp(new StepperFactory<Scalar>());
66  startUpStepper_ =
67  sf->createStepper(startupStepperPL, this->wrapperModel_->getAppModel());
68 }
69 
70 
71 /** \brief Set the start up stepper to the supplied Parameter sublist.
72  *
73  * This adds a new start up stepper Parameter sublist to the Stepper's
74  * ParameterList. If the start up stepper sublist is null, it tests if
75  * the stepper sublist is set in the Stepper's ParameterList.
76  */
77 template<class Scalar>
79  Teuchos::RCP<Teuchos::ParameterList> startupStepperPL)
80 {
81  using Teuchos::RCP;
82  using Teuchos::ParameterList;
83 
84  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
85  std::string startupStepperName =
86  stepperPL->get<std::string>("Start Up Stepper Name","None");
87  if (is_null(startupStepperPL)) {
88  // Create startUpStepper, otherwise keep current startUpStepper.
89  if (startUpStepper_ == Teuchos::null) {
90  if (startupStepperName != "None") {
91  // Construct from ParameterList
92  startupStepperPL =
93  Teuchos::sublist(this->stepperPL_, startupStepperName, true);
94  RCP<StepperFactory<Scalar> > sf =
95  Teuchos::rcp(new StepperFactory<Scalar>());
96  startUpStepper_ =
97  sf->createStepper(startupStepperPL,this->wrapperModel_->getAppModel());
98  } else {
99  // Construct default start-up Stepper
100  RCP<StepperFactory<Scalar> > sf =
101  Teuchos::rcp(new StepperFactory<Scalar>());
102  startUpStepper_ =
103  sf->createStepper("IRK 1 Stage Theta Method",
104  this->wrapperModel_->getAppModel());
105 
106  startupStepperName = startUpStepper_->description();
107  startupStepperPL = startUpStepper_->getNonconstParameterList();
108  this->stepperPL_->set("Start Up Stepper Name", startupStepperName);
109  this->stepperPL_->set(startupStepperName, *startupStepperPL); // Add sublist
110  }
111  }
112  } else {
113  TEUCHOS_TEST_FOR_EXCEPTION( startupStepperName == startupStepperPL->name(),
114  std::logic_error,
115  "Error - Trying to add a startup stepper that is already in "
116  << "ParameterList!\n"
117  << " Stepper Type = "<< stepperPL->get<std::string>("Stepper Type")
118  << "\n" << " Start Up Stepper Name = "<<startupStepperName<<"\n");
119  startupStepperName = startupStepperPL->name();
120  this->stepperPL_->set("Start Up Stepper Name", startupStepperName);
121  this->stepperPL_->set(startupStepperName, *startupStepperPL); // Add sublist
122  RCP<StepperFactory<Scalar> > sf =
123  Teuchos::rcp(new StepperFactory<Scalar>());
124  startUpStepper_ =
125  sf->createStepper(startupStepperPL, this->wrapperModel_->getAppModel());
126  }
127 }
128 
129 
130 template<class Scalar>
132  Teuchos::RCP<StepperObserver<Scalar> > obs)
133 {
134  if (obs == Teuchos::null) {
135  // Create default observer, otherwise keep current observer.
136  if (this->stepperObserver_ == Teuchos::null) {
137  stepperBDF2Observer_ =
138  Teuchos::rcp(new StepperBDF2Observer<Scalar>());
139  this->stepperObserver_ =
140  Teuchos::rcp_dynamic_cast<StepperObserver<Scalar> >
141  (stepperBDF2Observer_);
142  }
143  } else {
144  this->stepperObserver_ = obs;
145  stepperBDF2Observer_ =
146  Teuchos::rcp_dynamic_cast<StepperBDF2Observer<Scalar> >(this->stepperObserver_);
147  }
148 }
149 
150 
151 template<class Scalar>
153 {
154  TEUCHOS_TEST_FOR_EXCEPTION( this->wrapperModel_ == Teuchos::null,
155  std::logic_error,
156  "Error - Need to set the model, setModel(), before calling "
157  "StepperBDF2::initialize()\n");
158 
159  this->setParameterList(this->stepperPL_);
160  this->setSolver();
161  this->setStartUpStepper();
162  this->setObserver();
163  order_ = Scalar(2.0);
164 }
165 
166 
167 template<class Scalar>
169  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
170 {
171  using Teuchos::RCP;
172 
173  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
174 
175  // Check if we need Stepper storage for xDot
176  if (initialState->getXDot() == Teuchos::null)
177  this->setStepperXDot(initialState->getX()->clone_v());
178 
180 
181  if (this->getUseFSAL()) {
182  RCP<Teuchos::FancyOStream> out = this->getOStream();
183  Teuchos::OSTab ostab(out,1,"StepperBDF2::setInitialConditions()");
184  *out << "\nWarning -- The First-Step-As-Last (FSAL) principle is not "
185  << "needed with Backward Euler. The default is to set useFSAL=false, "
186  << "however useFSAL=true will also work but have no affect "
187  << "(i.e., no-op).\n" << std::endl;
188  }
189 }
190 
191 
192 template<class Scalar>
194  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
195 {
196  using Teuchos::RCP;
197 
198  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperBDF2::takeStep()");
199  {
200  int numStates = solutionHistory->getNumStates();
201 
202  RCP<Thyra::VectorBase<Scalar> > xOld;
203  RCP<Thyra::VectorBase<Scalar> > xOldOld;
204 
205  // If there are less than 3 states (e.g., first time step), call
206  // startup stepper and return.
207  if (numStates < 3) {
208  computeStartUp(solutionHistory);
209  return;
210  }
211  TEUCHOS_TEST_FOR_EXCEPTION( (numStates < 3), std::logic_error,
212  "Error in Tempus::StepperBDF2::takeStep(): numStates after \n"
213  << "startup stepper must be at least 3, whereas numStates = "
214  << numStates <<"!\n" << "If running with Storage Type = Static, "
215  << "make sure Storage Limit > 2.\n");
216 
217  //IKT, FIXME: add error checking regarding states being consecutive and
218  //whether interpolated states are OK to use.
219 
220  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
221 
222  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
223  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
224 
225  RCP<Thyra::VectorBase<Scalar> > x = workingState->getX();
226  RCP<Thyra::VectorBase<Scalar> > xDot = this->getStepperXDot(workingState);
227 
228  //get time, dt and dtOld
229  const Scalar time = workingState->getTime();
230  const Scalar dt = workingState->getTimeStep();
231  const Scalar dtOld = currentState->getTimeStep();
232 
233  xOld = solutionHistory->getStateTimeIndexNM1()->getX();
234  xOldOld = solutionHistory->getStateTimeIndexNM2()->getX();
235  order_ = Scalar(2.0);
236 
237  // Setup TimeDerivative
238  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
239  Teuchos::rcp(new StepperBDF2TimeDerivative<Scalar>(dt, dtOld, xOld, xOldOld));
240 
241  const Scalar alpha = getAlpha(dt, dtOld);
242  const Scalar beta = getBeta (dt);
243 
244  Teuchos::RCP<ImplicitODEParameters<Scalar> > p =
245  Teuchos::rcp(new ImplicitODEParameters<Scalar>(timeDer,dt,alpha,beta,
246  SOLVE_FOR_X));
247 
248  const Thyra::SolveStatus<Scalar> sStatus =
249  this->solveImplicitODE(x, xDot, time, p);
250 
251  if (!Teuchos::is_null(stepperBDF2Observer_))
252  stepperBDF2Observer_->observeAfterSolve(solutionHistory, *this);
253 
254  if (workingState->getXDot() != Teuchos::null)
255  timeDer->compute(x, xDot);
256 
257  workingState->setSolutionStatus(sStatus); // Converged --> pass.
258  workingState->setOrder(getOrder());
259  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
260  }
261  return;
262 }
263 
264 template<class Scalar>
266  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
267 {
268  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
269  Teuchos::OSTab ostab(out,1,"StepperBDF2::computeStartUp()");
270  *out << "Warning -- Taking a startup step for BDF2 using '"
271  << startUpStepper_->description()<<"'!" << std::endl;
272 
273  //Take one step using startUpStepper_
274  startUpStepper_->takeStep(solutionHistory);
275 
276  order_ = startUpStepper_->getOrder();
277 }
278 
279 /** \brief Provide a StepperState to the SolutionState.
280  * This Stepper does not have any special state data,
281  * so just provide the base class StepperState with the
282  * Stepper description. This can be checked to ensure
283  * that the input StepperState can be used by this Stepper.
284  */
285 template<class Scalar>
286 Teuchos::RCP<Tempus::StepperState<Scalar> >
289 {
290  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
291  rcp(new StepperState<Scalar>(description()));
292  return stepperState;
293 }
294 
295 
296 template<class Scalar>
298 {
299  std::string name = "BDF2";
300  return(name);
301 }
302 
303 
304 template<class Scalar>
306  Teuchos::FancyOStream &out,
307  const Teuchos::EVerbosityLevel /* verbLevel */) const
308 {
309  out << description() << "::describe:" << std::endl
310  << "wrapperModel_ = " << this->wrapperModel_->description() << std::endl;
311 }
312 
313 
314 template <class Scalar>
316  Teuchos::RCP<Teuchos::ParameterList> const& pList)
317 {
318  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
319  if (pList == Teuchos::null) {
320  // Create default parameters if null, otherwise keep current parameters.
321  if (stepperPL == Teuchos::null) stepperPL = this->getDefaultParameters();
322  } else {
323  stepperPL = pList;
324  }
325  if (!(stepperPL->isParameter("Solver Name"))) {
326  stepperPL->set<std::string>("Solver Name", "Default Solver");
327  Teuchos::RCP<Teuchos::ParameterList> solverPL =
328  this->defaultSolverParameters();
329  stepperPL->set("Default Solver", *solverPL);
330  }
331  // Can not validate because of optional Parameters (e.g., Solver Name).
332  //stepperPL->validateParametersAndSetDefaults(*this->getValidParameters());
333 
334  std::string stepperType = stepperPL->get<std::string>("Stepper Type");
335  TEUCHOS_TEST_FOR_EXCEPTION( stepperType != "BDF2", std::logic_error,
336  "Error - Stepper Type is not 'BDF2'!\n"
337  << " Stepper Type = "<<stepperPL->get<std::string>("Stepper Type")<<"\n");
338 
339  this->stepperPL_ = stepperPL;
340 }
341 
342 
343 template<class Scalar>
344 Teuchos::RCP<const Teuchos::ParameterList>
346 {
347  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
348  pl->setName("Default Stepper - " + this->description());
349  pl->set<std::string>("Stepper Type", this->description());
350  this->getValidParametersBasic(pl);
351  pl->set<bool>("Initial Condition Consistency Check", false);
352  pl->set<bool>("Zero Initial Guess", false);
353  pl->set<std::string>("Solver Name", "",
354  "Name of ParameterList containing the solver specifications.");
355 
356  return pl;
357 }
358 
359 
360 template<class Scalar>
361 Teuchos::RCP<Teuchos::ParameterList>
363 {
364  using Teuchos::RCP;
365  using Teuchos::ParameterList;
366  using Teuchos::rcp_const_cast;
367 
368  RCP<ParameterList> pl =
369  rcp_const_cast<ParameterList>(this->getValidParameters());
370 
371  pl->set<std::string>("Solver Name", "Default Solver");
372  RCP<ParameterList> solverPL = this->defaultSolverParameters();
373  pl->set("Default Solver", *solverPL);
374 
375  return pl;
376 }
377 
378 
379 template <class Scalar>
380 Teuchos::RCP<Teuchos::ParameterList>
382 {
383  return(this->stepperPL_);
384 }
385 
386 
387 template <class Scalar>
388 Teuchos::RCP<Teuchos::ParameterList>
390 {
391  Teuchos::RCP<Teuchos::ParameterList> temp_plist = this->stepperPL_;
392  this->stepperPL_ = Teuchos::null;
393  return(temp_plist);
394 }
395 
396 
397 } // namespace Tempus
398 #endif // Tempus_StepperBDF2_impl_hpp
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Time-derivative interface for BDF2.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)
virtual void computeStartUp(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Compute the first time step given the supplied startup stepper.
StepperState is a simple class to hold state information about the stepper.
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 > getDefaultParameters() const
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
virtual std::string description() const
void setStartUpStepper(std::string startupStepperName)
Set the stepper to use in first step.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
Solve for x and determine xDot from x.
virtual void initialize()
Initialize during construction and after changing input parameters.
StepperBDF2()
Default constructor.
StepperBDF2Observer class for StepperBDF2.