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  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  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
170  timeDer, dt, alpha, beta, SOLVE_FOR_XDOT_CONST_X));
171 
172  auto xDot = this->getStepperXDot(initialState);
173  const Thyra::SolveStatus<Scalar> sStatus =
174  this->solveImplicitODE(x, xDot, time, p);
175 
176  TEUCHOS_TEST_FOR_EXCEPTION(
177  sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED, std::logic_error,
178  "Error - Solver failed while determining the initial conditions.\n"
179  " Solver status is "<<Thyra::toString(sStatus.solveStatus)<<".\n");
180  }
181  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
182 
183  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
184  "Error - setInitialConditions(): 'Consistent' for second-order ODE\n"
185  " has not been implemented.\n");
186  }
187  }
188  else {
189  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
190  "Error - setInitialConditions() invalid IC consistency, "
191  << icConsistency << ".\n");
192  }
193 
194  // At this point, x and xDot are sync'ed or consistent
195  // at the same time level for the initialState.
196  initialState->setIsSynced(true);
197 
198  // Test for consistency.
199  if (this->getICConsistencyCheck()) {
200  auto f = initialState->getX()->clone_v();
201  auto xDot = this->getStepperXDot(initialState);
202 
203  const Scalar time = initialState->getTime();
204  const Scalar dt = initialState->getTimeStep();
205  RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
206  const Scalar alpha = Scalar(0.0);
207  const Scalar beta = Scalar(0.0);
208  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
209  timeDer, dt, alpha, beta, EVALUATE_RESIDUAL));
210 
211  this->evaluateImplicitODE(f, x, xDot, time, p);
212 
213  Scalar normX = Thyra::norm(*x);
214  Scalar reldiff = Scalar(0.0);
215  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
216  else reldiff = Thyra::norm(*f)/normX;
217 
218  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
219  if (reldiff > eps) {
220  RCP<Teuchos::FancyOStream> out = this->getOStream();
221  Teuchos::OSTab ostab(out,1,"StepperImplicit::setInitialConditions()");
222  *out << "Warning -- Failed consistency check but continuing!\n"
223  << " ||f(x,xDot,t)||/||x|| > eps" << std::endl
224  << " ||f(x,xDot,t)|| = " << Thyra::norm(*f) << std::endl
225  << " ||x|| = " << Thyra::norm(*x) << std::endl
226  << " ||f(x,xDot,t)||/||x|| = " << reldiff << std::endl
227  << " eps = " << eps << std::endl;
228  }
229  }
230 }
231 
232 
233 template<class Scalar>
235  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
236 {
237  if (solver == Teuchos::null) {
238  solver = rcp(new Thyra::NOXNonlinearSolver());
239  solver->setParameterList(defaultSolverParameters());
240  }
241 
242  solver_ = solver;
243 
244  TEUCHOS_TEST_FOR_EXCEPTION(wrapperModel_ == Teuchos::null, std::logic_error,
245  "Error - ModelEvaluator is unset! Should call setModel() first.\n");
246 
247  solver_->setModel(wrapperModel_);
248 
249 }
250 
251 template<class Scalar>
252 Teuchos::RCP<Thyra::VectorBase<Scalar> >
255 {
256  if (state->getXDot() != Teuchos::null) stepperXDot_ = state->getXDot();
257  // Else use temporary storage stepperXDot_ which should have been set in
258  // setInitialConditions().
259 
260  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDot_ == Teuchos::null, std::logic_error,
261  "Error - stepperXDot_ has not been set in setInitialConditions() or\n"
262  " can not be set from the state!\n");
263 
264  return stepperXDot_;
265 }
266 
267 
268 template<class Scalar>
269 Teuchos::RCP<Thyra::VectorBase<Scalar> >
272 {
273  if (state->getXDotDot() != Teuchos::null) stepperXDotDot_=state->getXDotDot();
274  // Else use temporary storage stepperXDotDot_ which should have been set in
275  // setInitialConditions().
276 
277  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDotDot_ == Teuchos::null,std::logic_error,
278  "Error - stepperXDotDot_ has not been set in setInitialConditions() or\n"
279  " can not be set from the state!\n");
280 
281  return stepperXDotDot_;
282 }
283 
284 
285 template<class Scalar>
286 const Thyra::SolveStatus<Scalar>
288  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x)
289 {
290  if (getZeroInitialGuess())
291  Thyra::assign(x.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
292 
293  const Thyra::SolveStatus<Scalar> sStatus = (*solver_).solve(&*x);
294 
295  return sStatus;
296 }
297 
298 
299 template<class Scalar>
300 const Thyra::SolveStatus<Scalar>
302  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
303  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
304  const Scalar time,
305  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
306 {
307  typedef Thyra::ModelEvaluatorBase MEB;
308  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
309  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
310  inArgs.set_x(x);
311  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
312  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
313  if (inArgs.supports(MEB::IN_ARG_step_size))
314  inArgs.set_step_size(p->timeStepSize_);
315  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (p->alpha_);
316  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (p->beta_);
317  if (inArgs.supports(MEB::IN_ARG_stage_number))
318  inArgs.set_stage_number(p->stageNumber_);
319 
320  wrapperModel_->setForSolve(p->timeDer_, inArgs, outArgs, p->evaluationType_);
321 
322  Thyra::SolveStatus<Scalar> sStatus;
323  typedef Teuchos::ScalarTraits<Scalar> ST;
324  switch (p->evaluationType_)
325  {
326  case SOLVE_FOR_X: {
327  if (getZeroInitialGuess()) Thyra::assign(x.ptr(), ST::zero());
328  sStatus = (*solver_).solve(&*x);
329  break;
330  }
331  case SOLVE_FOR_XDOT_CONST_X: {
332  //if (getZeroInitialGuess()) Thyra::assign(xDot.ptr(), ST::zero());
333  sStatus = (*solver_).solve(&*xDot);
334  break;
335  }
336  default: {
337  TEUCHOS_TEST_FOR_EXCEPT("Invalid EVALUATION_TYPE!");
338  }
339  }
340 
341  return sStatus;
342 }
343 
344 
345 template<class Scalar>
346 void
348  Teuchos::RCP<Thyra::VectorBase<Scalar> > & f,
349  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
350  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
351  const Scalar time,
352  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
353 {
354  typedef Thyra::ModelEvaluatorBase MEB;
355  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
356  inArgs.set_x(x);
357  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
358  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
359  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(p->timeStepSize_);
360  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (Scalar(0.0));
361  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (Scalar(0.0));
362 
363  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
364  outArgs.set_f(f);
365 
366  wrapperModel_->setForSolve(Teuchos::null,inArgs,outArgs,p->evaluationType_);
367 
368  wrapperModel_->evalModel(inArgs, outArgs);
369 }
370 
371 
372 } // namespace Tempus
373 #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)
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver=Teuchos::null)
Set solver.
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.
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 residual, f(x, xDot, t, p).
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.
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.
void validImplicitODE_DAE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate ME supports implicit ODE/DAE evaluation, f(xdot,x,t) [= 0].
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.