Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperIMEX_RK_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_StepperIMEX_RK_impl_hpp
10 #define Tempus_StepperIMEX_RK_impl_hpp
11 
12 #include "Tempus_config.hpp"
14 #include "Tempus_WrapperModelEvaluatorPairIMEX_Basic.hpp"
15 #include "Teuchos_VerboseObjectParameterListHelpers.hpp"
16 #include "Thyra_VectorStdOps.hpp"
17 #include "NOX_Thyra.H"
18 
19 
20 namespace Tempus {
21 
22 // Forward Declaration for recursive includes (this Stepper <--> StepperFactory)
23 template<class Scalar> class StepperFactory;
24 
25 
26 template<class Scalar>
28 {
29  this->setStepperType( "IMEX RK SSP2");
30  this->setUseFSAL( this->getUseFSALDefault());
31  this->setICConsistency( this->getICConsistencyDefault());
32  this->setICConsistencyCheck( this->getICConsistencyCheckDefault());
33  this->setZeroInitialGuess( false);
34 
35  this->setTableaus("IMEX RK SSP2");
36  this->setObserver();
37 }
38 
39 
40 template<class Scalar>
42  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
43  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
44  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
45  bool useFSAL,
46  std::string ICConsistency,
47  bool ICConsistencyCheck,
48  bool zeroInitialGuess,
49  std::string stepperType,
50  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
51  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau,
52  Scalar order)
53 {
54  this->setStepperType( stepperType);
55  this->setUseFSAL( useFSAL);
56  this->setICConsistency( ICConsistency);
57  this->setICConsistencyCheck( ICConsistencyCheck);
58  this->setZeroInitialGuess( zeroInitialGuess);
59 
60  this->setExplicitTableau(explicitTableau);
61  this->setImplicitTableau(implicitTableau);
62  this->setOrder(order);
63  this->setObserver(obs);
64 
65  if (appModel != Teuchos::null) {
66 
67  this->setModel(appModel);
68  this->setSolver(solver);
69  this->initialize();
70  }
71 }
72 
73 
74 template<class Scalar>
75 void StepperIMEX_RK<Scalar>::setTableaus(std::string stepperType,
76  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
77  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
78 {
79  if (stepperType == "") stepperType = "IMEX RK SSP2";
80 
81  if (stepperType == "IMEX RK 1st order") {
82  {
83  // Explicit Tableau
84  typedef Teuchos::ScalarTraits<Scalar> ST;
85  int NumStages = 2;
86  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
87  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
88  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
89  const Scalar one = ST::one();
90  const Scalar zero = ST::zero();
91 
92  // Fill A:
93  A(0,0) = zero; A(0,1) = zero;
94  A(1,0) = one; A(1,1) = zero;
95 
96  // Fill b:
97  b(0) = one; b(1) = zero;
98 
99  // Fill c:
100  c(0) = zero; c(1) = one;
101 
102  int order = 1;
103 
104  auto explicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
105  "Explicit Tableau - IMEX RK 1st order",
106  A,b,c,order,order,order));
107 
108  this->setExplicitTableau(explicitTableau);
109  }
110  {
111  // Implicit Tableau
112  typedef Teuchos::ScalarTraits<Scalar> ST;
113  int NumStages = 2;
114  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
115  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
116  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
117  const Scalar one = ST::one();
118  const Scalar zero = ST::zero();
119 
120  // Fill A:
121  A(0,0) = zero; A(0,1) = zero;
122  A(1,0) = zero; A(1,1) = one;
123 
124  // Fill b:
125  b(0) = zero; b(1) = one;
126 
127  // Fill c:
128  c(0) = zero; c(1) = one;
129 
130  int order = 1;
131 
132  auto implicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
133  "Implicit Tableau - IMEX RK 1st order",
134  A,b,c,order,order,order));
135 
136  this->setImplicitTableau(implicitTableau);
137  }
138  this->setStepperType("IMEX RK 1st order");
139  this->setOrder(1);
140 
141  } else if (stepperType == "IMEX RK SSP2") {
142  // Explicit Tableau
143  auto stepperERK = Teuchos::rcp(new StepperERK_Trapezoidal<Scalar>());
144  this->setExplicitTableau(stepperERK->getTableau());
145 
146  // Implicit Tableau
147  auto stepperSDIRK = Teuchos::rcp(new StepperSDIRK_2Stage3rdOrder<Scalar>());
148  stepperSDIRK->setGammaType("2nd Order L-stable");
149  this->setImplicitTableau(stepperSDIRK->getTableau());
150 
151  this->setStepperType("IMEX RK SSP2");
152  this->setOrder(2);
153  } else if (stepperType == "IMEX RK ARS 233") {
154  typedef Teuchos::ScalarTraits<Scalar> ST;
155  int NumStages = 3;
156  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
157  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
158  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
159  const Scalar one = ST::one();
160  const Scalar zero = ST::zero();
161  const Scalar onehalf = ST::one()/(2*ST::one());
162  const Scalar gamma = (3*one+ST::squareroot(3*one))/(6*one);
163  {
164  // Explicit Tableau
165  // Fill A:
166  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
167  A(1,0) = gamma; A(1,1) = zero; A(1,2) = zero;
168  A(2,0) = (gamma-1.0); A(2,1) = (2.0-2.0*gamma); A(2,2) = zero;
169 
170  // Fill b:
171  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
172 
173  // Fill c:
174  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
175 
176  int order = 2;
177 
178  auto explicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
179  "Partition IMEX-RK Explicit Stepper",A,b,c,order,order,order));
180 
181  this->setExplicitTableau(explicitTableau);
182  }
183  {
184  // Implicit Tableau
185  // Fill A:
186  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
187  A(1,0) = zero; A(1,1) = gamma; A(1,2) = zero;
188  A(2,0) = zero; A(2,1) = (1.0-2.0*gamma); A(2,2) = gamma;
189 
190  // Fill b:
191  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
192 
193  // Fill c:
194  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
195 
196  int order = 3;
197 
198  auto implicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
199  "Partition IMEX-RK Implicit Stepper",A,b,c,order,order,order));
200 
201  this->setImplicitTableau(implicitTableau);
202  }
203  this->setStepperType("IMEX RK ARS 233");
204  this->setOrder(3);
205 
206  } else if (stepperType == "General IMEX RK") {
207  this->setExplicitTableau(explicitTableau);
208  this->setImplicitTableau(implicitTableau);
209  this->setStepperType("General IMEX RK");
210  this->setOrder(1);
211 
212  } else {
213  TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error,
214  "Error - Not a valid StepperIMEX_RK type! Stepper Type = "
215  << stepperType << "\n"
216  << " Current valid types are: " << "\n"
217  << " 'IMEX RK 1st order'" << "\n"
218  << " 'IMEX RK SSP2'" << "\n"
219  << " 'IMEX RK ARS 233'" << "\n"
220  << " 'General IMEX RK'" << "\n");
221  }
222 
223  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau_==Teuchos::null,
224  std::runtime_error,
225  "Error - StepperIMEX_RK - Explicit tableau is null!");
226  TEUCHOS_TEST_FOR_EXCEPTION(implicitTableau_==Teuchos::null,
227  std::runtime_error,
228  "Error - StepperIMEX_RK - Implicit tableau is null!");
229  TEUCHOS_TEST_FOR_EXCEPTION(
230  explicitTableau_->numStages()!=implicitTableau_->numStages(),
231  std::runtime_error,
232  "Error - StepperIMEX_RK - Number of stages do not match!\n"
233  << " Explicit tableau = " << explicitTableau_->description() << "\n"
234  << " number of stages = " << explicitTableau_->numStages() << "\n"
235  << " Implicit tableau = " << implicitTableau_->description() << "\n"
236  << " number of stages = " << implicitTableau_->numStages() << "\n");
237 }
238 
239 
240 template<class Scalar>
242  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau)
243 {
244  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau->isImplicit() == true,
245  std::logic_error,
246  "Error - Received an implicit Tableau for setExplicitTableau()!\n" <<
247  " Tableau = " << explicitTableau->description() << "\n");
248  explicitTableau_ = explicitTableau;
249 }
250 
251 
252 template<class Scalar>
254  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
255 {
256  TEUCHOS_TEST_FOR_EXCEPTION( implicitTableau->isDIRK() != true,
257  std::logic_error,
258  "Error - Did not receive a DIRK Tableau for setImplicitTableau()!\n" <<
259  " Tableau = " << implicitTableau->description() << "\n");
260  implicitTableau_ = implicitTableau;
261 }
262 
263 template<class Scalar>
265  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
266 {
267  using Teuchos::RCP;
268  using Teuchos::rcp_const_cast;
269  using Teuchos::rcp_dynamic_cast;
270  RCP<Thyra::ModelEvaluator<Scalar> > ncModel =
271  rcp_const_cast<Thyra::ModelEvaluator<Scalar> > (appModel);
272  RCP<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > modelPairIMEX =
273  rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > (ncModel);
274  TEUCHOS_TEST_FOR_EXCEPTION( modelPairIMEX == Teuchos::null, std::logic_error,
275  "Error - StepperIMEX_RK::setModel() was given a ModelEvaluator that\n"
276  " could not be cast to a WrapperModelEvaluatorPairIMEX_Basic!\n"
277  " From: " << appModel << "\n"
278  " To : " << modelPairIMEX << "\n"
279  " Likely have given the wrong ModelEvaluator to this Stepper.\n");
280 
281  setModelPair(modelPairIMEX);
282 }
283 
284 
285 /** \brief Create WrapperModelPairIMEX from user-supplied ModelEvaluator pair.
286  *
287  * The user-supplied ME pair can contain any user-specific IMEX interactions
288  * between explicit and implicit MEs.
289  */
290 template<class Scalar>
292  const Teuchos::RCP<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > &
293  modelPairIMEX)
294 {
295  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
296  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
297  this->wrapperModel_);
298  validExplicitODE (modelPairIMEX->getExplicitModel());
299  validImplicitODE_DAE(modelPairIMEX->getImplicitModel());
300  wrapperModelPairIMEX = modelPairIMEX;
301  wrapperModelPairIMEX->initialize();
302  int expXDim = wrapperModelPairIMEX->getExplicitModel()->get_x_space()->dim();
303  int impXDim = wrapperModelPairIMEX->getImplicitModel()->get_x_space()->dim();
304  TEUCHOS_TEST_FOR_EXCEPTION( expXDim != impXDim, std::logic_error,
305  "Error - \n"
306  " Explicit and Implicit x vectors are incompatible!\n"
307  " Explicit vector dim = " << expXDim << "\n"
308  " Implicit vector dim = " << impXDim << "\n");
309 
310  this->wrapperModel_ = wrapperModelPairIMEX;
311 }
312 
313 /** \brief Create WrapperModelPairIMEX from explicit/implicit ModelEvaluators.
314  *
315  * Use the supplied explicit/implicit MEs to create a WrapperModelPairIMEX
316  * with basic IMEX interactions between explicit and implicit MEs.
317  */
318 template<class Scalar>
320  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& explicitModel,
321  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& implicitModel)
322 {
323  validExplicitODE (explicitModel);
324  validImplicitODE_DAE(implicitModel);
325  this->wrapperModel_ = Teuchos::rcp(
327  explicitModel, implicitModel));
328 }
329 
330 
331 template<class Scalar>
333  Teuchos::RCP<StepperObserver<Scalar> > obs)
334 {
335 
336  if (this->stepperObserver_ == Teuchos::null)
337  this->stepperObserver_ =
338  Teuchos::rcp(new StepperRKObserverComposite<Scalar>());
339 
340  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() >0 ) )
341  return;
342 
343  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() == 0) )
344  obs = Teuchos::rcp(new StepperRKObserver<Scalar>());
345 
346  // Check that this casts to prevent a runtime error if it doesn't
347  if (Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs) != Teuchos::null) {
348  this->stepperObserver_->addObserver(
349  Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs, true) );
350  } else {
351  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
352  Teuchos::OSTab ostab(out,0,"setObserver");
353  *out << "Tempus::StepperIMEX_RK::setObserver: Warning: An observer has been provided that";
354  *out << " does not support Tempus::StepperRKObserver. This observer WILL NOT be added.";
355  *out << " In the future, this will result in a runtime error!" << std::endl;
356  }
357 
358 
359 }
360 
361 
362 template<class Scalar>
364 {
365  TEUCHOS_TEST_FOR_EXCEPTION(
366  (explicitTableau_ == Teuchos::null) || (implicitTableau_ == Teuchos::null),
367  std::logic_error,
368  "Error - Need to set the Butcher Tableaus, setTableaus(), before calling "
369  "StepperIMEX_RK::initialize()\n");
370 
371  TEUCHOS_TEST_FOR_EXCEPTION( this->wrapperModel_ == Teuchos::null,
372  std::logic_error,
373  "Error - Need to set the model, setModel(), before calling "
374  "StepperIMEX_RK::initialize()\n");
375 
376  // Initialize the stage vectors
377  const int numStages = explicitTableau_->numStages();
378  stageF_.resize(numStages);
379  stageG_.resize(numStages);
380  for(int i=0; i < numStages; i++) {
381  stageF_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
382  stageG_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
383  assign(stageF_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
384  assign(stageG_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
385  }
386 
387  xTilde_ = Thyra::createMember(this->wrapperModel_->get_x_space());
388  assign(xTilde_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
389 }
390 
391 
392 template<class Scalar>
394  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
395 {
396  using Teuchos::RCP;
397 
398  int numStates = solutionHistory->getNumStates();
399 
400  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
401  "Error - setInitialConditions() needs at least one SolutionState\n"
402  " to set the initial condition. Number of States = " << numStates);
403 
404  if (numStates > 1) {
405  RCP<Teuchos::FancyOStream> out = this->getOStream();
406  Teuchos::OSTab ostab(out,1,"StepperIMEX_RK::setInitialConditions()");
407  *out << "Warning -- SolutionHistory has more than one state!\n"
408  << "Setting the initial conditions on the currentState.\n"<<std::endl;
409  }
410 
411  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
412  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
413 
414  // Use x from inArgs as ICs, if needed.
415  auto inArgs = this->wrapperModel_->getNominalValues();
416  if (x == Teuchos::null) {
417  TEUCHOS_TEST_FOR_EXCEPTION( (x == Teuchos::null) &&
418  (inArgs.get_x() == Teuchos::null), std::logic_error,
419  "Error - setInitialConditions() needs the ICs from the SolutionHistory\n"
420  " or getNominalValues()!\n");
421 
422  x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
423  initialState->setX(x);
424  }
425 
426  // Perform IC Consistency
427  std::string icConsistency = this->getICConsistency();
428  TEUCHOS_TEST_FOR_EXCEPTION(icConsistency != "None", std::logic_error,
429  "Error - setInitialConditions() requested a consistency of '"
430  << icConsistency << "'.\n"
431  " But only 'None' is available for IMEX-RK!\n");
432 
433  TEUCHOS_TEST_FOR_EXCEPTION( this->getUseFSAL(), std::logic_error,
434  "Error - The First-Step-As-Last (FSAL) principle is not "
435  << "available for IMEX-RK. Set useFSAL=false.\n");
436 }
437 
438 
439 template <typename Scalar>
441  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & X,
442  Scalar time, Scalar stepSize, Scalar stageNumber,
443  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & G) const
444 {
445  typedef Thyra::ModelEvaluatorBase MEB;
446  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
447  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
448  this->wrapperModel_);
449  MEB::InArgs<Scalar> inArgs = wrapperModelPairIMEX->getInArgs();
450  inArgs.set_x(X);
451  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
452  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
453  if (inArgs.supports(MEB::IN_ARG_stage_number))
454  inArgs.set_stage_number(stageNumber);
455 
456  // For model evaluators whose state function f(x, x_dot, t) describes
457  // an implicit ODE, and which accept an optional x_dot input argument,
458  // make sure the latter is set to null in order to request the evaluation
459  // of a state function corresponding to the explicit ODE formulation
460  // x_dot = f(x, t)
461  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
462 
463  MEB::OutArgs<Scalar> outArgs = wrapperModelPairIMEX->getOutArgs();
464  outArgs.set_f(G);
465 
466  wrapperModelPairIMEX->getImplicitModel()->evalModel(inArgs,outArgs);
467  Thyra::Vt_S(G.ptr(), -1.0);
468 }
469 
470 
471 template <typename Scalar>
473  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & X,
474  Scalar time, Scalar stepSize, Scalar stageNumber,
475  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & F) const
476 {
477  typedef Thyra::ModelEvaluatorBase MEB;
478 
479  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
480  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
481  this->wrapperModel_);
482  MEB::InArgs<Scalar> inArgs =
483  wrapperModelPairIMEX->getExplicitModel()->createInArgs();
484  inArgs.set_x(X);
485  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
486  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
487  if (inArgs.supports(MEB::IN_ARG_stage_number))
488  inArgs.set_stage_number(stageNumber);
489 
490  // For model evaluators whose state function f(x, x_dot, t) describes
491  // an implicit ODE, and which accept an optional x_dot input argument,
492  // make sure the latter is set to null in order to request the evaluation
493  // of a state function corresponding to the explicit ODE formulation
494  // x_dot = f(x, t)
495  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
496 
497  MEB::OutArgs<Scalar> outArgs =
498  wrapperModelPairIMEX->getExplicitModel()->createOutArgs();
499  outArgs.set_f(F);
500 
501  wrapperModelPairIMEX->getExplicitModel()->evalModel(inArgs, outArgs);
502  Thyra::Vt_S(F.ptr(), -1.0);
503 }
504 
505 
506 template<class Scalar>
508  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
509 {
510  using Teuchos::RCP;
511  using Teuchos::SerialDenseMatrix;
512  using Teuchos::SerialDenseVector;
513 
514  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperIMEX_RK::takeStep()");
515  {
516  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
517  std::logic_error,
518  "Error - StepperIMEX_RK<Scalar>::takeStep(...)\n"
519  "Need at least two SolutionStates for IMEX_RK.\n"
520  " Number of States = " << solutionHistory->getNumStates() << "\n"
521  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
522  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
523 
524  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
525  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
526  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
527  const Scalar dt = workingState->getTimeStep();
528  const Scalar time = currentState->getTime();
529 
530  const int numStages = explicitTableau_->numStages();
531  const SerialDenseMatrix<int,Scalar> & AHat = explicitTableau_->A();
532  const SerialDenseVector<int,Scalar> & bHat = explicitTableau_->b();
533  const SerialDenseVector<int,Scalar> & cHat = explicitTableau_->c();
534  const SerialDenseMatrix<int,Scalar> & A = implicitTableau_->A();
535  const SerialDenseVector<int,Scalar> & b = implicitTableau_->b();
536  const SerialDenseVector<int,Scalar> & c = implicitTableau_->c();
537 
538  bool pass = true;
539  stageX_ = workingState->getX();
540  Thyra::assign(stageX_.ptr(), *(currentState->getX()));
541 
542  // Compute stage solutions
543  for (int i = 0; i < numStages; ++i) {
544  this->stepperObserver_->observeBeginStage(solutionHistory, *this);
545  Thyra::assign(xTilde_.ptr(), *(currentState->getX()));
546  for (int j = 0; j < i; ++j) {
547  if (AHat(i,j) != Teuchos::ScalarTraits<Scalar>::zero())
548  Thyra::Vp_StV(xTilde_.ptr(), -dt*AHat(i,j), *(stageF_[j]));
549  if (A (i,j) != Teuchos::ScalarTraits<Scalar>::zero())
550  Thyra::Vp_StV(xTilde_.ptr(), -dt*A (i,j), *(stageG_[j]));
551  }
552 
553  Scalar ts = time + c(i)*dt;
554  Scalar tHats = time + cHat(i)*dt;
555  if (A(i,i) == Teuchos::ScalarTraits<Scalar>::zero()) {
556  // Explicit stage for the ImplicitODE_DAE
557  bool isNeeded = false;
558  for (int k=i+1; k<numStages; ++k) if (A(k,i) != 0.0) isNeeded = true;
559  if (b(i) != 0.0) isNeeded = true;
560  if (isNeeded == false) {
561  // stageG_[i] is not needed.
562  assign(stageG_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
563  } else {
564  Thyra::assign(stageX_.ptr(), *xTilde_);
565  this->stepperObserver_->observeBeforeImplicitExplicitly(solutionHistory, *this);
566  evalImplicitModelExplicitly(stageX_, ts, dt, i, stageG_[i]);
567  }
568  } else {
569  // Implicit stage for the ImplicitODE_DAE
570  const Scalar alpha = Scalar(1.0)/(dt*A(i,i));
571  const Scalar beta = Scalar(1.0);
572 
573  // Setup TimeDerivative
574  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
575  Teuchos::rcp(new StepperIMEX_RKTimeDerivative<Scalar>(
576  alpha, xTilde_.getConst()));
577 
578  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
579  timeDer, dt, alpha, beta, SOLVE_FOR_X, i));
580 
581  this->stepperObserver_->observeBeforeSolve(solutionHistory, *this);
582 
583  const Thyra::SolveStatus<Scalar> sStatus =
584  this->solveImplicitODE(stageX_, stageG_[i], ts, p);
585 
586  if (sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) pass = false;
587 
588  this->stepperObserver_->observeAfterSolve(solutionHistory, *this);
589 
590  // Update contributions to stage values
591  Thyra::V_StVpStV(stageG_[i].ptr(), -alpha, *stageX_, alpha, *xTilde_);
592  }
593 
594  this->stepperObserver_->observeBeforeExplicit(solutionHistory, *this);
595  evalExplicitModel(stageX_, tHats, dt, i, stageF_[i]);
596  this->stepperObserver_->observeEndStage(solutionHistory, *this);
597  }
598 
599  // Sum for solution: x_n = x_n-1 - dt*Sum{ bHat(i)*f(i) + b(i)*g(i) }
600  Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
601  for (int i=0; i < numStages; ++i) {
602  if (bHat(i) != Teuchos::ScalarTraits<Scalar>::zero())
603  Thyra::Vp_StV((workingState->getX()).ptr(), -dt*bHat(i), *(stageF_[i]));
604  if (b (i) != Teuchos::ScalarTraits<Scalar>::zero())
605  Thyra::Vp_StV((workingState->getX()).ptr(), -dt*b (i), *(stageG_[i]));
606  }
607 
608  if (pass == true) workingState->setSolutionStatus(Status::PASSED);
609  else workingState->setSolutionStatus(Status::FAILED);
610  workingState->setOrder(this->getOrder());
611  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
612  }
613  return;
614 }
615 
616 /** \brief Provide a StepperState to the SolutionState.
617  * This Stepper does not have any special state data,
618  * so just provide the base class StepperState with the
619  * Stepper description. This can be checked to ensure
620  * that the input StepperState can be used by this Stepper.
621  */
622 template<class Scalar>
623 Teuchos::RCP<Tempus::StepperState<Scalar> >
626 {
627  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
628  rcp(new StepperState<Scalar>(this->getStepperType()));
629  return stepperState;
630 }
631 
632 
633 template<class Scalar>
635  Teuchos::FancyOStream &out,
636  const Teuchos::EVerbosityLevel /* verbLevel */) const
637 {
638  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
639  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
640  this->wrapperModel_);
641  out << this->getStepperType() << "::describe:" << std::endl
642  << "wrapperModelPairIMEX = " << wrapperModelPairIMEX->description()
643  << std::endl;
644 }
645 
646 
647 template<class Scalar>
648 Teuchos::RCP<const Teuchos::ParameterList>
650 {
651  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
652  getValidParametersBasic(pl, this->getStepperType());
653  pl->set<bool>("Initial Condition Consistency Check",
654  this->getICConsistencyCheckDefault());
655  pl->set<std::string>("Solver Name", "Default Solver");
656  pl->set<bool> ("Zero Initial Guess", false);
657  Teuchos::RCP<Teuchos::ParameterList> solverPL = defaultSolverParameters();
658  pl->set("Default Solver", *solverPL);
659 
660  return pl;
661 }
662 
663 
664 } // namespace Tempus
665 #endif // Tempus_StepperIMEX_RK_impl_hpp
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setImplicitTableau(Teuchos::RCP< const RKButcherTableau< Scalar > > implicitTableau)
Set the implicit tableau from tableau.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
ModelEvaluator pair for implicit and explicit (IMEX) evaulations.
virtual void setExplicitTableau(Teuchos::RCP< const RKButcherTableau< Scalar > > explicitTableau)
Set the explicit tableau from tableau.
ModelEvaluator pair for implicit and explicit (IMEX) evaluations.
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.
void validExplicitODE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate that the model supports explicit ODE evaluation, f(x,t) [=xdot].
virtual void setModelPair(const Teuchos::RCP< WrapperModelEvaluatorPairIMEX_Basic< Scalar > > &mePair)
Create WrapperModelPairIMEX from user-supplied ModelEvaluator pair.
StepperState is a simple class to hold state information about the stepper.
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getExplicitModel() const =0
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
StepperIMEX_RK()
Default constructor.
virtual void initialize()
Initialize during construction and after changing input parameters.
virtual Thyra::ModelEvaluatorBase::InArgs< Scalar > getInArgs()=0
Get InArgs the wrapper ModelEvalutor.
void evalExplicitModel(const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &X, Scalar time, Scalar stepSize, Scalar stageNumber, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &F) const
StepperObserver class for Stepper class.
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
virtual void setTableaus(std::string stepperType="", Teuchos::RCP< const RKButcherTableau< Scalar > > explicitTableau=Teuchos::null, Teuchos::RCP< const RKButcherTableau< Scalar > > implicitTableau=Teuchos::null)
Set both the explicit and implicit tableau from ParameterList.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
void evalImplicitModelExplicitly(const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &X, Scalar time, Scalar stepSize, Scalar stageNumber, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &G) const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Provide a StepperState to the SolutionState. This Stepper does not have any special state data...
StepperRKObserver class for StepperRK.
Time-derivative interface for IMEX RK.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
void validImplicitODE_DAE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate ME supports implicit ODE/DAE evaluation, f(xdot,x,t) [= 0].
Solve for x and determine xDot from x.
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.