Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tempus_StepperIMEX_RK_Partition_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_Partition_impl_hpp
10 #define Tempus_StepperIMEX_RK_Partition_impl_hpp
11 
12 #include "Tempus_config.hpp"
14 #include "Tempus_WrapperModelEvaluatorPairPartIMEX_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( "Partitioned 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("Partitioned 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->setObserver(obs);
63 
64  if (appModel != Teuchos::null) {
65 
66  this->setModel(appModel);
67  this->setSolver(solver);
68  this->initialize();
69  }
70 }
71 
72 
73 template<class Scalar>
75  std::string stepperType,
76  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau,
77  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
78 {
79  if (stepperType == "") stepperType = "Partitioned IMEX RK SSP2";
80 
81  if (stepperType == "Partitioned 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 - Partitioned 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 - Partitioned IMEX RK 1st order",
134  A,b,c,order,order,order));
135 
136  this->setImplicitTableau(implicitTableau);
137  }
138  this->setStepperType("Partitioned IMEX RK 1st order");
139  this->setOrder(1);
140 
141  } else if (stepperType == "Partitioned 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("Partitioned IMEX RK SSP2");
152  this->setOrder(2);
153 
154  } else if (stepperType == "Partitioned IMEX RK ARS 233") {
155  typedef Teuchos::ScalarTraits<Scalar> ST;
156  int NumStages = 3;
157  Teuchos::SerialDenseMatrix<int,Scalar> A(NumStages,NumStages);
158  Teuchos::SerialDenseVector<int,Scalar> b(NumStages);
159  Teuchos::SerialDenseVector<int,Scalar> c(NumStages);
160  const Scalar one = ST::one();
161  const Scalar zero = ST::zero();
162  const Scalar onehalf = ST::one()/(2*ST::one());
163  const Scalar gamma = (3*one+ST::squareroot(3*one))/(6*one);
164  {
165  // Explicit Tableau
166  // Fill A:
167  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
168  A(1,0) = gamma; A(1,1) = zero; A(1,2) = zero;
169  A(2,0) = (gamma-1.0); A(2,1) = (2.0-2.0*gamma); A(2,2) = zero;
170 
171  // Fill b:
172  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
173 
174  // Fill c:
175  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
176 
177  int order = 2;
178 
179  auto explicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
180  "Explicit Tableau - Partitioned IMEX RK ARS 233",
181  A,b,c,order,order,order));
182 
183  this->setExplicitTableau(explicitTableau);
184  }
185  {
186  // Implicit Tableau
187  // Fill A:
188  A(0,0) = zero; A(0,1) = zero; A(0,2) = zero;
189  A(1,0) = zero; A(1,1) = gamma; A(1,2) = zero;
190  A(2,0) = zero; A(2,1) = (1.0-2.0*gamma); A(2,2) = gamma;
191 
192  // Fill b:
193  b(0) = zero; b(1) = onehalf; b(2) = onehalf;
194 
195  // Fill c:
196  c(0) = zero; c(1) = gamma; c(2) = one-gamma;
197 
198  int order = 3;
199 
200  auto implicitTableau = Teuchos::rcp(new RKButcherTableau<Scalar>(
201  "Implicit Tableau - Partitioned IMEX RK ARS 233",
202  A,b,c,order,order,order));
203 
204  this->setImplicitTableau(implicitTableau);
205  }
206  this->setStepperType("Partitioned IMEX RK ARS 233");
207  this->setOrder(3);
208 
209  } else if (stepperType == "General Partitioned IMEX RK") {
210  this->setExplicitTableau(explicitTableau);
211  this->setImplicitTableau(implicitTableau);
212  this->setStepperType("General Partitioned IMEX RK");
213  this->setOrder(1);
214 
215  } else {
216  TEUCHOS_TEST_FOR_EXCEPTION( true, std::logic_error,
217  "Error - Not a valid StepperIMEX_RK_Partition type! Stepper Type = "
218  << stepperType << "\n"
219  << " Current valid types are: " << "\n"
220  << " 'Partitioned IMEX RK 1st order'" << "\n"
221  << " 'Partitioned IMEX RK SSP2'" << "\n"
222  << " 'Partitioned IMEX RK ARS 233'" << "\n"
223  << " 'General Partitioned IMEX RK'" << "\n");
224  }
225 
226  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau_==Teuchos::null,
227  std::runtime_error,
228  "Error - StepperIMEX_RK_Partition - Explicit tableau is null!");
229  TEUCHOS_TEST_FOR_EXCEPTION(implicitTableau_==Teuchos::null,
230  std::runtime_error,
231  "Error - StepperIMEX_RK_Partition - Implicit tableau is null!");
232  TEUCHOS_TEST_FOR_EXCEPTION(
233  explicitTableau_->numStages()!=implicitTableau_->numStages(),
234  std::runtime_error,
235  "Error - StepperIMEX_RK_Partition - Number of stages do not match!\n"
236  << " Explicit tableau = " << explicitTableau_->description() << "\n"
237  << " number of stages = " << explicitTableau_->numStages() << "\n"
238  << " Implicit tableau = " << implicitTableau_->description() << "\n"
239  << " number of stages = " << implicitTableau_->numStages() << "\n");
240 }
241 
242 
243 template<class Scalar>
245  Teuchos::RCP<const RKButcherTableau<Scalar> > explicitTableau)
246 {
247  TEUCHOS_TEST_FOR_EXCEPTION(explicitTableau->isImplicit() == true,
248  std::logic_error,
249  "Error - Received an implicit Tableau for setExplicitTableau()!\n" <<
250  " Tableau = " << explicitTableau->description() << "\n");
251  explicitTableau_ = explicitTableau;
252 }
253 
254 
255 template<class Scalar>
257  Teuchos::RCP<const RKButcherTableau<Scalar> > implicitTableau)
258 {
259  TEUCHOS_TEST_FOR_EXCEPTION( implicitTableau->isDIRK() != true,
260  std::logic_error,
261  "Error - Did not receive a DIRK Tableau for setImplicitTableau()!\n" <<
262  " Tableau = " << implicitTableau->description() << "\n");
263  implicitTableau_ = implicitTableau;
264 }
265 
266 template<class Scalar>
268  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
269 {
270  using Teuchos::RCP;
271  using Teuchos::rcp_const_cast;
272  using Teuchos::rcp_dynamic_cast;
273  RCP<Thyra::ModelEvaluator<Scalar> > ncModel =
274  rcp_const_cast<Thyra::ModelEvaluator<Scalar> > (appModel);
275  RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> > modelPairIMEX =
276  rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >(ncModel);
277  TEUCHOS_TEST_FOR_EXCEPTION( modelPairIMEX == Teuchos::null, std::logic_error,
278  "Error - StepperIMEX_RK::setModel() was given a ModelEvaluator that\n"
279  " could not be cast to a WrapperModelEvaluatorPairPartIMEX_Basic!\n"
280  " From: " << appModel << "\n"
281  " To : " << modelPairIMEX << "\n"
282  " Likely have given the wrong ModelEvaluator to this Stepper.\n");
283 
284  setModelPair(modelPairIMEX);
285 }
286 
287 /** \brief Create WrapperModelPairIMEX from user-supplied ModelEvaluator pair.
288  *
289  * The user-supplied ME pair can contain any user-specific IMEX interactions
290  * between explicit and implicit MEs.
291  */
292 template<class Scalar>
295  mePairIMEX)
296 {
297  Teuchos::RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
298  wrapperModelPairIMEX =
299  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
300  (this->wrapperModel_);
301  validExplicitODE (mePairIMEX->getExplicitModel());
302  validImplicitODE_DAE(mePairIMEX->getImplicitModel());
303  wrapperModelPairIMEX = mePairIMEX;
304  wrapperModelPairIMEX->initialize();
305 
306  this->wrapperModel_ = wrapperModelPairIMEX;
307 }
308 
309 /** \brief Create WrapperModelPairIMEX from explicit/implicit ModelEvaluators.
310  *
311  * Use the supplied explicit/implicit MEs to create a WrapperModelPairIMEX
312  * with basic IMEX interactions between explicit and implicit MEs.
313  */
314 template<class Scalar>
316  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& explicitModel,
317  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& implicitModel)
318 {
319  validExplicitODE (explicitModel);
320  validImplicitODE_DAE(implicitModel);
321  this->wrapperModel_ = Teuchos::rcp(
323  explicitModel, implicitModel));
324 }
325 
326 
327 template<class Scalar>
329  Teuchos::RCP<StepperObserver<Scalar> > obs)
330 {
331  if (this->stepperObserver_ == Teuchos::null)
332  this->stepperObserver_ =
333  Teuchos::rcp(new StepperRKObserverComposite<Scalar>());
334 
335  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() >0 ) )
336  return;
337 
338  if (( obs == Teuchos::null ) and (this->stepperObserver_->getSize() == 0) )
339  obs = Teuchos::rcp(new StepperRKObserver<Scalar>());
340 
341  // Check that this casts to prevent a runtime error if it doesn't
342  if (Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs) != Teuchos::null) {
343  this->stepperObserver_->addObserver(
344  Teuchos::rcp_dynamic_cast<StepperRKObserver<Scalar> > (obs, true) );
345  } else {
346  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
347  Teuchos::OSTab ostab(out,0,"setObserver");
348  *out << "Tempus::StepperIMEX_RK_Partition::setObserver: Warning: An observer has been provided that";
349  *out << " does not support Tempus::StepperRKObserver. This observer WILL NOT be added.";
350  *out << " In the future, this will result in a runtime error!" << std::endl;
351  }
352 }
353 
354 
355 template<class Scalar>
357 {
358  TEUCHOS_TEST_FOR_EXCEPTION(
359  (explicitTableau_ == Teuchos::null) || (implicitTableau_ == Teuchos::null),
360  std::logic_error,
361  "Error - Need to set the Butcher Tableaus, setTableaus(), before calling "
362  "StepperIMEX_RK_Partition::initialize()\n");
363 
364  Teuchos::RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
365  wrapperModelPairIMEX =
366  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
367  (this->wrapperModel_);
368  TEUCHOS_TEST_FOR_EXCEPTION( wrapperModelPairIMEX == Teuchos::null,
369  std::logic_error,
370  "Error - Need to set the model, setModel(), before calling "
371  "StepperIMEX_RK_Partition::initialize()\n");
372 
373  // Initialize the stage vectors
374  const int numStages = explicitTableau_->numStages();
375  stageF_.resize(numStages);
376  stageGx_.resize(numStages);
377  for(int i=0; i < numStages; i++) {
378  stageF_[i] = Thyra::createMember(wrapperModelPairIMEX->
379  getExplicitModel()->get_f_space());
380  stageGx_[i] = Thyra::createMember(wrapperModelPairIMEX->
381  getImplicitModel()->get_f_space());
382  assign(stageF_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
383  assign(stageGx_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
384  }
385 
386  xTilde_ = Thyra::createMember(wrapperModelPairIMEX->
387  getImplicitModel()->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 
427  // Perform IC Consistency
428  std::string icConsistency = this->getICConsistency();
429  TEUCHOS_TEST_FOR_EXCEPTION(icConsistency != "None", std::logic_error,
430  "Error - setInitialConditions() requested a consistency of '"
431  << icConsistency << "'.\n"
432  " But only 'None' is available for IMEX-RK!\n");
433 
434  TEUCHOS_TEST_FOR_EXCEPTION( this->getUseFSAL(), std::logic_error,
435  "Error - The First-Step-As-Last (FSAL) principle is not "
436  << "available for IMEX-RK. Set useFSAL=false.\n");
437 }
438 
439 
440 template <typename Scalar>
442  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & X,
443  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & Y,
444  Scalar time, Scalar stepSize, Scalar stageNumber,
445  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & G) const
446 {
447  typedef Thyra::ModelEvaluatorBase MEB;
448  Teuchos::RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
449  wrapperModelPairIMEX =
450  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
451  (this->wrapperModel_);
452  MEB::InArgs<Scalar> inArgs = wrapperModelPairIMEX->getInArgs();
453  inArgs.set_x(X);
454  inArgs.set_p(wrapperModelPairIMEX->getParameterIndex(), Y);
455  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
456  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
457  if (inArgs.supports(MEB::IN_ARG_stage_number))
458  inArgs.set_stage_number(stageNumber);
459 
460  // For model evaluators whose state function f(x, x_dot, t) describes
461  // an implicit ODE, and which accept an optional x_dot input argument,
462  // make sure the latter is set to null in order to request the evaluation
463  // of a state function corresponding to the explicit ODE formulation
464  // x_dot = f(x, t)
465  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
466 
467  MEB::OutArgs<Scalar> outArgs = wrapperModelPairIMEX->getOutArgs();
468  outArgs.set_f(G);
469 
470  wrapperModelPairIMEX->getImplicitModel()->evalModel(inArgs,outArgs);
471  Thyra::Vt_S(G.ptr(), -1.0);
472 }
473 
474 
475 template <typename Scalar>
477  const Teuchos::RCP<const Thyra::VectorBase<Scalar> > & Z,
478  Scalar time, Scalar stepSize, Scalar stageNumber,
479  const Teuchos::RCP<Thyra::VectorBase<Scalar> > & F) const
480 {
481  typedef Thyra::ModelEvaluatorBase MEB;
482 
483  Teuchos::RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
484  wrapperModelPairIMEX =
485  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
486  (this->wrapperModel_);
487  MEB::InArgs<Scalar> inArgs =
488  wrapperModelPairIMEX->getExplicitModel()->createInArgs();
489  inArgs.set_x(Z);
490  if (inArgs.supports(MEB::IN_ARG_t)) inArgs.set_t(time);
491  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(stepSize);
492  if (inArgs.supports(MEB::IN_ARG_stage_number))
493  inArgs.set_stage_number(stageNumber);
494 
495  // For model evaluators whose state function f(x, x_dot, t) describes
496  // an implicit ODE, and which accept an optional x_dot input argument,
497  // make sure the latter is set to null in order to request the evaluation
498  // of a state function corresponding to the explicit ODE formulation
499  // x_dot = f(x, t)
500  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(Teuchos::null);
501 
502  MEB::OutArgs<Scalar> outArgs =
503  wrapperModelPairIMEX->getExplicitModel()->createOutArgs();
504  outArgs.set_f(F);
505 
506  wrapperModelPairIMEX->getExplicitModel()->evalModel(inArgs, outArgs);
507  Thyra::Vt_S(F.ptr(), -1.0);
508 }
509 
510 
511 template<class Scalar>
513  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
514 {
515  using Teuchos::RCP;
516  using Teuchos::SerialDenseMatrix;
517  using Teuchos::SerialDenseVector;
518 
519  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperIMEX_RK_Partition::takeStep()");
520  {
521  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
522  std::logic_error,
523  "Error - StepperIMEX_RK_Partition<Scalar>::takeStep(...)\n"
524  "Need at least two SolutionStates for IMEX_RK_Partition.\n"
525  " Number of States = " << solutionHistory->getNumStates() << "\n"
526  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
527  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
528 
529  this->stepperObserver_->observeBeginTakeStep(solutionHistory, *this);
530  RCP<SolutionState<Scalar> > currentState=solutionHistory->getCurrentState();
531  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
532  const Scalar dt = workingState->getTimeStep();
533  const Scalar time = currentState->getTime();
534 
535  const int numStages = explicitTableau_->numStages();
536  const SerialDenseMatrix<int,Scalar> & AHat = explicitTableau_->A();
537  const SerialDenseVector<int,Scalar> & bHat = explicitTableau_->b();
538  const SerialDenseVector<int,Scalar> & cHat = explicitTableau_->c();
539  const SerialDenseMatrix<int,Scalar> & A = implicitTableau_->A();
540  const SerialDenseVector<int,Scalar> & b = implicitTableau_->b();
541  const SerialDenseVector<int,Scalar> & c = implicitTableau_->c();
542 
543  Teuchos::RCP<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
544  wrapperModelPairIMEX =
545  Teuchos::rcp_dynamic_cast<WrapperModelEvaluatorPairPartIMEX_Basic<Scalar> >
546  (this->wrapperModel_);
547 
548  bool pass = true;
549  Thyra::SolveStatus<Scalar> sStatus;
550  stageZ_ = workingState->getX();
551  Thyra::assign(stageZ_.ptr(), *(currentState->getX()));
552  RCP<Thyra::VectorBase<Scalar> > stageY =
553  wrapperModelPairIMEX->getExplicitOnlyVector(stageZ_);
554  RCP<Thyra::VectorBase<Scalar> > stageX =
555  wrapperModelPairIMEX->getIMEXVector(stageZ_);
556 
557  // Compute stage solutions
558  for (int i = 0; i < numStages; ++i) {
559  this->stepperObserver_->observeBeginStage(solutionHistory, *this);
560 
561  Thyra::assign(stageY.ptr(),
562  *(wrapperModelPairIMEX->getExplicitOnlyVector(currentState->getX())));
563  Thyra::assign(xTilde_.ptr(),
564  *(wrapperModelPairIMEX->getIMEXVector(currentState->getX())));
565  for (int j = 0; j < i; ++j) {
566  if (AHat(i,j) != Teuchos::ScalarTraits<Scalar>::zero()) {
567  RCP<Thyra::VectorBase<Scalar> > stageFy =
568  wrapperModelPairIMEX->getExplicitOnlyVector(stageF_[j]);
569  RCP<Thyra::VectorBase<Scalar> > stageFx =
570  wrapperModelPairIMEX->getIMEXVector(stageF_[j]);
571  Thyra::Vp_StV(stageY.ptr(), -dt*AHat(i,j), *stageFy);
572  Thyra::Vp_StV(xTilde_.ptr(), -dt*AHat(i,j), *stageFx);
573  }
574  if (A (i,j) != Teuchos::ScalarTraits<Scalar>::zero())
575  Thyra::Vp_StV(xTilde_.ptr(), -dt*A (i,j), *(stageGx_[j]));
576  }
577 
578  Scalar ts = time + c(i)*dt;
579  Scalar tHats = time + cHat(i)*dt;
580  if (A(i,i) == Teuchos::ScalarTraits<Scalar>::zero()) {
581  // Explicit stage for the ImplicitODE_DAE
582  bool isNeeded = false;
583  for (int k=i+1; k<numStages; ++k) if (A(k,i) != 0.0) isNeeded = true;
584  if (b(i) != 0.0) isNeeded = true;
585  if (isNeeded == false) {
586  // stageGx_[i] is not needed.
587  assign(stageGx_[i].ptr(), Teuchos::ScalarTraits<Scalar>::zero());
588  } else {
589  Thyra::assign(stageX.ptr(), *xTilde_);
590  this->stepperObserver_->observeBeforeImplicitExplicitly(solutionHistory, *this);
591  evalImplicitModelExplicitly(stageX, stageY, ts, dt, i, stageGx_[i]);
592  }
593  } else {
594  // Implicit stage for the ImplicitODE_DAE
595  const Scalar alpha = Scalar(1.0)/(dt*A(i,i));
596  const Scalar beta = Scalar(1.0);
597 
598  // Setup TimeDerivative
599  RCP<TimeDerivative<Scalar> > timeDer =
601  alpha, xTilde_.getConst()));
602 
603  // Setup InArgs and OutArgs
604  typedef Thyra::ModelEvaluatorBase MEB;
605  //MEB::InArgs<Scalar> inArgs = wrapperModelPairIMEX->getInArgs();
606  //MEB::OutArgs<Scalar> outArgs = wrapperModelPairIMEX->getOutArgs();
607  wrapperModelPairIMEX->setUseImplicitModel(true);
608  MEB::InArgs<Scalar> inArgs = wrapperModelPairIMEX->createInArgs();
609  MEB::OutArgs<Scalar> outArgs = wrapperModelPairIMEX->createOutArgs();
610  inArgs.set_x(stageX);
611  if (wrapperModelPairIMEX->getParameterIndex() >= 0)
612  inArgs.set_p(wrapperModelPairIMEX->getParameterIndex(), stageY);
613  if (inArgs.supports(MEB::IN_ARG_x_dot)) inArgs.set_x_dot(stageGx_[i]);
614  if (inArgs.supports(MEB::IN_ARG_t )) inArgs.set_t (ts);
615  if (inArgs.supports(MEB::IN_ARG_step_size)) inArgs.set_step_size(dt);
616  if (inArgs.supports(MEB::IN_ARG_alpha )) inArgs.set_alpha (alpha);
617  if (inArgs.supports(MEB::IN_ARG_beta )) inArgs.set_beta (beta);
618  if (inArgs.supports(MEB::IN_ARG_stage_number))
619  inArgs.set_stage_number(i);
620 
621  wrapperModelPairIMEX->setForSolve(timeDer, inArgs, outArgs);
622 
623  this->stepperObserver_->observeBeforeSolve(solutionHistory, *this);
624 
625  this->solver_->setModel(wrapperModelPairIMEX);
626  sStatus = this->solveImplicitODE(stageX);
627  if (sStatus.solveStatus != Thyra::SOLVE_STATUS_CONVERGED) pass = false;
628 
629  wrapperModelPairIMEX->setUseImplicitModel(false);
630 
631  this->stepperObserver_->observeAfterSolve(solutionHistory, *this);
632 
633  // Update contributions to stage values
634  Thyra::V_StVpStV(stageGx_[i].ptr(), -alpha, *stageX, alpha, *xTilde_);
635  }
636 
637  this->stepperObserver_->observeBeforeExplicit(solutionHistory, *this);
638  evalExplicitModel(stageZ_, tHats, dt, i, stageF_[i]);
639  this->stepperObserver_->observeEndStage(solutionHistory, *this);
640  }
641 
642  // Sum for solution: y_n = y_n-1 - dt*Sum{ bHat(i)*fy(i) }
643  // Sum for solution: x_n = x_n-1 - dt*Sum{ bHat(i)*fx(i) + b(i)*gx(i) }
644  Thyra::assign((workingState->getX()).ptr(), *(currentState->getX()));
645  RCP<Thyra::VectorBase<Scalar> > Z = workingState->getX();
646  RCP<Thyra::VectorBase<Scalar> > X = wrapperModelPairIMEX->getIMEXVector(Z);
647  for (int i=0; i < numStages; ++i) {
648  if (bHat(i) != Teuchos::ScalarTraits<Scalar>::zero())
649  Thyra::Vp_StV(Z.ptr(), -dt*bHat(i), *(stageF_[i]));
650  if (b (i) != Teuchos::ScalarTraits<Scalar>::zero())
651  Thyra::Vp_StV(X.ptr(), -dt*b (i), *(stageGx_[i]));
652  }
653 
654  if (pass == true) workingState->setSolutionStatus(Status::PASSED);
655  else workingState->setSolutionStatus(Status::FAILED);
656  workingState->setOrder(this->getOrder());
657  this->stepperObserver_->observeEndTakeStep(solutionHistory, *this);
658  }
659  return;
660 }
661 
662 /** \brief Provide a StepperState to the SolutionState.
663  * This Stepper does not have any special state data,
664  * so just provide the base class StepperState with the
665  * Stepper description. This can be checked to ensure
666  * that the input StepperState can be used by this Stepper.
667  */
668 template<class Scalar>
669 Teuchos::RCP<Tempus::StepperState<Scalar> >
672 {
673  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
674  rcp(new StepperState<Scalar>(this->getStepperType()));
675  return stepperState;
676 }
677 
678 
679 template<class Scalar>
681  Teuchos::FancyOStream &out,
682  const Teuchos::EVerbosityLevel /* verbLevel */) const
683 {
684  out << this->getStepperType() << "::describe:" << std::endl
685  << "wrapperModelPairIMEX = " << this->wrapperModel_->description()
686  << std::endl;
687 }
688 
689 
690 template<class Scalar>
691 Teuchos::RCP<const Teuchos::ParameterList>
693 {
694  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
695  pl->setName("Default Stepper - Partitioned IMEX RK SSP2");
696  pl->set<std::string>("Stepper Type", "Partitioned IMEX RK SSP2");
697  getValidParametersBasic(pl, this->getStepperType());
698  pl->set<bool>("Initial Condition Consistency Check",
699  this->getICConsistencyCheckDefault());
700  pl->set<std::string>("Solver Name", "Default Solver");
701  pl->set<bool> ("Zero Initial Guess", false);
702  Teuchos::RCP<Teuchos::ParameterList> solverPL = defaultSolverParameters();
703  pl->set("Default Solver", *solverPL);
704 
705  return pl;
706 }
707 
708 
709 } // namespace Tempus
710 #endif // Tempus_StepperIMEX_RK_Partition_impl_hpp
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
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.
virtual void setModelPair(const Teuchos::RCP< WrapperModelEvaluatorPairPartIMEX_Basic< Scalar > > &modelPair)
Create WrapperModelPairIMEX from user-supplied ModelEvaluator pair.
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 Thyra::ModelEvaluatorBase::InArgs< Scalar > getInArgs()
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
StepperState is a simple class to hold state information about the stepper.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Provide a StepperState to the SolutionState. This Stepper does not have any special state data...
ModelEvaluator pair for implicit and explicit (IMEX) evaulations.
void evalImplicitModelExplicitly(const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &X, const Teuchos::RCP< const Thyra::VectorBase< Scalar > > &Y, Scalar time, Scalar stepSize, Scalar stageNumber, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &G) const
StepperObserver class for Stepper class.
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
virtual void setExplicitTableau(Teuchos::RCP< const RKButcherTableau< Scalar > > explicitTableau)
Set the explicit tableau from tableau.
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
virtual void setImplicitTableau(Teuchos::RCP< const RKButcherTableau< Scalar > > implicitTableau)
Set the implicit tableau from tableau.
Time-derivative interface for Partitioned IMEX RK.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getExplicitModel() const
StepperRKObserver class for StepperRK.
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Take the specified timestep, dt, and return true if successful.
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
void validImplicitODE_DAE(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Validate ME supports implicit ODE/DAE evaluation, f(xdot,x,t) [= 0].
virtual void initialize()
Initialize during construction and after changing input parameters.
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.