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<SolutionHistory<Scalar> >& solutionHistory)
31 {
32  using Teuchos::RCP;
33 
34  int numStates = solutionHistory->getNumStates();
35 
36  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
37  "Error - setInitialConditions() needs at least one SolutionState\n"
38  " to set the initial condition. Number of States = " << numStates);
39 
40  if (numStates > 1) {
41  RCP<Teuchos::FancyOStream> out = this->getOStream();
42  Teuchos::OSTab ostab(out,1, "StepperExplicit::setInitialConditions()");
43  *out << "Warning -- SolutionHistory has more than one state!\n"
44  << "Setting the initial conditions on the currentState.\n"<<std::endl;
45  }
46 
47  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
48  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
49 
50  inArgs_ = appModel_->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  if (x == Teuchos::null) {
67  // Use x from inArgs as ICs.
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  using Teuchos::rcp_const_cast;
79  // Use the x and xDot from getNominalValues() as the ICs.
80  if ( initialState->getX() == Teuchos::null ||
81  initialState->getXDot() == 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  RCP<Thyra::VectorBase<Scalar> > xDot
89  = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs_.get_x_dot());
90  initialState->setXDot(xDot);
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  RCP<Teuchos::FancyOStream> out = this->getOStream();
100  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
101  *out << "Warning -- Requested IC consistency of 'None' but\n"
102  << " initialState does not have an xDot.\n"
103  << " Setting a 'Consistent' xDot!\n" << std::endl;
104  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
105  evaluateExplicitODE(this->getStepperXDot(initialState), x,
106  initialState->getTime(), p);
107  initialState->setIsSynced(true);
108  }
109  }
110  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
111  if (initialState->getXDotDot() == Teuchos::null) {
112  RCP<Teuchos::FancyOStream> out = this->getOStream();
113  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
114  *out << "Warning -- Requested IC consistency of 'None' but\n"
115  << " initialState does not have an xDotDot.\n"
116  << " Setting a 'Consistent' xDotDot!\n" << std::endl;
117  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
118  this->evaluateExplicitODE(this->getStepperXDotDot(initialState), x,
119  initialState->getXDot(),
120  initialState->getTime(), p);
121  initialState->setIsSynced(true);
122  }
123  }
124  }
125  else if (icConsistency == "Zero") {
126  if (this->getOrderODE() == FIRST_ORDER_ODE)
127  Thyra::assign(this->getStepperXDot(initialState).ptr(), Scalar(0.0));
128  else if (this->getOrderODE() == SECOND_ORDER_ODE)
129  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
130  }
131  else if (icConsistency == "App") {
132  if (this->getOrderODE() == FIRST_ORDER_ODE) {
133  auto xDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
134  inArgs_.get_x_dot());
135  TEUCHOS_TEST_FOR_EXCEPTION(xDot == Teuchos::null, std::logic_error,
136  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
137  " but 'App' returned a null pointer for xDot!\n");
138  Thyra::assign(this->getStepperXDot(initialState).ptr(), *xDot);
139  }
140  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
141  auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
142  inArgs_.get_x_dot_dot());
143  TEUCHOS_TEST_FOR_EXCEPTION(xDotDot == Teuchos::null, std::logic_error,
144  "Error - setInitialConditions() requested 'App' for IC consistency,\n"
145  " but 'App' returned a null pointer for xDotDot!\n");
146  Thyra::assign(this->getStepperXDotDot(initialState).ptr(), *xDotDot);
147  }
148  }
149  else if (icConsistency == "Consistent") {
150  if (this->getOrderODE() == FIRST_ORDER_ODE) {
151  // Evaluate xDot = f(x,t).
152  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
153  evaluateExplicitODE(this->getStepperXDot(initialState), x,
154  initialState->getTime(), p);
155  }
156  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
157  // Evaluate xDotDot = f(x,xDot,t).
158  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
159  this->evaluateExplicitODE(initialState->getXDotDot(), x,
160  initialState->getXDot(),
161  initialState->getTime(), p);
162  }
163  }
164  else {
165  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
166  "Error - setInitialConditions() invalid IC consistency, '"
167  << icConsistency << "'.\n");
168  }
169 
170  // At this point, x, and xDot (and xDotDot) sync'ed or consistent
171  // at the same time level for the initialState.
172  initialState->setIsSynced(true);
173 
174  // Test for consistency.
175  if (this->getICConsistencyCheck()) {
176  if (this->getOrderODE() == FIRST_ORDER_ODE) {
177  auto xDot = this->getStepperXDot(initialState);
178  auto f = initialState->getX()->clone_v();
179  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
180  evaluateExplicitODE(f, x, initialState->getTime(), p);
181  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDot));
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,"StepperExplicit::setInitialConditions()");
191  *out << "Warning -- Failed consistency check but continuing!\n"
192  << " ||xDot-f(x,t)||/||x|| > eps" << std::endl
193  << " ||xDot-f(x,t)|| = " << Thyra::norm(*f) << std::endl
194  << " ||x|| = " << Thyra::norm(*x) << std::endl
195  << " ||xDot-f(x,t)||/||x|| = " << reldiff << std::endl
196  << " eps = " << eps << std::endl;
197  }
198  }
199  else if (this->getOrderODE() == SECOND_ORDER_ODE) {
200  auto xDotDot = initialState->getXDotDot();
201  auto f = initialState->getX()->clone_v();
202  auto p = Teuchos::rcp(new ExplicitODEParameters<Scalar>(0.0));
203  this->evaluateExplicitODE(f, x, initialState->getXDot(),
204  initialState->getTime(), p);
205  Thyra::Vp_StV(f.ptr(), Scalar(-1.0), *(xDotDot));
206  Scalar normX = Thyra::norm(*x);
207  Scalar reldiff = Scalar(0.0);
208  if (normX == Scalar(0.0)) reldiff = Thyra::norm(*f);
209  else reldiff = Thyra::norm(*f)/normX;
210 
211  Scalar eps = Scalar(100.0)*std::abs(Teuchos::ScalarTraits<Scalar>::eps());
212  if (reldiff > eps) {
213  RCP<Teuchos::FancyOStream> out = this->getOStream();
214  Teuchos::OSTab ostab(out,1,"StepperExplicit::setInitialConditions()");
215  *out << "Warning -- Failed consistency check but continuing!\n"
216  << " ||xDotDot-f(x,xDot,t)||/||x|| > eps" << std::endl
217  << " ||xDotDot-f(x,xDot,t)|| = " << Thyra::norm(*f)
218  << std::endl
219  << " ||x|| = " << Thyra::norm(*x)
220  << std::endl
221  << " ||xDotDot-f(x,xDot,t)||/||x|| = " << reldiff << std::endl
222  << " eps = " << eps << std::endl;
223  }
224  }
225  }
226 }
227 
228 template<class Scalar>
230  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > /* solver */)
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 template<class Scalar>
239 void
241 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDot,
242  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
243  const Scalar time,
244  const Teuchos::RCP<ExplicitODEParameters<Scalar> > & p )
245 {
246  typedef Thyra::ModelEvaluatorBase MEB;
247 
248  inArgs_.set_x(x);
249  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
250  if (inArgs_.supports(MEB::IN_ARG_step_size))
251  inArgs_.set_step_size(p->timeStepSize_);
252  if (inArgs_.supports(MEB::IN_ARG_stage_number))
253  inArgs_.set_stage_number(p->stageNumber_);
254 
255  // For model evaluators whose state function f(x, xDot, t) describes
256  // an implicit ODE, and which accept an optional xDot input argument,
257  // make sure the latter is set to null in order to request the evaluation
258  // of a state function corresponding to the explicit ODE formulation
259  // xDot = f(x, t).
260  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(Teuchos::null);
261 
262  outArgs_.set_f(xDot);
263 
264  appModel_->evalModel(inArgs_, outArgs_);
265 }
266 
267 template<class Scalar>
268 void
270 evaluateExplicitODE(Teuchos::RCP< Thyra::VectorBase<Scalar> > xDotDot,
271  Teuchos::RCP<const Thyra::VectorBase<Scalar> > x,
272  Teuchos::RCP<const Thyra::VectorBase<Scalar> > xDot,
273  const Scalar time,
274  const Teuchos::RCP<ExplicitODEParameters<Scalar> > & p )
275 {
276  typedef Thyra::ModelEvaluatorBase MEB;
277 
278  inArgs_.set_x(x);
279  if (inArgs_.supports(MEB::IN_ARG_x_dot)) inArgs_.set_x_dot(xDot);
280  if (inArgs_.supports(MEB::IN_ARG_t)) inArgs_.set_t(time);
281  if (inArgs_.supports(MEB::IN_ARG_step_size))
282  inArgs_.set_step_size(p->timeStepSize_);
283  if (inArgs_.supports(MEB::IN_ARG_stage_number))
284  inArgs_.set_stage_number(p->stageNumber_);
285 
286  // For model evaluators whose state function f(x, xDot, xDotDot, t) describes
287  // an implicit ODE, and which accept an optional xDotDot input argument,
288  // make sure the latter is set to null in order to request the evaluation
289  // of a state function corresponding to the explicit ODE formulation
290  // xDotDot = f(x, xDot, t).
291  if (inArgs_.supports(MEB::IN_ARG_x_dot_dot))
292  inArgs_.set_x_dot_dot(Teuchos::null);
293 
294  outArgs_.set_f(xDotDot);
295 
296  appModel_->evalModel(inArgs_, outArgs_);
297 }
298 
299 
300 
301 template<class Scalar>
302 void StepperExplicit<Scalar>::describe(Teuchos::FancyOStream & out,
303  const Teuchos::EVerbosityLevel verbLevel) const
304 {
305  out << "--- StepperExplicit ---\n";
306  out << " appModel_ = " << appModel_ << std::endl;
307  out << " inArgs_ = " << inArgs_ << std::endl;
308  out << " outArgs_ = " << outArgs_ << std::endl;
309 }
310 
311 
312 template<class Scalar>
313 bool StepperExplicit<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
314 {
315  bool isValidSetup = true;
316 
317  if (appModel_ == Teuchos::null) {
318  isValidSetup = false;
319  out << "The application ModelEvaluator is not set!\n";
320  }
321 
322  return isValidSetup;
323 }
324 
325 
326 } // namespace Tempus
327 #endif // Tempus_StepperExplicit_impl_hpp
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
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.
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
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
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).