Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_IMEX_RKTest.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_WrapperModelEvaluatorPairIMEX_Basic.hpp"
17 #include "Tempus_StepperIMEX_RK.hpp"
18 
19 #include "../TestModels/VanDerPol_IMEX_ExplicitModel.hpp"
20 #include "../TestModels/VanDerPol_IMEX_ImplicitModel.hpp"
21 #include "../TestUtils/Tempus_ConvergenceTestUtils.hpp"
22 
23 #include <fstream>
24 #include <vector>
25 
26 namespace Tempus_Test {
27 
28 using Teuchos::getParametersFromXmlFile;
30 using Teuchos::RCP;
31 using Teuchos::rcp;
32 using Teuchos::rcp_const_cast;
33 using Teuchos::sublist;
34 
38 
39 // ************************************************************
40 // ************************************************************
41 TEUCHOS_UNIT_TEST(IMEX_RK, ConstructingFromDefaults)
42 {
43  double dt = 0.025;
44 
45  // Read params from .xml file
46  RCP<ParameterList> pList =
47  getParametersFromXmlFile("Tempus_IMEX_RK_VanDerPol.xml");
48  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
49 
50  // Setup the explicit VanDerPol ModelEvaluator
51  RCP<ParameterList> vdpmPL = sublist(pList, "VanDerPolModel", true);
52  auto explicitModel = rcp(new VanDerPol_IMEX_ExplicitModel<double>(vdpmPL));
53 
54  // Setup the implicit VanDerPol ModelEvaluator (reuse vdpmPL)
55  auto implicitModel = rcp(new VanDerPol_IMEX_ImplicitModel<double>(vdpmPL));
56 
57  // Setup the IMEX Pair ModelEvaluator
59  explicitModel, implicitModel));
60 
61  // Setup Stepper for field solve ----------------------------
62  auto stepper = rcp(new Tempus::StepperIMEX_RK<double>());
63  stepper->setModel(model);
64  stepper->initialize();
65 
66  // Setup TimeStepControl ------------------------------------
67  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
68  ParameterList tscPL =
69  pl->sublist("Default Integrator").sublist("Time Step Control");
70  timeStepControl->setInitIndex(tscPL.get<int>("Initial Time Index"));
71  timeStepControl->setInitTime(tscPL.get<double>("Initial Time"));
72  timeStepControl->setFinalTime(tscPL.get<double>("Final Time"));
73  timeStepControl->setInitTimeStep(dt);
74  timeStepControl->initialize();
75 
76  // Setup initial condition SolutionState --------------------
77  auto inArgsIC = model->getNominalValues();
78  auto icSolution = rcp_const_cast<Thyra::VectorBase<double>>(inArgsIC.get_x());
79  auto icState = Tempus::createSolutionStateX(icSolution);
80  icState->setTime(timeStepControl->getInitTime());
81  icState->setIndex(timeStepControl->getInitIndex());
82  icState->setTimeStep(0.0);
83  icState->setOrder(stepper->getOrder());
84  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
85 
86  // Setup SolutionHistory ------------------------------------
87  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
88  solutionHistory->setName("Forward States");
89  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
90  solutionHistory->setStorageLimit(2);
91  solutionHistory->addState(icState);
92 
93  // Setup Integrator -----------------------------------------
95  Tempus::createIntegratorBasic<double>();
96  integrator->setStepper(stepper);
97  integrator->setTimeStepControl(timeStepControl);
98  integrator->setSolutionHistory(solutionHistory);
99  integrator->initialize();
100 
101  // Integrate to timeMax
102  bool integratorStatus = integrator->advanceTime();
103  TEST_ASSERT(integratorStatus)
104 
105  // Test if at 'Final Time'
106  double time = integrator->getTime();
107  double timeFinal = pl->sublist("Default Integrator")
108  .sublist("Time Step Control")
109  .get<double>("Final Time");
110  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
111 
112  // Time-integrated solution and the exact solution
113  RCP<Thyra::VectorBase<double>> x = integrator->getX();
114 
115  // Check the order and intercept
116  out << " Stepper = " << stepper->description() << std::endl;
117  out << " =========================" << std::endl;
118  out << " Computed solution: " << get_ele(*(x), 0) << " "
119  << get_ele(*(x), 1) << std::endl;
120  out << " =========================" << std::endl;
121  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 1.810210, 1.0e-4);
122  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), -0.754602, 1.0e-4);
123 }
124 
125 // ************************************************************
126 // ************************************************************
127 TEUCHOS_UNIT_TEST(IMEX_RK, VanDerPol)
128 {
129  std::vector<std::string> stepperTypes;
130  stepperTypes.push_back("IMEX RK 1st order");
131  stepperTypes.push_back("SSP1_111");
132  stepperTypes.push_back("IMEX RK SSP2");
133  stepperTypes.push_back("SSP2_222");
134  stepperTypes.push_back("IMEX RK ARS 233");
135  stepperTypes.push_back("General IMEX RK");
136  stepperTypes.push_back("IMEX RK SSP3");
137 
138  std::vector<double> stepperOrders;
139  stepperOrders.push_back(1.07964);
140  stepperOrders.push_back(1.07964); // SSP1_111
141  stepperOrders.push_back(2.00408);
142  stepperOrders.push_back(2.76941); // SSP2_222
143  stepperOrders.push_back(2.70655);
144  stepperOrders.push_back(2.00211);
145  stepperOrders.push_back(2.00211);
146 
147  std::vector<double> stepperErrors;
148  stepperErrors.push_back(0.0046423);
149  stepperErrors.push_back(0.103569); // SSP1_111
150  stepperErrors.push_back(0.0154534);
151  stepperErrors.push_back(0.000533759); // SSP2_222
152  stepperErrors.push_back(0.000298908);
153  stepperErrors.push_back(0.0071546);
154  stepperErrors.push_back(0.0151202);
155 
156  std::vector<double> stepperInitDt;
157  stepperInitDt.push_back(0.0125);
158  stepperInitDt.push_back(0.0125);
159  stepperInitDt.push_back(0.05);
160  stepperInitDt.push_back(0.05);
161  stepperInitDt.push_back(0.05);
162  stepperInitDt.push_back(0.05);
163  stepperInitDt.push_back(0.05);
164 
165  TEUCHOS_ASSERT(stepperTypes.size() == stepperOrders.size());
166  TEUCHOS_ASSERT(stepperTypes.size() == stepperErrors.size());
167  TEUCHOS_ASSERT(stepperTypes.size() == stepperInitDt.size());
168 
169  std::vector<std::string>::size_type m;
170  for (m = 0; m != stepperTypes.size(); m++) {
171  std::string stepperType = stepperTypes[m];
172  std::string stepperName = stepperTypes[m];
173  std::replace(stepperName.begin(), stepperName.end(), ' ', '_');
174  std::replace(stepperName.begin(), stepperName.end(), '/', '.');
175 
177  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
178  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
179  std::vector<double> StepSize;
180  std::vector<double> xErrorNorm;
181  std::vector<double> xDotErrorNorm;
182 
183  const int nTimeStepSizes = 3; // 6 for error plot
184  double dt = stepperInitDt[m];
185  double time = 0.0;
186  for (int n = 0; n < nTimeStepSizes; n++) {
187  // Read params from .xml file
188  RCP<ParameterList> pList =
189  getParametersFromXmlFile("Tempus_IMEX_RK_VanDerPol.xml");
190 
191  // Setup the explicit VanDerPol ModelEvaluator
192  RCP<ParameterList> vdpmPL = sublist(pList, "VanDerPolModel", true);
193  auto explicitModel =
195 
196  // Setup the implicit VanDerPol ModelEvaluator (reuse vdpmPL)
197  auto implicitModel =
199 
200  // Setup the IMEX Pair ModelEvaluator
202  explicitModel, implicitModel));
203 
204  // Set the Stepper
205  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
206  if (stepperType == "General IMEX RK") {
207  // use the appropriate stepper sublist
208  pl->sublist("Default Integrator")
209  .set("Stepper Name", "General IMEX RK");
210  }
211  else {
212  pl->sublist("Default Stepper").set("Stepper Type", stepperType);
213  }
214 
215  // Set the step size
216  if (n == nTimeStepSizes - 1)
217  dt /= 10.0;
218  else
219  dt /= 2;
220 
221  // Setup the Integrator and reset initial time step
222  pl->sublist("Default Integrator")
223  .sublist("Time Step Control")
224  .set("Initial Time Step", dt);
225  integrator = Tempus::createIntegratorBasic<double>(pl, model);
226 
227  // Integrate to timeMax
228  bool integratorStatus = integrator->advanceTime();
229  TEST_ASSERT(integratorStatus)
230 
231  // Test if at 'Final Time'
232  time = integrator->getTime();
233  double timeFinal = pl->sublist("Default Integrator")
234  .sublist("Time Step Control")
235  .get<double>("Final Time");
236  double tol = 100.0 * std::numeric_limits<double>::epsilon();
237  TEST_FLOATING_EQUALITY(time, timeFinal, tol);
238 
239  // Store off the final solution and step size
240  StepSize.push_back(dt);
241  auto solution = Thyra::createMember(model->get_x_space());
242  Thyra::copy(*(integrator->getX()), solution.ptr());
243  solutions.push_back(solution);
244  auto solutionDot = Thyra::createMember(model->get_x_space());
245  Thyra::copy(*(integrator->getXDot()), solutionDot.ptr());
246  solutionsDot.push_back(solutionDot);
247 
248  // Output finest temporal solution for plotting
249  // This only works for ONE MPI process
250  if ((n == 0) || (n == nTimeStepSizes - 1)) {
251  std::string fname = "Tempus_" + stepperName + "_VanDerPol-Ref.dat";
252  if (n == 0) fname = "Tempus_" + stepperName + "_VanDerPol.dat";
253  RCP<const SolutionHistory<double>> solutionHistory =
254  integrator->getSolutionHistory();
255  writeSolution(fname, solutionHistory);
256  }
257  }
258 
259  // Check the order and intercept
260  double xSlope = 0.0;
261  double xDotSlope = 0.0;
262  RCP<Tempus::Stepper<double>> stepper = integrator->getStepper();
263  // double order = stepper->getOrder();
264 
265  // xDot not yet available for IMEX-RK methods, e.g., are not calc. and zero.
266  solutionsDot.clear();
267 
268  writeOrderError("Tempus_" + stepperName + "_VanDerPol-Error.dat", stepper,
269  StepSize, solutions, xErrorNorm, xSlope, solutionsDot,
270  xDotErrorNorm, xDotSlope, out);
271 
272  TEST_FLOATING_EQUALITY(xSlope, stepperOrders[m], 0.02);
273  TEST_FLOATING_EQUALITY(xErrorNorm[0], stepperErrors[m], 1.0e-4);
274  // TEST_FLOATING_EQUALITY( xDotSlope, 1.74898, 0.10 );
275  // TEST_FLOATING_EQUALITY( xDotErrorNorm[0], 1.0038, 1.0e-4 );
276  }
277  // Teuchos::TimeMonitor::summarize();
278 }
279 
280 } // 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)
ModelEvaluator pair for implicit and explicit (IMEX) evaulations.
Implicit-Explicit Runge-Kutta (IMEX-RK) time stepper.
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, Teuchos::FancyOStream &out)
#define TEST_FLOATING_EQUALITY(v1, v2, tol)
#define TEST_ASSERT(v1)
void writeSolution(const std::string filename, Teuchos::RCP< const Tempus::SolutionHistory< Scalar >> solutionHistory)
TEUCHOS_UNIT_TEST(BackwardEuler, SinCos_ASA)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
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.
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
#define TEUCHOS_ASSERT(assertion_test)
Solution state for integrators and steppers.