Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros 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 
13 namespace Tempus {
14 
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 
28 template<class Scalar>
30  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& appModel)
31 {
32  setModel(appModel);
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  if (numStates > 1) {
48  RCP<Teuchos::FancyOStream> out = this->getOStream();
49  Teuchos::OSTab ostab(out,1, "StepperExplicit::setInitialConditions()");
50  *out << "Warning -- SolutionHistory has more than one state!\n"
51  << "Setting the initial conditions on the currentState.\n"<<std::endl;
52  }
53 
54  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
55  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
56 
57  inArgs_ = appModel_->getNominalValues();
58  if (this->getOrderODE() == SECOND_ORDER_ODE) {
59  RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
60 
61  // If initialState has x and xDot set, treat them as the initial conditions.
62  // Otherwise use the x and xDot from getNominalValues() as the ICs.
63  TEUCHOS_TEST_FOR_EXCEPTION(
64  !((x != Teuchos::null && xDot != Teuchos::null) ||
65  (inArgs_.get_x() != Teuchos::null &&
66  inArgs_.get_x_dot() != Teuchos::null)), std::logic_error,
67  "Error - We need to set the initial conditions for x and xDot from\n"
68  " either initialState or appModel_->getNominalValues::InArgs\n"
69  " (but not from a mixture of the two).\n");
70  }
71 
72  if (this->getOrderODE() == FIRST_ORDER_ODE) {
73  if (x == Teuchos::null) {
74  // Use x from inArgs as ICs.
75  TEUCHOS_TEST_FOR_EXCEPTION( (x == Teuchos::null) &&
76  (inArgs_.get_x() == Teuchos::null), std::logic_error,
77  "Error - setInitialConditions needs the ICs from the 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 xDot from getNominalValues() as the ICs.
87  if ( initialState->getX() == Teuchos::null ||
88  initialState->getXDot() == Teuchos::null ) {
89  TEUCHOS_TEST_FOR_EXCEPTION( (inArgs_.get_x() == Teuchos::null) ||
90  (inArgs_.get_x_dot() == Teuchos::null), std::logic_error,
91  "Error - setInitialConditions() needs the ICs from the initialState\n"
92  " or getNominalValues()!\n");
93  x = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x());
94  initialState->setX(x);
95  RCP<Thyra::VectorBase<Scalar> > xDot
96  = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x_dot());
97  initialState->setXDot(xDot);
98  }
99  }
100 
101  // Perform IC Consistency
102  std::string icConsistency = this->getICConsistency();
103  if (icConsistency == "None") {
104  if (this->getOrderODE() == FIRST_ORDER_ODE) {
105  if (initialState->getXDot() == Teuchos::null) {
106  RCP<Teuchos::FancyOStream> out = this->getOStream();
107  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
108  *out << "Warning -- Requested IC consistency of 'None' but\n"
109  << " initialState does not have an xDot.\n"
110  << " Setting a 'Consistent' xDot!\n" << std::endl;
111  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
112  evaluateExplicitODE(getStepperXDot(initialState), x,
113  initialState->getTime(), p);
114  initialState->setIsSynced(true);
115  }
116  }
117  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
118  if (initialState->getXDotDot() == Teuchos::null) {
119  RCP<Teuchos::FancyOStream> out = this->getOStream();
120  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
121  *out << "Warning -- Requested IC consistency of 'None' but\n"
122  << " initialState does not have an xDotDot.\n"
123  << " Setting a 'Consistent' xDotDot!\n" << std::endl;
124  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
125  this->evaluateExplicitODE(getStepperXDotDot(initialState), x,
126  initialState->getXDot(),
127  initialState->getTime(), p);
128  initialState->setIsSynced(true);
129  }
130  }
131  }
132  else if (icConsistency == "Zero") {
133  if (this->getOrderODE() == FIRST_ORDER_ODE)
134  Thyra::assign(getStepperXDot(initialState).ptr(), Scalar(0.0));
135  else if (this->getOrderODE() == SECOND_ORDER_ODE)
136  Thyra::assign(getStepperXDotDot(initialState).ptr(), Scalar(0.0));
137  }
138  else if (icConsistency == "App") {
139  if (this->getOrderODE() == FIRST_ORDER_ODE) {
140  auto xDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
141  inArgs_.get_x_dot());
142  TEUCHOS_TEST_FOR_EXCEPTION(xDot == Teuchos::null, std::logic_error,
143  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
144  " but 'App' returned a null pointer for xDot!\n");
145  Thyra::assign(getStepperXDot(initialState).ptr(), *xDot);
146  }
147  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
148  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
149  inArgs_.get_x_dot_dot());
150  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
151  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
152  " but 'App' returned a null pointer for xDotDot!\n");
153  Thyra::assign(getStepperXDotDot(initialState).ptr(), *xDotDot);
154  }
155  }
156  else if (icConsistency == "Consistent") {
157  if (this->getOrderODE() == FIRST_ORDER_ODE) {
158  // Evaluate xDot = f(x,t).
159  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
160  evaluateExplicitODE(getStepperXDot(initialState), x,
161  initialState->getTime(), p);
162  }
163  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
164  // Evaluate xDotDot = f(x,xDot,t).
165  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
166  this->evaluateExplicitODE(initialState->getXDotDot(), x,
167  initialState->getXDot(),
168  initialState->getTime(), p);
169  }
170  }
171  else {
172  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
173  "Error - setInitialConditions() invalid IC consistency, '"
174  << icConsistency << "'.\n");
175  }
176 
177  // At this point, x, and xDot (and xDotDot) sync'ed or consistent
178  // at the same time level for the initialState.
179  initialState->setIsSynced(true);
180 
181  // Test for consistency.
182  if (this->getICConsistencyCheck()) {
183  if (this->getOrderODE() == FIRST_ORDER_ODE) {
184  auto xDot = getStepperXDot(initialState);
185  auto f = initialState->getX()->clone_v();
186  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
187  evaluateExplicitODE(f, x, initialState->getTime(), p);
188  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDot));
189  Scalar normX = Thyra::norm(*x);
190  Scalar reldiff = Scalar(0.0);
191  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
192  else reldiff = Thyra::norm(*f)/normX;
193 
194  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
195  if (reldiff > eps) {
196  RCP<Teuchos::FancyOStream> out = this->getOStream();
197  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
198  *out << "Warning -- Failed consistency check but continuing!\n"
199  << " ||xDot-f(x,t)||/||x|| > eps" << std::endl
200  << " ||xDot-f(x,t)|| = " << Thyra::norm(*f) << std::endl
201  << " ||x|| = " << Thyra::norm(*x) << std::endl
202  << " ||xDot-f(x,t)||/||x|| = " << reldiff << std::endl
203  << " eps = " << eps << std::endl;
204  }
205  }
206  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
207  auto xDotDot = initialState->getXDotDot();
208  auto f = initialState->getX()->clone_v();
209  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
210  this->evaluateExplicitODE(f, x, initialState->getXDot(),
211  initialState->getTime(), p);
212  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
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,"StepperExplicit::setInitialConditions()");
222  *out << "Warning -- Failed consistency check but continuing!\n"
223  << " ||xDotDot-f(x,xDot,t)||/||x|| > eps" << std::endl
224  << " ||xDotDot-f(x,xDot,t)|| = " << Thyra::norm(*f)
225  << std::endl
226  << " ||x|| = " << Thyra::norm(*x)
227  << std::endl
228  << " ||xDotDot-f(x,xDot,t)||/||x|| = " << reldiff << std::endl
229  << " eps = " << eps << std::endl;
230  }
231  }
232  }
233 }
234 
235 template<class Scalar>
237  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > /* solver */)
238 {
239  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
240  Teuchos::OSTab ostab(out,1,"StepperExplicit::setSolver()");
241  *out << "Warning -- No solver to set for StepperExplicit "
242  << "(i.e., explicit method).\n" << std::endl;
243  return;
244 }
245 
246 template<class Scalar>
247 Teuchos::RCP<Thyra::VectorBase<Scalar> >
249 getStepperX(Teuchos::RCP<SolutionState<Scalar> > state)
250 {
251  if (state->getX() != Teuchos::null) stepperX_ = state->getX();
252  // Else use temporary storage stepperXp_ which should have been set in
253  // setInitialConditions().
254 
255  TEUCHOS_TEST_FOR_EXCEPTION( stepperX_ == Teuchos::null, std::logic_error,
256  "Error - stepperX_ has not been set in setInitialConditions() or\n"
257  " can not be set from the state!\n");
258 
259  return stepperX_;
260 }
261 
262 template<class Scalar>
263 Teuchos::RCP<Thyra::VectorBase<Scalar> >
266 {
267  if (state->getXDot() != Teuchos::null) stepperXDot_ = state->getXDot();
268  // Else use temporary storage stepperXDot_ which should have been set in
269  // setInitialConditions().
270 
271  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDot_ == Teuchos::null, std::logic_error,
272  "Error - stepperXDot_ has not set in setInitialConditions() or\n"
273  " can not be set from the state!\n");
274 
275  return stepperXDot_;
276 }
277 
278 template<class Scalar>
279 Teuchos::RCP<Thyra::VectorBase<Scalar> >
282 {
283  if (state->getXDotDot() != Teuchos::null) stepperXDotDot_=state->getXDotDot();
284  // Else use temporary storage stepperXDotDot_ which should have been set in
285  // setInitialConditions().
286 
287  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDotDot_==Teuchos::null, std::logic_error,
288  "Error - stepperXDotDot_ has not set in setInitialConditions() or\n"
289  " can not be set from the state!\n");
290 
291  return stepperXDotDot_;
292 }
293 
294 template<class Scalar>
295 void
297 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDot,
298  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
299  const Scalar time,
300  const Teuchos::RCP<ExplicitODEParameters<Scalar> > & p )
301 {
302  typedef Thyra::ModelEvaluatorBase MEB;
303 
304  inArgs_.set_x(x);
305  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
306  if (inArgs_.supports(MEB::IN_ARG_step_size))
307  inArgs_.set_step_size(p->timeStepSize_);
308  if (inArgs_.supports(MEB::IN_ARG_stage_number))
309  inArgs_.set_stage_number(p->stageNumber_);
310 
311  // For model evaluators whose state function f(x, xDot, t) describes
312  // an implicit ODE, and which accept an optional xDot input argument,
313  // make sure the latter is set to null in order to request the evaluation
314  // of a state function corresponding to the explicit ODE formulation
315  // xDot = f(x, t).
316  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
317 
318  outArgs_.set_f(xDot);
319 
320  appModel_->evalModel(inArgs_, outArgs_);
321 }
322 
323 template<class Scalar>
324 void
326 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDotDot,
327  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
328  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xDot,
329  const Scalar time,
330  const Teuchos::RCP<ExplicitODEParameters<Scalar> > & p )
331 {
332  typedef Thyra::ModelEvaluatorBase MEB;
333 
334  inArgs_.set_x(x);
335  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(xDot);
336  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
337  if (inArgs_.supports(MEB::IN_ARG_step_size))
338  inArgs_.set_step_size(p->timeStepSize_);
339  if (inArgs_.supports(MEB::IN_ARG_stage_number))
340  inArgs_.set_stage_number(p->stageNumber_);
341 
342  // For model evaluators whose state function f(x, xDot, xDotDot, t) describes
343  // an implicit ODE, and which accept an optional xDotDot input argument,
344  // make sure the latter is set to null in order to request the evaluation
345  // of a state function corresponding to the explicit ODE formulation
346  // xDotDot = f(x, xDot, t).
347  if (inArgs_.supports(MEB::IN_ARG_x_dot_dot))
348  inArgs_.set_x_dot_dot(Teuchos::null);
349 
350  outArgs_.set_f(xDotDot);
351 
352  appModel_->evalModel(inArgs_, outArgs_);
353 }
354 
355 
356 } // namespace Tempus
357 #endif // Tempus_StepperExplicit_impl_hpp
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDot(Teuchos::RCP< SolutionState< Scalar > > state)
Get xDot from SolutionState or Stepper storage.
void validExplicitODE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate that the model supports explicit ODE evaluation, f(x,t) [=xdot].
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDotDot(Teuchos::RCP< SolutionState< Scalar > > state)
Get xDotDot from SolutionState or Stepper storage.
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.
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...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperX(Teuchos::RCP< SolutionState< Scalar > > state)
Get x from SolutionState or Stepper storage.
Stepper integrates first-order ODEs.
virtual void setNonConstModel(const Teuchos::RCP< Thyra::ModelEvaluator< Scalar > > &appModel)
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).
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver=Teuchos::null)
Set solver.
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...