Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_StepperOperatorSplit_impl.hpp
Go to the documentation of this file.
1 //@HEADER
2 // *****************************************************************************
3 // Tempus: Time Integration and Sensitivity Analysis Package
4 //
5 // Copyright 2017 NTESS and the Tempus contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 //@HEADER
9 
10 #ifndef Tempus_StepperOperatorSplit_impl_hpp
11 #define Tempus_StepperOperatorSplit_impl_hpp
12 
13 #include "Tempus_StepperFactory.hpp"
15 
16 namespace Tempus {
17 
18 template <class Scalar>
20 {
21  this->setStepperName("Operator Split");
22  this->setStepperType("Operator Split");
23  this->setUseFSAL(false);
24  this->setICConsistency("None");
25  this->setICConsistencyCheck(false);
26 
27  this->setOrder(1);
28  this->setOrderMin(1);
29  this->setOrderMax(1);
30  this->setAppAction(Teuchos::null);
31 
32  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
33  OpSpSolnHistory_->setStorageLimit(2);
34  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
35 }
36 
37 template <class Scalar>
39  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
40  std::vector<Teuchos::RCP<Stepper<Scalar> > > subStepperList, bool useFSAL,
41  std::string ICConsistency, bool ICConsistencyCheck, int order, int orderMin,
42  int orderMax,
44  stepperOSAppAction)
45 {
46  this->setStepperName("Operator Split");
47  this->setStepperType("Operator Split");
48  this->setUseFSAL(useFSAL);
49  this->setICConsistency(ICConsistency);
50  this->setICConsistencyCheck(ICConsistencyCheck);
51 
52  this->setSubStepperList(subStepperList);
53  this->setOrder(order);
54  this->setOrderMin(orderMin);
55  this->setOrderMax(orderMax);
56 
57  this->setAppAction(stepperOSAppAction);
58  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
59  OpSpSolnHistory_->setStorageLimit(2);
60  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
61 
62  if (!(appModels.empty())) {
63  this->setModels(appModels);
64  this->initialize();
65  }
66 }
67 
68 template <class Scalar>
70  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
71 {
72  if (appModel != Teuchos::null) {
73  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
74  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::setModel()");
75  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
76  << "because it is a Stepper of Steppers.\n"
77  << std::endl;
78  }
79 }
80 
81 template <class Scalar>
84 {
86  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
87  subStepperIter = subStepperList_.begin();
88  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
89  model = (*subStepperIter)->getModel();
90  if (model != Teuchos::null) break;
91  }
92  if (model == Teuchos::null) {
93  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
94  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::getModel()");
95  *out << "Warning -- StepperOperatorSplit::getModel() "
96  << "Could not find a valid model! Returning null!" << std::endl;
97  }
98 
99  return model;
100 }
101 
102 template <class Scalar>
105 {
106  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
107  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::setSolver()");
108  *out << "Warning -- No solver to set for StepperOperatorSplit "
109  << "because it is a Stepper of Steppers.\n"
110  << std::endl;
111 
112  this->isInitialized_ = false;
113 }
114 
115 template <class Scalar>
118 {
119  if (appAction == Teuchos::null) {
120  // Create default appAction, otherwise keep current.
121  if (stepperOSAppAction_ == Teuchos::null) {
122  stepperOSAppAction_ =
124  }
125  }
126  else {
127  stepperOSAppAction_ =
128  Teuchos::rcp_dynamic_cast<StepperOperatorSplitAppAction<Scalar> >(
129  appAction, true);
130  }
131  this->isInitialized_ = false;
132 }
133 
134 template <class Scalar>
136  Teuchos::RCP<Stepper<Scalar> > stepper, bool useFSAL)
137 {
138  stepper->setUseFSAL(useFSAL);
139  subStepperList_.push_back(stepper);
140 }
141 
142 template <class Scalar>
144  std::vector<Teuchos::RCP<Stepper<Scalar> > > subStepperList)
145 {
147  using Teuchos::RCP;
148 
149  subStepperList_ = subStepperList;
150 
151  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
152  subStepperIter = subStepperList_.begin();
153 
154  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
155  auto subStepper = *(subStepperIter);
156  bool useFSAL = subStepper->getUseFSAL();
157  if (useFSAL) {
158  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
159  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::setSubStepperList()");
160  *out << "Warning -- subStepper = '" << subStepper->getStepperType()
161  << "' has \n"
162  << " subStepper->getUseFSAL() = " << useFSAL << ".\n"
163  << " subSteppers usually can not use the FSAL priniciple with\n"
164  << " operator splitting. Proceeding with it set to true.\n"
165  << std::endl;
166  }
167  }
168 
169  this->isInitialized_ = false;
170 }
171 
172 template <class Scalar>
174  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels)
175 {
177  using Teuchos::RCP;
178 
180  subStepperList_.size() != appModels.size(), std::logic_error,
181  "Error - Number of models and Steppers do not match!\n"
182  << " There are " << appModels.size() << " models.\n"
183  << " There are " << subStepperList_.size() << " steppers.\n");
184 
185  typename std::vector<RCP<const Thyra::ModelEvaluator<Scalar> > >::iterator
186  appModelIter = appModels.begin();
187 
188  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
189  subStepperIter = subStepperList_.begin();
190 
191  for (;
192  appModelIter < appModels.end() || subStepperIter < subStepperList_.end();
193  appModelIter++, subStepperIter++) {
194  auto appModel = *(appModelIter);
195  auto subStepper = *(subStepperIter);
196  subStepper->setModel(appModel);
197  }
198 
199  this->isInitialized_ = false;
200 }
201 
202 template <class Scalar>
204 {
205  if (tempState_ == Teuchos::null) {
206  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model = this->getModel();
208  model == Teuchos::null, std::logic_error,
209  "Error - StepperOperatorSplit::initialize() Could not find "
210  "a valid model!\n");
211  tempState_ = createSolutionStateME(model, this->getDefaultStepperState());
212  }
213 
214  if (!isOneStepMethod()) {
215  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
216  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::initialize()");
217  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
218  subStepperIter = subStepperList_.begin();
219  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
220  *out << "SubStepper, " << (*subStepperIter)->getStepperType()
221  << ", isOneStepMethod = " << (*subStepperIter)->isOneStepMethod()
222  << std::endl;
223  }
225  !isOneStepMethod(), std::logic_error,
226  "Error - OperatorSplit only works for one-step methods!\n");
227  }
228 
229  // Ensure that subSteppers are initialized.
230  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
231  subStepperIter = subStepperList_.begin();
232  for (; subStepperIter < subStepperList_.end(); subStepperIter++)
233  (*subStepperIter)->initialize();
234 
236 }
237 
238 template <class Scalar>
240  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
241 {
242  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
243  subStepperIter = subStepperList_.begin();
244  for (; subStepperIter < subStepperList_.end(); subStepperIter++)
245  (*subStepperIter)->setInitialConditions(solutionHistory);
246 
247  Teuchos::RCP<SolutionState<Scalar> > initialState =
248  solutionHistory->getCurrentState();
249 
250  // Check if we need Stepper storage for xDot
251  this->setStepperXDot(initialState->getXDot());
252  if (initialState->getXDot() == Teuchos::null)
253  this->setStepperXDot(initialState->getX()->clone_v());
254 }
255 
256 template <class Scalar>
258  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
259 {
260  this->checkInitialized();
261 
262  using Teuchos::RCP;
263 
264  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperOperatorSplit::takeStep()");
265  {
267  solutionHistory->getNumStates() < 2, std::logic_error,
268  "Error - StepperOperatorSplit<Scalar>::takeStep(...)\n"
269  << "Need at least two SolutionStates for OperatorSplit.\n"
270  << " Number of States = " << solutionHistory->getNumStates()
271  << "\nTry setting in \"Solution History\" \"Storage Type\" = "
272  << "\"Undo\"\n"
273  << " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = "
274  << "\"2\"\n");
275  RCP<StepperOperatorSplit<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
276  stepperOSAppAction_->execute(
277  solutionHistory, thisStepper,
279 
280  RCP<SolutionState<Scalar> > workingState =
281  solutionHistory->getWorkingState();
282 
283  // Create OperatorSplit SolutionHistory to pass to subSteppers.
284  tempState_->copy(solutionHistory->getCurrentState());
285  OpSpSolnHistory_->clear();
286  OpSpSolnHistory_->addState(tempState_);
287  OpSpSolnHistory_->addWorkingState(workingState, false);
288 
289  RCP<SolutionState<Scalar> > currentSubState =
290  OpSpSolnHistory_->getCurrentState();
291  RCP<SolutionState<Scalar> > workingSubState =
292  OpSpSolnHistory_->getWorkingState();
293 
294  bool pass = true;
295  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
296  subStepperIter = subStepperList_.begin();
297  for (; subStepperIter < subStepperList_.end() && pass; subStepperIter++) {
298  stepperOSAppAction_->execute(
299  solutionHistory, thisStepper,
301  Scalar>::ACTION_LOCATION::BEFORE_STEPPER);
302 
303  (*subStepperIter)->takeStep(OpSpSolnHistory_);
304 
305  stepperOSAppAction_->execute(solutionHistory, thisStepper,
307  Scalar>::ACTION_LOCATION::AFTER_STEPPER);
308 
309  if (workingSubState->getSolutionStatus() == Status::FAILED) {
310  pass = false;
311  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
312  Teuchos::OSTab ostab(out, 1, "StepperOperatorSplit::takeStep()");
313  *out << "SubStepper, " << (*subStepperIter)->getStepperType()
314  << ", failed!" << std::endl;
315  break;
316  }
317 
318  // "promote" workingSubState
319  currentSubState = OpSpSolnHistory_->getCurrentState();
320  currentSubState->copySolutionData(workingSubState);
321  }
322 
323  if (pass == true)
324  workingState->setSolutionStatus(Status::PASSED);
325  else
326  workingState->setSolutionStatus(Status::FAILED);
327  workingState->setOrder(this->getOrder());
328  workingState->computeNorms(solutionHistory->getCurrentState());
329  OpSpSolnHistory_->clear();
330 
331  stepperOSAppAction_->execute(
332  solutionHistory, thisStepper,
334  }
335  return;
336 }
337 
344 template <class Scalar>
347 {
349  rcp(new StepperState<Scalar>(this->getStepperType()));
350  return stepperState;
351 }
352 
353 template <class Scalar>
355  Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
356 {
357  out.setOutputToRootOnly(0);
358  out << std::endl;
359  Stepper<Scalar>::describe(out, verbLevel);
360 
361  out << "--- StepperOperatorSplit ---\n";
362  out << " subStepperList_.size() = " << subStepperList_.size() << std::endl;
363  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
364  subStepperIter = subStepperList_.begin();
365  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
366  out << " SubStepper = " << (*subStepperIter)->getStepperType()
367  << std::endl;
368  out << " = " << (*subStepperIter)->isInitialized()
369  << std::endl;
370  out << " = " << (*subStepperIter) << std::endl;
371  }
372  out << " OpSpSolnHistory_ = " << OpSpSolnHistory_ << std::endl;
373  out << " tempState_ = " << tempState_ << std::endl;
374  out << " stepperOSAppAction_ = " << stepperOSAppAction_ << std::endl;
375  out << " order_ = " << order_ << std::endl;
376  out << " orderMin_ = " << orderMin_ << std::endl;
377  out << " orderMax_ = " << orderMax_ << std::endl;
378  out << "----------------------------" << std::endl;
379 }
380 
381 template <class Scalar>
383  Teuchos::FancyOStream& out) const
384 {
385  out.setOutputToRootOnly(0);
386  bool isValidSetup = true;
387 
388  if (!Stepper<Scalar>::isValidSetup(out)) isValidSetup = false;
389 
390  if (subStepperList_.size() == 0) {
391  isValidSetup = false;
392  out << "The substepper list is empty!\n";
393  }
394 
395  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
396  subStepperIter = subStepperList_.begin();
397 
398  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
399  auto subStepper = *(subStepperIter);
400  if (!subStepper->isInitialized()) {
401  isValidSetup = false;
402  out << "The subStepper, " << subStepper->description()
403  << ", is not initialized!\n";
404  }
405  }
406  if (stepperOSAppAction_ == Teuchos::null) {
407  isValidSetup = false;
408  out << "The Operator-Split AppAction is not set!\n";
409  }
410 
411  return isValidSetup;
412 }
413 
414 template <class Scalar>
417 {
418  auto pl = this->getValidParametersBasic();
419  pl->template set<int>("Minimum Order", orderMin_,
420  "Minimum Operator-split order. (default = 1)\n");
421  pl->template set<int>("Order", order_,
422  "Operator-split order. (default = 1)\n");
423  pl->template set<int>("Maximum Order", orderMax_,
424  "Maximum Operator-split order. (default = 1)\n");
425 
426  std::ostringstream list;
427  size_t size = subStepperList_.size();
428  for (std::size_t i = 0; i < size - 1; ++i) {
429  list << "'" << subStepperList_[i]->getStepperName() << "', ";
430  }
431  list << "'" << subStepperList_[size - 1]->getStepperName() << "'";
432  pl->template set<std::string>(
433  "Stepper List", list.str(),
434  "Comma deliminated list of single quoted Steppers, e.g., \"'Operator 1', "
435  "'Operator 2'\".");
436 
437  for (std::size_t i = 0; i < size; ++i) {
438  pl->set(subStepperList_[i]->getStepperName(),
439  *(subStepperList_[i]->getValidParameters()));
440  }
441 
442  return pl;
443 }
444 
445 template <class Scalar>
447  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
449 {
450  if (stepperPL != Teuchos::null) {
452  using Teuchos::RCP;
453 
454  // Parse Stepper List String
455  std::vector<std::string> stepperListStr;
456  stepperListStr.clear();
457  std::string str = stepperPL->get<std::string>("Stepper List");
458  std::string delimiters(",");
459  // Skip delimiters at the beginning
460  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
461  // Find the first delimiter
462  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
463  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
464  std::string token = str.substr(lastPos, pos - lastPos);
465  // Strip single quotes
466  std::string::size_type beg = token.find_first_of("'") + 1;
467  std::string::size_type end = token.find_last_of("'");
468  stepperListStr.push_back(token.substr(beg, end - beg));
469 
470  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
471  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
472  }
473 
475  stepperListStr.size() != appModels.size(), std::logic_error,
476  "Error - Number of models and Steppers do not match!\n"
477  << " There are " << appModels.size() << " models.\n"
478  << " There are " << stepperListStr.size() << " steppers.\n"
479  << " " << str << "\n");
480 
481  typename std::vector<RCP<const Thyra::ModelEvaluator<Scalar> > >::iterator
482  aMI = appModels.begin();
483  typename std::vector<std::string>::iterator sLSI = stepperListStr.begin();
484 
485  for (; aMI < appModels.end() || sLSI < stepperListStr.end();
486  aMI++, sLSI++) {
487  RCP<ParameterList> subStepperPL =
488  Teuchos::sublist(stepperPL, *sLSI, true);
489  auto name = subStepperPL->name();
490  lastPos = name.rfind("->");
491  std::string newName = name.substr(lastPos + 2, name.length());
492  subStepperPL->setName(newName);
493  bool useFSAL = subStepperPL->template get<bool>("Use FSAL", false);
494  auto sf = Teuchos::rcp(new StepperFactory<Scalar>());
495  auto subStepper = sf->createStepper(subStepperPL, *aMI);
496  if (useFSAL) {
499  Teuchos::OSTab ostab(out, 1, "StepperFactory::createSubSteppers()");
500  *out << "Warning -- subStepper = '" << subStepper->getStepperType()
501  << "' has \n"
502  << " subStepper->getUseFSAL() = " << useFSAL << ".\n"
503  << " subSteppers usually can not use the FSAL priniciple with\n"
504  << " operator splitting. Proceeding with it set to true.\n"
505  << std::endl;
506  }
507  this->addStepper(subStepper, useFSAL);
508  }
509  }
510 }
511 
512 // Nonmember constructor - ModelEvaluator and ParameterList
513 // ------------------------------------------------------------------------
514 template <class Scalar>
516  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
518 {
519  auto stepper = Teuchos::rcp(new StepperOperatorSplit<Scalar>());
520 
521  if (pl != Teuchos::null) {
522  stepper->setStepperValues(pl);
523  stepper->setOrderMin(pl->get<int>("Minimum Order", 1));
524  stepper->setOrder(pl->get<int>("Order", 1));
525  stepper->setOrderMax(pl->get<int>("Maximum Order", 1));
526  }
527 
528  if (!(appModels.empty())) {
529  stepper->createSubSteppers(appModels, pl);
530  stepper->initialize();
531  }
532 
533  return stepper;
534 }
535 
536 } // namespace Tempus
537 #endif // Tempus_StepperOperatorSplit_impl_hpp
virtual void setAppAction(Teuchos::RCP< StepperOperatorSplitAppAction< Scalar >> appAction)
T & get(const std::string &name, T def_value)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual void setSubStepperList(std::vector< Teuchos::RCP< Stepper< Scalar >>> subStepperList)
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
virtual void initialize()
Initialize after construction and changing input parameters.
OperatorSplit stepper loops through the Stepper list.
Thyra Base interface for time steppers.
virtual void setModels(std::vector< Teuchos::RCP< const Thyra::ModelEvaluator< Scalar >>> appModels)
StepperState is a simple class to hold state information about the stepper.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
static RCP< FancyOStream > getDefaultOStream()
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar >> &solutionHistory)
Set the initial conditions and make them consistent.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
void createSubSteppers(std::vector< Teuchos::RCP< const Thyra::ModelEvaluator< Scalar >>> appModels, Teuchos::RCP< Teuchos::ParameterList > pl)
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel() const
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
basic_FancyOStream & setOutputToRootOnly(const int rootRank)
Teuchos::RCP< SolutionState< Scalar > > createSolutionStateME(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model, const Teuchos::RCP< StepperState< Scalar > > &stepperState=Teuchos::null, const Teuchos::RCP< PhysicsState< Scalar > > &physicsState=Teuchos::null)
Nonmember constructor from Thyra ModelEvaluator.
Keep a fix number of states.
Teuchos::RCP< StepperOperatorSplit< Scalar > > createStepperOperatorSplit(std::vector< Teuchos::RCP< const Thyra::ModelEvaluator< Scalar >>> appModels, Teuchos::RCP< Teuchos::ParameterList > pl)
Nonmember constructor - ModelEvaluator and ParameterList.
virtual void takeStep(const Teuchos::RCP< SolutionHistory< Scalar >> &solutionHistory)
Take the specified timestep, dt, and return true if successful.
StepperOperatorSplitAppAction class for StepperOperatorSplit.
virtual bool isValidSetup(Teuchos::FancyOStream &out) const
virtual void setSolver(Teuchos::RCP< Thyra::NonlinearSolverBase< Scalar >> solver)
virtual void initialize()
Initialize during construction and after changing input parameters.
virtual void addStepper(Teuchos::RCP< Stepper< Scalar >> stepper, bool useFSAL=false)
Add Stepper to subStepper list. In most cases, subSteppers cannot use xDotOld (thus the default)...
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar >> &appModel)