Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Tempus_StepperDIRK_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_StepperDIRK_impl_hpp
11#define Tempus_StepperDIRK_impl_hpp
12
13#include "Thyra_VectorStdOps.hpp"
14
15#include "Tempus_WrapperModelEvaluatorBasic.hpp"
16
17namespace Tempus {
18
19template <class Scalar>
21{
22 this->setUseEmbedded(false);
23 this->setZeroInitialGuess(false);
24 this->setStageNumber(-1);
25
26 this->setAppAction(Teuchos::null);
27 this->setDefaultSolver();
28}
29
30template <class Scalar>
32 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
33 const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
34 bool useFSAL, std::string ICConsistency, bool ICConsistencyCheck,
35 bool useEmbedded, bool zeroInitialGuess,
36 const Teuchos::RCP<StepperRKAppAction<Scalar> >& stepperRKAppAction)
37{
38 this->setUseFSAL(useFSAL);
39 this->setICConsistency(ICConsistency);
40 this->setICConsistencyCheck(ICConsistencyCheck);
41 this->setUseEmbedded(useEmbedded);
42 this->setZeroInitialGuess(zeroInitialGuess);
43
44 this->setStageNumber(-1);
45 this->setErrorNorm();
46 this->setAppAction(stepperRKAppAction);
47 this->setSolver(solver);
48
49 if (appModel != Teuchos::null) {
50 this->setModel(appModel);
51 this->initialize();
52 }
53}
54
55template <class Scalar>
56Teuchos::RCP<Teuchos::ParameterList>
58{
59 auto pl = this->getValidParametersBasicImplicit();
60 pl->template set<bool>(
61 "Use Embedded", this->getUseEmbedded(),
62 "'Whether to use Embedded Stepper (if available) or not\n"
63 " 'true' - Stepper will compute embedded solution and is adaptive.\n"
64 " 'false' - Stepper is not embedded(adaptive).\n");
65 pl->template set<std::string>("Description", this->getDescription());
66 pl->template set<bool>("Reset Initial Guess", this->getResetInitialGuess());
67
68 return pl;
69}
70
71template <class Scalar>
73{
74 TEUCHOS_TEST_FOR_EXCEPTION(this->tableau_ == Teuchos::null, std::logic_error,
75 "Error - Need to set the tableau, before calling "
76 "StepperDIRK::initialize()\n");
77
78 TEUCHOS_TEST_FOR_EXCEPTION(
79 this->wrapperModel_ == Teuchos::null, std::logic_error,
80 "Error - Need to set the model, setModel(), before calling "
81 "StepperDIRK::initialize()\n");
82
84}
85
86template <class Scalar>
88 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
89{
91
92 // Set the stage vectors
93 const int numStages = this->tableau_->numStages();
94 stageXDot_.resize(numStages);
95 for (int i = 0; i < numStages; ++i) {
96 stageXDot_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
97 assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
98 }
99 xTilde_ = Thyra::createMember(this->wrapperModel_->get_x_space());
100 assign(xTilde_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
101
102 this->setEmbeddedMemory();
103 this->setErrorNorm();
104
105 this->isInitialized_ = false;
106}
107
108template <class Scalar>
110{
111 if (this->getModel() == Teuchos::null)
112 return; // Embedded memory will be set when setModel() is called.
113
114 if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
115 this->ee_ = Thyra::createMember(this->wrapperModel_->get_f_space());
116 this->abs_u0 = Thyra::createMember(this->wrapperModel_->get_f_space());
117 this->abs_u = Thyra::createMember(this->wrapperModel_->get_f_space());
118 this->sc = Thyra::createMember(this->wrapperModel_->get_f_space());
119 }
120 else {
121 this->ee_ = Teuchos::null;
122 this->abs_u0 = Teuchos::null;
123 this->abs_u = Teuchos::null;
124 this->sc = Teuchos::null;
125 }
126}
127
128template <class Scalar>
130 const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
131{
132 this->setStepperXDot(stageXDot_.back());
134}
135
136template <class Scalar>
138 const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
139{
140 this->checkInitialized();
141
142 using Teuchos::RCP;
143
144 TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperDIRK::takeStep()");
145 {
146 TEUCHOS_TEST_FOR_EXCEPTION(
147 solutionHistory->getNumStates() < 2, std::logic_error,
148 "Error - StepperDIRK<Scalar>::takeStep(...)\n"
149 << "Need at least two SolutionStates for DIRK.\n"
150 << " Number of States = " << solutionHistory->getNumStates()
151 << "\nTry setting in \"Solution History\" "
152 << "\"Storage Type\" = \"Undo\"\n"
153 << " or \"Storage Type\" = \"Static\" and "
154 << "\"Storage Limit\" = \"2\"\n");
155
156 RCP<SolutionState<Scalar> > currentState =
157 solutionHistory->getCurrentState();
158 RCP<SolutionState<Scalar> > workingState =
159 solutionHistory->getWorkingState();
160 const Scalar dt = workingState->getTimeStep();
161 const Scalar time = currentState->getTime();
162
163 const int numStages = this->tableau_->numStages();
164 Teuchos::SerialDenseMatrix<int, Scalar> A = this->tableau_->A();
165 Teuchos::SerialDenseVector<int, Scalar> b = this->tableau_->b();
166 Teuchos::SerialDenseVector<int, Scalar> c = this->tableau_->c();
167
168 // Reset non-zero initial guess.
169 if (this->getResetInitialGuess() && (!this->getZeroInitialGuess()))
170 Thyra::assign(workingState->getX().ptr(), *(currentState->getX()));
171
172 RCP<StepperDIRK<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
173 this->stepperRKAppAction_->execute(
174 solutionHistory, thisStepper,
176
177 // Compute stage solutions
178 bool pass = true;
179 Thyra::SolveStatus<Scalar> sStatus;
180 for (int i = 0; i < numStages; ++i) {
181 this->setStageNumber(i);
182
183 Thyra::assign(xTilde_.ptr(), *(currentState->getX()));
184 for (int j = 0; j < i; ++j) {
185 if (A(i, j) != Teuchos::ScalarTraits<Scalar>::zero()) {
186 Thyra::Vp_StV(xTilde_.ptr(), dt * A(i, j), *(stageXDot_[j]));
187 }
188 }
189 this->setStepperXDot(stageXDot_[i]);
190
191 this->stepperRKAppAction_->execute(
192 solutionHistory, thisStepper,
194
195 Scalar ts = time + c(i) * dt;
196
197 // Check if stageXDot_[i] is needed.
198 bool isNeeded = false;
199 for (int k = i + 1; k < numStages; ++k)
200 if (A(k, i) != 0.0) isNeeded = true;
201 if (b(i) != 0.0) isNeeded = true;
202 if (this->tableau_->isEmbedded() && this->getUseEmbedded() &&
203 this->tableau_->bstar()(i) != 0.0)
204 isNeeded = true;
205 if (isNeeded == false) {
206 assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
207 }
208 else if (A(i, i) == Teuchos::ScalarTraits<Scalar>::zero()) {
209 // Explicit stage for the ImplicitODE_DAE
210 if (i == 0 && this->getUseFSAL() &&
211 workingState->getNConsecutiveFailures() == 0) {
212 // Reuse last evaluation for first step
213 RCP<Thyra::VectorBase<Scalar> > tmp = stageXDot_[0];
214 stageXDot_[0] = stageXDot_.back();
215 stageXDot_.back() = tmp;
216 this->setStepperXDot(stageXDot_[0]);
217 }
218 else {
219 // Calculate explicit stage
220 typedef Thyra::ModelEvaluatorBase MEB;
221 MEB::InArgs<Scalar> inArgs = this->wrapperModel_->createInArgs();
222 MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->createOutArgs();
223 inArgs.set_x(xTilde_);
224 if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(ts);
225 if (inArgs.supports(MEB::IN_ARG_x_dot))
226 inArgs.set_x_dot(Teuchos::null);
227 outArgs.set_f(stageXDot_[i]);
228
229 this->wrapperModel_->getAppModel()->evalModel(inArgs, outArgs);
230 }
231 }
232 else {
233 // Implicit stage for the ImplicitODE_DAE
234 const Scalar alpha = 1.0 / (dt * A(i, i));
235 const Scalar beta = 1.0;
236
237 // Setup TimeDerivative
238 Teuchos::RCP<TimeDerivative<Scalar> > timeDer = Teuchos::rcp(
239 new StepperDIRKTimeDerivative<Scalar>(alpha, xTilde_.getConst()));
240
241 auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
242 timeDer, dt, alpha, beta, SOLVE_FOR_X, i));
243
244 this->stepperRKAppAction_->execute(
245 solutionHistory, thisStepper,
247
248 sStatus =
249 this->solveImplicitODE(workingState->getX(), stageXDot_[i], ts, p);
250
251 if (sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) pass = false;
252
253 this->stepperRKAppAction_->execute(
254 solutionHistory, thisStepper,
256
257 timeDer->compute(workingState->getX(), stageXDot_[i]);
258 }
259 this->stepperRKAppAction_->execute(
260 solutionHistory, thisStepper,
262 this->stepperRKAppAction_->execute(
263 solutionHistory, thisStepper,
265 }
266 // reset the stage number
267 this->setStageNumber(-1);
268
269 // Sum for solution: x_n = x_n-1 + Sum{ dt*b(i) * f(i) }
270 Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
271 for (int i = 0; i < numStages; ++i) {
272 if (b(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
273 Thyra::Vp_StV((workingState->getX()).ptr(), dt * b(i),
274 *(stageXDot_[i]));
275 }
276 }
277
278 if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
279 const Scalar tolRel = workingState->getTolRel();
280 const Scalar tolAbs = workingState->getTolAbs();
281
282 // update the tolerance
283 this->stepperErrorNormCalculator_->setRelativeTolerance(tolRel);
284 this->stepperErrorNormCalculator_->setAbsoluteTolerance(tolAbs);
285
286 // just compute the error weight vector
287 // (all that is needed is the error, and not the embedded solution)
288 Teuchos::SerialDenseVector<int, Scalar> errWght = b;
289 errWght -= this->tableau_->bstar();
290
291 // compute local truncation error estimate: | u^{n+1} - \hat{u}^{n+1} |
292 // Sum for solution: ee_n = Sum{ (b(i) - bstar(i)) * dt*f(i) }
293 assign(this->ee_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
294 for (int i = 0; i < numStages; ++i) {
295 if (errWght(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
296 Thyra::Vp_StV(this->ee_.ptr(), dt * errWght(i), *(stageXDot_[i]));
297 }
298 }
299
300 Scalar err = this->stepperErrorNormCalculator_->computeWRMSNorm(
301 currentState->getX(), workingState->getX(), this->ee_);
302 workingState->setErrorRel(err);
303
304 // test if step should be rejected
305 if (std::isinf(err) || std::isnan(err) || err > Teuchos::as<Scalar>(1.0))
306 pass = false;
307 }
308
309 if (pass)
310 workingState->setSolutionStatus(Status::PASSED);
311 else
312 workingState->setSolutionStatus(Status::FAILED);
313
314 workingState->setOrder(this->getOrder());
315 workingState->computeNorms(currentState);
316 this->stepperRKAppAction_->execute(
317 solutionHistory, thisStepper,
319 }
320 return;
321}
322
329template <class Scalar>
330Teuchos::RCP<Tempus::StepperState<Scalar> >
332{
333 Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
334 rcp(new StepperState<Scalar>(this->getStepperType()));
335 return stepperState;
336}
337
338template <class Scalar>
340 Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
341{
342 out.setOutputToRootOnly(0);
343 out << std::endl;
344 Stepper<Scalar>::describe(out, verbLevel);
345 StepperImplicit<Scalar>::describe(out, verbLevel);
346
347 out << "--- StepperDIRK ---\n";
348 out << " tableau_ = " << this->tableau_ << std::endl;
349 if (this->tableau_ != Teuchos::null) this->tableau_->describe(out, verbLevel);
350 out << " stepperRKAppAction_ = " << this->stepperRKAppAction_ << std::endl;
351 out << " xTilde_ = " << xTilde_ << std::endl;
352 out << " stageXDot_.size() = " << stageXDot_.size() << std::endl;
353 const int numStages = stageXDot_.size();
354 for (int i = 0; i < numStages; ++i)
355 out << " stageXDot_[" << i << "] = " << stageXDot_[i] << std::endl;
356 out << " useEmbedded_ = " << Teuchos::toString(this->useEmbedded_)
357 << std::endl;
358 out << " ee_ = " << this->ee_ << std::endl;
359 out << " abs_u0 = " << this->abs_u0 << std::endl;
360 out << " abs_u = " << this->abs_u << std::endl;
361 out << " sc = " << this->sc << std::endl;
362 out << "-------------------" << std::endl;
363}
364
365template <class Scalar>
366bool StepperDIRK<Scalar>::isValidSetup(Teuchos::FancyOStream& out) const
367{
368 out.setOutputToRootOnly(0);
369 bool isValidSetup = true;
370
373
374 if (this->tableau_ == Teuchos::null) {
375 isValidSetup = false;
376 out << "The tableau is not set!\n";
377 }
378
379 if (this->stepperRKAppAction_ == Teuchos::null) {
380 isValidSetup = false;
381 out << "The AppAction is not set!\n";
382 }
383
384 return isValidSetup;
385}
386
387template <class Scalar>
388Teuchos::RCP<const Teuchos::ParameterList>
393
394} // namespace Tempus
395#endif // Tempus_StepperDIRK_impl_hpp
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void initialize() override
Initialize after construction and changing input parameters.
Teuchos::RCP< Thyra::VectorBase< Scalar > > xTilde_
virtual void setupDefault()
Default setup for constructor.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const override
virtual bool getResetInitialGuess() const
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Take the specified timestep, dt, and return true if successful.
virtual std::string getDescription() const =0
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicDIRK() const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const override
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const override
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel) override
Set the model.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState() override
Get a default (initial) StepperState.
virtual void setup(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &wrapperModel, const Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > &solver, bool useFSAL, std::string ICConsistency, bool ICConsistencyCheck, bool useEmbedded, bool zeroInitialGuess, const Teuchos::RCP< StepperRKAppAction< Scalar > > &stepperRKAppAction)
Setup for constructor.
virtual void setEmbeddedMemory() override
std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar > > > stageXDot_
Time-derivative interface for DIRK.
bool isInitialized_
True if stepper's member data is initialized.
void setICConsistencyCheck(bool c)
virtual void setStepperXDot(Teuchos::RCP< Thyra::VectorBase< Scalar > > xDot)
Set xDot for Stepper storage.
virtual void initialize()
Initialize after construction and changing input parameters.
std::string getStepperType() const
Get the stepper type. The stepper type is used as an identifier for the stepper, and can only be set ...
virtual void setUseFSAL(bool a)
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void checkInitialized()
Check initialization, and error out on failure.
void setICConsistency(std::string s)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory) override
Set the initial conditions and make them consistent.
Teuchos::RCP< WrapperModelEvaluator< Scalar > > wrapperModel_
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicImplicit() const
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel() const override
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar > > solver) override
Set solver.
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.
virtual void setZeroInitialGuess(bool zIG)
Application Action for StepperRKBase.
@ BEGIN_STEP
At the beginning of the step.
@ BEFORE_SOLVE
Before the implicit solve.
@ BEFORE_EXPLICIT_EVAL
Before the explicit evaluation.
@ AFTER_SOLVE
After the implicit solve.
@ BEGIN_STAGE
At the beginning of the stage.
@ END_STAGE
At the end of the stage.
Teuchos::RCP< Thyra::VectorBase< Scalar > > ee_
virtual void setStageNumber(int s)
Teuchos::RCP< Thyra::VectorBase< Scalar > > abs_u0
Teuchos::RCP< StepperRKAppAction< Scalar > > stepperRKAppAction_
virtual void setUseEmbedded(bool a)
Teuchos::RCP< Thyra::VectorBase< Scalar > > sc
virtual void setErrorNorm(const Teuchos::RCP< Stepper_ErrorNorm< Scalar > > &errCalculator=Teuchos::null)
virtual Scalar getOrder() const
virtual void setAppAction(Teuchos::RCP< StepperRKAppAction< Scalar > > appAction)
virtual bool getUseEmbedded() const
Teuchos::RCP< Thyra::VectorBase< Scalar > > abs_u
Teuchos::RCP< Stepper_ErrorNorm< Scalar > > stepperErrorNormCalculator_
Teuchos::RCP< RKButcherTableau< Scalar > > tableau_
StepperState is a simple class to hold state information about the stepper.
@ SOLVE_FOR_X
Solve for x and determine xDot from x.