Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Tempus_StepperImplicit_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_StepperImplicit_impl_hpp
11#define Tempus_StepperImplicit_impl_hpp
12
13// Thrya
14#include "NOX_Thyra.H"
15
16namespace Tempus {
17
18template <class Scalar>
20 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
21{
22 validImplicitODE_DAE(appModel);
23 wrapperModel_ =
24 Teuchos::rcp(new WrapperModelEvaluatorBasic<Scalar>(appModel));
25
26 TEUCHOS_TEST_FOR_EXCEPTION(solver_ == Teuchos::null, std::logic_error,
27 "Error - Solver is not set!\n");
28 solver_->setModel(wrapperModel_);
29
30 this->isInitialized_ = false;
31}
32
33template <class Scalar>
35 const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
36{
37 using Teuchos::RCP;
38
39 int numStates = solutionHistory->getNumStates();
40
41 TEUCHOS_TEST_FOR_EXCEPTION(
42 numStates < 1, std::logic_error,
43 "Error - setInitialConditions() needs at least one SolutionState\n"
44 " to set the initial condition. Number of States = "
45 << numStates);
46
47 RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
48 RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
49 RCP<Thyra::VectorBase<Scalar> > xDot = initialState->getXDot();
50 if (xDot() == Teuchos::null) xDot = this->getStepperXDot();
51
52 auto inArgs = this->wrapperModel_->getNominalValues();
53 if (this->getOrderODE() == SECOND_ORDER_ODE) {
54 RCP<Thyra::VectorBase<Scalar> > initialXDot = initialState->getXDot();
55 // If initialState has x and xDot set, treat them as the initial conditions.
56 // Otherwise use the x and xDot from getNominalValues() as the ICs.
57 TEUCHOS_TEST_FOR_EXCEPTION(
58 !((x != Teuchos::null && initialXDot != Teuchos::null) ||
59 (inArgs.get_x() != Teuchos::null &&
60 inArgs.get_x_dot() != Teuchos::null)),
61 std::logic_error,
62 "Error - We need to set the initial conditions for x and xDot from\n"
63 " either initialState or appModel_->getNominalValues::InArgs\n"
64 " (but not from a mixture of the two).\n");
65 }
66
67 if (this->getOrderODE() == FIRST_ORDER_ODE) {
68 // Use x from inArgs as ICs.
69 if (x == Teuchos::null) {
70 TEUCHOS_TEST_FOR_EXCEPTION(
71 (x == Teuchos::null) && (inArgs.get_x() == Teuchos::null),
72 std::logic_error,
73 "Error - setInitialConditions needs the ICs from the "
74 "SolutionHistory\n"
75 " or getNominalValues()!\n");
76
77 x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
78 initialState->setX(x);
79 }
80 }
81 else if (this->getOrderODE() == SECOND_ORDER_ODE) {
82 // Use the x and xDot from getNominalValues() as the ICs.
83 using Teuchos::rcp_const_cast;
84 if (x == Teuchos::null || xDot == Teuchos::null) {
85 TEUCHOS_TEST_FOR_EXCEPTION(
86 (inArgs.get_x() == Teuchos::null) ||
87 (inArgs.get_x_dot() == Teuchos::null),
88 std::logic_error,
89 "Error - setInitialConditions() needs the ICs from the initialState\n"
90 " or getNominalValues()!\n");
91 x = rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
92 initialState->setX(x);
93 RCP<Thyra::VectorBase<Scalar> > x_dot =
94 rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x_dot());
95 initialState->setXDot(x_dot);
96 }
97 }
98
99 // Perform IC Consistency
100 std::string icConsistency = this->getICConsistency();
101 if (icConsistency == "None") {
102 if (this->getOrderODE() == FIRST_ORDER_ODE) {
103 if (initialState->getXDot() == Teuchos::null)
104 Thyra::assign(xDot.ptr(), Scalar(0.0));
105 }
106 else if (this->getOrderODE() == SECOND_ORDER_ODE) {
107 if (initialState->getXDotDot() == Teuchos::null)
108 Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
109 }
110 }
111 else if (icConsistency == "Zero") {
112 if (this->getOrderODE() == FIRST_ORDER_ODE)
113 Thyra::assign(xDot.ptr(), Scalar(0.0));
114 else if (this->getOrderODE() == SECOND_ORDER_ODE)
115 Thyra::assign(this->getStepperXDotDot(initialState).ptr(), Scalar(0.0));
116 }
117 else if (icConsistency == "App") {
118 if (this->getOrderODE() == FIRST_ORDER_ODE) {
119 auto x_dot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
120 inArgs.get_x_dot());
121 TEUCHOS_TEST_FOR_EXCEPTION(
122 x_dot == Teuchos::null, std::logic_error,
123 "Error - setInitialConditions() requested 'App' for IC consistency,\n"
124 " but 'App' returned a null pointer for xDot!\n");
125 Thyra::assign(xDot.ptr(), *x_dot);
126 }
127 else if (this->getOrderODE() == SECOND_ORDER_ODE) {
128 auto xDotDot = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(
129 inArgs.get_x_dot_dot());
130 TEUCHOS_TEST_FOR_EXCEPTION(
131 xDotDot == Teuchos::null, std::logic_error,
132 "Error - setInitialConditions() requested 'App' for IC consistency,\n"
133 " but 'App' returned a null pointer for xDotDot!\n");
134 Thyra::assign(this->getStepperXDotDot(initialState).ptr(), *xDotDot);
135 }
136 }
137 else if (icConsistency == "Consistent") {
138 if (this->getOrderODE() == FIRST_ORDER_ODE) {
139 // Solve f(x, xDot,t) = 0.
140 const Scalar time = initialState->getTime();
141 const Scalar dt = initialState->getTimeStep();
142 RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
143 const Scalar alpha = Scalar(1.0); // d(xDot)/d(xDot)
144 const Scalar beta = Scalar(0.0); // d(x )/d(xDot)
145 auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
146 timeDer, dt, alpha, beta, SOLVE_FOR_XDOT_CONST_X));
147
148 const Thyra::SolveStatus<Scalar> sStatus =
149 this->solveImplicitODE(x, xDot, time, p);
150
151 TEUCHOS_TEST_FOR_EXCEPTION(
152 sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED,
153 std::logic_error,
154 "Error - Solver failed while determining the initial conditions.\n"
155 " Solver status is "
156 << Thyra::toString(sStatus.solveStatus) << ".\n");
157 }
158 else if (this->getOrderODE() == SECOND_ORDER_ODE) {
159 TEUCHOS_TEST_FOR_EXCEPTION(
160 true, std::logic_error,
161 "Error - setInitialConditions(): 'Consistent' for second-order ODE\n"
162 " has not been implemented.\n");
163 }
164 }
165 else {
166 TEUCHOS_TEST_FOR_EXCEPTION(
167 true, std::logic_error,
168 "Error - setInitialConditions() invalid IC consistency, "
169 << icConsistency << ".\n");
170 }
171
172 // At this point, x and xDot are sync'ed or consistent
173 // at the same time level for the initialState.
174 initialState->setIsSynced(true);
175
176 // Test for consistency.
177 if (this->getICConsistencyCheck()) {
178 auto f = initialState->getX()->clone_v();
179
180 const Scalar time = initialState->getTime();
181 const Scalar dt = initialState->getTimeStep();
182 RCP<TimeDerivative<Scalar> > timeDer = Teuchos::null;
183 const Scalar alpha = Scalar(0.0);
184 const Scalar beta = Scalar(0.0);
185 auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
186 timeDer, dt, alpha, beta, EVALUATE_RESIDUAL));
187
188 this->evaluateImplicitODE(f, x, xDot, time, p);
189
190 Scalar normX = Thyra::norm(*x);
191 Scalar reldiff = Scalar(0.0);
192 if (normX == Scalar(0.0))
193 reldiff = Thyra::norm(*f);
194 else
195 reldiff = Thyra::norm(*f) / normX;
196
197 Scalar eps = Scalar(100.0) * std::abs(Teuchos::ScalarTraits<Scalar>::eps());
198 RCP<Teuchos::FancyOStream> out = this->getOStream();
199 Teuchos::OSTab ostab(out, 1, "StepperImplicit::setInitialConditions()");
200 if (reldiff < eps) {
201 *out << "\n---------------------------------------------------\n"
202 << "Info -- Stepper = " << this->getStepperType() << "\n"
203 << " Initial condition PASSED consistency check!\n"
204 << " (||f(x,xDot,t)||/||x|| = " << reldiff << ") < "
205 << "(eps = " << eps << ")" << std::endl
206 << "---------------------------------------------------\n"
207 << std::endl;
208 }
209 else {
210 *out << "\n---------------------------------------------------\n"
211 << "Info -- Stepper = " << this->getStepperType() << "\n"
212 << " Initial condition FAILED consistency check but continuing!\n"
213 << " (||f(x,xDot,t)||/||x|| = " << reldiff << ") > "
214 << "(eps = " << eps << ")" << std::endl
215 << " ||f(x,xDot,t)|| = " << Thyra::norm(*f) << std::endl
216 << " ||x|| = " << Thyra::norm(*x) << std::endl
217 << "---------------------------------------------------\n"
218 << std::endl;
219 }
220 }
221}
222
223template <class Scalar>
225{
226 solver_ = rcp(new Thyra::NOXNonlinearSolver());
227 auto solverPL = defaultSolverParameters();
228 this->setSolverName("Default Solver");
229 auto subPL = sublist(solverPL, "NOX");
230 solver_->setParameterList(subPL);
231
232 if (wrapperModel_ != Teuchos::null) solver_->setModel(wrapperModel_);
233
234 this->isInitialized_ = false;
235}
236
237template <class Scalar>
239 Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
240{
241 TEUCHOS_TEST_FOR_EXCEPTION(
242 solver == Teuchos::null, std::logic_error,
243 "Error - Can not set the solver to Teuchos::null.\n");
244
245 solver_ = solver;
246 if (wrapperModel_ != Teuchos::null) solver_->setModel(wrapperModel_);
247
248 this->isInitialized_ = false;
249}
250
251template <class Scalar>
252const Thyra::SolveStatus<Scalar> StepperImplicit<Scalar>::solveImplicitODE(
253 const Teuchos::RCP<Thyra::VectorBase<Scalar> >& x,
254 const Teuchos::RCP<Thyra::VectorBase<Scalar> >& xDot, const Scalar time,
255 const Teuchos::RCP<ImplicitODEParameters<Scalar> >& p,
256 const Teuchos::RCP<Thyra::VectorBase<Scalar> >& y, const int index)
257{
258 wrapperModel_->setForSolve(x, xDot, time, p, y, index);
259
260 Thyra::SolveStatus<Scalar> sStatus;
261 typedef Teuchos::ScalarTraits<Scalar> ST;
262 switch (p->evaluationType_) {
263 case SOLVE_FOR_X: {
264 if (getZeroInitialGuess()) Thyra::assign(x.ptr(), ST::zero());
265 sStatus = (*solver_).solve(&*x);
266 break;
267 }
269 // if (getZeroInitialGuess()) Thyra::assign(xDot.ptr(), ST::zero());
270 sStatus = (*solver_).solve(&*xDot);
271 break;
272 }
273 default: {
274 TEUCHOS_TEST_FOR_EXCEPT("Invalid EVALUATION_TYPE!");
275 }
276 }
277
278 return sStatus;
279}
280
281template <class Scalar>
283 Teuchos::RCP<Thyra::VectorBase<Scalar> >& f,
284 const Teuchos::RCP<Thyra::VectorBase<Scalar> >& x,
285 const Teuchos::RCP<Thyra::VectorBase<Scalar> >& xDot, const Scalar time,
286 const Teuchos::RCP<ImplicitODEParameters<Scalar> >& p)
287{
288 typedef Thyra::ModelEvaluatorBase MEB;
289 MEB::InArgs<Scalar> inArgs = wrapperModel_->createInArgs();
290 inArgs.set_x(x);
291 if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(xDot);
292 if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
293 if (inArgs.supports(MEB::IN_ARG_step_size))
294 inArgs.set_step_size(p->timeStepSize_);
295 if (inArgs.supports(MEB::IN_ARG_alpha)) inArgs.set_alpha(Scalar(0.0));
296 if (inArgs.supports(MEB::IN_ARG_beta)) inArgs.set_beta(Scalar(0.0));
297
298 MEB::OutArgs<Scalar> outArgs = wrapperModel_->createOutArgs();
299 outArgs.set_f(f);
300
301 wrapperModel_->setForSolve(x, xDot, time, p);
302
303 wrapperModel_->evalModel(inArgs, outArgs);
304}
305
306template <class Scalar>
308 Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
309{
310 out.setOutputToRootOnly(0);
311 out << "--- StepperImplicit ---\n";
312 out << " wrapperModel_ = " << wrapperModel_ << std::endl;
313 out << " solver_ = " << solver_ << std::endl;
314 out << " initialGuess_ = " << initialGuess_ << std::endl;
315 out << " zeroInitialGuess_ = " << Teuchos::toString(zeroInitialGuess_)
316 << std::endl;
317}
318
319template <class Scalar>
320bool StepperImplicit<Scalar>::isValidSetup(Teuchos::FancyOStream& out) const
321{
322 out.setOutputToRootOnly(0);
323 bool isValidSetup = true;
324
325 if (wrapperModel_->getAppModel() == Teuchos::null) {
326 isValidSetup = false;
327 out << "The application ModelEvaluator is not set!\n";
328 }
329
330 if (wrapperModel_ == Teuchos::null) {
331 isValidSetup = false;
332 out << "The wrapper ModelEvaluator is not set!\n";
333 }
334
335 if (solver_ == Teuchos::null) {
336 isValidSetup = false;
337 out << "The solver is not set!\n";
338 }
339
340 if (solver_ != Teuchos::null) {
341 if (solver_->getModel() == Teuchos::null) {
342 isValidSetup = false;
343 out << "The solver's ModelEvaluator is not set!\n";
344 }
345 }
346
347 return isValidSetup;
348}
349
350template <class Scalar>
351Teuchos::RCP<const Teuchos::ParameterList>
353{
354 return this->getValidParametersBasicImplicit();
355}
356
357template <class Scalar>
358Teuchos::RCP<Teuchos::ParameterList>
360{
361 auto pl = this->getValidParametersBasic();
362 pl->template set<std::string>("Solver Name", this->getSolverName());
363 pl->template set<bool>("Zero Initial Guess", this->getZeroInitialGuess());
364 auto noxSolverPL = this->getSolver()->getParameterList();
365 auto solverPL = Teuchos::parameterList(this->getSolverName());
366 solverPL->set("NOX", *noxSolverPL);
367 pl->set(this->getSolverName(), *solverPL);
368
369 return pl;
370}
371
372template <class Scalar>
374 Teuchos::RCP<Teuchos::ParameterList> pl)
375{
376 if (pl != Teuchos::null) {
377 // Can not validate because of optional Parameters, e.g., 'Solver Name'.
378 // pl->validateParametersAndSetDefaults(*this->getValidParameters());
379 this->setStepperValues(pl);
380 this->setZeroInitialGuess(pl->get<bool>("Zero Initial Guess", false));
381 }
382 this->setStepperSolverValues(pl);
383}
384
385template <class Scalar>
387 Teuchos::RCP<Teuchos::ParameterList> pl)
388{
389 if (pl != Teuchos::null) {
390 setDefaultSolver();
391 std::string solverName = pl->get<std::string>("Solver Name");
392 if (pl->isSublist(solverName)) {
393 auto solverPL = Teuchos::parameterList();
394 solverPL = Teuchos::sublist(pl, solverName);
395 this->setSolverName(solverName);
396 Teuchos::RCP<Teuchos::ParameterList> noxPL =
397 Teuchos::sublist(solverPL, "NOX", true);
398 getSolver()->setParameterList(noxPL);
399 }
400 }
401}
402
403} // namespace Tempus
404#endif // Tempus_StepperImplicit_impl_hpp
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicImplicit() const
void setStepperImplicitValues(Teuchos::RCP< Teuchos::ParameterList > pl)
Set StepperImplicit member data from the ParameterList.
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
void setStepperSolverValues(Teuchos::RCP< Teuchos::ParameterList > pl)
Set solver from ParameterList.
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver) override
Set solver.
void evaluateImplicitODE(Teuchos::RCP< Thyra::VectorBase< Scalar > > &f, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xDot, const Scalar time, const Teuchos::RCP< ImplicitODEParameters< Scalar > > &p)
Evaluate implicit ODE residual, f(x, xDot, t, p).
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const override
const Thyra::SolveStatus< Scalar > solveImplicitODE(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xDot, const Scalar time, const Teuchos::RCP< ImplicitODEParameters< Scalar > > &p, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &y=Teuchos::null, const int index=-1)
Solve implicit ODE, f(x, xDot, t, p) = 0.
A ModelEvaluator for residual evaluations given a state. This ModelEvaluator takes a state,...
void validImplicitODE_DAE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate ME supports implicit ODE/DAE evaluation, f(xdot,x,t) [= 0].
@ SECOND_ORDER_ODE
Stepper integrates second-order ODEs.
@ FIRST_ORDER_ODE
Stepper integrates first-order ODEs.
@ SOLVE_FOR_XDOT_CONST_X
Solve for xDot keeping x constant (for ICs).
@ SOLVE_FOR_X
Solve for x and determine xDot from x.
@ EVALUATE_RESIDUAL
Evaluate residual for the implicit ODE.
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.