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  this->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 = 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  evaluateExplicitODE(getStepperXDot(initialState), x,
112  initialState->getTime());
113  initialState->setIsSynced(true);
114  }
115  }
116  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
117  if (initialState->getXDotDot() == Teuchos::null) {
118  RCP<Teuchos::FancyOStream> out = this->getOStream();
119  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
120  *out << "Warning -- Requested IC consistency of 'None' but\n"
121  << " initialState does not have an xDotDot.\n"
122  << " Setting a 'Consistent' xDotDot!\n" << std::endl;
123  this->evaluateExplicitODE(getStepperXDotDot(initialState), x,
124  initialState->getXDot(),
125  initialState->getTime());
126  initialState->setIsSynced(true);
127  }
128  }
129  }
130  else if (icConsistency == "Zero") {
131  if (this->getOrderODE() == FIRST_ORDER_ODE)
132  Thyra::assign(getStepperXDot(initialState).ptr(), Scalar(0.0));
133  else if (this->getOrderODE() == SECOND_ORDER_ODE)
134  Thyra::assign(getStepperXDotDot(initialState).ptr(), Scalar(0.0));
135  }
136  else if (icConsistency == "App") {
137  if (this->getOrderODE() == FIRST_ORDER_ODE) {
138  auto xDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
139  inArgs_.get_x_dot());
140  TEUCHOS_TEST_FOR_EXCEPTION(xDot == Teuchos::null, std::logic_error,
141  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
142  " but 'App' returned a null pointer for xDot!\n");
143  Thyra::assign(getStepperXDot(initialState).ptr(), *xDot);
144  }
145  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
146  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
147  inArgs_.get_x_dot_dot());
148  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
149  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
150  " but 'App' returned a null pointer for xDotDot!\n");
151  Thyra::assign(getStepperXDotDot(initialState).ptr(), *xDotDot);
152  }
153  }
154  else if (icConsistency == "Consistent") {
155  if (this->getOrderODE() == FIRST_ORDER_ODE) {
156  // Evaluate xDot = f(x,t).
157  evaluateExplicitODE(getStepperXDot(initialState), x,
158  initialState->getTime());
159  }
160  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
161  // Evaluate xDotDot = f(x,xDot,t).
162  this->evaluateExplicitODE(initialState->getXDotDot(), x,
163  initialState->getXDot(),
164  initialState->getTime());
165  }
166  }
167  else {
168  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
169  "Error - setInitialConditions() invalid IC consistency, "
170  << icConsistency << ".\n");
171  }
172 
173  // At this point, x, and xDot (and xDotDot) sync'ed or consistent
174  // at the same time level for the initialState.
175  initialState->setIsSynced(true);
176 
177  // Test for consistency.
178  if (getICConsistencyCheck()) {
179  if (this->getOrderODE() == FIRST_ORDER_ODE) {
180  auto xDot = getStepperXDot(initialState);
181  auto f = initialState->getX()->clone_v();
182  evaluateExplicitODE(f, x, initialState->getTime());
183  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDot));
184  Scalar normX = Thyra::norm(*x);
185  Scalar reldiff = Scalar(0.0);
186  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
187  else reldiff = Thyra::norm(*f)/normX;
188 
189  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
190  if (reldiff > eps) {
191  RCP<Teuchos::FancyOStream> out = this->getOStream();
192  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
193  *out << "Warning -- Failed consistency check but continuing!\n"
194  << " ||xDot-f(x,t)||/||x|| > eps" << std::endl
195  << " ||xDot-f(x,t)|| = " << Thyra::norm(*f) << std::endl
196  << " ||x|| = " << Thyra::norm(*x) << std::endl
197  << " ||xDot-f(x,t)||/||x|| = " << reldiff << std::endl
198  << " eps = " << eps << std::endl;
199  }
200  }
201  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
202  auto xDotDot = initialState->getXDotDot();
203  auto f = initialState->getX()->clone_v();
204  this->evaluateExplicitODE(f, x, initialState->getXDot(),
205  initialState->getTime());
206  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
207  Scalar normX = Thyra::norm(*x);
208  Scalar reldiff = Scalar(0.0);
209  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
210  else reldiff = Thyra::norm(*f)/normX;
211 
212  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
213  if (reldiff > eps) {
214  RCP<Teuchos::FancyOStream> out = this->getOStream();
215  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
216  *out << "Warning -- Failed consistency check but continuing!\n"
217  << " ||xDotDot-f(x,xDot,t)||/||x|| > eps" << std::endl
218  << " ||xDotDot-f(x,xDot,t)|| = " << Thyra::norm(*f)
219  << std::endl
220  << " ||x|| = " << Thyra::norm(*x)
221  << std::endl
222  << " ||xDotDot-f(x,xDot,t)||/||x|| = " << reldiff << std::endl
223  << " eps = " << eps << std::endl;
224  }
225  }
226  }
227 }
228 
229 template<class Scalar>
230 void StepperExplicit<Scalar>::setSolver(std::string /* solverName */)
231 {
232  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
233  Teuchos::OSTab ostab(out,1,"StepperExplicit::setSolver()");
234  *out << "Warning -- No solver to set for StepperExplicit "
235  << "(i.e., explicit method).\n" << std::endl;
236  return;
237 }
238 
239 template<class Scalar>
241  Teuchos::RCP<Teuchos::ParameterList> /* solverPL */)
242 {
243  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
244  Teuchos::OSTab ostab(out,1,"StepperExplicit::setSolver()");
245  *out << "Warning -- No solver to set for StepperExplicit "
246  << "(i.e., explicit method).\n" << std::endl;
247  return;
248 }
249 
250 template<class Scalar>
252  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > /* solver */)
253 {
254  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
255  Teuchos::OSTab ostab(out,1,"StepperExplicit::setSolver()");
256  *out << "Warning -- No solver to set for StepperExplicit "
257  << "(i.e., explicit method).\n" << std::endl;
258  return;
259 }
260 
261 template<class Scalar>
262 Teuchos::RCP<Thyra::VectorBase<Scalar> >
264 getStepperX(Teuchos::RCP<SolutionState<Scalar> > state)
265 {
266  if (state->getX() != Teuchos::null) stepperX_ = state->getX();
267  // Else use temporary storage stepperXp_ which should have been set in
268  // setInitialConditions().
269 
270  TEUCHOS_TEST_FOR_EXCEPTION( stepperX_ == Teuchos::null, std::logic_error,
271  "Error - stepperX_ has not been set in setInitialConditions() or\n"
272  " can not be set from the state!\n");
273 
274  return stepperX_;
275 }
276 
277 template<class Scalar>
278 Teuchos::RCP<Thyra::VectorBase<Scalar> >
281 {
282  if (state->getXDot() != Teuchos::null) stepperXDot_ = state->getXDot();
283  // Else use temporary storage stepperXDot_ which should have been set in
284  // setInitialConditions().
285 
286  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDot_ == Teuchos::null, std::logic_error,
287  "Error - stepperXDot_ has not set in setInitialConditions() or\n"
288  " can not be set from the state!\n");
289 
290  return stepperXDot_;
291 }
292 
293 template<class Scalar>
294 Teuchos::RCP<Thyra::VectorBase<Scalar> >
297 {
298  if (state->getXDotDot() != Teuchos::null) stepperXDotDot_=state->getXDotDot();
299  // Else use temporary storage stepperXDotDot_ which should have been set in
300  // setInitialConditions().
301 
302  TEUCHOS_TEST_FOR_EXCEPTION( stepperXDotDot_==Teuchos::null, std::logic_error,
303  "Error - stepperXDotDot_ has not set in setInitialConditions() or\n"
304  " can not be set from the state!\n");
305 
306  return stepperXDotDot_;
307 }
308 
309 template<class Scalar>
310 void
312 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDot,
313  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
314  const Scalar time)
315 {
316  typedef Thyra::ModelEvaluatorBase MEB;
317 
318  inArgs_.set_x(x);
319  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
320 
321  // For model evaluators whose state function f(x, xDot, t) describes
322  // an implicit ODE, and which accept an optional xDot 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  // xDot = f(x, t).
326  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
327 
328  outArgs_.set_f(xDot);
329 
330  appModel_->evalModel(inArgs_, outArgs_);
331 }
332 
333 template<class Scalar>
334 void
336 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDotDot,
337  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
338  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xDot,
339  const Scalar time)
340 {
341  typedef Thyra::ModelEvaluatorBase MEB;
342 
343  inArgs_.set_x(x);
344  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(xDot);
345  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
346 
347  // For model evaluators whose state function f(x, xDot, xDotDot, t) describes
348  // an implicit ODE, and which accept an optional xDotDot input argument,
349  // make sure the latter is set to null in order to request the evaluation
350  // of a state function corresponding to the explicit ODE formulation
351  // xDotDot = f(x, xDot, t).
352  if (inArgs_.supports(MEB::IN_ARG_x_dot_dot))
353  inArgs_.set_x_dot_dot(Teuchos::null);
354 
355  outArgs_.set_f(xDotDot);
356 
357  appModel_->evalModel(inArgs_, outArgs_);
358 }
359 
360 
361 } // namespace Tempus
362 #endif // Tempus_StepperExplicit_impl_hpp
virtual Teuchos::RCP< Thyra::VectorBase< Scalar > > getStepperXDot(Teuchos::RCP< SolutionState< Scalar > > state)
Get xDot from SolutionState or Stepper storage.
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 setSolver(std::string solverName)
Set solver via ParameterList solver name.
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)
Evaluate xDot = f(x,t).
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...