Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_StepperExplicit_impl.hpp
Go to the documentation of this file.
1 //@HEADER
2 // *****************************************************************************
3 // Tempus: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef Tempus_StepperExplicit_impl_hpp
11 #define Tempus_StepperExplicit_impl_hpp
12 
13 #include "Thyra_VectorStdOps.hpp"
14 
15 namespace Tempus {
16 
17 template <class Scalar>
19  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
20 {
21  validExplicitODE(appModel);
22  appModel_ = appModel;
23 
24  inArgs_ = appModel_->getNominalValues();
25  outArgs_ = appModel_->createOutArgs();
26 }
27 
28 template <class Scalar>
30  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
31 {
32  using Teuchos::RCP;
33 
34  int numStates = solutionHistory->getNumStates();
35 
37  numStates < 1, std::logic_error,
38  "Error - setInitialConditions() needs at least one SolutionState\n"
39  " to set the initial condition. Number of States = "
40  << numStates);
41 
42  if (numStates > 1) {
43  RCP<Teuchos::FancyOStream> out = this->getOStream();
44  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setInitialConditions()");
45  *out << "Warning -- SolutionHistory has more than one state!\n"
46  << "Setting the initial conditions on the currentState.\n"
47  << std::endl;
48  }
49 
50  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
51  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
52  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
53  if (xDot == Teuchos::null) xDot = this->getStepperXDot();
54 
55  inArgs_ = appModel_->getNominalValues();
56  if (this->getOrderODE() == SECOND_ORDER_ODE) {
57  RCP<Thyra::VectorBase<Scalar> > initialXDot = initialState->getXDot();
58  // If initialState has x and xDot set, treat them as the initial conditions.
59  // Otherwise use the x and xDot from getNominalValues() as the ICs.
61  !((x != Teuchos::null && initialXDot != Teuchos::null) ||
62  (inArgs_.get_x() != Teuchos::null &&
63  inArgs_.get_x_dot() != Teuchos::null)),
64  std::logic_error,
65  "Error - We need to set the initial conditions for x and xDot from\n"
66  " either initialState or appModel_->getNominalValues::InArgs\n"
67  " (but not from a mixture of the two).\n");
68  }
69 
70  if (this->getOrderODE() == FIRST_ORDER_ODE) {
71  if (x == Teuchos::null) {
72  // Use x from inArgs as ICs.
74  (x == Teuchos::null) && (inArgs_.get_x() == Teuchos::null),
75  std::logic_error,
76  "Error - setInitialConditions needs the ICs from the "
77  "SolutionHistory\n"
78  " or getNominalValues()!\n");
79 
80  x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x());
81  initialState->setX(x);
82  }
83  }
84  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
85  using Teuchos::rcp_const_cast;
86  // Use the x and x_dot from getNominalValues() as the ICs.
87  if (initialState->getX() == Teuchos::null ||
88  initialState->getXDot() == Teuchos::null) {
90  (inArgs_.get_x() == Teuchos::null) ||
91  (inArgs_.get_x_dot() == Teuchos::null),
92  std::logic_error,
93  "Error - setInitialConditions() needs the ICs from the initialState\n"
94  " or getNominalValues()!\n");
95  x = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x());
96  initialState->setX(x);
97  RCP<Thyra::VectorBase<Scalar> > x_dot =
98  rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x_dot());
99  initialState->setXDot(x_dot);
100  }
101  }
102 
103  // Perform IC Consistency
104  std::string icConsistency = this->getICConsistency();
105  if (icConsistency == "None") {
106  if (this->getOrderODE() == FIRST_ORDER_ODE) {
107  if (initialState->getXDot() == Teuchos::null) {
108  RCP<Teuchos::FancyOStream> out = this->getOStream();
109  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setInitialConditions()");
110  *out << "Warning -- Requested IC consistency of 'None' but\n"
111  << " initialState does not have an xDot.\n"
112  << " Setting a 'Consistent' xDot!\n"
113  << std::endl;
114  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
115  evaluateExplicitODE(xDot, x, initialState->getTime(), p);
116  initialState->setIsSynced(true);
117  }
118  }
119  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
120  if (initialState->getXDotDot() == Teuchos::null) {
121  RCP<Teuchos::FancyOStream> out = this->getOStream();
122  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setInitialConditions()");
123  *out << "Warning -- Requested IC consistency of 'None' but\n"
124  << " initialState does not have an xDotDot.\n"
125  << " Setting a 'Consistent' xDotDot!\n"
126  << std::endl;
127  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
128  this->evaluateExplicitODE(this->getStepperXDotDot(initialState), x,
129  initialState->getXDot(),
130  initialState->getTime(), p);
131  initialState->setIsSynced(true);
132  }
133  }
134  }
135  else if (icConsistency == "Zero") {
136  if (this->getOrderODE() == FIRST_ORDER_ODE)
137  Thyra::assign(xDot.ptr(), Scalar(0.0));
138  else if (this->getOrderODE() == SECOND_ORDER_ODE)
139  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
140  }
141  else if (icConsistency == "App") {
142  if (this->getOrderODE() == FIRST_ORDER_ODE) {
143  auto x_dot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
144  inArgs_.get_x_dot());
146  xDot == Teuchos::null, std::logic_error,
147  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
148  " but 'App' returned a null pointer for xDot!\n");
149  Thyra::assign(xDot.ptr(), *x_dot);
150  }
151  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
152  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
153  inArgs_.get_x_dot_dot());
155  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(this->getStepperXDotDot(initialState).ptr(), *xDotDot);
159  }
160  }
161  else if (icConsistency == "Consistent") {
162  if (this->getOrderODE() == FIRST_ORDER_ODE) {
163  // Evaluate xDot = f(x,t).
164  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
165  evaluateExplicitODE(xDot, x, initialState->getTime(), p);
166  }
167  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
168  // Evaluate xDotDot = f(x,xDot,t).
169  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
170  this->evaluateExplicitODE(initialState->getXDotDot(), x,
171  initialState->getXDot(),
172  initialState->getTime(), p);
173  }
174  }
175  else {
177  true, std::logic_error,
178  "Error - setInitialConditions() invalid IC consistency, '"
179  << icConsistency << "'.\n");
180  }
181 
182  // At this point, x, and xDot (and xDotDot) sync'ed or consistent
183  // at the same time level for the initialState.
184  initialState->setIsSynced(true);
185 
186  // Test for consistency.
187  if (this->getICConsistencyCheck()) {
188  if (this->getOrderODE() == FIRST_ORDER_ODE) {
189  auto f = initialState->getX()->clone_v();
190  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
191  evaluateExplicitODE(f, x, initialState->getTime(), p);
192  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDot));
193  Scalar normX = Thyra::norm(*x);
194  Scalar reldiff = Scalar(0.0);
195  if (normX == Scalar(0.0))
196  reldiff = Thyra::norm(*f);
197  else
198  reldiff = Thyra::norm(*f) / normX;
199 
200  Scalar eps =
201  Scalar(100.0) * std::abs(Teuchos::ScalarTraits<Scalar>::eps());
202  RCP<Teuchos::FancyOStream> out = this->getOStream();
203  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setInitialConditions()");
204  if (reldiff < eps) {
205  *out << "\n---------------------------------------------------\n"
206  << "Info -- Stepper = " << this->getStepperType() << "\n"
207  << " Initial condition PASSED consistency check!\n"
208  << " (||xDot-f(x,t)||/||x|| = " << reldiff << ") < "
209  << "(eps = " << eps << ")" << std::endl
210  << "---------------------------------------------------\n"
211  << std::endl;
212  }
213  else {
214  *out << "\n---------------------------------------------------\n"
215  << "Info -- Stepper = " << this->getStepperType() << "\n"
216  << " Initial condition FAILED consistency check but continuing!\n"
217  << " (||xDot-f(x,t)||/||x|| = " << reldiff << ") > "
218  << "(eps = " << eps << ")" << std::endl
219  << " ||xDot-f(x,t)|| = " << Thyra::norm(*f) << std::endl
220  << " ||x|| = " << Thyra::norm(*x) << std::endl
221  << "---------------------------------------------------\n"
222  << std::endl;
223  }
224  }
225  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
226  auto xDotDot = initialState->getXDotDot();
227  auto f = initialState->getX()->clone_v();
228  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
229  this->evaluateExplicitODE(f, x, initialState->getXDot(),
230  initialState->getTime(), p);
231  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
232  Scalar normX = Thyra::norm(*x);
233  Scalar reldiff = Scalar(0.0);
234  if (normX == Scalar(0.0))
235  reldiff = Thyra::norm(*f);
236  else
237  reldiff = Thyra::norm(*f) / normX;
238 
239  Scalar eps =
240  Scalar(100.0) * std::abs(Teuchos::ScalarTraits<Scalar>::eps());
241  RCP<Teuchos::FancyOStream> out = this->getOStream();
242  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setInitialConditions()");
243  if (reldiff < eps) {
244  *out << "\n---------------------------------------------------\n"
245  << "Info -- Stepper = " << this->getStepperType() << "\n"
246  << " Initial condition PASSED consistency check!\n"
247  << " (||xDotDot-f(x,xDot,t)||/||x|| = " << reldiff << ") > "
248  << "(eps = " << eps << ")" << std::endl
249  << "---------------------------------------------------\n"
250  << std::endl;
251  }
252  else {
253  *out << "\n---------------------------------------------------\n"
254  << "Info -- Stepper = " << this->getStepperType() << "\n"
255  << "Initial condition FAILED consistency check but continuing!\n"
256  << " (||xDotDot-f(x,xDot,t)||/||x|| = " << reldiff << ") > "
257  << "(eps = " << eps << ")" << std::endl
258  << " ||xDotDot-f(x,xDot,t)|| = " << Thyra::norm(*f) << std::endl
259  << " ||x|| = " << Thyra::norm(*x) << std::endl
260  << "---------------------------------------------------\n"
261  << std::endl;
262  }
263  }
264  }
265 }
266 
267 template <class Scalar>
270 {
271  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
272  Teuchos::OSTab ostab(out, 1, "StepperExplicit::setSolver()");
273  *out << "Warning -- No solver to set for StepperExplicit "
274  << "(i.e., explicit method).\n"
275  << std::endl;
276  return;
277 }
278 template <class Scalar>
281  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x, const Scalar time,
283 {
284  typedef Thyra::ModelEvaluatorBase MEB;
285 
286  inArgs_.set_x(x);
287  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
288  if (inArgs_.supports(MEB::IN_ARG_step_size))
289  inArgs_.set_step_size(p->timeStepSize_);
290  if (inArgs_.supports(MEB::IN_ARG_stage_number))
291  inArgs_.set_stage_number(p->stageNumber_);
292 
293  // For model evaluators whose state function f(x, xDot, t) describes
294  // an implicit ODE, and which accept an optional xDot input argument,
295  // make sure the latter is set to null in order to request the evaluation
296  // of a state function corresponding to the explicit ODE formulation
297  // xDot = f(x, t).
298  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
299 
300  outArgs_.set_f(xDot);
301 
302  appModel_->evalModel(inArgs_, outArgs_);
303 }
304 
305 template <class Scalar>
309  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xDot, const Scalar time,
311 {
312  typedef Thyra::ModelEvaluatorBase MEB;
313 
314  inArgs_.set_x(x);
315  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(xDot);
316  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
317  if (inArgs_.supports(MEB::IN_ARG_step_size))
318  inArgs_.set_step_size(p->timeStepSize_);
319  if (inArgs_.supports(MEB::IN_ARG_stage_number))
320  inArgs_.set_stage_number(p->stageNumber_);
321 
322  // For model evaluators whose state function f(x, xDot, xDotDot, t) describes
323  // an implicit ODE, and which accept an optional xDotDot input argument,
324  // make sure the latter is set to null in order to request the evaluation
325  // of a state function corresponding to the explicit ODE formulation
326  // xDotDot = f(x, xDot, t).
327  if (inArgs_.supports(MEB::IN_ARG_x_dot_dot))
328  inArgs_.set_x_dot_dot(Teuchos::null);
329 
330  outArgs_.set_f(xDotDot);
331 
332  appModel_->evalModel(inArgs_, outArgs_);
333 }
334 
335 template <class Scalar>
337  Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
338 {
339  auto l_out = Teuchos::fancyOStream(out.getOStream());
340  Teuchos::OSTab ostab(*l_out, 2, this->description());
341  l_out->setOutputToRootOnly(0);
342 
343  *l_out << "--- StepperExplicit ---\n"
344  << " appModel_ = " << appModel_ << std::endl
345  << " inArgs_ = " << inArgs_ << std::endl
346  << " outArgs_ = " << outArgs_ << std::endl;
347 }
348 
349 template <class Scalar>
351 {
352  out.setOutputToRootOnly(0);
353  bool isValidSetup = true;
354 
355  if (appModel_ == Teuchos::null) {
356  isValidSetup = false;
357  out << "The application ModelEvaluator is not set!\n";
358  }
359 
360  return isValidSetup;
361 }
362 
363 template <class Scalar>
366 {
367  if (pl != Teuchos::null) {
368  pl->validateParametersAndSetDefaults(*this->getValidParameters(), 0);
369  this->setStepperValues(pl);
370  }
371 }
372 
373 } // namespace Tempus
374 #endif // Tempus_StepperExplicit_impl_hpp
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void validExplicitODE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate that the model supports explicit ODE evaluation, f(x,t) [=xdot].
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver)
Set solver.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Stepper integrates second-order ODEs.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions, make them consistent, and set needed memory.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
Set model.
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Stepper integrates first-order ODEs.
virtual void evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase< Scalar > > xDot, Teuchos::RCP< const Thyra::VectorBase< Scalar > > x, const Scalar time, const Teuchos::RCP< ExplicitODEParameters< Scalar > > &p)
Evaluate xDot = f(x,t).
RCP< std::basic_ostream< char_type, traits_type > > getOStream()
void setStepperExplicitValues(Teuchos::RCP< Teuchos::ParameterList > pl)
Set StepperExplicit member data from the ParameterList.