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