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