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 // Thrya
13 #include "NOX_Thyra.H"
14 
15 
16 namespace Tempus {
17 
18 
19 template<class Scalar>
21  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
22 {
23  validImplicitODE_DAE(appModel);
24  wrapperModel_ =
25  Teuchos::rcp(new WrapperModelEvaluatorBasic<Scalar>(appModel));
26 
27  TEUCHOS_TEST_FOR_EXCEPTION(solver_ == Teuchos::null, std::logic_error,
28  "Error - Solver is not set!\n");
29  solver_->setModel(wrapperModel_);
30 
31  this->isInitialized_ = false;
32 }
33 
34 
35 template<class Scalar>
37  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
38 {
39  using Teuchos::RCP;
40 
41  int numStates = solutionHistory->getNumStates();
42 
43  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
44  "Error - setInitialConditions() needs at least one SolutionState\n"
45  " to set the initial condition. Number of States = " << numStates);
46 
47  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
48  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
49 
50  auto inArgs = this->wrapperModel_->getNominalValues();
51  if (this->getOrderODE() == SECOND_ORDER_ODE) {
52  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
53 
54  // If initialState has x and xDot set, treat them as the initial conditions.
55  // Otherwise use the x and xDot from getNominalValues() as the ICs.
56  TEUCHOS_TEST_FOR_EXCEPTION(
57  !((x != Teuchos::null && xDot != Teuchos::null) ||
58  (inArgs.get_x() != Teuchos::null &&
59  inArgs.get_x_dot() != Teuchos::null)), std::logic_error,
60  "Error - We need to set the initial conditions for x and xDot from\n"
61  " either initialState or appModel_->getNominalValues::InArgs\n"
62  " (but not from a mixture of the two).\n");
63  }
64 
65  if (this->getOrderODE() == FIRST_ORDER_ODE) {
66  // Use x from inArgs as ICs.
67  if (x == Teuchos::null) {
68  TEUCHOS_TEST_FOR_EXCEPTION( (x == Teuchos::null) &&
69  (inArgs.get_x() == Teuchos::null), std::logic_error,
70  "Error - setInitialConditions needs the ICs from the SolutionHistory\n"
71  " or getNominalValues()!\n");
72 
73  x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
74  initialState->setX(x);
75  }
76  }
77  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
78  // Use the x and xDot from getNominalValues() as the ICs.
79  using Teuchos::rcp_const_cast;
80  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
81  if ( x == Teuchos::null || xDot == Teuchos::null ) {
82  TEUCHOS_TEST_FOR_EXCEPTION( (inArgs.get_x() == Teuchos::null) ||
83  (inArgs.get_x_dot() == Teuchos::null), std::logic_error,
84  "Error - setInitialConditions() needs the ICs from the initialState\n"
85  " or getNominalValues()!\n");
86  x = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
87  initialState->setX(x);
88  xDot = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x_dot());
89  initialState->setXDot(xDot);
90  }
91  }
92 
93 
94  // Perform IC Consistency
95  std::string icConsistency = this->getICConsistency();
96  if (icConsistency == "None") {
97  if (this->getOrderODE() == FIRST_ORDER_ODE) {
98  if (initialState->getXDot() == Teuchos::null)
99  Thyra::assign(this->getStepperXDot(initialState).ptr(), Scalar(0.0));
100  }
101  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
102  if (initialState->getXDotDot() == Teuchos::null)
103  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
104  }
105  }
106  else if (icConsistency == "Zero") {
107  if (this->getOrderODE() == FIRST_ORDER_ODE)
108  Thyra::assign(this->getStepperXDot(initialState).ptr(), Scalar(0.0));
109  else if (this->getOrderODE() == SECOND_ORDER_ODE)
110  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
111  }
112  else if (icConsistency == "App") {
113  if (this->getOrderODE() == FIRST_ORDER_ODE) {
114  auto xDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
115  inArgs.get_x_dot());
116  TEUCHOS_TEST_FOR_EXCEPTION(xDot == Teuchos::null, std::logic_error,
117  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
118  " but 'App' returned a null pointer for xDot!\n");
119  Thyra::assign(this->getStepperXDot(initialState).ptr(), *xDot);
120  }
121  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
122  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
123  inArgs.get_x_dot_dot());
124  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
125  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
126  " but 'App' returned a null pointer for xDotDot!\n");
127  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), *xDotDot);
128  }
129  }
130  else if (icConsistency == "Consistent") {
131  if (this->getOrderODE() == FIRST_ORDER_ODE) {
132  // Solve f(x, xDot,t) = 0.
133  const Scalar time = initialState->getTime();
134  const Scalar dt = initialState->getTimeStep();
135  RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
136  const Scalar alpha = Scalar(1.0); // d(xDot)/d(xDot)
137  const Scalar beta = Scalar(0.0); // d(x )/d(xDot)
138  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
139  timeDer, dt, alpha, beta, SOLVE_FOR_XDOT_CONST_X));
140 
141  auto xDot = this->getStepperXDot(initialState);
142  const Thyra::SolveStatus<Scalar> sStatus =
143  this->solveImplicitODE(x, xDot, time, p);
144 
145  TEUCHOS_TEST_FOR_EXCEPTION(
146  sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED, std::logic_error,
147  "Error - Solver failed while determining the initial conditions.\n"
148  " Solver status is "<<Thyra::toString(sStatus.solveStatus)<<".\n");
149  }
150  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
151 
152  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
153  "Error - setInitialConditions(): 'Consistent' for second-order ODE\n"
154  " has not been implemented.\n");
155  }
156  }
157  else {
158  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
159  "Error - setInitialConditions() invalid IC consistency, "
160  << icConsistency << ".\n");
161  }
162 
163  // At this point, x and xDot are sync'ed or consistent
164  // at the same time level for the initialState.
165  initialState->setIsSynced(true);
166 
167  // Test for consistency.
168  if (this->getICConsistencyCheck()) {
169  auto f = initialState->getX()->clone_v();
170  auto xDot = this->getStepperXDot(initialState);
171 
172  const Scalar time = initialState->getTime();
173  const Scalar dt = initialState->getTimeStep();
174  RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
175  const Scalar alpha = Scalar(0.0);
176  const Scalar beta = Scalar(0.0);
177  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
178  timeDer, dt, alpha, beta, EVALUATE_RESIDUAL));
179 
180  this->evaluateImplicitODE(f, x, xDot, time, p);
181 
182  Scalar normX = Thyra::norm(*x);
183  Scalar reldiff = Scalar(0.0);
184  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
185  else reldiff = Thyra::norm(*f)/normX;
186 
187  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
188  if (reldiff > eps) {
189  RCP<Teuchos::FancyOStream> out = this->getOStream();
190  Teuchos::OSTab ostab(out,1,"StepperImplicit::setInitialConditions()");
191  *out << "Info -- Failed consistency check but continuing!\n"
192  << " ||f(x,xDot,t)||/||x|| > eps" << std::endl
193  << " ||f(x,xDot,t)|| = " << Thyra::norm(*f) << std::endl
194  << " ||x|| = " << Thyra::norm(*x) << std::endl
195  << " ||f(x,xDot,t)||/||x|| = " << reldiff << std::endl
196  << " eps = " << eps << std::endl;
197  }
198  }
199 }
200 
201 
202 template<class Scalar>
204 {
205  solver_ = rcp(new Thyra::NOXNonlinearSolver());
206  auto solverPL = Tempus::defaultSolverParameters();
207  auto subPL = sublist(solverPL, "NOX");
208  solver_->setParameterList(subPL);
209 
210  if (wrapperModel_ != Teuchos::null) solver_->setModel(wrapperModel_);
211 
212  this->isInitialized_ = false;
213 }
214 
215 
216 template<class Scalar>
218  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
219 {
220  TEUCHOS_TEST_FOR_EXCEPTION(solver == Teuchos::null, std::logic_error,
221  "Error - Can not set the solver to Teuchos::null.\n");
222 
223  solver_ = solver;
224  if (wrapperModel_ != Teuchos::null) solver_->setModel(wrapperModel_);
225 
226  this->isInitialized_ = false;
227 }
228 
229 
230 template<class Scalar>
231 const Thyra::SolveStatus<Scalar>
233  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x)
234 {
235  if (getZeroInitialGuess())
236  Thyra::assign(x.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
237 
238  const Thyra::SolveStatus<Scalar> sStatus = (*solver_).solve(&*x);
239 
240  return sStatus;
241 }
242 
243 
244 template<class Scalar>
245 const Thyra::SolveStatus<Scalar>
247  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
248  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
249  const Scalar time,
250  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
251 {
252  typedef Thyra::ModelEvaluatorBase MEB;
253  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
254  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
255  inArgs.set_x(x);
256  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
257  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
258  if (inArgs.supports(MEB::IN_ARG_step_size))
259  inArgs.set_step_size(p->timeStepSize_);
260  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (p->alpha_);
261  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (p->beta_);
262  if (inArgs.supports(MEB::IN_ARG_stage_number))
263  inArgs.set_stage_number(p->stageNumber_);
264 
265  wrapperModel_->setForSolve(p->timeDer_, inArgs, outArgs, p->evaluationType_);
266 
267  Thyra::SolveStatus<Scalar> sStatus;
268  typedef Teuchos::ScalarTraits<Scalar> ST;
269  switch (p->evaluationType_)
270  {
271  case SOLVE_FOR_X: {
272  if (getZeroInitialGuess()) Thyra::assign(x.ptr(), ST::zero());
273  sStatus = (*solver_).solve(&*x);
274  break;
275  }
276  case SOLVE_FOR_XDOT_CONST_X: {
277  //if (getZeroInitialGuess()) Thyra::assign(xDot.ptr(), ST::zero());
278  sStatus = (*solver_).solve(&*xDot);
279  break;
280  }
281  default: {
282  TEUCHOS_TEST_FOR_EXCEPT("Invalid EVALUATION_TYPE!");
283  }
284  }
285 
286  return sStatus;
287 }
288 
289 
290 template<class Scalar>
291 void
293  Teuchos::RCP<Thyra::VectorBase<Scalar> > & f,
294  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & x,
295  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & xDot,
296  const Scalar time,
297  const Teuchos::RCP<ImplicitODEParameters<Scalar> > & p )
298 {
299  typedef Thyra::ModelEvaluatorBase MEB;
300  MEB::InArgs<Scalar> inArgs = wrapperModel_->getInArgs();
301  inArgs.set_x(x);
302  if (inArgs.supports(MEB::IN_ARG_x_dot )) inArgs.set_x_dot (xDot);
303  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (time);
304  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(p->timeStepSize_);
305  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (Scalar(0.0));
306  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (Scalar(0.0));
307 
308  MEB::OutArgs<Scalar> outArgs = wrapperModel_->getOutArgs();
309  outArgs.set_f(f);
310 
311  wrapperModel_->setForSolve(Teuchos::null,inArgs,outArgs,p->evaluationType_);
312 
313  wrapperModel_->evalModel(inArgs, outArgs);
314 }
315 
316 
317 template<class Scalar>
318 void StepperImplicit<Scalar>::describe(Teuchos::FancyOStream & out,
319  const Teuchos::EVerbosityLevel verbLevel) const
320 {
321  out << "--- StepperImplicit ---\n";
322  out << " wrapperModel_ = " << wrapperModel_ << std::endl;
323  out << " solver_ = " << solver_ << std::endl;
324  out << " initialGuess_ = " << initialGuess_ << std::endl;
325  out << " zeroInitialGuess_ = "
326  << Teuchos::toString(zeroInitialGuess_) << std::endl;
327 }
328 
329 
330 template<class Scalar>
331 bool StepperImplicit<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
332 {
333  bool isValidSetup = true;
334 
335  if (wrapperModel_->getAppModel() == Teuchos::null) {
336  isValidSetup = false;
337  out << "The application ModelEvaluator is not set!\n";
338  }
339 
340  if (wrapperModel_ == Teuchos::null) {
341  isValidSetup = false;
342  out << "The wrapper ModelEvaluator is not set!\n";
343  }
344 
345  if (solver_ == Teuchos::null) {
346  isValidSetup = false;
347  out << "The solver is not set!\n";
348  }
349 
350  if (solver_ != Teuchos::null) {
351  if (solver_->getModel() == Teuchos::null) {
352  isValidSetup = false;
353  out << "The solver's ModelEvaluator is not set!\n";
354  }
355  }
356 
357  return isValidSetup;
358 }
359 
360 
361 } // namespace Tempus
362 #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)
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).
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver)
Set solver.
Stepper integrates second-order ODEs.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
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.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
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.