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