Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_UnitTest_BackwardEuler.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 
10 
11 #include "Tempus_StepperForwardEuler.hpp"
12 #include "Tempus_StepperBackwardEuler.hpp"
13 
20 
21 namespace Tempus_Unit_Test {
22 
24 using Teuchos::RCP;
25 using Teuchos::rcp;
26 using Teuchos::rcp_const_cast;
27 using Teuchos::rcp_dynamic_cast;
28 using Teuchos::sublist;
29 
30 // ************************************************************
31 // ************************************************************
32 TEUCHOS_UNIT_TEST(BackwardEuler, Default_Construction)
33 {
34  auto model = rcp(new Tempus_Test::SinCosModel<double>());
35 
36  // Default construction.
37  auto stepper = rcp(new Tempus::StepperBackwardEuler<double>());
38  stepper->setModel(model);
39  stepper->initialize();
40  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
41 
42  // Default values for construction.
43  auto modifier =
45  auto modifierX =
47  auto observer =
49  auto solver = rcp(new Thyra::NOXNonlinearSolver());
50  solver->setParameterList(Tempus::defaultSolverParameters());
51 
52  auto predictorStepper = rcp(new Tempus::StepperForwardEuler<double>());
53  predictorStepper->setModel(
54  model); // Can use the same model since both steppers are implicit ODEs.
55  predictorStepper->initialize();
56 
57  auto defaultStepper = rcp(new Tempus::StepperBackwardEuler<double>());
58  bool useFSAL = defaultStepper->getUseFSAL();
59  std::string ICConsistency = defaultStepper->getICConsistency();
60  bool ICConsistencyCheck = defaultStepper->getICConsistencyCheck();
61  bool zeroInitialGuess = defaultStepper->getZeroInitialGuess();
62 
63  // Test the set functions.
64  stepper->setAppAction(modifier);
65  stepper->initialize();
66  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
67  stepper->setAppAction(modifierX);
68  stepper->initialize();
69  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
70  stepper->setAppAction(observer);
71  stepper->initialize();
72  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
73  stepper->setSolver(solver);
74  stepper->initialize();
75  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
76  stepper->setPredictor(predictorStepper);
77  stepper->initialize();
78  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
79  stepper->setUseFSAL(useFSAL);
80  stepper->initialize();
81  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
82  stepper->setICConsistency(ICConsistency);
83  stepper->initialize();
84  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
85  stepper->setICConsistencyCheck(ICConsistencyCheck);
86  stepper->initialize();
87  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
88  stepper->setZeroInitialGuess(zeroInitialGuess);
89  stepper->initialize();
90  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
91 
92  // Full argument list construction.
94  model, solver, predictorStepper, useFSAL, ICConsistency,
95  ICConsistencyCheck, zeroInitialGuess, modifier));
96  TEUCHOS_TEST_FOR_EXCEPT(!stepper->isInitialized());
97 
98  // Test stepper properties.
99  TEUCHOS_ASSERT(stepper->getOrder() == 1);
100 }
101 
102 // ************************************************************
103 // ************************************************************
104 TEUCHOS_UNIT_TEST(BackwardEuler, StepperFactory_Construction)
105 {
106  auto model = rcp(new Tempus_Test::SinCosModel<double>());
107  testFactoryConstruction("Backward Euler", model);
108 }
109 
110 // ************************************************************
111 // ************************************************************
112 class StepperBackwardEulerModifierTest
113  : virtual public Tempus::StepperBackwardEulerModifierBase<double> {
114  public:
116  StepperBackwardEulerModifierTest()
117  : testBEGIN_STEP(false),
118  testBEFORE_SOLVE(false),
119  testAFTER_SOLVE(false),
120  testEND_STEP(false),
121  testCurrentValue(-0.99),
122  testWorkingValue(-0.99),
123  testDt(-1.5),
124  testName("")
125  {
126  }
127 
129  virtual ~StepperBackwardEulerModifierTest() {}
130 
132  virtual void modify(
136  double>::ACTION_LOCATION actLoc)
137  {
138  switch (actLoc) {
140  testBEGIN_STEP = true;
141  auto x = sh->getCurrentState()->getX();
142  testCurrentValue = get_ele(*(x), 0);
143  break;
144  }
146  testBEFORE_SOLVE = true;
147  testDt = sh->getWorkingState()->getTimeStep() / 10.0;
148  sh->getWorkingState()->setTimeStep(testDt);
149  break;
150  }
152  testAFTER_SOLVE = true;
153  testName = "Backward Euler - Modifier";
154  stepper->setStepperName(testName);
155  break;
156  }
158  testEND_STEP = true;
159  auto x = sh->getWorkingState()->getX();
160  testWorkingValue = get_ele(*(x), 0);
161  break;
162  }
163  default:
164  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
165  "Error - unknown action location.\n");
166  }
167  }
168 
169  bool testBEGIN_STEP;
170  bool testBEFORE_SOLVE;
171  bool testAFTER_SOLVE;
172  bool testEND_STEP;
173  double testCurrentValue;
174  double testWorkingValue;
175  double testDt;
176  std::string testName;
177 };
178 
179 TEUCHOS_UNIT_TEST(BackwardEuler, AppAction_Modifier)
180 {
183 
184  // Setup Stepper for field solve ----------------------------
185  auto stepper = rcp(new Tempus::StepperBackwardEuler<double>());
186  stepper->setModel(model);
187  auto modifier = rcp(new StepperBackwardEulerModifierTest());
188  stepper->setAppAction(modifier);
189  stepper->initialize();
190 
191  // Create a SolutionHistory.
192  auto solutionHistory = Tempus::createSolutionHistoryME(model);
193 
194  // Take one time step.
195  stepper->setInitialConditions(solutionHistory);
196  solutionHistory->initWorkingState();
197  double dt = 0.1;
198  solutionHistory->getWorkingState()->setTimeStep(dt);
199  stepper->takeStep(solutionHistory);
200 
201  // Testing that each ACTION_LOCATION has been called.
202  TEST_COMPARE(modifier->testBEGIN_STEP, ==, true);
203  TEST_COMPARE(modifier->testBEFORE_SOLVE, ==, true);
204  TEST_COMPARE(modifier->testAFTER_SOLVE, ==, true);
205  TEST_COMPARE(modifier->testEND_STEP, ==, true);
206 
207  // Testing that values can be set through the Modifier.
208  auto x = solutionHistory->getCurrentState()->getX();
209  TEST_FLOATING_EQUALITY(modifier->testCurrentValue, get_ele(*(x), 0), 1.0e-14);
210  x = solutionHistory->getWorkingState()->getX();
211  TEST_FLOATING_EQUALITY(modifier->testWorkingValue, get_ele(*(x), 0), 1.0e-14);
212  auto Dt = solutionHistory->getWorkingState()->getTimeStep();
213  TEST_FLOATING_EQUALITY(modifier->testDt, Dt, 1.0e-14);
214 
215  TEST_COMPARE(modifier->testName, ==, "Backward Euler - Modifier");
216 }
217 
218 // ************************************************************
219 // ************************************************************
220 class StepperBackwardEulerObserverTest
221  : virtual public Tempus::StepperBackwardEulerObserverBase<double> {
222  public:
224  StepperBackwardEulerObserverTest()
225  : testBEGIN_STEP(false),
226  testBEFORE_SOLVE(false),
227  testAFTER_SOLVE(false),
228  testEND_STEP(false),
229  testCurrentValue(-0.99),
230  testWorkingValue(-0.99),
231  testDt(-1.5),
232  testName("")
233  {
234  }
235 
237  virtual ~StepperBackwardEulerObserverTest() {}
238 
240  virtual void observe(
244  double>::ACTION_LOCATION actLoc)
245  {
246  switch (actLoc) {
248  testBEGIN_STEP = true;
249  auto x = sh->getCurrentState()->getX();
250  testCurrentValue = get_ele(*(x), 0);
251  break;
252  }
254  testBEFORE_SOLVE = true;
255  testDt = sh->getWorkingState()->getTimeStep();
256  break;
257  }
259  testAFTER_SOLVE = true;
260  testName = stepper->getStepperType();
261  break;
262  }
264  testEND_STEP = true;
265  auto x = sh->getWorkingState()->getX();
266  testWorkingValue = get_ele(*(x), 0);
267  break;
268  }
269  default:
270  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
271  "Error - unknown action location.\n");
272  }
273  }
274 
275  bool testBEGIN_STEP;
276  bool testBEFORE_SOLVE;
277  bool testAFTER_SOLVE;
278  bool testEND_STEP;
279  double testCurrentValue;
280  double testWorkingValue;
281  double testDt;
282  std::string testName;
283 };
284 
285 TEUCHOS_UNIT_TEST(BackwardEuler, AppAction_Observer)
286 {
289 
290  // Setup Stepper for field solve ----------------------------
291  auto stepper = rcp(new Tempus::StepperBackwardEuler<double>());
292  stepper->setModel(model);
293  auto observer = rcp(new StepperBackwardEulerObserverTest());
294  stepper->setAppAction(observer);
295  stepper->initialize();
296 
297  // Setup a SolutionHistory.
298  auto solutionHistory = Tempus::createSolutionHistoryME(model);
299 
300  // Take one time step.
301  stepper->setInitialConditions(solutionHistory);
302  solutionHistory->initWorkingState();
303  double dt = 0.1;
304  solutionHistory->getWorkingState()->setTimeStep(dt);
305  stepper->takeStep(solutionHistory);
306 
307  // Testing that each ACTION_LOCATION has been called.
308  TEST_COMPARE(observer->testBEGIN_STEP, ==, true);
309  TEST_COMPARE(observer->testBEFORE_SOLVE, ==, true);
310  TEST_COMPARE(observer->testAFTER_SOLVE, ==, true);
311  TEST_COMPARE(observer->testEND_STEP, ==, true);
312 
313  // Testing that values can be observed through the observer.
314  auto x = solutionHistory->getCurrentState()->getX();
315  TEST_FLOATING_EQUALITY(observer->testCurrentValue, get_ele(*(x), 0), 1.0e-14);
316  x = solutionHistory->getWorkingState()->getX();
317  TEST_FLOATING_EQUALITY(observer->testWorkingValue, get_ele(*(x), 0), 1.0e-14);
318  TEST_FLOATING_EQUALITY(observer->testDt, dt, 1.0e-14);
319 
320  TEST_COMPARE(observer->testName, ==, "Backward Euler");
321 }
322 
323 // ************************************************************
324 // ************************************************************
325 class StepperBackwardEulerModifierXTest
326  : virtual public Tempus::StepperBackwardEulerModifierXBase<double> {
327  public:
329  StepperBackwardEulerModifierXTest()
330  : testX_BEGIN_STEP(false),
331  testX_BEFORE_SOLVE(false),
332  testX_AFTER_SOLVE(false),
333  testXDOT_END_STEP(false),
334  testX(-0.99),
335  testXDot(-0.99),
336  testDt(-1.5),
337  testTime(-1.5)
338  {
339  }
340 
342  virtual ~StepperBackwardEulerModifierXTest() {}
343 
346  const double time, const double dt,
348  double>::MODIFIER_TYPE modType)
349  {
350  switch (modType) {
352  testX_BEGIN_STEP = true;
353  testX = get_ele(*(x), 0);
354  break;
355  }
357  testX_BEFORE_SOLVE = true;
358  testDt = dt;
359  break;
360  }
362  testX_AFTER_SOLVE = true;
363  testTime = time;
364  break;
365  }
367  testXDOT_END_STEP = true;
368  testXDot = get_ele(*(x), 0);
369  break;
370  }
371  default:
372  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
373  "Error - unknown action location.\n");
374  }
375  }
376 
377  bool testX_BEGIN_STEP;
378  bool testX_BEFORE_SOLVE;
379  bool testX_AFTER_SOLVE;
380  bool testXDOT_END_STEP;
381  double testX;
382  double testXDot;
383  double testDt;
384  double testTime;
385 };
386 
387 TEUCHOS_UNIT_TEST(BackwardEuler, AppAction_ModifierX)
388 {
391 
392  // Setup Stepper for field solve ----------------------------
393  auto stepper = rcp(new Tempus::StepperBackwardEuler<double>());
394  stepper->setModel(model);
395  auto modifierX = rcp(new StepperBackwardEulerModifierXTest());
396  stepper->setAppAction(modifierX);
397  stepper->initialize();
398 
399  // Setup a SolutionHistory.
400  auto solutionHistory = Tempus::createSolutionHistoryME(model);
401 
402  // Take one time step.
403  stepper->setInitialConditions(solutionHistory);
404  solutionHistory->initWorkingState();
405  double dt = 0.1;
406  solutionHistory->getWorkingState()->setTimeStep(dt);
407  stepper->takeStep(solutionHistory);
408 
409  // Testing that each ACTION_LOCATION has been called.
410  TEST_COMPARE(modifierX->testX_BEGIN_STEP, ==, true);
411  TEST_COMPARE(modifierX->testX_BEFORE_SOLVE, ==, true);
412  TEST_COMPARE(modifierX->testX_AFTER_SOLVE, ==, true);
413  TEST_COMPARE(modifierX->testXDOT_END_STEP, ==, true);
414 
415  // Testing that values can be set through the Modifier.
416  auto x = solutionHistory->getCurrentState()->getX();
417  TEST_FLOATING_EQUALITY(modifierX->testX, get_ele(*(x), 0), 1.0e-14);
418  // Temporary memory for xDot is not guarranteed to exist outside the Stepper.
419  auto xDot = solutionHistory->getWorkingState()->getXDot();
420  if (xDot == Teuchos::null) xDot = stepper->getStepperXDot();
421 
422  TEST_FLOATING_EQUALITY(modifierX->testXDot, get_ele(*(xDot), 0), 1.0e-14);
423  auto Dt = solutionHistory->getWorkingState()->getTimeStep();
424  TEST_FLOATING_EQUALITY(modifierX->testDt, Dt, 1.0e-14);
425 
426  auto time = solutionHistory->getWorkingState()->getTime();
427  TEST_FLOATING_EQUALITY(modifierX->testTime, time, 1.0e-14);
428 }
429 
430 // ************************************************************
431 // ************************************************************
433 {
434  // Read params from .xml file
435  RCP<ParameterList> pList =
436  Teuchos::getParametersFromXmlFile("Tempus_BackwardEuler_SinCos.xml");
437 
438  // Setup the SinCosModel
439  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
440  auto model = rcp(new Tempus_Test::SinCosModel<double>(scm_pl));
441 
442  RCP<ParameterList> tempusPL = sublist(pList, "Tempus", true);
443 
444  // Test constructor IntegratorBasic(tempusPL, model)
445  {
447  Tempus::createIntegratorBasic<double>(tempusPL, model);
448 
449  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
450  RCP<const ParameterList> defaultPL =
451  integrator->getStepper()->getValidParameters();
452 
453  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
454  if (!pass) {
455  out << std::endl;
456  out << "stepperPL -------------- \n"
457  << *stepperPL << std::endl;
458  out << "defaultPL -------------- \n"
459  << *defaultPL << std::endl;
460  }
461  TEST_ASSERT(pass)
462  }
463 
464  // Test constructor IntegratorBasic(model, stepperType)
465  {
467  Tempus::createIntegratorBasic<double>(model,
468  std::string("Backward Euler"));
469 
470  RCP<ParameterList> stepperPL = sublist(tempusPL, "Default Stepper", true);
471  // Match Predictor for comparison
472  stepperPL->set("Predictor Stepper Type", "None");
473  RCP<const ParameterList> defaultPL =
474  integrator->getStepper()->getValidParameters();
475 
476  bool pass = haveSameValuesSorted(*stepperPL, *defaultPL, true);
477  if (!pass) {
478  out << std::endl;
479  out << "stepperPL -------------- \n"
480  << *stepperPL << std::endl;
481  out << "defaultPL -------------- \n"
482  << *defaultPL << std::endl;
483  }
484  TEST_ASSERT(pass)
485  }
486 }
487 
488 // ************************************************************
489 // ************************************************************
490 TEUCHOS_UNIT_TEST(BackwardEuler, ConstructingFromDefaults)
491 {
492  double dt = 0.1;
493  std::vector<std::string> options;
494  options.push_back("Default Parameters");
495  options.push_back("ICConsistency and Check");
496 
497  for (const auto& option : options) {
498  // Read params from .xml file
499  RCP<ParameterList> pList =
500  Teuchos::getParametersFromXmlFile("Tempus_BackwardEuler_SinCos.xml");
501  RCP<ParameterList> pl = sublist(pList, "Tempus", true);
502 
503  // Setup the SinCosModel
504  RCP<ParameterList> scm_pl = sublist(pList, "SinCosModel", true);
505  // RCP<SinCosModel<double> > model = sineCosineModel(scm_pl);
506  auto model = rcp(new Tempus_Test::SinCosModel<double>(scm_pl));
507 
508  // Setup Stepper for field solve ----------------------------
509  auto stepper = rcp(new Tempus::StepperBackwardEuler<double>());
510  stepper->setModel(model);
511  if (option == "ICConsistency and Check") {
512  stepper->setICConsistency("Consistent");
513  stepper->setICConsistencyCheck(true);
514  }
515  stepper->initialize();
516 
517  // Setup TimeStepControl ------------------------------------
518  auto timeStepControl = rcp(new Tempus::TimeStepControl<double>());
519  ParameterList tscPL =
520  pl->sublist("Default Integrator").sublist("Time Step Control");
521  timeStepControl->setInitIndex(tscPL.get<int>("Initial Time Index"));
522  timeStepControl->setInitTime(tscPL.get<double>("Initial Time"));
523  timeStepControl->setFinalTime(tscPL.get<double>("Final Time"));
524  timeStepControl->setInitTimeStep(dt);
525  timeStepControl->initialize();
526 
527  // Setup initial condition SolutionState --------------------
528  auto inArgsIC = model->getNominalValues();
529  auto icSolution =
530  rcp_const_cast<Thyra::VectorBase<double> >(inArgsIC.get_x());
531  auto icState = Tempus::createSolutionStateX(icSolution);
532  icState->setTime(timeStepControl->getInitTime());
533  icState->setIndex(timeStepControl->getInitIndex());
534  icState->setTimeStep(0.0);
535  icState->setOrder(stepper->getOrder());
536  icState->setSolutionStatus(Tempus::Status::PASSED); // ICs are passing.
537 
538  // Setup SolutionHistory ------------------------------------
539  auto solutionHistory = rcp(new Tempus::SolutionHistory<double>());
540  solutionHistory->setName("Forward States");
541  solutionHistory->setStorageType(Tempus::STORAGE_TYPE_STATIC);
542  solutionHistory->setStorageLimit(2);
543  solutionHistory->addState(icState);
544 
545  // Ensure ICs are consistent and stepper memory is set (e.g., xDot is set).
546  stepper->setInitialConditions(solutionHistory);
547 
548  // Setup Integrator -----------------------------------------
550  Tempus::createIntegratorBasic<double>();
551  integrator->setStepper(stepper);
552  integrator->setTimeStepControl(timeStepControl);
553  integrator->setSolutionHistory(solutionHistory);
554  // integrator->setObserver(...);
555  integrator->initialize();
556 
557  // Integrate to timeMax
558  bool integratorStatus = integrator->advanceTime();
559  TEST_ASSERT(integratorStatus)
560 
561  // Test if at 'Final Time'
562  double time = integrator->getTime();
563  double timeFinal = pl->sublist("Default Integrator")
564  .sublist("Time Step Control")
565  .get<double>("Final Time");
566  TEST_FLOATING_EQUALITY(time, timeFinal, 1.0e-14);
567 
568  // Time-integrated solution and the exact solution
569  RCP<Thyra::VectorBase<double> > x = integrator->getX();
571  model->getExactSolution(time).get_x();
572 
573  // Calculate the error
574  RCP<Thyra::VectorBase<double> > xdiff = x->clone_v();
575  Thyra::V_StVpStV(xdiff.ptr(), 1.0, *x_exact, -1.0, *(x));
576 
577  // Check the order and intercept
578  out << " Stepper = " << stepper->description() << " with " << option
579  << std::endl;
580  out << " =========================" << std::endl;
581  out << " Exact solution : " << get_ele(*(x_exact), 0) << " "
582  << get_ele(*(x_exact), 1) << std::endl;
583  out << " Computed solution: " << get_ele(*(x), 0) << " "
584  << get_ele(*(x), 1) << std::endl;
585  out << " Difference : " << get_ele(*(xdiff), 0) << " "
586  << get_ele(*(xdiff), 1) << std::endl;
587  out << " =========================" << std::endl;
588  TEST_FLOATING_EQUALITY(get_ele(*(x), 0), 0.798923, 1.0e-4);
589  TEST_FLOATING_EQUALITY(get_ele(*(x), 1), 0.516729, 1.0e-4);
590  }
591 }
592 
593 } // namespace Tempus_Unit_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.
void testFactoryConstruction(std::string stepperType, const Teuchos::RCP< const Thyra::ModelEvaluator< double > > &model)
Unit test utility for Stepper construction through StepperFactory.
T & get(const std::string &name, T def_value)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define TEST_COMPARE(v1, comp, v2)
#define TEST_FLOATING_EQUALITY(v1, v2, tol)
#define TEST_ASSERT(v1)
Sine-Cosine model problem from Rythmos. This is a canonical Sine-Cosine differential equation with a...
Teuchos::RCP< Teuchos::ParameterList > defaultSolverParameters()
Returns the default solver ParameterList for implicit Steppers.
virtual void modify(Teuchos::RCP< Thyra::VectorBase< double > >, const double, const double, const MODIFIER_TYPE modType)=0
Modify solution based on the MODIFIER_TYPE.
Application Action for StepperBackwardEuler.
Teuchos::RCP< SolutionHistory< Scalar > > createSolutionHistoryME(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Nonmember contructor from a Thyra ModelEvaluator.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Ptr< T > ptr() const
TEUCHOS_UNIT_TEST(BackwardEuler, Default_Construction)
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)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)