Tempus  Version of the Day
Time Integration
Tempus_LeapfrogTest.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 
9 #include "Teuchos_UnitTestHarness.hpp"
10 #include "Teuchos_XMLParameterListHelpers.hpp"
11 #include "Teuchos_TimeMonitor.hpp"
12 
13 #include "Thyra_VectorStdOps.hpp"
14 
15 #include "Tempus_config.hpp"
16 #include "Tempus_IntegratorBasic.hpp"
17 #include "Tempus_StepperLeapfrog.hpp"
18 
19 #include "../TestModels/HarmonicOscillatorModel.hpp"
20 #include "../TestUtils/Tempus_ConvergenceTestUtils.hpp"
21 
22 
23 #ifdef Tempus_ENABLE_MPI
24 #include "Epetra_MpiComm.h"
25 #else
26 #include "Epetra_SerialComm.h"
27 #endif
28 
29 #include <fstream>
30 #include <sstream>
31 #include <limits>
32 #include <vector>
33 
34 namespace Tempus_Test {
35 
36 using Teuchos::RCP;
37 using Teuchos::rcp;
38 using Teuchos::rcp_const_cast;
39 using Teuchos::ParameterList;
40 using Teuchos::sublist;
41 using Teuchos::getParametersFromXmlFile;
42 
46 
47 
48 
49 // ************************************************************
50 // ************************************************************
51 TEUCHOS_UNIT_TEST(Leapfrog, ConstructingFromDefaults)
52 {
53  double dt = 0.1;
54 
55  // Read params from .xml file
56  RCP<ParameterList> pList =
57  getParametersFromXmlFile("Tempus_Leapfrog_SinCos.xml");
58  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
59 
60  // Setup the HarmonicOscillatorModel
61  RCP<ParameterList> hom_pl = sublist(pList, "HarmonicOscillatorModel", true);
62  auto model = rcp(new HarmonicOscillatorModel<double>(hom_pl));
63 
64  // Setup Stepper for field solve ----------------------------
65  auto stepper = rcp(new Tempus::StepperLeapfrog<double>());
66  stepper->setModel(model);
67  stepper->initialize();
68 
69  // Setup TimeStepControl ------------------------------------
70  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
71  ParameterList tscPL = pl->sublist("Default Integrator")
72  .sublist("Time Step Control");
73  timeStepControl->setStepType (tscPL.get<std::string>("Integrator Step Type"));
74  timeStepControl->setInitIndex(tscPL.get<int> ("Initial Time Index"));
75  timeStepControl->setInitTime (tscPL.get<double>("Initial Time"));
76  timeStepControl->setFinalTime(tscPL.get<double>("Final Time"));
77  timeStepControl->setInitTimeStep(dt);
78  timeStepControl->initialize();
79 
80  // Setup initial condition SolutionState --------------------
81  Thyra::ModelEvaluatorBase::InArgs<double> inArgsIC =
82  stepper->getModel()->getNominalValues();
83  auto icX = rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x());
84  auto icXDot = rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x_dot());
85  auto icXDotDot = rcp_const_cast<Thyra::VectorBase<double> > (inArgsIC.get_x_dot_dot());
86  auto icState = Tempus::createSolutionStateX<double>(icX, icXDot, icXDotDot);
87  icState->setTime (timeStepControl->getInitTime());
88  icState->setIndex (timeStepControl->getInitIndex());
89  icState->setTimeStep(0.0);
90  icState->setOrder (stepper->getOrder());
91  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
92 
93  // Setup SolutionHistory ------------------------------------
94  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
95  solutionHistory->setName("Forward States");
96  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
97  solutionHistory->setStorageLimit(2);
98  solutionHistory->addState(icState);
99 
100  // Setup Integrator -----------------------------------------
101  RCP<Tempus::IntegratorBasic<double> > integrator =
102  Tempus::integratorBasic<double>();
103  integrator->setStepperWStepper(stepper);
104  integrator->setTimeStepControl(timeStepControl);
105  integrator->setSolutionHistory(solutionHistory);
106  //integrator->setObserver(...);
107  integrator->initialize();
108 
109 
110  // Integrate to timeMax
111  bool integratorStatus = integrator->advanceTime();
112  TEST_ASSERT(integratorStatus)
113 
114 
115  // Test if at 'Final Time'
116  double time = integrator->getTime();
117  double timeFinal =pl->sublist("Default Integrator")
118  .sublist("Time Step Control").get<double>("Final Time");
119  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
120 
121  // Time-integrated solution and the exact solution
122  RCP<Thyra::VectorBase<double> > x = integrator->getX();
123  RCP<const Thyra::VectorBase<double> > x_exact =
124  model->getExactSolution(time).get_x();
125 
126  // Calculate the error
127  RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
128  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
129 
130  // Check the order and intercept
131  std::cout << " Stepper = " << stepper->description() << std::endl;
132  std::cout << " =========================" << std::endl;
133  std::cout << " Exact solution : " << get_ele(*(x_exact), 0) << std::endl;
134  std::cout << " Computed solution: " << get_ele(*(x ), 0) << std::endl;
135  std::cout << " Difference : " << get_ele(*(xdiff ), 0) << std::endl;
136  std::cout << " =========================" << std::endl;
137  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.167158, 1.0e-4 );
138 }
139 
140 
141 // ************************************************************
142 // ************************************************************
143 TEUCHOS_UNIT_TEST(Leapfrog, SinCos)
144 {
145  RCP<Tempus::IntegratorBasic<double> > integrator;
146  std::vector<RCP<Thyra::VectorBase<double>>> solutions;
147  std::vector<RCP<Thyra::VectorBase<double>>> solutionsDot;
148  std::vector<double> StepSize;
149  std::vector<double> xErrorNorm;
150  std::vector<double> xDotErrorNorm;
151  const int nTimeStepSizes = 9;
152  double time = 0.0;
153 
154  // Read params from .xml file
155  RCP<ParameterList> pList =
156  getParametersFromXmlFile("Tempus_Leapfrog_SinCos.xml");
157 
158  // Setup the HarmonicOscillatorModel
159  RCP<ParameterList> hom_pl = sublist(pList, "HarmonicOscillatorModel", true);
160  auto model = rcp(new HarmonicOscillatorModel<double>(hom_pl));
161 
162 
163  // Setup the Integrator and reset initial time step
164  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
165 
166  //Set initial time step = 2*dt specified in input file (for convergence study)
167  double dt =pl->sublist("Default Integrator")
168  .sublist("Time Step Control").get<double>("Initial Time Step");
169  dt *= 2.0;
170 
171  for (int n=0; n<nTimeStepSizes; n++) {
172 
173  //Perform time-step refinement
174  dt /= 2;
175  std::cout << "\n \n time step #" << n
176  << " (out of " << nTimeStepSizes-1 << "), dt = " << dt << "\n";
177  pl->sublist("Default Integrator")
178  .sublist("Time Step Control").set("Initial Time Step", dt);
179  integrator = Tempus::integratorBasic<double>(pl, model);
180 
181  // Integrate to timeMax
182  bool integratorStatus = integrator->advanceTime();
183  TEST_ASSERT(integratorStatus)
184 
185  // Test if at 'Final Time'
186  time = integrator->getTime();
187  double timeFinal =pl->sublist("Default Integrator")
188  .sublist("Time Step Control").get<double>("Final Time");
189  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
190 
191  // Plot sample solution and exact solution at most-refined resolution
192  if (n == nTimeStepSizes-1) {
193  RCP<const SolutionHistory<double> > solutionHistory =
194  integrator->getSolutionHistory();
195  writeSolution("Tempus_Leapfrog_SinCos.dat", solutionHistory);
196 
197  auto solnHistExact = rcp(new Tempus::SolutionHistory<double>());
198  for (int i=0; i<solutionHistory->getNumStates(); i++) {
199  double time_i = (*solutionHistory)[i]->getTime();
200  auto state = Tempus::createSolutionStateX(
201  rcp_const_cast<Thyra::VectorBase<double> > (
202  model->getExactSolution(time_i).get_x()),
203  rcp_const_cast<Thyra::VectorBase<double> > (
204  model->getExactSolution(time_i).get_x_dot()));
205  state->setTime((*solutionHistory)[i]->getTime());
206  solnHistExact->addState(state);
207  }
208  writeSolution("Tempus_Leapfrog_SinCos-Ref.dat", solnHistExact);
209  }
210 
211  // Store off the final solution and step size
212 
213 
214  StepSize.push_back(dt);
215  auto solution = Thyra::createMember(model->get_x_space());
216  Thyra::copy(*(integrator->getX()),solution.ptr());
217  solutions.push_back(solution);
218  auto solutionDot = Thyra::createMember(model->get_x_space());
219  Thyra::copy(*(integrator->getXdot()),solutionDot.ptr());
220  solutionsDot.push_back(solutionDot);
221  if (n == nTimeStepSizes-1) { // Add exact solution last in vector.
222  StepSize.push_back(0.0);
223  auto solutionExact = Thyra::createMember(model->get_x_space());
224  Thyra::copy(*(model->getExactSolution(time).get_x()),solutionExact.ptr());
225  solutions.push_back(solutionExact);
226  auto solutionDotExact = Thyra::createMember(model->get_x_space());
227  Thyra::copy(*(model->getExactSolution(time).get_x_dot()),
228  solutionDotExact.ptr());
229  solutionsDot.push_back(solutionDotExact);
230  }
231  }
232 
233  // Check the order and intercept
234  double xSlope = 0.0;
235  double xDotSlope = 0.0;
236  RCP<Tempus::Stepper<double> > stepper = integrator->getStepper();
237  double order = stepper->getOrder();
238  writeOrderError("Tempus_Leapfrog_SinCos-Error.dat",
239  stepper, StepSize,
240  solutions, xErrorNorm, xSlope,
241  solutionsDot, xDotErrorNorm, xDotSlope);
242 
243  TEST_FLOATING_EQUALITY( xSlope, order, 0.02 );
244  TEST_FLOATING_EQUALITY( xErrorNorm[0], 0.0157928, 1.0e-4 );
245  TEST_FLOATING_EQUALITY( xDotSlope, 1.09387, 0.01 );
246  TEST_FLOATING_EQUALITY( xDotErrorNorm[0], 0.563002, 1.0e-4 );
247 
248  Teuchos::TimeMonitor::summarize();
249 }
250 
251 
252 }
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...
TimeStepControl manages the time step size. There several mechanicisms that effect the time step size...
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)
TEUCHOS_UNIT_TEST(BackwardEuler, SinCos_ASA)
@ STORAGE_TYPE_STATIC
Keep a fix number of states.
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.