Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros 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 "Teuchos_VerboseObjectParameterListHelpers.hpp"
13 #include "Thyra_VectorStdOps.hpp"
15 
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22  : stepperPL_(Teuchos::null), OpSpSolnHistory_(Teuchos::null),
23  stepperOSObserver_(Teuchos::null)
24 {
25  this->setParameterList(Teuchos::null);
26 
27  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
28  Teuchos::OSTab ostab(out,1,this->description());
29  *out << "Warning -- Constructing " << this->description()
30  << " without ModelEvaluators!\n"
31  << " - Can reset ParameterList with setParameterList().\n"
32  << " - Requires subsequent addStepper()/createSubSteppers()\n"
33  << " and initialize() calls before calling takeStep().\n"
34  << std::endl;
35 }
36 
37 template<class Scalar>
39  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
40  Teuchos::RCP<Teuchos::ParameterList> pList)
41  : stepperPL_(Teuchos::null), OpSpSolnHistory_(Teuchos::null),
42  stepperOSObserver_(Teuchos::null)
43 {
44  this->setParameterList(pList);
45 
46  if (appModels.empty()) {
47  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
48  Teuchos::OSTab ostab(out,1,this->description());
49  *out << "Warning -- Constructing " << this->description()
50  << " without ModelEvaluators!\n"
51  << " - Can reset ParameterList with setParameterList().\n"
52  << " - Requires subsequent addStepper()/createSubSteppers\n"
53  << " and initialize() calls before calling takeStep().\n"
54  << std::endl;
55  }
56  else {
57  this->createSubSteppers(appModels);
58  this->initialize();
59  }
60 }
61 
62 template<class Scalar>
64  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
65 {
66  if (appModel != Teuchos::null) {
67  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
68  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setModel()");
69  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
70  << "because it is a Stepper of Steppers.\n" << std::endl;
71  }
72  return;
73 }
74 
75 template<class Scalar>
77  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& appModel)
78 {
79  if (appModel != Teuchos::null) {
80  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
81  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setModel()");
82  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
83  << "because it is a Stepper of Steppers.\n" << std::endl;
84  }
85  return;
86 }
87 
88 template<class Scalar>
89 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
91 {
92  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model;
93  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
94  subStepperIter = subStepperList_.begin();
95  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
96  model = (*subStepperIter)->getModel();
97  if (model != Teuchos::null) break;
98  }
99  if ( model == Teuchos::null ) {
100  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
101  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::getModel()");
102  *out << "Warning -- StepperOperatorSplit::getModel() "
103  << "Could not find a valid model! Returning null!" << std::endl;
104  }
105 
106  return model;
107 }
108 
109 template<class Scalar>
110 void StepperOperatorSplit<Scalar>::setSolver(std::string /* solverName */)
111 {
112  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
113  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
114  *out << "Warning -- No solver to set for StepperOperatorSplit, "
115  << "because it is a Stepper of Steppers.\n" << std::endl;
116  return;
117 }
118 
119 template<class Scalar>
121  Teuchos::RCP<Teuchos::ParameterList> /* solverPL */)
122 {
123  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
124  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
125  *out << "Warning -- No solver to set for StepperOperatorSplit "
126  << "because it is a Stepper of Steppers.\n" << std::endl;
127  return;
128 }
129 
130 template<class Scalar>
132  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > /* solver */)
133 {
134  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
135  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
136  *out << "Warning -- No solver to set for StepperOperatorSplit "
137  << "because it is a Stepper of Steppers.\n" << std::endl;
138  return;
139 }
140 
141 template<class Scalar>
143  Teuchos::RCP<StepperObserver<Scalar> > obs)
144 {
145  if (obs == Teuchos::null) {
146  // Create default observer, otherwise keep current observer.
147  if (stepperOSObserver_ == Teuchos::null) {
148  stepperOSObserver_ =
149  Teuchos::rcp(new StepperOperatorSplitObserver<Scalar>());
150  }
151  } else {
152  stepperOSObserver_ =
153  Teuchos::rcp_dynamic_cast<StepperOperatorSplitObserver<Scalar> > (obs);
154  }
155 }
156 
157 template<class Scalar>
159  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels)
160 {
161  using Teuchos::RCP;
162  using Teuchos::ParameterList;
163 
164  // Parse Stepper List String
165  std::vector<std::string> stepperListStr;
166  stepperListStr.clear();
167  std::string str = stepperPL_->get<std::string>("Stepper List");
168  std::string delimiters(",");
169  // Skip delimiters at the beginning
170  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
171  // Find the first delimiter
172  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
173  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
174  std::string token = str.substr(lastPos,pos-lastPos);
175  // Strip single quotes
176  std::string::size_type beg = token.find_first_of("'") + 1;
177  std::string::size_type end = token.find_last_of ("'");
178  stepperListStr.push_back(token.substr(beg,end-beg));
179 
180  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
181  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
182  }
183 
184  TEUCHOS_TEST_FOR_EXCEPTION(stepperListStr.size() != appModels.size(),
185  std::logic_error, "Error - Number of models and Steppers do not match!\n"
186  << " There are " << appModels.size() << " models.\n"
187  << " There are " << stepperListStr.size() << " steppers.\n"
188  << " " << str << "\n");
189 
190  RCP<StepperFactory<Scalar> > sf = Teuchos::rcp(new StepperFactory<Scalar>());
191  typename
192  std::vector<RCP<const Thyra::ModelEvaluator<Scalar> > >::iterator
193  aMI = appModels.begin();
194  typename std::vector<std::string>::iterator sLSI = stepperListStr.begin();
195 
196  for (; aMI<appModels.end() || sLSI<stepperListStr.end(); aMI++, sLSI++) {
197  RCP<ParameterList> subStepperPL = Teuchos::sublist(stepperPL_,*sLSI,true);
198  bool useFSAL = subStepperPL->template get<bool>("Use FSAL",false);
199  auto subStepper = sf->createStepper(subStepperPL, *aMI);
200  if (useFSAL) {
201  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
202  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::createSubSteppers()");
203  *out << "Warning -- subStepper = "
204  << subStepper->getStepperType() << " has \n"
205  << " subStepper->getUseFSAL() = " << useFSAL << ".\n"
206  << " subSteppers usually can not use the FSAL priniciple with\n"
207  << " operator splitting. Proceeding with it set to true.\n"
208  << std::endl;
209  }
210  addStepper(subStepper, useFSAL);
211  }
212 }
213 
214 template<class Scalar>
216 {
217  TEUCHOS_TEST_FOR_EXCEPTION( subStepperList_.size() == 0, std::logic_error,
218  "Error - Need to set the subSteppers, createSubSteppers(), before calling "
219  "StepperOperatorSplit::initialize()\n");
220 
221  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
222  OpSpSolnHistory_->setStorageLimit(2);
223  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
224 
225  if (tempState_ == Teuchos::null) {
226  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >model = this->getModel();
227  TEUCHOS_TEST_FOR_EXCEPTION( model == Teuchos::null, std::logic_error,
228  "Error - StepperOperatorSplit::initialize() Could not find "
229  "a valid model!\n");
230  //tempState_ = rcp(new SolutionState<Scalar>()); Doesn't seem to work?!
231  tempState_ = rcp(new SolutionState<Scalar>(
232  model, this->getDefaultStepperState()));
233  }
234  this->setParameterList(this->stepperPL_);
235  this->setObserver();
236 
237  if (!isOneStepMethod() ) {
238  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
239  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::initialize()");
240  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
241  subStepperIter = subStepperList_.begin();
242  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
243  *out << "SubStepper, " << (*subStepperIter)->description()
244  << ", isOneStepMethod = " << (*subStepperIter)->isOneStepMethod()
245  << std::endl;
246  }
247  TEUCHOS_TEST_FOR_EXCEPTION(!isOneStepMethod(), std::logic_error,
248  "Error - OperatorSplit only works for one-step methods!\n");
249  }
250 }
251 
252 template<class Scalar>
254  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
255 {
256  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
257  subStepperIter = subStepperList_.begin();
258  for (; subStepperIter < subStepperList_.end(); subStepperIter++)
259  (*subStepperIter)->setInitialConditions(solutionHistory);
260 }
261 
262 template<class Scalar>
264  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
265 {
266  using Teuchos::RCP;
267 
268  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperOperatorSplit::takeStep()");
269  {
270  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
271  std::logic_error,
272  "Error - StepperOperatorSplit<Scalar>::takeStep(...)\n"
273  "Need at least two SolutionStates for OperatorSplit.\n"
274  " Number of States = " << solutionHistory->getNumStates() << "\n"
275  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
276  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
277 
278  stepperOSObserver_->observeBeginTakeStep(solutionHistory, *this);
279 
280  RCP<SolutionState<Scalar> > workingState=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() and pass; subStepperIter++) {
297  int index = subStepperIter - subStepperList_.begin();
298 
299  stepperOSObserver_->observeBeforeStepper(index, solutionHistory, *this);
300 
301  (*subStepperIter)->takeStep(OpSpSolnHistory_);
302 
303  stepperOSObserver_->observeAfterStepper(index, solutionHistory, *this);
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)->description()
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  OpSpSolnHistory_->clear();
323  stepperOSObserver_->observeEndTakeStep(solutionHistory, *this);
324  }
325  return;
326 }
327 
328 
329 /** \brief Provide a StepperState to the SolutionState.
330  * This Stepper does not have any special state data,
331  * so just provide the base class StepperState with the
332  * Stepper description. This can be checked to ensure
333  * that the input StepperState can be used by this Stepper.
334  */
335 template<class Scalar>
336 Teuchos::RCP<Tempus::StepperState<Scalar> > StepperOperatorSplit<Scalar>::
338 {
339  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
340  rcp(new StepperState<Scalar>(description()));
341  return stepperState;
342 }
343 
344 
345 template<class Scalar>
347 {
348  std::string name = "Operator Split";
349  return(name);
350 }
351 
352 
353 template<class Scalar>
355  Teuchos::FancyOStream &out,
356  const Teuchos::EVerbosityLevel /* verbLevel */) const
357 {
358  out << description() << "::describe:" << std::endl;
359 }
360 
361 
362 template <class Scalar>
364  const Teuchos::RCP<Teuchos::ParameterList> & pList)
365 {
366  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
367  if (pList == Teuchos::null) {
368  // Create default parameters if null, otherwise keep current parameters.
369  if (stepperPL == Teuchos::null) stepperPL = this->getDefaultParameters();
370  } else {
371  stepperPL = pList;
372  }
373  // Can not validate because of optional Parameters, e.g. operators.
374  //stepperPL->validateParametersAndSetDefaults(*this->getValidParameters());
375 
376  std::string stepperType = stepperPL->get<std::string>("Stepper Type");
377  TEUCHOS_TEST_FOR_EXCEPTION( stepperType != "Operator Split", std::logic_error,
378  "Error - Stepper Type is not 'Operator Split'!\n"
379  << " Stepper Type = "<< pList->get<std::string>("Stepper Type") << "\n");
380 
381  this->stepperPL_ = stepperPL;
382 }
383 
384 
385 template<class Scalar>
386 Teuchos::RCP<const Teuchos::ParameterList>
388 {
389  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
390  pl->setName("Default Stepper - " + this->description());
391  pl->set<std::string>("Stepper Type", "Operator Split",
392  "'Stepper Type' must be 'Operator Split'.");
393  this->getValidParametersBasic(pl);
394  pl->set<int> ("Minimum Order", 1,
395  "Minimum Operator-split order. (default = 1)\n");
396  pl->set<int> ("Order", 1,
397  "Operator-split order. (default = 1)\n");
398  pl->set<int> ("Maximum Order", 1,
399  "Maximum Operator-split order. (default = 1)\n");
400 
401  pl->set<std::string>("Stepper List", "",
402  "Comma deliminated list of single quoted Steppers, e.g., \"'Operator 1', 'Operator 2'\".");
403 
404  return pl;
405 }
406 
407 
408 template<class Scalar>
409 Teuchos::RCP<Teuchos::ParameterList>
411 {
412  using Teuchos::RCP;
413  using Teuchos::ParameterList;
414  using Teuchos::rcp_const_cast;
415 
416  RCP<ParameterList> pl =
417  rcp_const_cast<ParameterList>(this->getValidParameters());
418 
419  return pl;
420 }
421 
422 
423 template <class Scalar>
424 Teuchos::RCP<Teuchos::ParameterList>
426 {
427  return(stepperPL_);
428 }
429 
430 
431 template <class Scalar>
432 Teuchos::RCP<Teuchos::ParameterList>
434 {
435  Teuchos::RCP<Teuchos::ParameterList> temp_plist = stepperPL_;
436  stepperPL_ = Teuchos::null;
437  return(temp_plist);
438 }
439 
440 
441 } // namespace Tempus
442 #endif // Tempus_StepperOperatorSplit_impl_hpp
Teuchos::RCP< Teuchos::ParameterList > unsetParameterList()
virtual void setSolver(std::string solverName)
Set solver via ParameterList solver name.
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel()
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual void setModel(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void setNonConstModel(const Teuchos::RCP< Thyra::ModelEvaluator< Scalar > > &appModel)
virtual void createSubSteppers(std::vector< Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > > appModels)
Take models and ParameterList and create subSteppers.
virtual Teuchos::RCP< Tempus::StepperState< Scalar > > getDefaultStepperState()
Get a default (initial) StepperState.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &pl)
StepperState is a simple class to hold state information about the stepper.
StepperOperatorSplitObserver class for StepperOperatorSplit.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
StepperObserver class for Stepper class.
Teuchos::RCP< SolutionHistory< Scalar > > solutionHistory(Teuchos::RCP< Teuchos::ParameterList > pList=Teuchos::null)
Nonmember constructor.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< Teuchos::ParameterList > getDefaultParameters() const
virtual void setInitialConditions(const Teuchos::RCP< SolutionHistory< Scalar > > &solutionHistory)
Set the initial conditions and make them consistent.
Keep a fix number of states.
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.
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...