Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_DIRKTest.cpp
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 
11 #include "Teuchos_TimeMonitor.hpp"
12 
13 #include "Thyra_VectorStdOps.hpp"
14 
15 #include "Tempus_IntegratorBasic.hpp"
16 #include "Tempus_StepperFactory.hpp"
17 
18 #include "../TestModels/SinCosModel.hpp"
19 #include "../TestModels/VanDerPolModel.hpp"
20 #include "../TestUtils/Tempus_ConvergenceTestUtils.hpp"
21 
22 #include <fstream>
23 #include <vector>
24 
25 namespace Tempus_Test {
26 
27 using Teuchos::RCP;
28 using Teuchos::rcp;
29 using Teuchos::rcp_const_cast;
30 using Teuchos::rcp_dynamic_cast;
32 using Teuchos::parameterList;
33 using Teuchos::sublist;
34 using Teuchos::getParametersFromXmlFile;
35 
39 
40 
41 // ************************************************************
42 // ************************************************************
44 {
45  std::vector<std::string> RKMethods;
46  RKMethods.push_back("General DIRK");
47  RKMethods.push_back("RK Backward Euler");
48  RKMethods.push_back("DIRK 1 Stage Theta Method");
49  RKMethods.push_back("RK Implicit 1 Stage 1st order Radau IA");
50  RKMethods.push_back("RK Implicit Midpoint");
51  RKMethods.push_back("SDIRK 2 Stage 2nd order");
52  RKMethods.push_back("RK Implicit 2 Stage 2nd order Lobatto IIIB");
53  RKMethods.push_back("SDIRK 2 Stage 3rd order");
54  RKMethods.push_back("EDIRK 2 Stage 3rd order");
55  RKMethods.push_back("EDIRK 2 Stage Theta Method");
56  RKMethods.push_back("SDIRK 3 Stage 4th order");
57  RKMethods.push_back("SDIRK 5 Stage 4th order");
58  RKMethods.push_back("SDIRK 5 Stage 5th order");
59  RKMethods.push_back("SDIRK 2(1) Pair");
60  RKMethods.push_back("RK Trapezoidal Rule");
61  RKMethods.push_back("RK Crank-Nicolson");
62 
63  for(std::vector<std::string>::size_type m = 0; m != RKMethods.size(); m++) {
64 
65  std::string RKMethod = RKMethods[m];
66 
67  // Read params from .xml file
68  RCP<ParameterList> pList =
69  getParametersFromXmlFile("Tempus_DIRK_SinCos.xml");
70 
71  // Setup the SinCosModel
72  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
73  auto model = rcp(new SinCosModel<double>(scm_pl));
74 
75  RCP<ParameterList> tempusPL = sublist(pList, "Tempus", true);
76  tempusPL->sublist("Default Stepper").set("Stepper Type", RKMethods[m]);
77 
78  if (RKMethods[m] == "DIRK 1 Stage Theta Method" ||
79  RKMethods[m] == "EDIRK 2 Stage Theta Method") {
80  // Construct in the same order as default.
81  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
82  RCP<ParameterList> solverPL = parameterList();
83  *solverPL = *(sublist(stepperPL, "Default Solver", true));
84  if (RKMethods[m] == "EDIRK 2 Stage Theta Method")
85  tempusPL->sublist("Default Stepper").set<bool>("Use FSAL", 1);
86  tempusPL->sublist("Default Stepper").remove("Zero Initial Guess");
87  tempusPL->sublist("Default Stepper").remove("Default Solver");
88  tempusPL->sublist("Default Stepper").set<bool>("Zero Initial Guess", 0);
89  tempusPL->sublist("Default Stepper").remove("Reset Initial Guess");
90  tempusPL->sublist("Default Stepper").set<bool>("Reset Initial Guess", 1);
91  tempusPL->sublist("Default Stepper").set("Default Solver", *solverPL);
92  tempusPL->sublist("Default Stepper").set<double>("theta", 0.5);
93  } else if (RKMethods[m] == "SDIRK 2 Stage 2nd order") {
94  // Construct in the same order as default.
95  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
96  RCP<ParameterList> solverPL = parameterList();
97  *solverPL = *(sublist(stepperPL, "Default Solver", true));
98  tempusPL->sublist("Default Stepper").remove("Default Solver");
99  tempusPL->sublist("Default Stepper").remove("Zero Initial Guess");
100  tempusPL->sublist("Default Stepper").set<bool>("Zero Initial Guess", 0);
101  tempusPL->sublist("Default Stepper").remove("Reset Initial Guess");
102  tempusPL->sublist("Default Stepper").set<bool>("Reset Initial Guess", 1);
103  tempusPL->sublist("Default Stepper").set("Default Solver", *solverPL);
104  tempusPL->sublist("Default Stepper")
105  .set<double>("gamma", 0.2928932188134524);
106  } else if (RKMethods[m] == "SDIRK 2 Stage 3rd order") {
107  // Construct in the same order as default.
108  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
109  RCP<ParameterList> solverPL = parameterList();
110  *solverPL = *(sublist(stepperPL, "Default Solver", true));
111  tempusPL->sublist("Default Stepper").remove("Zero Initial Guess");
112  tempusPL->sublist("Default Stepper").set<bool>("Zero Initial Guess", 0);
113  tempusPL->sublist("Default Stepper").remove("Default Solver");
114  tempusPL->sublist("Default Stepper").remove("Reset Initial Guess");
115  tempusPL->sublist("Default Stepper").set<bool>("Reset Initial Guess", 1);
116  tempusPL->sublist("Default Stepper").set("Default Solver", *solverPL);
117  tempusPL->sublist("Default Stepper")
118  .set<std::string>("Gamma Type", "3rd Order A-stable");
119  tempusPL->sublist("Default Stepper")
120  .set<double>("gamma", 0.7886751345948128);
121  } else if (RKMethods[m] == "RK Trapezoidal Rule") {
122  tempusPL->sublist("Default Stepper").set<bool>("Use FSAL", 1);
123  } else if (RKMethods[m] == "RK Crank-Nicolson") {
124  tempusPL->sublist("Default Stepper").set<bool>("Use FSAL", 1);
125  // Match default Stepper Type
126  tempusPL->sublist("Default Stepper")
127  .set("Stepper Type", "RK Trapezoidal Rule");
128  } else if (RKMethods[m] == "General DIRK") {
129  // Add the default tableau.
130  Teuchos::RCP<Teuchos::ParameterList> tableauPL = Teuchos::parameterList();
131  tableauPL->set<std::string>("A", "0.292893218813452 0; 0.707106781186548 0.292893218813452");
132  tableauPL->set<std::string>("b", "0.707106781186548 0.292893218813452");
133  tableauPL->set<std::string>("c", "0.292893218813452 1");
134  tableauPL->set<int>("order", 2);
135  tableauPL->set<std::string>("bstar", "");
136  tempusPL->sublist("Default Stepper").set("Tableau", *tableauPL);
137  }
138 
139 
140  // Test constructor IntegratorBasic(tempusPL, model)
141  {
143  Tempus::createIntegratorBasic<double>(tempusPL, model);
144 
145  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
146  RCP<ParameterList> defaultPL =
147  Teuchos::rcp_const_cast<Teuchos::ParameterList>(
148  integrator->getStepper()->getValidParameters());
149 
150  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
151  if (!pass) {
152  std::cout << std::endl;
153  std::cout << "stepperPL -------------- \n" << *stepperPL << std::endl;
154  std::cout << "defaultPL -------------- \n" << *defaultPL << std::endl;
155  }
156  TEST_ASSERT(pass)
157  }
158 
159  // Test constructor IntegratorBasic(model, stepperType)
160  {
162  Tempus::createIntegratorBasic<double>(model, RKMethods[m]);
163 
164  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
165  RCP<ParameterList> defaultPL =
166  Teuchos::rcp_const_cast<Teuchos::ParameterList>(
167  integrator->getStepper()->getValidParameters());
168 
169  // These Steppers have 'Initial Condition Consistency = Consistent'
170  // set as the default, so the ParameterList has been modified by
171  // NOX (filled in default parameters). Thus solver comparison
172  // will be removed.
173  if (RKMethods[m] == "EDIRK 2 Stage Theta Method" ||
174  RKMethods[m] == "RK Trapezoidal Rule" ||
175  RKMethods[m] == "RK Crank-Nicolson") {
176  stepperPL->set<std::string>("Initial Condition Consistency", "Consistent");
177  stepperPL->remove("Default Solver");
178  defaultPL->remove("Default Solver");
179  }
180 
181  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
182  if (!pass) {
183  std::cout << std::endl;
184  std::cout << "stepperPL -------------- \n" << *stepperPL << std::endl;
185  std::cout << "defaultPL -------------- \n" << *defaultPL << std::endl;
186  }
187  TEST_ASSERT(pass)
188  }
189  }
190 }
191 
192 
193 // ************************************************************
194 // ************************************************************
195 TEUCHOS_UNIT_TEST(DIRK, ConstructingFromDefaults)
196 {
197  double dt = 0.025;
198  std::vector<std::string> options;
199  options.push_back("Default Parameters");
200  options.push_back("ICConsistency and Check");
201 
202  for(const auto& option: options) {
203 
204  // Read params from .xml file
205  RCP<ParameterList> pList =
206  getParametersFromXmlFile("Tempus_DIRK_SinCos.xml");
207  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
208 
209  // Setup the SinCosModel
210  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
211  //RCP<SinCosModel<double> > model = sineCosineModel(scm_pl);
212  auto model = rcp(new SinCosModel<double>(scm_pl));
213 
214  // Setup Stepper for field solve ----------------------------
217  RCP<Tempus::Stepper<double> > stepper =
218  sf->createStepper("SDIRK 2 Stage 2nd order");
219  stepper->setModel(model);
220  if ( option == "ICConsistency and Check") {
221  stepper->setICConsistency("Consistent");
222  stepper->setICConsistencyCheck(true);
223  }
224  stepper->initialize();
225 
226  // Setup TimeStepControl ------------------------------------
227  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
228  ParameterList tscPL = pl->sublist("Default Integrator")
229  .sublist("Time Step Control");
230  timeStepControl->setInitIndex(tscPL.get<int> ("Initial Time Index"));
231  timeStepControl->setInitTime (tscPL.get<double>("Initial Time"));
232  timeStepControl->setFinalTime(tscPL.get<double>("Final Time"));
233  timeStepControl->setInitTimeStep(dt);
234  timeStepControl->initialize();
235 
236  // Setup initial condition SolutionState --------------------
237  auto inArgsIC = model->getNominalValues();
238  auto icSolution = rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x());
239  auto icState = Tempus::createSolutionStateX(icSolution);
240  icState->setTime (timeStepControl->getInitTime());
241  icState->setIndex (timeStepControl->getInitIndex());
242  icState->setTimeStep(0.0);
243  icState->setOrder (stepper->getOrder());
244  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
245 
246  // Setup SolutionHistory ------------------------------------
247  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
248  solutionHistory->setName("Forward States");
249  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
250  solutionHistory->setStorageLimit(2);
251  solutionHistory->addState(icState);
252 
253  // Setup Integrator -----------------------------------------
255  Tempus::createIntegratorBasic<double>();
256  integrator->setStepper(stepper);
257  integrator->setTimeStepControl(timeStepControl);
258  integrator->setSolutionHistory(solutionHistory);
259  //integrator->setObserver(...);
260  integrator->initialize();
261 
262 
263  // Integrate to timeMax
264  bool integratorStatus = integrator->advanceTime();
265  TEST_ASSERT(integratorStatus)
266 
267 
268  // Test if at 'Final Time'
269  double time = integrator->getTime();
270  double timeFinal =pl->sublist("Default Integrator")
271  .sublist("Time Step Control").get<double>("Final Time");
272  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
273 
274  // Time-integrated solution and the exact solution
275  RCP<Thyra::VectorBase<double> > x = integrator->getX();
277  model->getExactSolution(time).get_x();
278 
279  // Calculate the error
280  RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
281  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
282 
283  // Check the order and intercept
284  std::cout << " Stepper = " << stepper->description()
285  << " with " << option << std::endl;
286  std::cout << " =========================" << std::endl;
287  std::cout << " Exact solution : " << get_ele(*(x_exact), 0) << " "
288  << get_ele(*(x_exact), 1) << std::endl;
289  std::cout << " Computed solution: " << get_ele(*(x ), 0) << " "
290  << get_ele(*(x ), 1) << std::endl;
291  std::cout << " Difference : " << get_ele(*(xdiff ), 0) << " "
292  << get_ele(*(xdiff ), 1) << std::endl;
293  std::cout << " =========================" << std::endl;
294  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.841470, 1.0e-4 );
295  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.540304, 1.0e-4 );
296  }
297 }
298 
299 
300 // ************************************************************
301 // ************************************************************
302 TEUCHOS_UNIT_TEST(DIRK, useFSAL_false)
303 {
304  double dt = 0.1;
305  std::vector<std::string> RKMethods;
306  RKMethods.push_back("EDIRK 2 Stage Theta Method");
307  RKMethods.push_back("RK Trapezoidal Rule");
308 
309  for(std::vector<std::string>::size_type m = 0; m != RKMethods.size(); m++) {
310 
311  // Setup the SinCosModel ------------------------------------
312  auto model = rcp(new SinCosModel<double>());
313 
314  // Setup Stepper for field solve ----------------------------
316  auto stepper = sf->createStepper(RKMethods[m]);
317  stepper->setModel(model);
318  stepper->setUseFSAL(false);
319  stepper->initialize();
320 
321  // Setup TimeStepControl ------------------------------------
322  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
323  timeStepControl->setInitTime (0.0);
324  timeStepControl->setFinalTime(1.0);
325  timeStepControl->setInitTimeStep(dt);
326  timeStepControl->initialize();
327 
328  // Setup initial condition SolutionState --------------------
329  auto inArgsIC = model->getNominalValues();
330  auto icSolution = rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x());
331  auto icState = Tempus::createSolutionStateX(icSolution);
332  icState->setTime (timeStepControl->getInitTime());
333  icState->setIndex (timeStepControl->getInitIndex());
334  icState->setTimeStep(0.0);
335  icState->setOrder (stepper->getOrder());
336  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
337 
338  // Setup SolutionHistory ------------------------------------
339  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
340  solutionHistory->setName("Forward States");
341  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
342  solutionHistory->setStorageLimit(2);
343  solutionHistory->addState(icState);
344 
345  // Setup Integrator -----------------------------------------
346  auto integrator = Tempus::createIntegratorBasic<double>();
347  integrator->setStepper(stepper);
348  integrator->setTimeStepControl(timeStepControl);
349  integrator->setSolutionHistory(solutionHistory);
350  integrator->initialize();
351 
352 
353  // Integrate to timeMax
354  bool integratorStatus = integrator->advanceTime();
355  TEST_ASSERT(integratorStatus)
356 
357 
358  // Test if at 'Final Time'
359  double time = integrator->getTime();
360  TEST_FLOATING_EQUALITY(time, 1.0, 1.0e-14);
361 
362  // Time-integrated solution and the exact solution
363  auto x = integrator->getX();
364  auto x_exact = model->getExactSolution(time).get_x();
365 
366  // Calculate the error
367  RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
368  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
369 
370  // Check the order and intercept
371  std::cout << " Stepper = " << stepper->description()
372  << "\n with " << "useFSAL=false" << std::endl;
373  std::cout << " =========================" << std::endl;
374  std::cout << " Exact solution : " << get_ele(*(x_exact), 0) << " "
375  << get_ele(*(x_exact), 1) << std::endl;
376  std::cout << " Computed solution: " << get_ele(*(x ), 0) << " "
377  << get_ele(*(x ), 1) << std::endl;
378  std::cout << " Difference : " << get_ele(*(xdiff ), 0) << " "
379  << get_ele(*(xdiff ), 1) << std::endl;
380  std::cout << " =========================" << std::endl;
381  if (RKMethods[m] == "EDIRK 2 Stage Theta Method") {
382  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.841021, 1.0e-4 );
383  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.541002, 1.0e-4 );
384  } else if (RKMethods[m] == "RK Trapezoidal Rule") {
385  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.841021, 1.0e-4 );
386  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.541002, 1.0e-4 );
387  }
388  }
389 }
390 
391 
392 // ************************************************************
393 // ************************************************************
394 TEUCHOS_UNIT_TEST(DIRK, SinCos)
395 {
396  std::vector<std::string> RKMethods;
397  RKMethods.push_back("General DIRK");
398  RKMethods.push_back("RK Backward Euler");
399  RKMethods.push_back("DIRK 1 Stage Theta Method");
400  RKMethods.push_back("RK Implicit 1 Stage 1st order Radau IA");
401  RKMethods.push_back("RK Implicit Midpoint");
402  RKMethods.push_back("SDIRK 2 Stage 2nd order");
403  RKMethods.push_back("RK Implicit 2 Stage 2nd order Lobatto IIIB");
404  RKMethods.push_back("SDIRK 2 Stage 3rd order");
405  RKMethods.push_back("EDIRK 2 Stage 3rd order");
406  RKMethods.push_back("EDIRK 2 Stage Theta Method");
407  RKMethods.push_back("SDIRK 3 Stage 4th order");
408  RKMethods.push_back("SDIRK 5 Stage 4th order");
409  RKMethods.push_back("SDIRK 5 Stage 5th order");
410  RKMethods.push_back("SDIRK 2(1) Pair");
411  RKMethods.push_back("RK Trapezoidal Rule");
412  RKMethods.push_back("RK Crank-Nicolson");
413  RKMethods.push_back("SSPDIRK22");
414  RKMethods.push_back("SSPDIRK32");
415  RKMethods.push_back("SSPDIRK23");
416  RKMethods.push_back("SSPDIRK33");
417  RKMethods.push_back("SDIRK 3 Stage 2nd order");
418 
419  std::vector<double> RKMethodErrors;
420  RKMethodErrors.push_back(2.52738e-05);
421  RKMethodErrors.push_back(0.0124201);
422  RKMethodErrors.push_back(5.20785e-05);
423  RKMethodErrors.push_back(0.0124201);
424  RKMethodErrors.push_back(5.20785e-05);
425  RKMethodErrors.push_back(2.52738e-05);
426  RKMethodErrors.push_back(5.20785e-05);
427  RKMethodErrors.push_back(1.40223e-06);
428  RKMethodErrors.push_back(2.17004e-07);
429  RKMethodErrors.push_back(5.20785e-05);
430  RKMethodErrors.push_back(6.41463e-08);
431  RKMethodErrors.push_back(3.30631e-10);
432  RKMethodErrors.push_back(1.35728e-11);
433  RKMethodErrors.push_back(0.0001041);
434  RKMethodErrors.push_back(5.20785e-05);
435  RKMethodErrors.push_back(5.20785e-05);
436  RKMethodErrors.push_back(1.30205e-05);
437  RKMethodErrors.push_back(5.7869767e-06);
438  RKMethodErrors.push_back(1.00713e-07);
439  RKMethodErrors.push_back(3.94916e-08);
440  RKMethodErrors.push_back(2.52738e-05);
441 
442  TEUCHOS_ASSERT( RKMethods.size() == RKMethodErrors.size() );
443 
444  for(std::vector<std::string>::size_type m = 0; m != RKMethods.size(); m++) {
445 
446  std::string RKMethod = RKMethods[m];
447  std::replace(RKMethod.begin(), RKMethod.end(), ' ', '_');
448  std::replace(RKMethod.begin(), RKMethod.end(), '/', '.');
449 
451  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
452  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
453  std::vector<double> StepSize;
454  std::vector<double> xErrorNorm;
455  std::vector<double> xDotErrorNorm;
456 
457  const int nTimeStepSizes = 2; // 7 for error plots
458  double dt = 0.05;
459  double time = 0.0;
460  for (int n=0; n<nTimeStepSizes; n++) {
461 
462  // Read params from .xml file
463  RCP<ParameterList> pList =
464  getParametersFromXmlFile("Tempus_DIRK_SinCos.xml");
465 
466  // Setup the SinCosModel
467  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
468  auto model = rcp(new SinCosModel<double>(scm_pl));
469 
470  // Set the Stepper
471  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
472  pl->sublist("Default Stepper").set("Stepper Type", RKMethods[m]);
473  if (RKMethods[m] == "DIRK 1 Stage Theta Method" ||
474  RKMethods[m] == "EDIRK 2 Stage Theta Method") {
475  pl->sublist("Default Stepper").set<double>("theta", 0.5);
476  } else if (RKMethods[m] == "SDIRK 2 Stage 2nd order") {
477  pl->sublist("Default Stepper").set("gamma", 0.2928932188134524);
478  } else if (RKMethods[m] == "SDIRK 2 Stage 3rd order") {
479  pl->sublist("Default Stepper")
480  .set<std::string>("Gamma Type", "3rd Order A-stable");
481  }
482 
483  dt /= 2;
484 
485  // Setup the Integrator and reset initial time step
486  pl->sublist("Default Integrator")
487  .sublist("Time Step Control").set("Initial Time Step", dt);
488  integrator = Tempus::createIntegratorBasic<double>(pl, model);
489 
490  // Initial Conditions
491  // During the Integrator construction, the initial SolutionState
492  // is set by default to model->getNominalVales().get_x(). However,
493  // the application can set it also by integrator->initializeSolutionHistory.
495  model->getNominalValues().get_x()->clone_v();
496  integrator->initializeSolutionHistory(0.0, x0);
497 
498  // Integrate to timeMax
499  bool integratorStatus = integrator->advanceTime();
500  TEST_ASSERT(integratorStatus)
501 
502  // Test if at 'Final Time'
503  time = integrator->getTime();
504  double timeFinal = pl->sublist("Default Integrator")
505  .sublist("Time Step Control").get<double>("Final Time");
506  double tol = 100.0 * std::numeric_limits<double>::epsilon();
507  TEST_FLOATING_EQUALITY(time, timeFinal, tol);
508 
509  // Plot sample solution and exact solution
510  if (n == 0) {
511  RCP<const SolutionHistory<double> > solutionHistory =
512  integrator->getSolutionHistory();
513  writeSolution("Tempus_"+RKMethod+"_SinCos.dat", solutionHistory);
514 
515  auto solnHistExact = rcp(new Tempus::SolutionHistory<double>());
516  for (int i=0; i<solutionHistory->getNumStates(); i++) {
517  double time_i = (*solutionHistory)[i]->getTime();
518  auto state = Tempus::createSolutionStateX(
519  rcp_const_cast<Thyra::VectorBase<double> > (
520  model->getExactSolution(time_i).get_x()),
521  rcp_const_cast<Thyra::VectorBase<double> > (
522  model->getExactSolution(time_i).get_x_dot()));
523  state->setTime((*solutionHistory)[i]->getTime());
524  solnHistExact->addState(state);
525  }
526  writeSolution("Tempus_"+RKMethod+"_SinCos-Ref.dat", solnHistExact);
527  }
528 
529  // Store off the final solution and step size
530  StepSize.push_back(dt);
531  auto solution = Thyra::createMember(model->get_x_space());
532  Thyra::copy(*(integrator->getX()),solution.ptr());
533  solutions.push_back(solution);
534  auto solutionDot = Thyra::createMember(model->get_x_space());
535  Thyra::copy(*(integrator->getXDot()),solutionDot.ptr());
536  solutionsDot.push_back(solutionDot);
537  if (n == nTimeStepSizes-1) { // Add exact solution last in vector.
538  StepSize.push_back(0.0);
539  auto solutionExact = Thyra::createMember(model->get_x_space());
540  Thyra::copy(*(model->getExactSolution(time).get_x()),solutionExact.ptr());
541  solutions.push_back(solutionExact);
542  auto solutionDotExact = Thyra::createMember(model->get_x_space());
543  Thyra::copy(*(model->getExactSolution(time).get_x_dot()),
544  solutionDotExact.ptr());
545  solutionsDot.push_back(solutionDotExact);
546  }
547  }
548 
549  // Check the order and intercept
550  double xSlope = 0.0;
551  double xDotSlope = 0.0;
552  RCP<Tempus::Stepper<double> > stepper = integrator->getStepper();
553  double order = stepper->getOrder();
554  writeOrderError("Tempus_"+RKMethod+"_SinCos-Error.dat",
555  stepper, StepSize,
556  solutions, xErrorNorm, xSlope,
557  solutionsDot, xDotErrorNorm, xDotSlope);
558 
559  TEST_FLOATING_EQUALITY( xSlope, order, 0.01 );
560  TEST_FLOATING_EQUALITY( xErrorNorm[0], RKMethodErrors[m], 5.0e-4 );
561  // xDot not yet available for DIRK methods.
562  //TEST_FLOATING_EQUALITY( xDotSlope, order, 0.01 );
563  //TEST_FLOATING_EQUALITY( xDotErrorNorm[0], 0.0486418, 1.0e-4 );
564 
565  }
566 }
567 
568 
569 // ************************************************************
570 // ************************************************************
571 TEUCHOS_UNIT_TEST(DIRK, VanDerPol)
572 {
573  std::vector<std::string> RKMethods;
574  RKMethods.push_back("SDIRK 2 Stage 2nd order");
575 
576  std::string RKMethod = RKMethods[0];
577  std::replace(RKMethod.begin(), RKMethod.end(), ' ', '_');
578  std::replace(RKMethod.begin(), RKMethod.end(), '/', '.');
579 
581  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
582  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
583  std::vector<double> StepSize;
584  std::vector<double> xErrorNorm;
585  std::vector<double> xDotErrorNorm;
586 
587  const int nTimeStepSizes = 3; // 8 for error plot
588  double dt = 0.05;
589  double time = 0.0;
590  for (int n=0; n<nTimeStepSizes; n++) {
591 
592  // Read params from .xml file
593  RCP<ParameterList> pList =
594  getParametersFromXmlFile("Tempus_DIRK_VanDerPol.xml");
595 
596  // Setup the VanDerPolModel
597  RCP<ParameterList> vdpm_pl = sublist(pList, "VanDerPolModel", true);
598  auto model = rcp(new VanDerPolModel<double>(vdpm_pl));
599 
600  // Set the Stepper
601  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
602  pl->sublist("Default Stepper").set("Stepper Type", RKMethods[0]);
603  pl->sublist("Default Stepper").set("gamma", 0.2928932188134524);
604 
605  // Set the step size
606  dt /= 2;
607  if (n == nTimeStepSizes-1) dt /= 10.0;
608 
609  // Setup the Integrator and reset initial time step
610  pl->sublist("Default Integrator")
611  .sublist("Time Step Control").set("Initial Time Step", dt);
612  integrator = Tempus::createIntegratorBasic<double>(pl, model);
613 
614  // Integrate to timeMax
615  bool integratorStatus = integrator->advanceTime();
616  TEST_ASSERT(integratorStatus)
617 
618  // Test if at 'Final Time'
619  time = integrator->getTime();
620  double timeFinal =pl->sublist("Default Integrator")
621  .sublist("Time Step Control").get<double>("Final Time");
622  double tol = 100.0 * std::numeric_limits<double>::epsilon();
623  TEST_FLOATING_EQUALITY(time, timeFinal, tol);
624 
625  // Store off the final solution and step size
626  StepSize.push_back(dt);
627  auto solution = Thyra::createMember(model->get_x_space());
628  Thyra::copy(*(integrator->getX()),solution.ptr());
629  solutions.push_back(solution);
630  auto solutionDot = Thyra::createMember(model->get_x_space());
631  Thyra::copy(*(integrator->getXDot()),solutionDot.ptr());
632  solutionsDot.push_back(solutionDot);
633 
634  // Output finest temporal solution for plotting
635  // This only works for ONE MPI process
636  if ((n == 0) || (n == nTimeStepSizes-1)) {
637  std::string fname = "Tempus_"+RKMethod+"_VanDerPol-Ref.dat";
638  if (n == 0) fname = "Tempus_"+RKMethod+"_VanDerPol.dat";
639  RCP<const SolutionHistory<double> > solutionHistory =
640  integrator->getSolutionHistory();
641  writeSolution(fname, solutionHistory);
642  }
643  }
644 
645  // Check the order and intercept
646  double xSlope = 0.0;
647  double xDotSlope = 0.0;
648  RCP<Tempus::Stepper<double> > stepper = integrator->getStepper();
649  double order = stepper->getOrder();
650  writeOrderError("Tempus_"+RKMethod+"_VanDerPol-Error.dat",
651  stepper, StepSize,
652  solutions, xErrorNorm, xSlope,
653  solutionsDot, xDotErrorNorm, xDotSlope);
654 
655  TEST_FLOATING_EQUALITY( xSlope, order, 0.06 );
656  TEST_FLOATING_EQUALITY( xErrorNorm[0], 1.07525e-05, 1.0e-4 );
657  // xDot not yet available for DIRK methods.
658  //TEST_FLOATING_EQUALITY( xDotSlope, 1.74898, 0.10 );
659  //TEST_FLOATING_EQUALITY( xDotErrorNorm[0], 1.0038, 1.0e-4 );
660 
662 }
663 
664 
665 // ************************************************************
666 // ************************************************************
667 TEUCHOS_UNIT_TEST(DIRK, EmbeddedVanDerPol)
668 {
669 
670  std::vector<std::string> IntegratorList;
671  IntegratorList.push_back("Embedded_Integrator_PID");
672  IntegratorList.push_back("Embedded_Integrator");
673 
674  // the embedded solution will test the following:
675  const int refIstep = 217;
676 
677  for(auto integratorChoice : IntegratorList){
678 
679  std::cout << "Using Integrator: " << integratorChoice << " !!!" << std::endl;
680 
681  // Read params from .xml file
682  RCP<ParameterList> pList =
683  getParametersFromXmlFile("Tempus_DIRK_VanDerPol.xml");
684 
685 
686  // Setup the VanDerPolModel
687  RCP<ParameterList> vdpm_pl = sublist(pList, "VanDerPolModel", true);
688  auto model = rcp(new VanDerPolModel<double>(vdpm_pl));
689 
690  // Set the Integrator and Stepper
691  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
692  pl->set("Integrator Name", integratorChoice);
693 
694  // Setup the Integrator
696  Tempus::createIntegratorBasic<double>(pl, model);
697 
698  const std::string RKMethod_ =
699  pl->sublist(integratorChoice).get<std::string>("Stepper Name");
700 
701  // Integrate to timeMax
702  bool integratorStatus = integrator->advanceTime();
703  TEST_ASSERT(integratorStatus);
704 
705  // Test if at 'Final Time'
706  double time = integrator->getTime();
707  double timeFinal = pl->sublist(integratorChoice)
708  .sublist("Time Step Control").get<double>("Final Time");
709  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
710 
711 
712  // Numerical reference solution at timeFinal (for \epsilon = 0.1)
713  RCP<Thyra::VectorBase<double> > x = integrator->getX();
714  RCP<Thyra::VectorBase<double> > xref = x->clone_v();
715  Thyra::set_ele(0, -1.5484458614405929, xref.ptr());
716  Thyra::set_ele(1, 1.0181127316101317, xref.ptr());
717 
718  // Calculate the error
719  RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
720  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *xref, -1.0, *(x));
721  const double L2norm = Thyra::norm_2(*xdiff);
722 
723  // Test number of steps, failures, and accuracy
724  if (integratorChoice == "Embedded_Integrator_PID"){
725  const double absTol = pl->sublist(integratorChoice).
726  sublist("Time Step Control").get<double>("Maximum Absolute Error");
727  const double relTol = pl->sublist(integratorChoice).
728  sublist("Time Step Control").get<double>("Maximum Relative Error");
729 
730 
731  // get the number of time steps and number of step failure
732  //const int nFailure_c = integrator->getSolutionHistory()->
733  //getCurrentState()->getMetaData()->getNFailures();
734  const int iStep = integrator->getSolutionHistory()->
735  getCurrentState()->getIndex();
736  //const int nFail = integrator->getSolutionHistory()->
737  // getCurrentState()->getMetaData()->getNRunningFailures();
738 
739  // Should be close to the prescribed tolerance
740  TEST_FLOATING_EQUALITY(std::log10(L2norm),std::log10(absTol), 0.3 );
741  TEST_FLOATING_EQUALITY(std::log10(L2norm),std::log10(relTol), 0.3 );
742  // test for number of steps
743  TEST_COMPARE(iStep, <=, refIstep);
744  }
745 
746  // Plot sample solution and exact solution
747  std::ofstream ftmp("Tempus_"+integratorChoice+RKMethod_+"_VDP_Example.dat");
748  RCP<const SolutionHistory<double> > solutionHistory =
749  integrator->getSolutionHistory();
750  int nStates = solutionHistory->getNumStates();
751  //RCP<const Thyra::VectorBase<double> > x_exact_plot;
752  for (int i=0; i<nStates; i++) {
753  RCP<const SolutionState<double> > solutionState = (*solutionHistory)[i];
754  double time_i = solutionState->getTime();
755  RCP<const Thyra::VectorBase<double> > x_plot = solutionState->getX();
756  //x_exact_plot = model->getExactSolution(time_i).get_x();
757  ftmp << time_i << " "
758  << Thyra::get_ele(*(x_plot), 0) << " "
759  << Thyra::get_ele(*(x_plot), 1) << " " << std::endl;
760  }
761  ftmp.close();
762  }
763 
765 }
766 
767 
768 } // namespace Tempus_Test
Teuchos::RCP< SolutionState< Scalar > > createSolutionStateX(const Teuchos::RCP< Thyra::VectorBase< Scalar > > &x, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xdot=Teuchos::null, const Teuchos::RCP< Thyra::VectorBase< Scalar > > &xdotdot=Teuchos::null)
Nonmember constructor from non-const solution vectors, x.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#define TEST_COMPARE(v1, comp, v2)
#define TEST_FLOATING_EQUALITY(v1, v2, tol)
#define TEST_ASSERT(v1)
T * get() const
Sine-Cosine model problem from Rythmos. This is a canonical Sine-Cosine differential equation with a...
void writeSolution(const std::string filename, Teuchos::RCP< const Tempus::SolutionHistory< Scalar > > solutionHistory)
void writeOrderError(const std::string filename, Teuchos::RCP< Tempus::Stepper< Scalar > > stepper, std::vector< Scalar > &StepSize, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutions, std::vector< Scalar > &xErrorNorm, Scalar &xSlope, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutionsDot, std::vector< Scalar > &xDotErrorNorm, Scalar &xDotSlope, std::vector< Teuchos::RCP< Thyra::VectorBase< Scalar >>> &solutionsDotDot, std::vector< Scalar > &xDotDotErrorNorm, Scalar &xDotDotSlope)
bool remove(std::string const &name, bool throwIfNotExists=true)
TEUCHOS_UNIT_TEST(BackwardEuler, SinCos_ASA)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static void summarize(Ptr< const Comm< int > > comm, std::ostream &out=std::cout, const bool alwaysWriteLocal=false, const bool writeGlobalStats=true, const bool writeZeroTimers=true, const ECounterSetOp setOp=Intersection, const std::string &filter="", const bool ignoreZeroTimers=false)
Ptr< T > ptr() const
TimeStepControl manages the time step size. There several mechanisms that effect the time step size a...
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Keep a fix number of states.
van der Pol model problem for nonlinear electrical circuit.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
#define TEUCHOS_ASSERT(assertion_test)
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...