9 #include "Teuchos_UnitTestHarness.hpp"
10 #include "Teuchos_XMLParameterListHelpers.hpp"
11 #include "Teuchos_TimeMonitor.hpp"
13 #include "Thyra_VectorStdOps.hpp"
15 #include "Tempus_IntegratorBasic.hpp"
16 #include "Tempus_StepperDIRK.hpp"
18 #include "../TestModels/SinCosModel.hpp"
19 #include "../TestModels/VanDerPolModel.hpp"
20 #include "../TestUtils/Tempus_ConvergenceTestUtils.hpp"
28 using Teuchos::ParameterList;
29 using Teuchos::sublist;
30 using Teuchos::getParametersFromXmlFile;
37 #define TEST_PARAMETERLIST
38 #define TEST_CONSTRUCTING_FROM_DEFAULTS
40 #define TEST_VANDERPOL
41 #define TEST_EMBEDDED_DIRK
44 #ifdef TEST_PARAMETERLIST
49 std::vector<std::string> RKMethods;
50 RKMethods.push_back(
"RK Backward Euler");
51 RKMethods.push_back(
"IRK 1 Stage Theta Method");
52 RKMethods.push_back(
"Implicit Midpoint");
53 RKMethods.push_back(
"SDIRK 1 Stage 1st order");
54 RKMethods.push_back(
"SDIRK 2 Stage 2nd order");
55 RKMethods.push_back(
"SDIRK 2 Stage 3rd order");
56 RKMethods.push_back(
"EDIRK 2 Stage 3rd order");
57 RKMethods.push_back(
"EDIRK 2 Stage Theta Method");
58 RKMethods.push_back(
"SDIRK 3 Stage 4th order");
59 RKMethods.push_back(
"SDIRK 5 Stage 4th order");
60 RKMethods.push_back(
"SDIRK 5 Stage 5th order");
61 RKMethods.push_back(
"SDIRK 2(1) Pair");
63 for(std::vector<std::string>::size_type m = 0; m != RKMethods.size(); m++) {
65 std::string RKMethod = RKMethods[m];
68 RCP<ParameterList> pList =
69 getParametersFromXmlFile(
"Tempus_DIRK_SinCos.xml");
72 RCP<ParameterList> scm_pl = sublist(pList,
"SinCosModel",
true);
73 RCP<SinCosModel<double> > model =
76 RCP<ParameterList> tempusPL = sublist(pList,
"Tempus",
true);
77 tempusPL->sublist(
"Default Stepper").set(
"Stepper Type", RKMethods[m]);
79 if (RKMethods[m] ==
"IRK 1 Stage Theta Method" ||
80 RKMethods[m] ==
"Implicit Midpoint" ||
81 RKMethods[m] ==
"EDIRK 2 Stage Theta Method") {
83 RCP<ParameterList> stepperPL = sublist(tempusPL,
"Default Stepper",
true);
84 RCP<ParameterList> solverPL = Teuchos::parameterList();
85 *solverPL = *(sublist(stepperPL,
"Default Solver",
true));
86 tempusPL->sublist(
"Default Stepper").remove(
"Default Solver");
87 tempusPL->sublist(
"Default Stepper")
88 .set<
double>(
"theta", 0.5);
89 tempusPL->sublist(
"Default Stepper").remove(
"Zero Initial Guess");
90 tempusPL->sublist(
"Default Stepper").set<
bool>(
"Zero Initial Guess", 0);
91 tempusPL->sublist(
"Default Stepper").set(
"Default Solver", *solverPL);
92 }
else if (RKMethods[m] ==
"SDIRK 2 Stage 2nd order") {
94 RCP<ParameterList> stepperPL = sublist(tempusPL,
"Default Stepper",
true);
95 RCP<ParameterList> solverPL = Teuchos::parameterList();
96 *solverPL = *(sublist(stepperPL,
"Default Solver",
true));
97 tempusPL->sublist(
"Default Stepper").remove(
"Default Solver");
98 tempusPL->sublist(
"Default Stepper")
99 .set<
double>(
"gamma", 0.2928932188134524);
100 tempusPL->sublist(
"Default Stepper").remove(
"Zero Initial Guess");
101 tempusPL->sublist(
"Default Stepper").set<
bool>(
"Zero Initial Guess", 0);
102 tempusPL->sublist(
"Default Stepper").set(
"Default Solver", *solverPL);
103 }
else if (RKMethods[m] ==
"SDIRK 2 Stage 3rd order") {
105 RCP<ParameterList> stepperPL = sublist(tempusPL,
"Default Stepper",
true);
106 RCP<ParameterList> solverPL = Teuchos::parameterList();
107 *solverPL = *(sublist(stepperPL,
"Default Solver",
true));
108 tempusPL->sublist(
"Default Stepper").remove(
"Default Solver");
109 tempusPL->sublist(
"Default Stepper").set(
"3rd Order A-stable",
true);
110 tempusPL->sublist(
"Default Stepper").set(
"2nd Order L-stable",
false);
111 tempusPL->sublist(
"Default Stepper")
112 .set<
double>(
"gamma", 0.7886751345948128);
113 tempusPL->sublist(
"Default Stepper").remove(
"Zero Initial Guess");
114 tempusPL->sublist(
"Default Stepper").set<
bool>(
"Zero Initial Guess", 0);
115 tempusPL->sublist(
"Default Stepper").set(
"Default Solver", *solverPL);
120 RCP<Tempus::IntegratorBasic<double> > integrator =
121 Tempus::integratorBasic<double>(tempusPL, model);
123 RCP<ParameterList> stepperPL = sublist(tempusPL,
"Default Stepper",
true);
124 RCP<ParameterList> defaultPL =
125 integrator->getStepper()->getDefaultParameters();
126 defaultPL->remove(
"Description");
129 if ( RKMethods[m] ==
"Implicit Midpoint" ) {
130 defaultPL->set(
"Stepper Type",
"Implicit Midpoint");
132 TEST_ASSERT(haveSameValues(*stepperPL, *defaultPL,
true))
137 RCP<Tempus::IntegratorBasic<double> > integrator =
138 Tempus::integratorBasic<double>(model, RKMethods[m]);
140 RCP<ParameterList> stepperPL = sublist(tempusPL,
"Default Stepper",
true);
141 RCP<ParameterList> defaultPL =
142 integrator->getStepper()->getDefaultParameters();
143 defaultPL->remove(
"Description");
146 if ( RKMethods[m] ==
"Implicit Midpoint" ) {
147 defaultPL->set(
"Stepper Type",
"Implicit Midpoint");
152 TEST_ASSERT(haveSameValues(*stepperPL, *defaultPL,
true))
156 #endif // TEST_PARAMETERLIST
159 #ifdef TEST_CONSTRUCTING_FROM_DEFAULTS
167 RCP<ParameterList> pList =
168 getParametersFromXmlFile(
"Tempus_DIRK_SinCos.xml");
169 RCP<ParameterList> pl = sublist(pList,
"Tempus",
true);
172 RCP<ParameterList> scm_pl = sublist(pList,
"SinCosModel",
true);
174 RCP<SinCosModel<double> > model =
178 RCP<Tempus::StepperDIRK<double> > stepper =
182 RCP<Tempus::TimeStepControl<double> > timeStepControl =
184 ParameterList tscPL = pl->sublist(
"Default Integrator")
185 .sublist(
"Time Step Control");
186 timeStepControl->setStepType (tscPL.get<std::string>(
"Integrator Step Type"));
187 timeStepControl->setInitIndex(tscPL.get<
int> (
"Initial Time Index"));
188 timeStepControl->setInitTime (tscPL.get<
double>(
"Initial Time"));
189 timeStepControl->setFinalTime(tscPL.get<
double>(
"Final Time"));
190 timeStepControl->setInitTimeStep(dt);
191 timeStepControl->initialize();
194 Thyra::ModelEvaluatorBase::InArgs<double> inArgsIC =
195 stepper->getModel()->getNominalValues();
196 RCP<Thyra::VectorBase<double> > icSolution =
197 Teuchos::rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x());
198 RCP<Tempus::SolutionState<double> > icState =
200 icState->setTime (timeStepControl->getInitTime());
201 icState->setIndex (timeStepControl->getInitIndex());
202 icState->setTimeStep(0.0);
203 icState->setOrder (stepper->getOrder());
215 RCP<Tempus::IntegratorBasic<double> > integrator =
216 Tempus::integratorBasic<double>();
217 integrator->setStepperWStepper(stepper);
218 integrator->setTimeStepControl(timeStepControl);
221 integrator->initialize();
225 bool integratorStatus = integrator->advanceTime();
226 TEST_ASSERT(integratorStatus)
230 double time = integrator->getTime();
231 double timeFinal =pl->sublist(
"Default Integrator")
232 .sublist(
"Time Step Control").get<
double>(
"Final Time");
233 TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
236 RCP<Thyra::VectorBase<double> > x = integrator->getX();
237 RCP<const Thyra::VectorBase<double> > x_exact =
238 model->getExactSolution(time).get_x();
241 RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
242 Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
245 std::cout <<
" Stepper = SDIRK 2 Stage 2nd order" << std::endl;
246 std::cout <<
" =========================" << std::endl;
247 std::cout <<
" Exact solution : " << get_ele(*(x_exact), 0) <<
" "
248 << get_ele(*(x_exact), 1) << std::endl;
249 std::cout <<
" Computed solution: " << get_ele(*(x ), 0) <<
" "
250 << get_ele(*(x ), 1) << std::endl;
251 std::cout <<
" Difference : " << get_ele(*(xdiff ), 0) <<
" "
252 << get_ele(*(xdiff ), 1) << std::endl;
253 std::cout <<
" =========================" << std::endl;
254 TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.841470, 1.0e-4 );
255 TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.540304, 1.0e-4 );
257 #endif // TEST_CONSTRUCTING_FROM_DEFAULTS
265 std::vector<std::string> RKMethods;
266 RKMethods.push_back(
"RK Backward Euler");
267 RKMethods.push_back(
"IRK 1 Stage Theta Method");
268 RKMethods.push_back(
"Implicit Midpoint");
269 RKMethods.push_back(
"SDIRK 1 Stage 1st order");
270 RKMethods.push_back(
"SDIRK 2 Stage 2nd order");
271 RKMethods.push_back(
"SDIRK 2 Stage 3rd order");
272 RKMethods.push_back(
"EDIRK 2 Stage 3rd order");
273 RKMethods.push_back(
"EDIRK 2 Stage Theta Method");
274 RKMethods.push_back(
"SDIRK 3 Stage 4th order");
275 RKMethods.push_back(
"SDIRK 5 Stage 4th order");
276 RKMethods.push_back(
"SDIRK 5 Stage 5th order");
277 RKMethods.push_back(
"SDIRK 2(1) Pair");
279 std::vector<double> RKMethodErrors;
280 RKMethodErrors.push_back(0.0124201);
281 RKMethodErrors.push_back(5.20785e-05);
282 RKMethodErrors.push_back(5.20785e-05);
283 RKMethodErrors.push_back(0.0124201);
284 RKMethodErrors.push_back(2.52738e-05);
285 RKMethodErrors.push_back(1.40223e-06);
286 RKMethodErrors.push_back(2.17004e-07);
287 RKMethodErrors.push_back(5.20785e-05);
288 RKMethodErrors.push_back(6.41463e-08);
289 RKMethodErrors.push_back(3.30631e-10);
290 RKMethodErrors.push_back(1.35728e-11);
291 RKMethodErrors.push_back(0.0001041);
293 for(std::vector<std::string>::size_type m = 0; m != RKMethods.size(); m++) {
295 std::string RKMethod = RKMethods[m];
296 std::replace(RKMethod.begin(), RKMethod.end(),
' ',
'_');
297 std::replace(RKMethod.begin(), RKMethod.end(),
'/',
'.');
299 RCP<Tempus::IntegratorBasic<double> > integrator;
300 std::vector<RCP<Thyra::VectorBase<double>>> solutions;
301 std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
302 std::vector<double> StepSize;
303 std::vector<double> xErrorNorm;
304 std::vector<double> xDotErrorNorm;
306 const int nTimeStepSizes = 2;
309 for (
int n=0; n<nTimeStepSizes; n++) {
312 RCP<ParameterList> pList =
313 getParametersFromXmlFile(
"Tempus_DIRK_SinCos.xml");
316 RCP<ParameterList> scm_pl = sublist(pList,
"SinCosModel",
true);
317 RCP<SinCosModel<double> > model =
321 RCP<ParameterList> pl = sublist(pList,
"Tempus",
true);
322 pl->sublist(
"Default Stepper").set(
"Stepper Type", RKMethods[m]);
323 if (RKMethods[m] ==
"IRK 1 Stage Theta Method" ||
324 RKMethods[m] ==
"Implicit Midpoint" ||
325 RKMethods[m] ==
"EDIRK 2 Stage Theta Method") {
326 pl->sublist(
"Default Stepper").set<
double>(
"theta", 0.5);
327 }
else if (RKMethods[m] ==
"SDIRK 2 Stage 2nd order") {
328 pl->sublist(
"Default Stepper").set(
"gamma", 0.2928932188134524);
329 }
else if (RKMethods[m] ==
"SDIRK 2 Stage 3rd order") {
330 pl->sublist(
"Default Stepper").set(
"3rd Order A-stable",
true);
331 pl->sublist(
"Default Stepper").set(
"2nd Order L-stable",
false);
332 pl->sublist(
"Default Stepper").set(
"gamma", 0.7886751345948128);
338 pl->sublist(
"Default Integrator")
339 .sublist(
"Time Step Control").set(
"Initial Time Step", dt);
340 integrator = Tempus::integratorBasic<double>(pl, model);
346 RCP<Thyra::VectorBase<double> > x0 =
347 model->getNominalValues().get_x()->clone_v();
348 integrator->setInitialState(0.0, x0);
351 bool integratorStatus = integrator->advanceTime();
352 TEST_ASSERT(integratorStatus)
355 time = integrator->getTime();
356 double timeFinal = pl->sublist(
"Default Integrator")
357 .sublist(
"Time Step Control").get<
double>(
"Final Time");
358 double tol = 100.0 * std::numeric_limits<double>::epsilon();
359 TEST_FLOATING_EQUALITY(time, timeFinal, tol);
364 integrator->getSolutionHistory();
367 RCP<Tempus::SolutionHistory<double> > solnHistExact =
370 double time = (*solutionHistory)[i]->getTime();
371 RCP<Tempus::SolutionState<double> > state =
373 model->getExactSolution(time).get_x(),
374 model->getExactSolution(time).get_x_dot()));
376 solnHistExact->addState(state);
378 writeSolution(
"Tempus_"+RKMethod+
"_SinCos-Ref.dat", solnHistExact);
382 StepSize.push_back(dt);
383 auto solution = Thyra::createMember(model->get_x_space());
384 Thyra::copy(*(integrator->getX()),solution.ptr());
385 solutions.push_back(solution);
386 auto solutionDot = Thyra::createMember(model->get_x_space());
387 Thyra::copy(*(integrator->getXdot()),solutionDot.ptr());
388 solutionsDot.push_back(solutionDot);
389 if (n == nTimeStepSizes-1) {
390 StepSize.push_back(0.0);
391 auto solution = Thyra::createMember(model->get_x_space());
392 Thyra::copy(*(model->getExactSolution(time).get_x()),solution.ptr());
393 solutions.push_back(solution);
394 auto solutionDot = Thyra::createMember(model->get_x_space());
395 Thyra::copy(*(model->getExactSolution(time).get_x_dot()),
397 solutionsDot.push_back(solutionDot);
403 double xDotSlope = 0.0;
404 RCP<Tempus::Stepper<double> > stepper = integrator->getStepper();
405 double order = stepper->getOrder();
408 solutions, xErrorNorm, xSlope,
409 solutionsDot, xDotErrorNorm, xDotSlope);
411 TEST_FLOATING_EQUALITY( xSlope, order, 0.01 );
412 TEST_FLOATING_EQUALITY( xErrorNorm[0], RKMethodErrors[m], 5.0e-4 );
419 #endif // TEST_SINCOS
422 #ifdef TEST_VANDERPOL
427 std::vector<std::string> RKMethods;
428 RKMethods.push_back(
"SDIRK 2 Stage 2nd order");
430 std::string RKMethod = RKMethods[0];
431 std::replace(RKMethod.begin(), RKMethod.end(),
' ',
'_');
432 std::replace(RKMethod.begin(), RKMethod.end(),
'/',
'.');
434 RCP<Tempus::IntegratorBasic<double> > integrator;
435 std::vector<RCP<Thyra::VectorBase<double>>> solutions;
436 std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
437 std::vector<double> StepSize;
438 std::vector<double> xErrorNorm;
439 std::vector<double> xDotErrorNorm;
441 const int nTimeStepSizes = 3;
444 for (
int n=0; n<nTimeStepSizes; n++) {
447 RCP<ParameterList> pList =
448 getParametersFromXmlFile(
"Tempus_DIRK_VanDerPol.xml");
451 RCP<ParameterList> vdpm_pl = sublist(pList,
"VanDerPolModel",
true);
452 RCP<VanDerPolModel<double> > model =
456 RCP<ParameterList> pl = sublist(pList,
"Tempus",
true);
457 pl->sublist(
"Default Stepper").set(
"Stepper Type", RKMethods[0]);
458 pl->sublist(
"Default Stepper").set(
"gamma", 0.2928932188134524);
462 if (n == nTimeStepSizes-1) dt /= 10.0;
465 pl->sublist(
"Default Integrator")
466 .sublist(
"Time Step Control").set(
"Initial Time Step", dt);
467 integrator = Tempus::integratorBasic<double>(pl, model);
470 bool integratorStatus = integrator->advanceTime();
471 TEST_ASSERT(integratorStatus)
474 time = integrator->getTime();
475 double timeFinal =pl->sublist(
"Default Integrator")
476 .sublist(
"Time Step Control").get<
double>(
"Final Time");
477 double tol = 100.0 * std::numeric_limits<double>::epsilon();
478 TEST_FLOATING_EQUALITY(time, timeFinal, tol);
481 StepSize.push_back(dt);
482 auto solution = Thyra::createMember(model->get_x_space());
483 Thyra::copy(*(integrator->getX()),solution.ptr());
484 solutions.push_back(solution);
485 auto solutionDot = Thyra::createMember(model->get_x_space());
486 Thyra::copy(*(integrator->getXdot()),solutionDot.ptr());
487 solutionsDot.push_back(solutionDot);
491 if ((n == 0) or (n == nTimeStepSizes-1)) {
492 std::string fname =
"Tempus_"+RKMethod+
"_VanDerPol-Ref.dat";
493 if (n == 0) fname =
"Tempus_"+RKMethod+
"_VanDerPol.dat";
495 integrator->getSolutionHistory();
502 double xDotSlope = 0.0;
503 RCP<Tempus::Stepper<double> > stepper = integrator->getStepper();
504 double order = stepper->getOrder();
507 solutions, xErrorNorm, xSlope,
508 solutionsDot, xDotErrorNorm, xDotSlope);
510 TEST_FLOATING_EQUALITY( xSlope, order, 0.06 );
511 TEST_FLOATING_EQUALITY( xErrorNorm[0], 1.07525e-05, 1.0e-4 );
516 Teuchos::TimeMonitor::summarize();
518 #endif // TEST_VANDERPOL
521 #ifdef TEST_EMBEDDED_DIRK
527 std::vector<std::string> IntegratorList;
528 IntegratorList.push_back(
"Embedded_Integrator_PID");
529 IntegratorList.push_back(
"Embedded_Integrator");
532 const int refIstep = 213;
534 for(
auto integratorChoice : IntegratorList){
536 std::cout <<
"Using Integrator: " << integratorChoice <<
" !!!" << std::endl;
539 RCP<ParameterList> pList =
540 getParametersFromXmlFile(
"Tempus_DIRK_VanDerPol.xml");
544 RCP<ParameterList> vdpm_pl = sublist(pList,
"VanDerPolModel",
true);
545 RCP<VanDerPolModel<double> > model =
549 RCP<ParameterList> pl = sublist(pList,
"Tempus",
true);
550 pl->set(
"Integrator Name", integratorChoice);
553 RCP<Tempus::IntegratorBasic<double> > integrator =
554 Tempus::integratorBasic<double>(pl, model);
556 const std::string RKMethod_ =
557 pl->sublist(integratorChoice).get<std::string>(
"Stepper Name");
560 bool integratorStatus = integrator->advanceTime();
561 TEST_ASSERT(integratorStatus);
564 double time = integrator->getTime();
565 double timeFinal = pl->sublist(integratorChoice)
566 .sublist(
"Time Step Control").get<
double>(
"Final Time");
567 TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
571 RCP<Thyra::VectorBase<double> > x = integrator->getX();
572 RCP<Thyra::VectorBase<double> > xref = x->clone_v();
573 Thyra::set_ele(0, -1.5484458614405929, xref.ptr());
574 Thyra::set_ele(1, 1.0181127316101317, xref.ptr());
577 RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
578 Thyra::V_StVpStV(xdiff.ptr(), 1.0, *xref, -1.0, *(x));
579 const double L2norm = Thyra::norm_2(*xdiff);
582 if (integratorChoice ==
"Embedded_Integrator_PID"){
583 const double absTol = pl->sublist(integratorChoice).
584 sublist(
"Time Step Control").get<
double>(
"Maximum Absolute Error");
585 const double relTol = pl->sublist(integratorChoice).
586 sublist(
"Time Step Control").get<
double>(
"Maximum Relative Error");
592 const int iStep = integrator->getSolutionHistory()->
593 getCurrentState()->getIndex();
598 TEST_FLOATING_EQUALITY(std::log10(L2norm),std::log10(absTol), 0.3 );
599 TEST_FLOATING_EQUALITY(std::log10(L2norm),std::log10(relTol), 0.3 );
601 TEST_COMPARE(iStep, <=, refIstep);
605 std::ofstream ftmp(
"Tempus_"+integratorChoice+RKMethod_+
"_VDP_Example.dat");
607 integrator->getSolutionHistory();
610 for (
int i=0; i<nStates; i++) {
611 RCP<const SolutionState<double> > solutionState = (*solutionHistory)[i];
612 double time = solutionState->getTime();
613 RCP<const Thyra::VectorBase<double> > x_plot = solutionState->getX();
616 << Thyra::get_ele(*(x_plot), 0) <<
" "
617 << Thyra::get_ele(*(x_plot), 1) <<
" " << std::endl;
622 Teuchos::TimeMonitor::summarize();