Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_StepperDIRK_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_StepperDIRK_impl_hpp
10 #define Tempus_StepperDIRK_impl_hpp
11 
12 #include "Thyra_VectorStdOps.hpp"
13 
14 #include "Tempus_WrapperModelEvaluatorBasic.hpp"
15 
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22 {
23  this->setUseEmbedded( false);
24  this->setZeroInitialGuess( false);
25  this->setStageNumber(-1);
26 
27  this->setAppAction(Teuchos::null);
28  this->setDefaultSolver();
29 }
30 
31 
32 template<class Scalar>
34  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
36  bool useFSAL,
37  std::string ICConsistency,
38  bool ICConsistencyCheck,
39  bool useEmbedded,
40  bool zeroInitialGuess,
41  const Teuchos::RCP<StepperRKAppAction<Scalar> >& stepperRKAppAction)
42 {
43  this->setUseFSAL( useFSAL);
44  this->setICConsistency( ICConsistency);
45  this->setICConsistencyCheck( ICConsistencyCheck);
46  this->setUseEmbedded( useEmbedded);
47  this->setZeroInitialGuess( zeroInitialGuess);
48 
49  this->setStageNumber(-1);
50  this->setAppAction(stepperRKAppAction);
51  this->setSolver(solver);
52 
53  if (appModel != Teuchos::null) {
54  this->setModel(appModel);
55  this->initialize();
56  }
57 }
58 
59 
60 template<class Scalar>
63 {
64  auto pl = this->getValidParametersBasicImplicit();
65  pl->template set<bool>("Use Embedded", this->getUseEmbedded(),
66  "'Whether to use Embedded Stepper (if available) or not\n"
67  " 'true' - Stepper will compute embedded solution and is adaptive.\n"
68  " 'false' - Stepper is not embedded(adaptive).\n");
69  pl->template set<std::string>("Description", this->getDescription());
70  pl->template set<bool>("Reset Initial Guess", this->getResetInitialGuess());
71 
72  return pl;
73 }
74 
75 
76 template<class Scalar>
78 {
79  // Initialize the stage vectors
80  const int numStages = this->tableau_->numStages();
81  stageXDot_.resize(numStages);
82  for (int i=0; i<numStages; ++i) {
83  stageXDot_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
84  assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
85  }
86  xTilde_ = Thyra::createMember(this->wrapperModel_->get_x_space());
87  assign(xTilde_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
88 
89  if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
90  this->ee_ = Thyra::createMember(this->wrapperModel_->get_f_space());
91  this->abs_u0 = Thyra::createMember(this->wrapperModel_->get_f_space());
92  this->abs_u = Thyra::createMember(this->wrapperModel_->get_f_space());
93  this->sc = Thyra::createMember(this->wrapperModel_->get_f_space());
94  }
95 
97 }
98 
99 
100 template<class Scalar>
102  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
103 {
104  this->setStepperXDot(stageXDot_.back());
106 }
107 
108 
109 template<class Scalar>
111  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
112 {
113  this->checkInitialized();
114 
115  using Teuchos::RCP;
116 
117  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperDIRK::takeStep()");
118  {
119  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
120  std::logic_error,
121  "Error - StepperDIRK<Scalar>::takeStep(...)\n"
122  "Need at least two SolutionStates for DIRK.\n"
123  " Number of States = " << solutionHistory->getNumStates() << "\n"
124  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
125  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
126 
127  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
128  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
129  const Scalar dt = workingState->getTimeStep();
130  const Scalar time = currentState->getTime();
131 
132  const int numStages = this->tableau_->numStages();
133  Teuchos::SerialDenseMatrix<int,Scalar> A = this->tableau_->A();
134  Teuchos::SerialDenseVector<int,Scalar> b = this->tableau_->b();
135  Teuchos::SerialDenseVector<int,Scalar> c = this->tableau_->c();
136 
137  // Reset non-zero initial guess.
138  if ( this->getResetInitialGuess() && (!this->getZeroInitialGuess()) )
139  Thyra::assign(workingState->getX().ptr(), *(currentState->getX()));
140 
141  RCP<StepperDIRK<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
142  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
144 
145  // Compute stage solutions
146  bool pass = true;
148  for (int i=0; i < numStages; ++i) {
149  this->setStageNumber(i);
150 
151  Thyra::assign(xTilde_.ptr(), *(currentState->getX()));
152  for (int j=0; j < i; ++j) {
153  if (A(i,j) != Teuchos::ScalarTraits<Scalar>::zero()) {
154  Thyra::Vp_StV(xTilde_.ptr(), dt*A(i,j), *(stageXDot_[j]));
155  }
156  }
157  this->setStepperXDot(stageXDot_[i]);
158 
159  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
161 
162  Scalar ts = time + c(i)*dt;
163 
164  // Check if stageXDot_[i] is needed.
165  bool isNeeded = false;
166  for (int k=i+1; k<numStages; ++k) if (A(k,i) != 0.0) isNeeded = true;
167  if (b(i) != 0.0) isNeeded = true;
168  if (this->tableau_->isEmbedded() && this->getUseEmbedded() &&
169  this->tableau_->bstar()(i) != 0.0)
170  isNeeded = true;
171  if (isNeeded == false) {
172  assign(stageXDot_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
173  } else if (A(i,i) == Teuchos::ScalarTraits<Scalar>::zero()) {
174  // Explicit stage for the ImplicitODE_DAE
175  if (i == 0 && this->getUseFSAL() &&
176  workingState->getNConsecutiveFailures() == 0) {
177  // Reuse last evaluation for first step
178  RCP<Thyra::VectorBase<Scalar> > tmp = stageXDot_[0];
179  stageXDot_[0] = stageXDot_.back();
180  stageXDot_.back() = tmp;
181  this->setStepperXDot(stageXDot_[0]);
182  } else {
183  // Calculate explicit stage
184  typedef Thyra::ModelEvaluatorBase MEB;
185  MEB::InArgs<Scalar> inArgs = this->wrapperModel_->getInArgs();
186  MEB::OutArgs<Scalar> outArgs = this->wrapperModel_->getOutArgs();
187  inArgs.set_x(xTilde_);
188  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(ts);
189  if (inArgs.supports(MEB::IN_ARG_x_dot))
190  inArgs.set_x_dot(Teuchos::null);
191  outArgs.set_f(stageXDot_[i]);
192 
193  this->wrapperModel_->getAppModel()->evalModel(inArgs,outArgs);
194  }
195  } else {
196  // Implicit stage for the ImplicitODE_DAE
197  const Scalar alpha = 1.0/(dt*A(i,i));
198  const Scalar beta = 1.0;
199 
200  // Setup TimeDerivative
203  alpha,xTilde_.getConst()));
204 
206  timeDer, dt, alpha, beta, SOLVE_FOR_X, i));
207 
208  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
210 
211  sStatus = this->solveImplicitODE(workingState->getX(), stageXDot_[i], ts, p);
212 
213  if (sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) pass=false;
214 
215  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
217 
218  timeDer->compute(workingState->getX(), stageXDot_[i]);
219  }
220  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
222  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
224  }
225  // reset the stage number
226  this->setStageNumber(-1);
227 
228  // Sum for solution: x_n = x_n-1 + Sum{ dt*b(i) * f(i) }
229  Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
230  for (int i=0; i < numStages; ++i) {
231  if (b(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
232  Thyra::Vp_StV((workingState->getX()).ptr(), dt*b(i), *(stageXDot_[i]));
233  }
234  }
235 
236  if (this->tableau_->isEmbedded() && this->getUseEmbedded()) {
237  const Scalar tolRel = workingState->getTolRel();
238  const Scalar tolAbs = workingState->getTolAbs();
239 
240  // just compute the error weight vector
241  // (all that is needed is the error, and not the embedded solution)
243  errWght -= this->tableau_->bstar();
244 
245  // compute local truncation error estimate: | u^{n+1} - \hat{u}^{n+1} |
246  // Sum for solution: ee_n = Sum{ (b(i) - bstar(i)) * dt*f(i) }
247  assign(this->ee_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
248  for (int i=0; i < numStages; ++i) {
249  if (errWght(i) != Teuchos::ScalarTraits<Scalar>::zero()) {
250  Thyra::Vp_StV(this->ee_.ptr(), dt*errWght(i), *(stageXDot_[i]));
251  }
252  }
253 
254  // compute: Atol + max(|u^n|, |u^{n+1}| ) * Rtol
255  Thyra::abs( *(currentState->getX()), this->abs_u0.ptr());
256  Thyra::abs( *(workingState->getX()), this->abs_u.ptr());
257  Thyra::pair_wise_max_update(tolRel, *this->abs_u0, this->abs_u.ptr());
258  Thyra::add_scalar(tolAbs, this->abs_u.ptr());
259 
260  // compute: || ee / sc ||
261  assign(this->sc.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
262  Thyra::ele_wise_divide(Teuchos::as<Scalar>(1.0), *this->ee_, *this->abs_u, this->sc.ptr());
263  const auto space_dim = this->ee_->space()->dim();
264  Scalar err = std::abs(Thyra::norm(*this->sc)) / space_dim ;
265  workingState->setErrorRel(err);
266 
267  // test if step should be rejected
268  if (std::isinf(err) || std::isnan(err) || err > Teuchos::as<Scalar>(1.0))
269  pass = false;
270  }
271 
272  if (pass) workingState->setSolutionStatus(Status::PASSED);
273  else workingState->setSolutionStatus(Status::FAILED);
274 
275  workingState->setOrder(this->getOrder());
276  workingState->computeNorms(currentState);
277  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
279  }
280  return;
281 }
282 
289 template<class Scalar>
293 {
295  rcp(new StepperState<Scalar>(this->getStepperType()));
296  return stepperState;
297 }
298 
299 
300 template<class Scalar>
303  const Teuchos::EVerbosityLevel verbLevel) const
304 {
305  out << std::endl;
306  Stepper<Scalar>::describe(out, verbLevel);
307  StepperImplicit<Scalar>::describe(out, verbLevel);
308 
309  out << "--- StepperDIRK ---\n";
310  out << " tableau_ = " << this->tableau_ << std::endl;
311  if (this->tableau_ != Teuchos::null) this->tableau_->describe(out, verbLevel);
312  out << " stepperRKAppAction_ = " << this->stepperRKAppAction_ << std::endl;
313  out << " xTilde_ = " << xTilde_ << std::endl;
314  out << " stageXDot_.size() = " << stageXDot_.size() << std::endl;
315  const int numStages = stageXDot_.size();
316  for (int i=0; i<numStages; ++i)
317  out << " stageXDot_["<<i<<"] = " << stageXDot_[i] << std::endl;
318  out << " useEmbedded_ = "
319  << Teuchos::toString(this->useEmbedded_) << std::endl;
320  out << " ee_ = " << this->ee_ << std::endl;
321  out << " abs_u0 = " << this->abs_u0 << std::endl;
322  out << " abs_u = " << this->abs_u << std::endl;
323  out << " sc = " << this->sc << std::endl;
324  out << "-------------------" << std::endl;
325 }
326 
327 
328 template<class Scalar>
330 {
331  bool isValidSetup = true;
332 
333  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
334  if ( !StepperImplicit<Scalar>::isValidSetup(out) ) isValidSetup = false;
335 
336  if (this->tableau_ == Teuchos::null) {
337  isValidSetup = false;
338  out << "The tableau is not set!\n";
339  }
340 
341  if (this->stepperRKAppAction_ == Teuchos::null) {
342  isValidSetup = false;
343  out << "The AppAction is not set!\n";
344  }
345 
346  return isValidSetup;
347 }
348 
349 
350 template<class Scalar>
353 {
354  return this->getValidParametersBasicDIRK();
355 }
356 
357 
358 } // namespace Tempus
359 #endif // Tempus_StepperDIRK_impl_hpp
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Teuchos::RCP< Teuchos::ParameterList > getValidParametersBasicDIRK() const
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void initialize()
Initialize after construction and changing input parameters.
Thyra Base interface for time steppers.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
StepperState is a simple class to hold state information about the stepper.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Thyra Base interface for implicit time steppers.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Application Action for StepperRKBase.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual void initialize()
Initialize after construction and changing input parameters.
Time-derivative interface for DIRK.
virtual void setupDefault()
Default setup for constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
ESolveStatus solveStatus
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
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.
Solve for x and determine xDot from x.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
std::string toString(const T &t)