Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperImplicit_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_StepperImplicit_impl_hpp
10 #define Tempus_StepperImplicit_impl_hpp
11 
12 // Tempus
13 //#include "Tempus_Stepper.hpp"
14 //#include "Tempus_TimeDerivative.hpp"
15 
16 // Thrya
17 //#include "Thyra_VectorBase.hpp"
18 //#include "Thyra_VectorStdOps.hpp"
19 #include "NOX_Thyra.H"
20 
21 
22 namespace Tempus {
23 
24 
25 template<class Scalar>
27  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
28 {
29  this->validImplicitODE_DAE(appModel);
30  wrapperModel_ =
31  Teuchos::rcp(new WrapperModelEvaluatorBasic<Scalar>(appModel));
32 }
33 
34 
35 template<class Scalar>
37  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& appModel)
38 {
39  this->setModel(appModel);
40 }
41 
42 
43 template<class Scalar>
45  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
46 {
47  using Teuchos::RCP;
48 
49  int numStates = solutionHistory->getNumStates();
50 
51  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
52  "Error - setInitialConditions() needs at least one SolutionState\n"
53  " to set the initial condition. Number of States = " << numStates);
54 
55  if (numStates > 1) {
56  RCP<Teuchos::FancyOStream> out = this->getOStream();
57  Teuchos::OSTab ostab(out,1,"StepperImplicit::setInitialConditions()");
58  *out << "Warning -- SolutionHistory has more than one state!\n"
59  << "Setting the initial conditions on the currentState.\n"<<std::endl;
60  }
61 
62  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
63  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
64 
65  auto inArgs = this->wrapperModel_->getNominalValues();
66  if (this->getOrderODE() == SECOND_ORDER_ODE) {
67  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
68 
69  // If initialState has x and xDot set, treat them as the initial conditions.
70  // Otherwise use the x and xDot from getNominalValues() as the ICs.
71  TEUCHOS_TEST_FOR_EXCEPTION(
72  !((x != Teuchos::null && xDot != Teuchos::null) ||
73  (inArgs.get_x() != Teuchos::null &&
74  inArgs.get_x_dot() != Teuchos::null)), std::logic_error,
75  "Error - We need to set the initial conditions for x and xDot from\n"
76  " either initialState or appModel_->getNominalValues::InArgs\n"
77  " (but not from a mixture of the two).\n");
78  }
79 
80  if (this->getOrderODE() == FIRST_ORDER_ODE) {
81  // Use x from inArgs as ICs.
82  if (x == Teuchos::null) {
83  TEUCHOS_TEST_FOR_EXCEPTION( (x == Teuchos::null) &&
84  (inArgs.get_x() == Teuchos::null), std::logic_error,
85  "Error - setInitialConditions needs the ICs from the SolutionHistory\n"
86  " or getNominalValues()!\n");
87 
88  x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
89  initialState->setX(x);
90  }
91  }
92  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
93  // Use the x and xDot from getNominalValues() as the ICs.
94  using Teuchos::rcp_const_cast;
95  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
96  if ( x == Teuchos::null || xDot == Teuchos::null ) {
97  TEUCHOS_TEST_FOR_EXCEPTION( (inArgs.get_x() == Teuchos::null) ||
98  (inArgs.get_x_dot() == Teuchos::null), std::logic_error,
99  "Error - setInitialConditions() needs the ICs from the initialState\n"
100  " or getNominalValues()!\n");
101  x = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
102  initialState->setX(x);
103  xDot = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x_dot());
104  initialState->setXDot(xDot);
105  }
106  }
107 
108 
109  // Perform IC Consistency
110  std::string icConsistency = this->getICConsistency();
111  if (icConsistency == "None") {
112  if (this->getOrderODE() == FIRST_ORDER_ODE) {
113  if (initialState->getXDot() == Teuchos::null) {
114  RCP<Teuchos::FancyOStream> out = this->getOStream();
115  Teuchos::OSTab ostab(out,1,
116  "StepperImplicit::setInitialConditions()");
117  *out << "Warning -- Requested IC consistency of 'None' but\n"
118  << " initialState does not have an xDot.\n"
119  << " Setting a 'Zero' xDot!\n" << std::endl;
120 
121  Thyra::assign(this->getStepperXDot(initialState).ptr(), Scalar(0.0));
122  }
123  }
124  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
125  if (initialState->getXDotDot() == Teuchos::null) {
126  RCP<Teuchos::FancyOStream> out = this->getOStream();
127  Teuchos::OSTab ostab(out,1,
128  "StepperImplicit::setInitialConditions()");
129  *out << "Warning -- Requested IC consistency of 'None' but\n"
130  << " initialState does not have an xDotDot.\n"
131  << " Setting a 'Zero' xDotDot!\n" << std::endl;
132 
133  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
134  }
135  }
136  }
137  else if (icConsistency == "Zero") {
138  if (this->getOrderODE() == FIRST_ORDER_ODE)
139  Thyra::assign(this->getStepperXDot(initialState).ptr(), Scalar(0.0));
140  else if (this->getOrderODE() == SECOND_ORDER_ODE)
141  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
142  }
143  else if (icConsistency == "App") {
144  if (this->getOrderODE() == FIRST_ORDER_ODE) {
145  auto xDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
146  inArgs.get_x_dot());
147  TEUCHOS_TEST_FOR_EXCEPTION(xDot == Teuchos::null, std::logic_error,
148  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
149  " but 'App' returned a null pointer for xDot!\n");
150  Thyra::assign(this->getStepperXDot(initialState).ptr(), *xDot);
151  }
152  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
153  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
154  inArgs.get_x_dot_dot());
155  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
156  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
157  " but 'App' returned a null pointer for xDotDot!\n");
158  Thyra::assign(getStepperXDotDot(initialState).ptr(), *xDotDot);
159  }
160  }
161  else if (icConsistency == "Consistent") {
162  if (this->getOrderODE() == FIRST_ORDER_ODE) {
163  // Solve f(x, xDot,t) = 0.
164  const Scalar time = initialState->getTime();
165  const Scalar dt = initialState->getTimeStep();
166  RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
167  const Scalar alpha = Scalar(1.0); // d(xDot)/d(xDot)
168  const Scalar beta = Scalar(0.0); // d(x )/d(xDot)
169  RCP<ImplicitODEParameters<Scalar> > p =
170  Teuchos::rcp(new ImplicitODEParameters<Scalar>(timeDer,dt,alpha,beta,
172 
173  auto xDot = this->getStepperXDot(initialState);
174  const Thyra::SolveStatus<Scalar> sStatus =
175  this->solveImplicitODE(x, xDot, time, p);
176 
177  TEUCHOS_TEST_FOR_EXCEPTION(
178  sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED, std::logic_error,
179  "Error - Solver failed while determining the initial conditions.\n"
180  " Solver status is "<<Thyra::toString(sStatus.solveStatus)<<".\n");
181  }
182  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
183 
184  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
185  "Error - setInitialConditions(): 'Consistent' for second-order ODE\n"
186  " has not been implemented.\n");
187  }
188  }
189  else {
190  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
191  "Error - setInitialConditions() invalid IC consistency, "
192  << icConsistency << ".\n");
193  }
194 
195  // At this point, x and xDot are sync'ed or consistent
196  // at the same time level for the initialState.
197  initialState->setIsSynced(true);
198 
199  // Test for consistency.
200  if (this->getICConsistencyCheck()) {
201  auto f = initialState->getX()->clone_v();
202  auto xDot = this->getStepperXDot(initialState);
203 
204  const Scalar time = initialState->getTime();
205  const Scalar dt = initialState->getTimeStep();
206  RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
207  const Scalar alpha = Scalar(0.0);
208  const Scalar beta = Scalar(0.0);
209  RCP<ImplicitODEParameters<Scalar> > p =
210  Teuchos::rcp(new ImplicitODEParameters<Scalar>(timeDer,dt,alpha,beta,
212 
213  this->evaluateImplicitODE(f, x, xDot, time, p);
214 
215  Scalar normX = Thyra::norm(*x);
216  Scalar reldiff = Scalar(0.0);
217  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
218  else reldiff = Thyra::norm(*f)/normX;
219 
220  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
221  if (reldiff > eps) {
222  RCP<Teuchos::FancyOStream> out = this->getOStream();
223  Teuchos::OSTab ostab(out,1,"StepperImplicit::setInitialConditions()");
224  *out << "Warning -- Failed consistency check but continuing!\n"
225  << " ||f(x,xDot,t)||/||x|| > eps" << std::endl
226  << " ||f(x,xDot,t)|| = " << Thyra::norm(*f) << std::endl
227  << " ||x|| = " << Thyra::norm(*x) << std::endl
228  << " ||f(x,xDot,t)||/||x|| = " << reldiff << std::endl
229  << " eps = " << eps << std::endl;
230  }
231  }
232 }
233 
234 
235 /** \brief Set the solver to a pre-defined solver in the ParameterList.
236  *
237  * The solver is set to solverName sublist in the Stepper's ParameterList.
238  * The solverName sublist should already be defined in the Stepper's
239  * ParameterList. Otherwise it will fail.
240  */
241 template<class Scalar>
242 void StepperImplicit<Scalar>::setSolver(std::string solverName)
243 {
244  Teuchos::RCP<Teuchos::ParameterList> solverPL =
245  Teuchos::sublist(stepperPL_, solverName, true);
246  this->setSolver(solverPL);
247 }
248 
249 
250 /** \brief Set the solver to the supplied Parameter sublist.
251  *
252  * This adds a new solver Parameter sublist to the Stepper's ParameterList.
253  * If the solver sublist is null, the solver is set to the solver name
254  * in the Stepper's ParameterList.
255  */
256 template<class Scalar>
258  Teuchos::RCP<Teuchos::ParameterList> solverPL)
259 {
260  using Teuchos::RCP;
261  using Teuchos::ParameterList;
262 
263  std::string solverName = stepperPL_->get<std::string>("Solver Name");
264  if (is_null(solverPL)) {
265  if ( stepperPL_->isSublist(solverName) )
266  solverPL = Teuchos::sublist(stepperPL_, solverName, true);
267  else
268  solverPL = this->defaultSolverParameters();
269  }
270 
271  solverName = solverPL->name();
272  stepperPL_->set("Solver Name", solverName);
273  stepperPL_->set(solverName, *solverPL); // Add sublist
274  RCP<ParameterList> noxPL = Teuchos::sublist(solverPL, "NOX", true);
275 
276  solver_ = rcp(new Thyra::NOXNonlinearSolver());
277  solver_->setParameterList(noxPL);
278 
279  TEUCHOS_TEST_FOR_EXCEPTION(wrapperModel_ == Teuchos::null, std::logic_error,
280  "Error - StepperImplicit<Scalar>::setSolver() wrapperModel_ is unset!\n"
281  << " Should call setModel(...) first.\n");
282  solver_->setModel(wrapperModel_);
283 }
284 
285 
286 /** \brief Set the solver.
287  *
288  * This sets the solver to supplied solver and adds solver's ParameterList
289  * to the Stepper ParameterList.
290  */
291 template<class Scalar>
293  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
294 {
295  Teuchos::RCP<Teuchos::ParameterList> solverPL =
296  solver->getNonconstParameterList();
297  this->setSolver(solverPL);
298 }
299 
300 template<class Scalar>
301 Teuchos::RCP<Thyra::VectorBase<Scalar> >
304 {
305  if (state->getXDot() != Teuchos::null) stepperXDot_ = state->getXDot();
306  // Else use temporary storage stepperXDot_ which should have been set in
307  // setInitialConditions().
308 
309  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDot_ == Teuchos::null, std::logic_error,
310  "Error - stepperXDot_ has not been set in setInitialConditions() or\n"
311  " can not be set from the state!\n");
312 
313  return stepperXDot_;
314 }
315 
316 
317 template<class Scalar>
318 Teuchos::RCP<Thyra::VectorBase<Scalar> >
321 {
322  if (state->getXDotDot() != Teuchos::null) stepperXDotDot_=state->getXDotDot();
323  // Else use temporary storage stepperXDotDot_ which should have been set in
324  // setInitialConditions().
325 
326  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDotDot_ == Teuchos::null,std::logic_error,
327  "Error - stepperXDotDot_ has not been set in setInitialConditions() or\n"
328  " can not be set from the state!\n");
329 
330  return stepperXDotDot_;
331 }
332 
333 
334 template<class Scalar>
335 const Thyra::SolveStatus<Scalar>
337  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x)
338 {
339  if (getZeroInitialGuess())
340  Thyra::assign(x.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
341 
342  const Thyra::SolveStatus<Scalar> sStatus = (*solver_).solve(&*x);
343 
344  return sStatus;
345 }
346 
347 
348 template<class Scalar>
349 const Thyra::SolveStatus<Scalar>
351  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
352  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
353  const Scalar time,
354  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
355 {
356  typedef Thyra::ModelEvaluatorBase MEB;
357  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
358  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
359  inArgs.set_x(x);
360  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
361  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
362  if (inArgs.supports(MEB::IN_ARG_step_size))
363  inArgs.set_step_size(p->timeStepSize_);
364  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (p->alpha_);
365  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (p->beta_);
366  if (inArgs.supports(MEB::IN_ARG_stage_number))
367  inArgs.set_stage_number(p->stageNumber_);
368 
369  wrapperModel_->setForSolve(p->timeDer_, inArgs, outArgs, p->evaluationType_);
370 
371  Thyra::SolveStatus<Scalar> sStatus;
372  typedef Teuchos::ScalarTraits<Scalar> ST;
373  switch (p->evaluationType_)
374  {
375  case SOLVE_FOR_X: {
376  if (getZeroInitialGuess()) Thyra::assign(x.ptr(), ST::zero());
377  sStatus = (*solver_).solve(&*x);
378  break;
379  }
380  case SOLVE_FOR_XDOT_CONST_X: {
381  //if (getZeroInitialGuess()) Thyra::assign(xDot.ptr(), ST::zero());
382  sStatus = (*solver_).solve(&*xDot);
383  break;
384  }
385  default: {
386  TEUCHOS_TEST_FOR_EXCEPT("Invalid EVALUATION_TYPE!");
387  }
388  }
389 
390  return sStatus;
391 }
392 
393 
394 template<class Scalar>
395 void
397  Teuchos::RCP<Thyra::VectorBase<Scalar> > & f,
398  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
399  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
400  const Scalar time,
401  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
402 {
403  typedef Thyra::ModelEvaluatorBase MEB;
404  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
405  inArgs.set_x(x);
406  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
407  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
408  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(p->timeStepSize_);
409  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (Scalar(0.0));
410  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (Scalar(0.0));
411 
412  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
413  outArgs.set_f(f);
414 
415  wrapperModel_->setForSolve(Teuchos::null,inArgs,outArgs,p->evaluationType_);
416 
417  wrapperModel_->evalModel(inArgs, outArgs);
418 }
419 
420 
421 } // namespace Tempus
422 #endif // Tempus_StepperImplicit_impl_hpp
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
const Thyra::SolveStatus< Scalar > solveImplicitODE(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x)
Solve problem using x in-place. (Needs to be deprecated!)
Evaluate residual for the implicit ODE.
const std::string toString(const Status status)
Convert Status to string.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
void evaluateImplicitODE(Teuchos::RCP< Thyra::VectorBase< Scalar > > &f, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xDot, const Scalar time, const Teuchos::RCP< ImplicitODEParameters< Scalar > > &p)
Evaluate implicit ODE, f(x, xDot, t, p), residual.
Stepper integrates second-order ODEs.
virtual void setNonConstModel(const Teuchos::RCP< Thyra::ModelEvaluator< Scalar > > &appModel)
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDot(Teuchos::RCP< SolutionState< Scalar > > state)
Get xDot from SolutionState or Stepper storage.
virtual void setSolver(std::string solverName)
Set solver via ParameterList solver name.
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...
Solve for xDot keeping x constant (for ICs).
Stepper integrates first-order ODEs.
A ModelEvaluator for residual evaluations given a state. This ModelEvaluator takes a state...
Solve for x and determine xDot from x.
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDotDot(Teuchos::RCP< SolutionState< Scalar > > state)
Get xDotDot from SolutionState or Stepper storage.