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->setStageNumber(-1);
36 
37  this->setTableaus("IMEX RK SSP2");
38 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
39  this->setObserver();
40 #endif
41  this->setAppAction(Teuchos::null);
42  this->setDefaultSolver();
43 }
44 
45 
46 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
47 template<class Scalar>
49  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
50  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
51  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
52  bool useFSAL,
53  std::string ICConsistency,
54  bool ICConsistencyCheck,
55  bool zeroInitialGuess,
56  std::string stepperType,
57  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
58  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau,
59  Scalar order)
60 {
61  this->setStepperType( stepperType);
62  this->setUseFSAL( useFSAL);
63  this->setICConsistency( ICConsistency);
64  this->setICConsistencyCheck( ICConsistencyCheck);
65  this->setZeroInitialGuess( zeroInitialGuess);
66 
67  this->setStageNumber(-1);
68 
69  this->setExplicitTableau(explicitTableau);
70  this->setImplicitTableau(implicitTableau);
71  this->setOrder(order);
72  this->setObserver(obs);
73  this->setAppAction(Teuchos::null);
74  this->setSolver(solver);
75 
76  if (appModel != Teuchos::null) {
77  this->setModel(appModel);
78  this->initialize();
79  }
80 }
81 #endif
82 template<class Scalar>
84  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel,
85  const Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> >& solver,
86  bool useFSAL,
87  std::string ICConsistency,
88  bool ICConsistencyCheck,
89  bool zeroInitialGuess,
90  const Teuchos::RCP<StepperRKAppAction<Scalar> >& stepperRKAppAction,
91  std::string stepperType,
92  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
93  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau,
94  Scalar order)
95 {
96  this->setStepperType( stepperType);
97  this->setUseFSAL( useFSAL);
98  this->setICConsistency( ICConsistency);
99  this->setICConsistencyCheck( ICConsistencyCheck);
100  this->setZeroInitialGuess( zeroInitialGuess);
101 
102  this->setStageNumber(-1);
103 
104  this->setExplicitTableau(explicitTableau);
105  this->setImplicitTableau(implicitTableau);
106  this->setOrder(order);
107 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
108  this->setObserver(Teuchos::null);
109 #endif
110  this->setAppAction(stepperRKAppAction);
111  this->setSolver(solver);
112 
113  if (appModel != Teuchos::null) {
114  this->setModel(appModel);
115  this->initialize();
116  }
117 }
118 
119 
120 template<class Scalar>
121 void StepperIMEX_RK<Scalar>::setTableaus(std::string stepperType,
122  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
123  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
124 {
125  if (stepperType == "") stepperType = "IMEX RK SSP2";
126 
127  if (stepperType == "IMEX RK 1st order" ) {
128  {
129  // Explicit Tableau
130  typedef Teuchos::ScalarTraits<Scalar> ST;
131  int NumStages = 2;
132  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
133  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
134  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
135  const Scalar one = ST::one();
136  const Scalar zero = ST::zero();
137 
138  // Fill A:
139  A(0,0) = zero; A(0,1) = zero;
140  A(1,0) = one; A(1,1) = zero;
141 
142  // Fill b:
143  b(0) = one; b(1) = zero;
144 
145  // Fill c:
146  c(0) = zero; c(1) = one;
147 
148  int order = 1;
149 
150  auto expTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
151  "Explicit Tableau - IMEX RK 1st order",
152  A,b,c,order,order,order));
153 
154  this->setExplicitTableau(expTableau);
155  }
156  {
157  // Implicit Tableau
158  typedef Teuchos::ScalarTraits<Scalar> ST;
159  int NumStages = 2;
160  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
161  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
162  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
163  const Scalar one = ST::one();
164  const Scalar zero = ST::zero();
165 
166  // Fill A:
167  A(0,0) = zero; A(0,1) = zero;
168  A(1,0) = zero; A(1,1) = one;
169 
170  // Fill b:
171  b(0) = zero; b(1) = one;
172 
173  // Fill c:
174  c(0) = zero; c(1) = one;
175 
176  int order = 1;
177 
178  auto impTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
179  "Implicit Tableau - IMEX RK 1st order",
180  A,b,c,order,order,order));
181 
182  this->setImplicitTableau(impTableau);
183  }
184  this->setStepperType("IMEX RK 1st order");
185  this->setOrder(1);
186 
187  } else if ( stepperType == "SSP1_111" )
188  {
189  {
190  // Explicit Tableau
191  typedef Teuchos::ScalarTraits<Scalar> ST;
192  const int NumStages = 1;
193  const int order = 1;
194  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
195  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
196  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
197  const Scalar one = ST::one();
198  const Scalar zero = ST::zero();
199 
200  // Fill A:
201  A(0,0) = zero;
202 
203  // Fill b:
204  b(0) = one;
205 
206  // Fill c:
207  c(0) = zero;
208 
209 
210  auto expTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
211  "Explicit Tableau - SSP1_111",
212  A,b,c,order,order,order));
213 
214  this->setExplicitTableau(expTableau);
215  }
216  {
217  // Implicit Tableau
218  typedef Teuchos::ScalarTraits<Scalar> ST;
219  const int NumStages = 1;
220  const int order = 1;
221  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
222  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
223  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
224  const Scalar one = ST::one();
225 
226  // Fill A:
227  A(0,0) = one;
228 
229  // Fill b:
230  b(0) = one;
231 
232  // Fill c:
233  c(0) = one;
234 
235  auto impTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
236  "Implicit Tableau - SSP1_111",
237  A,b,c,order,order,order));
238 
239  this->setImplicitTableau(impTableau);
240  }
241  this->setStepperType("IMEX RK 1st order (SSP1_111)");
242  this->setOrder(1);
243 
244  } else if (stepperType == "IMEX RK SSP2" || stepperType == "SSP2_222_L" ) {
245  // Explicit Tableau
246  auto stepperERK = Teuchos::rcp(new StepperERK_Trapezoidal<Scalar>());
247  this->setExplicitTableau(stepperERK->getTableau());
248 
249  // Implicit Tableau
250  auto stepperSDIRK = Teuchos::rcp(new StepperSDIRK_2Stage3rdOrder<Scalar>());
251  stepperSDIRK->setGammaType("2nd Order L-stable");
252  this->setImplicitTableau(stepperSDIRK->getTableau());
253 
254  this->setStepperType("IMEX RK SSP2");
255  this->setOrder(2);
256  } else if (stepperType == "SSP2_222" || stepperType == "SSP2_222_A" ) {
257  // Explicit Tableau
258  auto stepperERK = Teuchos::rcp(new StepperERK_Trapezoidal<Scalar>());
259  this->setExplicitTableau(stepperERK->getTableau());
260 
261  // Implicit Tableau
262  auto stepperSDIRK = Teuchos::rcp(new StepperSDIRK_2Stage3rdOrder<Scalar>());
263  stepperSDIRK->setGammaType("gamma");
264  stepperSDIRK->setGamma( 0.5 );
265  this->setImplicitTableau(stepperSDIRK->getTableau());
266 
267  this->setStepperType("IMEX RK SSP2( A-Stable, gamma = 0.5) ");
268  this->setOrder(2);
269  } else if (stepperType == "IMEX RK SSP3" || stepperType == "SSP3_332" ) {
270  // Explicit Tableau
271  auto stepperERK = Teuchos::rcp(new StepperERK_3Stage3rdOrderTVD<Scalar>());
272  this->setExplicitTableau(stepperERK->getTableau());
273 
274  // Implicit Tableau
275  auto stepperSDIRK = Teuchos::rcp(new StepperSDIRK_3Stage2ndOrder<Scalar>());
276  this->setImplicitTableau(stepperSDIRK->getTableau());
277 
278  this->setStepperType("IMEX RK SSP3");
279  this->setOrder(2);
280  } else if (stepperType == "IMEX RK ARS 233" || stepperType == "ARS 233" ) {
281  typedef Teuchos::ScalarTraits<Scalar> ST;
282  int NumStages = 3;
283  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
284  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
285  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
286  const Scalar one = ST::one();
287  const Scalar zero = ST::zero();
288  const Scalar onehalf = ST::one()/(2*ST::one());
289  const Scalar gamma = (3*one+ST::squareroot(3*one))/(6*one);
290  {
291  // Explicit Tableau
292  // Fill A:
293  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
294  A(1,0) = gamma; A(1,1) = zero; A(1,2) = zero;
295  A(2,0) = (gamma-1.0); A(2,1) = (2.0-2.0*gamma); A(2,2) = zero;
296 
297  // Fill b:
298  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
299 
300  // Fill c:
301  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
302 
303  int order = 2;
304 
305  auto expTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
306  "Partition IMEX-RK Explicit Stepper",A,b,c,order,order,order));
307 
308  this->setExplicitTableau(expTableau);
309  }
310  {
311  // Implicit Tableau
312  // Fill A:
313  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
314  A(1,0) = zero; A(1,1) = gamma; A(1,2) = zero;
315  A(2,0) = zero; A(2,1) = (1.0-2.0*gamma); A(2,2) = gamma;
316 
317  // Fill b:
318  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
319 
320  // Fill c:
321  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
322 
323  int order = 3;
324 
325  auto impTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
326  "Partition IMEX-RK Implicit Stepper",A,b,c,order,order,order));
327 
328  this->setImplicitTableau(impTableau);
329  }
330  this->setStepperType("IMEX RK ARS 233");
331  this->setOrder(3);
332 
333  } else if (stepperType == "General IMEX RK") {
334  this->setExplicitTableau(explicitTableau);
335  this->setImplicitTableau(implicitTableau);
336  this->setStepperType("General IMEX RK");
337  this->setOrder(1);
338 
339  } else {
340  TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error,
341  "Error - Not a valid StepperIMEX_RK type! Stepper Type = "
342  << stepperType << "\n"
343  << " Current valid types are: \n"
344  << " 'IMEX RK 1st order\n"
345  << " 'SSP1_111\n"
346  << " 'IMEX RK SSP2' ('SSP2_222_L')\n"
347  << " 'SSP2_222' ('SSP2_222_A')\n"
348  << " 'IMEX RK SSP3' ('SSP3_332')\n"
349  << " 'IMEX RK ARS 233' ('ARS 233')\n"
350  << " 'General IMEX RK'\n");
351  }
352 
353  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau_==Teuchos::null,
354  std::runtime_error,
355  "Error - StepperIMEX_RK - Explicit tableau is null!");
356  TEUCHOS_TEST_FOR_EXCEPTION(implicitTableau_==Teuchos::null,
357  std::runtime_error,
358  "Error - StepperIMEX_RK - Implicit tableau is null!");
359  TEUCHOS_TEST_FOR_EXCEPTION(
360  explicitTableau_->numStages()!=implicitTableau_->numStages(),
361  std::runtime_error,
362  "Error - StepperIMEX_RK - Number of stages do not match!\n"
363  << " Explicit tableau = " << explicitTableau_->description() << "\n"
364  << " number of stages = " << explicitTableau_->numStages() << "\n"
365  << " Implicit tableau = " << implicitTableau_->description() << "\n"
366  << " number of stages = " << implicitTableau_->numStages() << "\n");
367 
368  this->isInitialized_ = false;
369 }
370 
371 
372 template<class Scalar>
374  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau)
375 {
376  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau->isImplicit() == true,
377  std::logic_error,
378  "Error - Received an implicit Tableau for setExplicitTableau()!\n" <<
379  " Tableau = " << explicitTableau->description() << "\n");
380  explicitTableau_ = explicitTableau;
381 
382  this->isInitialized_ = false;
383 }
384 
385 
386 template<class Scalar>
388  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
389 {
390  TEUCHOS_TEST_FOR_EXCEPTION( implicitTableau->isDIRK() != true,
391  std::logic_error,
392  "Error - Did not receive a DIRK Tableau for setImplicitTableau()!\n" <<
393  " Tableau = " << implicitTableau->description() << "\n");
394  implicitTableau_ = implicitTableau;
395 
396  this->isInitialized_ = false;
397 }
398 
399 template<class Scalar>
401  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
402 {
403  using Teuchos::RCP;
404  using Teuchos::rcp_const_cast;
405  using Teuchos::rcp_dynamic_cast;
406  RCP<Thyra::ModelEvaluator<Scalar> > ncModel =
407  rcp_const_cast<Thyra::ModelEvaluator<Scalar> > (appModel);
408  RCP<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > modelPairIMEX =
409  rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > (ncModel);
410  TEUCHOS_TEST_FOR_EXCEPTION( modelPairIMEX == Teuchos::null, std::logic_error,
411  "Error - StepperIMEX_RK::setModel() was given a ModelEvaluator that\n"
412  " could not be cast to a WrapperModelEvaluatorPairIMEX_Basic!\n"
413  " From: " << appModel << "\n"
414  " To : " << modelPairIMEX << "\n"
415  " Likely have given the wrong ModelEvaluator to this Stepper.\n");
416 
417  setModelPair(modelPairIMEX);
418 
419  TEUCHOS_TEST_FOR_EXCEPTION(this->solver_ == Teuchos::null, std::logic_error,
420  "Error - Solver is not set!\n");
421  this->solver_->setModel(modelPairIMEX);
422 
423  this->isInitialized_ = false;
424 }
425 
426 
427 /** \brief Create WrapperModelPairIMEX from user-supplied ModelEvaluator pair.
428  *
429  * The user-supplied ME pair can contain any user-specific IMEX interactions
430  * between explicit and implicit MEs.
431  */
432 template<class Scalar>
434  const Teuchos::RCP<WrapperModelEvaluatorPairIMEX_Basic<Scalar> > &
435  modelPairIMEX)
436 {
437  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
438  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
439  this->wrapperModel_);
440  validExplicitODE (modelPairIMEX->getExplicitModel());
441  validImplicitODE_DAE(modelPairIMEX->getImplicitModel());
442  wrapperModelPairIMEX = modelPairIMEX;
443  wrapperModelPairIMEX->initialize();
444  int expXDim = wrapperModelPairIMEX->getExplicitModel()->get_x_space()->dim();
445  int impXDim = wrapperModelPairIMEX->getImplicitModel()->get_x_space()->dim();
446  TEUCHOS_TEST_FOR_EXCEPTION( expXDim != impXDim, std::logic_error,
447  "Error - \n"
448  " Explicit and Implicit x vectors are incompatible!\n"
449  " Explicit vector dim = " << expXDim << "\n"
450  " Implicit vector dim = " << impXDim << "\n");
451 
452  this->wrapperModel_ = wrapperModelPairIMEX;
453 
454  this->isInitialized_ = false;
455 }
456 
457 /** \brief Create WrapperModelPairIMEX from explicit/implicit ModelEvaluators.
458  *
459  * Use the supplied explicit/implicit MEs to create a WrapperModelPairIMEX
460  * with basic IMEX interactions between explicit and implicit MEs.
461  */
462 template<class Scalar>
464  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& explicitModel,
465  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& implicitModel)
466 {
467  validExplicitODE (explicitModel);
468  validImplicitODE_DAE(implicitModel);
469  this->wrapperModel_ = Teuchos::rcp(
471  explicitModel, implicitModel));
472 
473  this->isInitialized_ = false;
474 }
475 
476 
477 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
478 template<class Scalar>
480  Teuchos::RCP<StepperObserver<Scalar> > obs)
481 {
482  if (this->stepperObserver_ == Teuchos::null)
483  this->stepperObserver_ =
484  Teuchos::rcp(new StepperRKObserverComposite<Scalar>());
485 
486  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() >0 ) )
487  return;
488 
489  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() == 0) )
490  obs = Teuchos::rcp(new StepperRKObserver<Scalar>());
491 
492  // Check that this casts to prevent a runtime error if it doesn't
493  if (Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs) != Teuchos::null) {
494  this->stepperObserver_->addObserver(
495  Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs, true) );
496  } else {
497  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
498  Teuchos::OSTab ostab(out,0,"setObserver");
499  *out << "Tempus::StepperIMEX_RK::setObserver: Warning: An observer has been provided that";
500  *out << " does not support Tempus::StepperRKObserver. This observer WILL NOT be added.";
501  *out << " In the future, this will result in a runtime error!" << std::endl;
502  }
503 
504  this->isInitialized_ = false;
505 }
506 #endif
507 
508 
509 template<class Scalar>
511 {
512  TEUCHOS_TEST_FOR_EXCEPTION( this->wrapperModel_ == Teuchos::null,
513  std::logic_error,
514  "Error - Need to set the model, setModel(), before calling "
515  "StepperIMEX_RK::initialize()\n");
516 
517  // Initialize the stage vectors
518  const int numStages = explicitTableau_->numStages();
519  stageF_.resize(numStages);
520  stageG_.resize(numStages);
521  for(int i=0; i < numStages; i++) {
522  stageF_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
523  stageG_[i] = Thyra::createMember(this->wrapperModel_->get_f_space());
524  assign(stageF_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
525  assign(stageG_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
526  }
527 
528  xTilde_ = Thyra::createMember(this->wrapperModel_->get_x_space());
529  assign(xTilde_.ptr(), Teuchos::ScalarTraits<Scalar>::zero());
530 
532 }
533 
534 
535 template<class Scalar>
537  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
538 {
539  using Teuchos::RCP;
540 
541  int numStates = solutionHistory->getNumStates();
542 
543  TEUCHOS_TEST_FOR_EXCEPTION(numStates < 1, std::logic_error,
544  "Error - setInitialConditions() needs at least one SolutionState\n"
545  " to set the initial condition. Number of States = " << numStates);
546 
547  if (numStates > 1) {
548  RCP<Teuchos::FancyOStream> out = this->getOStream();
549  Teuchos::OSTab ostab(out,1,"StepperIMEX_RK::setInitialConditions()");
550  *out << "Warning -- SolutionHistory has more than one state!\n"
551  << "Setting the initial conditions on the currentState.\n"<<std::endl;
552  }
553 
554  RCP<SolutionState<Scalar> > initialState = solutionHistory->getCurrentState();
555  RCP<Thyra::VectorBase<Scalar> > x = initialState->getX();
556 
557  // Use x from inArgs as ICs, if needed.
558  auto inArgs = this->wrapperModel_->getNominalValues();
559  if (x == Teuchos::null) {
560  TEUCHOS_TEST_FOR_EXCEPTION( (x == Teuchos::null) &&
561  (inArgs.get_x() == Teuchos::null), std::logic_error,
562  "Error - setInitialConditions() needs the ICs from the SolutionHistory\n"
563  " or getNominalValues()!\n");
564 
565  x = Teuchos::rcp_const_cast<Thyra::VectorBase<Scalar> >(inArgs.get_x());
566  initialState->setX(x);
567  }
568 
569  // Perform IC Consistency
570  std::string icConsistency = this->getICConsistency();
571  TEUCHOS_TEST_FOR_EXCEPTION(icConsistency != "None", std::logic_error,
572  "Error - setInitialConditions() requested a consistency of '"
573  << icConsistency << "'.\n"
574  " But only 'None' is available for IMEX-RK!\n");
575 
576  TEUCHOS_TEST_FOR_EXCEPTION( this->getUseFSAL(), std::logic_error,
577  "Error - The First-Step-As-Last (FSAL) principle is not "
578  << "available for IMEX-RK. Set useFSAL=false.\n");
579 }
580 
581 
582 template <typename Scalar>
584  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & X,
585  Scalar time, Scalar stepSize, Scalar stageNumber,
586  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & G) const
587 {
588  typedef Thyra::ModelEvaluatorBase MEB;
589  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
590  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
591  this->wrapperModel_);
592  MEB::InArgs<Scalar> inArgs = wrapperModelPairIMEX->getInArgs();
593  inArgs.set_x(X);
594  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
595  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
596  if (inArgs.supports(MEB::IN_ARG_stage_number))
597  inArgs.set_stage_number(stageNumber);
598 
599  // For model evaluators whose state function f(x, x_dot, t) describes
600  // an implicit ODE, and which accept an optional x_dot input argument,
601  // make sure the latter is set to null in order to request the evaluation
602  // of a state function corresponding to the explicit ODE formulation
603  // x_dot = f(x, t)
604  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
605 
606  MEB::OutArgs<Scalar> outArgs = wrapperModelPairIMEX->getOutArgs();
607  outArgs.set_f(G);
608 
609  wrapperModelPairIMEX->getImplicitModel()->evalModel(inArgs,outArgs);
610  Thyra::Vt_S(G.ptr(), -1.0);
611 }
612 
613 
614 template <typename Scalar>
616  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & X,
617  Scalar time, Scalar stepSize, Scalar stageNumber,
618  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & F) const
619 {
620  typedef Thyra::ModelEvaluatorBase MEB;
621 
622  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
623  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
624  this->wrapperModel_);
625  MEB::InArgs<Scalar> inArgs =
626  wrapperModelPairIMEX->getExplicitModel()->createInArgs();
627  inArgs.set_x(X);
628  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
629  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
630  if (inArgs.supports(MEB::IN_ARG_stage_number))
631  inArgs.set_stage_number(stageNumber);
632 
633  // For model evaluators whose state function f(x, x_dot, t) describes
634  // an implicit ODE, and which accept an optional x_dot input argument,
635  // make sure the latter is set to null in order to request the evaluation
636  // of a state function corresponding to the explicit ODE formulation
637  // x_dot = f(x, t)
638  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
639 
640  MEB::OutArgs<Scalar> outArgs =
641  wrapperModelPairIMEX->getExplicitModel()->createOutArgs();
642  outArgs.set_f(F);
643 
644  wrapperModelPairIMEX->getExplicitModel()->evalModel(inArgs, outArgs);
645  Thyra::Vt_S(F.ptr(), -1.0);
646 }
647 
648 
649 template<class Scalar>
651  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
652 {
653  this->checkInitialized();
654 
655  using Teuchos::RCP;
656  using Teuchos::SerialDenseMatrix;
657  using Teuchos::SerialDenseVector;
658 
659  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperIMEX_RK::takeStep()");
660  {
661  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
662  std::logic_error,
663  "Error - StepperIMEX_RK<Scalar>::takeStep(...)\n"
664  "Need at least two SolutionStates for IMEX_RK.\n"
665  " Number of States = " << solutionHistory->getNumStates() << "\n"
666  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
667  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
668 
669 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
670  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
671 #endif
672  RCP<StepperIMEX_RK<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
673  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
675 
676  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
677  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
678  const Scalar dt = workingState->getTimeStep();
679  const Scalar time = currentState->getTime();
680 
681  const int numStages = explicitTableau_->numStages();
682  const SerialDenseMatrix<int,Scalar> & AHat = explicitTableau_->A();
683  const SerialDenseVector<int,Scalar> & bHat = explicitTableau_->b();
684  const SerialDenseVector<int,Scalar> & cHat = explicitTableau_->c();
685  const SerialDenseMatrix<int,Scalar> & A = implicitTableau_->A();
686  const SerialDenseVector<int,Scalar> & b = implicitTableau_->b();
687  const SerialDenseVector<int,Scalar> & c = implicitTableau_->c();
688 
689  bool pass = true;
690  this->stageX_ = workingState->getX();
691  Thyra::assign(this->stageX_.ptr(), *(currentState->getX()));
692 
693  // Compute stage solutions
694  for (int i = 0; i < numStages; ++i) {
695  this->setStageNumber(i);
696 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
697  this->stepperObserver_->observeBeginStage(solutionHistory, *this);
698 #endif
699  Thyra::assign(xTilde_.ptr(), *(currentState->getX()));
700  for (int j = 0; j < i; ++j) {
701  if (AHat(i,j) != Teuchos::ScalarTraits<Scalar>::zero())
702  Thyra::Vp_StV(xTilde_.ptr(), -dt*AHat(i,j), *(stageF_[j]));
703  if (A (i,j) != Teuchos::ScalarTraits<Scalar>::zero())
704  Thyra::Vp_StV(xTilde_.ptr(), -dt*A (i,j), *(stageG_[j]));
705  }
706 
707  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
709 
710  Scalar ts = time + c(i)*dt;
711  Scalar tHats = time + cHat(i)*dt;
712  if (A(i,i) == Teuchos::ScalarTraits<Scalar>::zero()) {
713  // Explicit stage for the ImplicitODE_DAE
714  bool isNeeded = false;
715  for (int k=i+1; k<numStages; ++k) if (A(k,i) != 0.0) isNeeded = true;
716  if (b(i) != 0.0) isNeeded = true;
717  if (isNeeded == false) {
718  // stageG_[i] is not needed.
719  assign(stageG_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
720  } else {
721  Thyra::assign(this->stageX_.ptr(), *xTilde_);
722 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
723  this->stepperObserver_->observeBeforeImplicitExplicitly(solutionHistory, *this);
724 #endif
725  evalImplicitModelExplicitly(this->stageX_, ts, dt, i, stageG_[i]);
726  }
727  } else {
728  // Implicit stage for the ImplicitODE_DAE
729  const Scalar alpha = Scalar(1.0)/(dt*A(i,i));
730  const Scalar beta = Scalar(1.0);
731 
732  // Setup TimeDerivative
733  Teuchos::RCP<TimeDerivative<Scalar> > timeDer =
734  Teuchos::rcp(new StepperIMEX_RKTimeDerivative<Scalar>(
735  alpha, xTilde_.getConst()));
736 
737  auto p = Teuchos::rcp(new ImplicitODEParameters<Scalar>(
738  timeDer, dt, alpha, beta, SOLVE_FOR_X, i));
739 
740 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
741  this->stepperObserver_->observeBeforeSolve(solutionHistory, *this);
742 #endif
743  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
745 
746  const Thyra::SolveStatus<Scalar> sStatus =
747  this->solveImplicitODE(this->stageX_, stageG_[i], ts, p);
748 
749  if (sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) pass = false;
750 
751 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
752  this->stepperObserver_->observeAfterSolve(solutionHistory, *this);
753 #endif
754  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
756 
757  // Update contributions to stage values
758  Thyra::V_StVpStV(stageG_[i].ptr(), -alpha, *this->stageX_, alpha, *xTilde_);
759  }
760 
761 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
762  this->stepperObserver_->observeBeforeExplicit(solutionHistory, *this);
763 #endif
764  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
766  evalExplicitModel(this->stageX_, tHats, dt, i, stageF_[i]);
767 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
768  this->stepperObserver_->observeEndStage(solutionHistory, *this);
769 #endif
770  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
772  }
773 
774  // Sum for solution: x_n = x_n-1 - dt*Sum{ bHat(i)*f(i) + b(i)*g(i) }
775  Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
776  for (int i=0; i < numStages; ++i) {
777  if (bHat(i) != Teuchos::ScalarTraits<Scalar>::zero())
778  Thyra::Vp_StV((workingState->getX()).ptr(), -dt*bHat(i), *(stageF_[i]));
779  if (b (i) != Teuchos::ScalarTraits<Scalar>::zero())
780  Thyra::Vp_StV((workingState->getX()).ptr(), -dt*b (i), *(stageG_[i]));
781  }
782 
783  if (pass == true) workingState->setSolutionStatus(Status::PASSED);
784  else workingState->setSolutionStatus(Status::FAILED);
785  workingState->setOrder(this->getOrder());
786  workingState->computeNorms(currentState);
787 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
788  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
789 #endif
790  this->stepperRKAppAction_->execute(solutionHistory, thisStepper,
792  }
793  // reset the stage number
794  this->setStageNumber(-1);
795  return;
796 }
797 
798 /** \brief Provide a StepperState to the SolutionState.
799  * This Stepper does not have any special state data,
800  * so just provide the base class StepperState with the
801  * Stepper description. This can be checked to ensure
802  * that the input StepperState can be used by this Stepper.
803  */
804 template<class Scalar>
805 Teuchos::RCP<Tempus::StepperState<Scalar> >
808 {
809  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
810  rcp(new StepperState<Scalar>(this->getStepperType()));
811  return stepperState;
812 }
813 
814 
815 template<class Scalar>
817  Teuchos::FancyOStream &out,
818  const Teuchos::EVerbosityLevel verbLevel) const
819 {
820  out << std::endl;
821  Stepper<Scalar>::describe(out, verbLevel);
822  StepperImplicit<Scalar>::describe(out, verbLevel);
823 
824  out << "--- StepperIMEX_RK_Partition ---\n";
825  out << " explicitTableau_ = " << explicitTableau_ << std::endl;
826  if (verbLevel == Teuchos::VERB_HIGH)
827  explicitTableau_->describe(out, verbLevel);
828  out << " implicitTableau_ = " << implicitTableau_ << std::endl;
829  if (verbLevel == Teuchos::VERB_HIGH)
830  implicitTableau_->describe(out, verbLevel);
831  out << " xTilde_ = " << xTilde_ << std::endl;
832  out << " stageX_ = " << this->stageX_ << std::endl;
833  out << " stageF_.size() = " << stageF_.size() << std::endl;
834  int numStages = stageF_.size();
835  for (int i=0; i<numStages; ++i)
836  out << " stageF_["<<i<<"] = " << stageF_[i] << std::endl;
837  out << " stageG_.size() = " << stageG_.size() << std::endl;
838  numStages = stageG_.size();
839  for (int i=0; i<numStages; ++i)
840  out << " stageG_["<<i<<"] = " << stageG_[i] << std::endl;
841 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
842  out << " stepperObserver_ = " << stepperObserver_ << std::endl;
843 #endif
844  out << " stepperRKAppAction_= " << this->stepperRKAppAction_ << std::endl;
845  out << " order_ = " << order_ << std::endl;
846  out << "--------------------------------" << std::endl;
847 }
848 
849 
850 template<class Scalar>
851 bool StepperIMEX_RK<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
852 {
853  bool isValidSetup = true;
854 
855  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
856 
857  Teuchos::RCP<WrapperModelEvaluatorPairIMEX<Scalar> > wrapperModelPairIMEX =
858  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairIMEX<Scalar> >(
859  this->wrapperModel_);
860 
861  if ( wrapperModelPairIMEX->getExplicitModel() == Teuchos::null) {
862  isValidSetup = false;
863  out << "The explicit ModelEvaluator is not set!\n";
864  }
865 
866  if ( wrapperModelPairIMEX->getImplicitModel() == Teuchos::null) {
867  isValidSetup = false;
868  out << "The implicit ModelEvaluator is not set!\n";
869  }
870 
871  if (this->wrapperModel_ == Teuchos::null) {
872  isValidSetup = false;
873  out << "The wrapper ModelEvaluator is not set!\n";
874  }
875 
876 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
877  if (stepperObserver_ == Teuchos::null) {
878  isValidSetup = false;
879  out << "The stepper observer is not set!\n";
880  }
881 #endif
882  if (this->stepperRKAppAction_ == Teuchos::null) {
883  isValidSetup = false;
884  out << "The AppAction is not set!\n";
885  }
886 
887  if ( explicitTableau_ == Teuchos::null ) {
888  isValidSetup = false;
889  out << "The explicit tableau is not set!\n";
890  }
891 
892  if ( implicitTableau_ == Teuchos::null ) {
893  isValidSetup = false;
894  out << "The implicit tableau is not set!\n";
895  }
896 
897  return isValidSetup;
898 }
899 
900 
901 template<class Scalar>
902 Teuchos::RCP<const Teuchos::ParameterList>
904 {
905  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
906  getValidParametersBasic(pl, this->getStepperType());
907  pl->set<bool>("Initial Condition Consistency Check",
908  this->getICConsistencyCheckDefault());
909  pl->set<std::string>("Solver Name", "Default Solver");
910  pl->set<bool> ("Zero Initial Guess", false);
911  Teuchos::RCP<Teuchos::ParameterList> solverPL = defaultSolverParameters();
912  pl->set("Default Solver", *solverPL);
913 
914  return pl;
915 }
916 
917 
918 } // namespace Tempus
919 #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 initialize()
Initialize after construction and changing input parameters.
Thyra Base interface for time steppers.
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 describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Application Action for StepperRKBase.
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.
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.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
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 describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
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.