Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_TrapezoidalTest.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 #include "Teuchos_DefaultComm.hpp"
13 
14 #include "Tempus_config.hpp"
15 #include "Tempus_IntegratorBasic.hpp"
16 #include "Tempus_StepperTrapezoidal.hpp"
17 
18 #include "../TestModels/SinCosModel.hpp"
19 #include "../TestModels/VanDerPolModel.hpp"
20 #include "../TestUtils/Tempus_ConvergenceTestUtils.hpp"
21 
22 #include <vector>
23 #include <fstream>
24 #include <sstream>
25 #include <limits>
26 
27 namespace Tempus_Test {
28 
29 using Teuchos::getParametersFromXmlFile;
31 using Teuchos::RCP;
32 using Teuchos::rcp;
33 using Teuchos::rcp_const_cast;
34 using Teuchos::sublist;
35 
39 
40 // ************************************************************
41 // ************************************************************
43 {
44  // Read params from .xml file
45  RCP<ParameterList> pList =
46  getParametersFromXmlFile("Tempus_Trapezoidal_SinCos.xml");
47 
48  // Setup the SinCosModel
49  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
50  auto model = rcp(new SinCosModel<double>(scm_pl));
51 
52  RCP<ParameterList> tempusPL = sublist(pList, "Tempus", true);
53 
54  // Test constructor IntegratorBasic(tempusPL, model)
55  {
57  Tempus::createIntegratorBasic<double>(tempusPL, model);
58 
59  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
60 
61  RCP<const ParameterList> defaultPL =
62  integrator->getStepper()->getValidParameters();
63  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
64  if (!pass) {
65  out << std::endl;
66  out << "stepperPL -------------- \n"
67  << *stepperPL << std::endl;
68  out << "defaultPL -------------- \n"
69  << *defaultPL << std::endl;
70  }
71  TEST_ASSERT(pass)
72  }
73 
74  // Test constructor IntegratorBasic(model, stepperType)
75  {
77  Tempus::createIntegratorBasic<double>(
78  model, std::string("Trapezoidal Method"));
79 
80  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
81  RCP<const ParameterList> defaultPL =
82  integrator->getStepper()->getValidParameters();
83 
84  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
85  if (!pass) {
86  out << std::endl;
87  out << "stepperPL -------------- \n"
88  << *stepperPL << std::endl;
89  out << "defaultPL -------------- \n"
90  << *defaultPL << std::endl;
91  }
92  TEST_ASSERT(pass)
93  }
94 }
95 
96 // ************************************************************
97 // ************************************************************
98 TEUCHOS_UNIT_TEST(Trapezoidal, ConstructingFromDefaults)
99 {
100  double dt = 0.1;
101  std::vector<std::string> options;
102  options.push_back("Default Parameters");
103  options.push_back("ICConsistency and Check");
104 
105  for (const auto& option : options) {
106  // Read params from .xml file
107  RCP<ParameterList> pList =
108  getParametersFromXmlFile("Tempus_Trapezoidal_SinCos.xml");
109  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
110 
111  // Setup the SinCosModel
112  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
113  // RCP<SinCosModel<double> > model = sineCosineModel(scm_pl);
114  auto model = rcp(new SinCosModel<double>(scm_pl));
115 
116  // Setup Stepper for field solve ----------------------------
117  auto stepper = rcp(new Tempus::StepperTrapezoidal<double>());
118  //{
119  // // Turn on NOX output.
120  // RCP<ParameterList> sPL = stepper->getNonconstParameterList();
121  // std::string solverName = sPL->get<std::string>("Solver Name");
122  // RCP<ParameterList> solverPL = Teuchos::sublist(sPL, solverName, true);
123  // solverPL->sublist("NOX").sublist("Printing")
124  // .sublist("Output Information").set("Outer Iteration", true);
125  // solverPL->sublist("NOX").sublist("Printing")
126  // .sublist("Output Information").set("Parameters", true);
127  // solverPL->sublist("NOX").sublist("Printing")
128  // .sublist("Output Information").set("Details", true);
129  // stepper->setSolver(solverPL);
130  //}
131  stepper->setModel(model);
132  if (option == "ICConsistency and Check") {
133  stepper->setICConsistency("Consistent");
134  stepper->setICConsistencyCheck(true);
135  }
136  stepper->initialize();
137 
138  // Setup TimeStepControl ------------------------------------
139  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
140  ParameterList tscPL =
141  pl->sublist("Default Integrator").sublist("Time Step Control");
142  timeStepControl->setInitIndex(tscPL.get<int>("Initial Time Index"));
143  timeStepControl->setInitTime(tscPL.get<double>("Initial Time"));
144  timeStepControl->setFinalTime(tscPL.get<double>("Final Time"));
145  timeStepControl->setInitTimeStep(dt);
146  timeStepControl->initialize();
147 
148  // Setup initial condition SolutionState --------------------
149  auto inArgsIC = model->getNominalValues();
150  auto icSoln = rcp_const_cast<Thyra::VectorBase<double>>(inArgsIC.get_x());
151  auto icSolnDot =
152  rcp_const_cast<Thyra::VectorBase<double>>(inArgsIC.get_x_dot());
153  auto icState = Tempus::createSolutionStateX(icSoln, icSolnDot);
154  icState->setTime(timeStepControl->getInitTime());
155  icState->setIndex(timeStepControl->getInitIndex());
156  icState->setTimeStep(0.0);
157  icState->setOrder(stepper->getOrder());
158  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
159 
160  // Setup SolutionHistory ------------------------------------
161  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
162  solutionHistory->setName("Forward States");
163  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
164  solutionHistory->setStorageLimit(2);
165  solutionHistory->addState(icState);
166 
167  // Setup Integrator -----------------------------------------
169  Tempus::createIntegratorBasic<double>();
170  integrator->setStepper(stepper);
171  integrator->setTimeStepControl(timeStepControl);
172  integrator->setSolutionHistory(solutionHistory);
173  // integrator->setObserver(...);
174  integrator->initialize();
175 
176  // Integrate to timeMax
177  bool integratorStatus = integrator->advanceTime();
178  TEST_ASSERT(integratorStatus)
179 
180  // Test if at 'Final Time'
181  double time = integrator->getTime();
182  double timeFinal = pl->sublist("Default Integrator")
183  .sublist("Time Step Control")
184  .get<double>("Final Time");
185  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
186 
187  // Time-integrated solution and the exact solution
188  RCP<Thyra::VectorBase<double>> x = integrator->getX();
190  model->getExactSolution(time).get_x();
191 
192  // Calculate the error
193  RCP<Thyra::VectorBase<double>> xdiff = x->clone_v();
194  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
195 
196  // Check the order and intercept
197  out << " Stepper = " << stepper->description() << "\n with "
198  << option << std::endl;
199  out << " =========================" << std::endl;
200  out << " Exact solution : " << get_ele(*(x_exact), 0) << " "
201  << get_ele(*(x_exact), 1) << std::endl;
202  out << " Computed solution: " << get_ele(*(x), 0) << " "
203  << get_ele(*(x), 1) << std::endl;
204  out << " Difference : " << get_ele(*(xdiff), 0) << " "
205  << get_ele(*(xdiff), 1) << std::endl;
206  out << " =========================" << std::endl;
207  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.841021, 1.0e-4);
208  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.541002, 1.0e-4);
209  }
210 }
211 
212 // ************************************************************
213 // ************************************************************
214 TEUCHOS_UNIT_TEST(Trapezoidal, SinCos)
215 {
217  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
218  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
219  std::vector<double> StepSize;
220  std::vector<double> xErrorNorm;
221  std::vector<double> xDotErrorNorm;
222  const int nTimeStepSizes = 7;
223  double dt = 0.2;
224  double time = 0.0;
225  for (int n = 0; n < nTimeStepSizes; n++) {
226  // Read params from .xml file
227  RCP<ParameterList> pList =
228  getParametersFromXmlFile("Tempus_Trapezoidal_SinCos.xml");
229 
230  // std::ofstream ftmp("PL.txt");
231  // pList->print(ftmp);
232  // ftmp.close();
233 
234  // Setup the SinCosModel
235  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
236  // RCP<SinCosModel<double> > model = sineCosineModel(scm_pl);
237  auto model = rcp(new SinCosModel<double>(scm_pl));
238 
239  dt /= 2;
240 
241  // Setup the Integrator and reset initial time step
242  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
243  pl->sublist("Default Integrator")
244  .sublist("Time Step Control")
245  .set("Initial Time Step", dt);
246  integrator = Tempus::createIntegratorBasic<double>(pl, model);
247 
248  // Initial Conditions
249  // During the Integrator construction, the initial SolutionState
250  // is set by default to model->getNominalVales().get_x(). However,
251  // the application can set it also by integrator->initializeSolutionHistory.
252  {
254  model->getNominalValues().get_x()->clone_v();
256  model->getNominalValues().get_x_dot()->clone_v();
257  integrator->initializeSolutionHistory(0.0, x0, xdot0);
258  }
259 
260  // Integrate to timeMax
261  bool integratorStatus = integrator->advanceTime();
262  TEST_ASSERT(integratorStatus)
263 
264  // Test if at 'Final Time'
265  time = integrator->getTime();
266  double timeFinal = pl->sublist("Default Integrator")
267  .sublist("Time Step Control")
268  .get<double>("Final Time");
269  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
270 
271  // Plot sample solution and exact solution
272  if (n == 0) {
273  RCP<const SolutionHistory<double>> solutionHistory =
274  integrator->getSolutionHistory();
275  writeSolution("Tempus_Trapezoidal_SinCos.dat", solutionHistory);
276 
277  auto solnHistExact = rcp(new Tempus::SolutionHistory<double>());
278  for (int i = 0; i < solutionHistory->getNumStates(); i++) {
279  double time_i = (*solutionHistory)[i]->getTime();
280  auto state = Tempus::createSolutionStateX(
281  rcp_const_cast<Thyra::VectorBase<double>>(
282  model->getExactSolution(time_i).get_x()),
283  rcp_const_cast<Thyra::VectorBase<double>>(
284  model->getExactSolution(time_i).get_x_dot()));
285  state->setTime((*solutionHistory)[i]->getTime());
286  solnHistExact->addState(state);
287  }
288  writeSolution("Tempus_Trapezoidal_SinCos-Ref.dat", solnHistExact);
289  }
290 
291  // Store off the final solution and step size
292  StepSize.push_back(dt);
293  auto solution = Thyra::createMember(model->get_x_space());
294  Thyra::copy(*(integrator->getX()), solution.ptr());
295  solutions.push_back(solution);
296  auto solutionDot = Thyra::createMember(model->get_x_space());
297  Thyra::copy(*(integrator->getXDot()), solutionDot.ptr());
298  solutionsDot.push_back(solutionDot);
299  if (n == nTimeStepSizes - 1) { // Add exact solution last in vector.
300  StepSize.push_back(0.0);
301  auto solutionExact = Thyra::createMember(model->get_x_space());
302  Thyra::copy(*(model->getExactSolution(time).get_x()),
303  solutionExact.ptr());
304  solutions.push_back(solutionExact);
305  auto solutionDotExact = Thyra::createMember(model->get_x_space());
306  Thyra::copy(*(model->getExactSolution(time).get_x_dot()),
307  solutionDotExact.ptr());
308  solutionsDot.push_back(solutionDotExact);
309  }
310  }
311 
312  double xSlope = 0.0;
313  double xDotSlope = 0.0;
314  RCP<Tempus::Stepper<double>> stepper = integrator->getStepper();
315  double order = stepper->getOrder();
316  writeOrderError("Tempus_Trapezoidal_SinCos-Error.dat", stepper, StepSize,
317  solutions, xErrorNorm, xSlope, solutionsDot, xDotErrorNorm,
318  xDotSlope, out);
319 
320  TEST_FLOATING_EQUALITY(xSlope, order, 0.01);
321  TEST_FLOATING_EQUALITY(xErrorNorm[0], 0.000832086, 1.0e-4);
322  TEST_FLOATING_EQUALITY(xDotSlope, order, 0.01);
323  TEST_FLOATING_EQUALITY(xDotErrorNorm[0], 0.000832086, 1.0e-4);
324 
326 }
327 
328 // ************************************************************
329 // ************************************************************
330 TEUCHOS_UNIT_TEST(Trapezoidal, VanDerPol)
331 {
333  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
334  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
335  std::vector<double> StepSize;
336  std::vector<double> xErrorNorm;
337  std::vector<double> xDotErrorNorm;
338  const int nTimeStepSizes = 4;
339  double dt = 0.05;
340  double time = 0.0;
341  for (int n = 0; n < nTimeStepSizes; n++) {
342  // Read params from .xml file
343  RCP<ParameterList> pList =
344  getParametersFromXmlFile("Tempus_Trapezoidal_VanDerPol.xml");
345 
346  // Setup the VanDerPolModel
347  RCP<ParameterList> vdpm_pl = sublist(pList, "VanDerPolModel", true);
348  auto model = rcp(new VanDerPolModel<double>(vdpm_pl));
349 
350  // Set the step size
351  dt /= 2;
352  if (n == nTimeStepSizes - 1) dt /= 10.0;
353 
354  // Setup the Integrator and reset initial time step
355  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
356  pl->sublist("Demo Integrator")
357  .sublist("Time Step Control")
358  .set("Initial Time Step", dt);
359  integrator = Tempus::createIntegratorBasic<double>(pl, model);
360 
361  // Integrate to timeMax
362  bool integratorStatus = integrator->advanceTime();
363  TEST_ASSERT(integratorStatus)
364 
365  // Test if at 'Final Time'
366  time = integrator->getTime();
367  double timeFinal = pl->sublist("Demo Integrator")
368  .sublist("Time Step Control")
369  .get<double>("Final Time");
370  double tol = 100.0 * std::numeric_limits<double>::epsilon();
371  TEST_FLOATING_EQUALITY(time, timeFinal, tol);
372 
373  // Store off the final solution and step size
374  StepSize.push_back(dt);
375  auto solution = Thyra::createMember(model->get_x_space());
376  Thyra::copy(*(integrator->getX()), solution.ptr());
377  solutions.push_back(solution);
378  auto solutionDot = Thyra::createMember(model->get_x_space());
379  Thyra::copy(*(integrator->getXDot()), solutionDot.ptr());
380  solutionsDot.push_back(solutionDot);
381 
382  // Output finest temporal solution for plotting
383  // This only works for ONE MPI process
384  if ((n == 0) || (n == nTimeStepSizes - 1)) {
385  std::string fname = "Tempus_Trapezoidal_VanDerPol-Ref.dat";
386  if (n == 0) fname = "Tempus_Trapezoidal_VanDerPol.dat";
387  RCP<const SolutionHistory<double>> solutionHistory =
388  integrator->getSolutionHistory();
389  writeSolution(fname, solutionHistory);
390  }
391  }
392  // Check the order and intercept
393  double xSlope = 0.0;
394  double xDotSlope = 0.0;
395  RCP<Tempus::Stepper<double>> stepper = integrator->getStepper();
396  double order = stepper->getOrder();
397  writeOrderError("Tempus_Trapezoidal_VanDerPol-Error.dat", stepper, StepSize,
398  solutions, xErrorNorm, xSlope, solutionsDot, xDotErrorNorm,
399  xDotSlope, out);
400 
401  TEST_FLOATING_EQUALITY(xSlope, order, 0.10);
402  TEST_FLOATING_EQUALITY(xDotSlope, order, 0.10); //=order at samll dt
403  TEST_FLOATING_EQUALITY(xErrorNorm[0], 0.00085855, 1.0e-4);
404  TEST_FLOATING_EQUALITY(xDotErrorNorm[0], 0.00120695, 1.0e-4);
405 
407 }
408 
409 } // 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.
Trapezoidal method time stepper.
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)
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)
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)
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="")
Solution state for integrators and steppers.