Tempus  Version of the Day
Time Integration
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 template<class Scalar>
21  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
22  Teuchos::RCP<Teuchos::ParameterList> pList)
23  : stepperPL_(Teuchos::null), OpSpSolnHistory_(Teuchos::null),
24  stepperOSObserver_(Teuchos::null)
25 {
26  this->setParameterList(pList);
27  this->createSubSteppers(appModels);
28  this->initialize();
29 }
30 
31 template<class Scalar>
33  : stepperPL_(Teuchos::null), OpSpSolnHistory_(Teuchos::null),
34  stepperOSObserver_(Teuchos::null)
35 {
36  this->setParameterList(Teuchos::null);
37  // Still require
38  // * Setting models and steppers, i.e., addStepper()
39  // * Calling initialize()
40 }
41 
42 template<class Scalar>
44  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
45 {
46  if (appModel != Teuchos::null) {
47  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
48  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setModel()");
49  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
50  << "because it is a Stepper of Steppers.\n" << std::endl;
51  }
52  return;
53 }
54 
55 template<class Scalar>
57  const Teuchos::RCP<Thyra::ModelEvaluator<Scalar> >& appModel)
58 {
59  if (appModel != Teuchos::null) {
60  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
61  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setModel()");
62  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
63  << "because it is a Stepper of Steppers.\n" << std::endl;
64  }
65  return;
66 }
67 
68 template<class Scalar>
69 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
71 {
72  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model;
73  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
74  subStepperIter = subStepperList_.begin();
75  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
76  model = (*subStepperIter)->getModel();
77  if (model != Teuchos::null) break;
78  }
79  if ( model == Teuchos::null ) {
80  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
81  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::getModel()");
82  *out << "Warning -- StepperOperatorSplit::getModel() "
83  << "Could not find a valid model! Returning null!" << std::endl;
84  }
85 
86  return model;
87 }
88 
89 template<class Scalar>
90 void StepperOperatorSplit<Scalar>::setSolver(std::string solverName)
91 {
92  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
93  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
94  *out << "Warning -- No solver to set for StepperOperatorSplit, "
95  << "because it is a Stepper of Steppers.\n" << std::endl;
96  return;
97 }
98 
99 template<class Scalar>
101  Teuchos::RCP<Teuchos::ParameterList> solverPL)
102 {
103  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
104  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
105  *out << "Warning -- No solver to set for StepperOperatorSplit "
106  << "because it is a Stepper of Steppers.\n" << std::endl;
107  return;
108 }
109 
110 template<class Scalar>
112  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > solver)
113 {
114  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
115  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
116  *out << "Warning -- No solver to set for StepperOperatorSplit "
117  << "because it is a Stepper of Steppers.\n" << std::endl;
118  return;
119 }
120 
121 template<class Scalar>
123  Teuchos::RCP<StepperObserver<Scalar> > obs)
124 {
125  if (obs == Teuchos::null) {
126  // Create default observer, otherwise keep current observer.
127  if (stepperOSObserver_ == Teuchos::null) {
128  stepperOSObserver_ =
129  Teuchos::rcp(new StepperOperatorSplitObserver<Scalar>());
130  }
131  } else {
132  stepperOSObserver_ =
133  Teuchos::rcp_dynamic_cast<StepperOperatorSplitObserver<Scalar> > (obs);
134  }
135 }
136 
137 template<class Scalar>
139  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels)
140 {
141  using Teuchos::RCP;
142  using Teuchos::ParameterList;
143 
144  // Parse Stepper List String
145  std::vector<std::string> stepperListStr;
146  stepperListStr.clear();
147  std::string str = stepperPL_->get<std::string>("Stepper List");
148  std::string delimiters(",");
149  // Skip delimiters at the beginning
150  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
151  // Find the first delimiter
152  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
153  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
154  std::string token = str.substr(lastPos,pos-lastPos);
155  // Strip single quotes
156  std::string::size_type beg = token.find_first_of("'") + 1;
157  std::string::size_type end = token.find_last_of ("'");
158  stepperListStr.push_back(token.substr(beg,end-beg));
159 
160  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
161  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
162  }
163 
164  TEUCHOS_TEST_FOR_EXCEPTION(stepperListStr.size() != appModels.size(),
165  std::logic_error, "Error - Number of models and Steppers do not match!\n"
166  << " There are " << appModels.size() << " models.\n"
167  << " There are " << stepperListStr.size() << " steppers.\n"
168  << " " << str << "\n");
169 
170  RCP<StepperFactory<Scalar> > sf = Teuchos::rcp(new StepperFactory<Scalar>());
171  typename
172  std::vector<RCP<const Thyra::ModelEvaluator<Scalar> > >::iterator
173  aMI = appModels.begin();
174  typename std::vector<std::string>::iterator sLSI = stepperListStr.begin();
175 
176  for (; aMI<appModels.end() || sLSI<stepperListStr.end(); aMI++, sLSI++) {
177  RCP<ParameterList> subStepperPL = Teuchos::sublist(stepperPL_,*sLSI,true);
178  subStepperList_.push_back(sf->createStepper(*aMI, subStepperPL));
179  }
180 }
181 
182 template<class Scalar>
184 {
185  TEUCHOS_TEST_FOR_EXCEPTION( subStepperList_.size() == 0, std::logic_error,
186  "Error - Need to set the subSteppers, createSubSteppers(), before calling "
187  "StepperOperatorSplit::initialize()\n");
188 
189  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
190  OpSpSolnHistory_->setStorageLimit(2);
191  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
192 
193  if (tempState_ == Teuchos::null) {
194  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >model = this->getModel();
195  TEUCHOS_TEST_FOR_EXCEPTION( model == Teuchos::null, std::logic_error,
196  "Error - StepperOperatorSplit::initialize() Could not find "
197  "a valid model!\n");
198  tempState_ = rcp(new SolutionState<Scalar>(
199  model, this->getDefaultStepperState()));
200  }
201  this->setParameterList(this->stepperPL_);
202  this->setObserver();
203 
204  if (!isOneStepMethod() ) {
205  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
206  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::initialize()");
207  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
208  subStepperIter = subStepperList_.begin();
209  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
210  *out << "SubStepper, " << (*subStepperIter)->description()
211  << ", isOneStepMethod = " << (*subStepperIter)->isOneStepMethod()
212  << std::endl;
213  }
214  TEUCHOS_TEST_FOR_EXCEPTION(!isOneStepMethod(), std::logic_error,
215  "Error - OperatorSplit only works for one-step methods!\n");
216  }
217 }
218 
219 template<class Scalar>
221  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
222 {
223  using Teuchos::RCP;
224 
225  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperOperatorSplit::takeStep()");
226  {
227  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
228  std::logic_error,
229  "Error - StepperOperatorSplit<Scalar>::takeStep(...)\n"
230  "Need at least two SolutionStates for OperatorSplit.\n"
231  " Number of States = " << solutionHistory->getNumStates() << "\n"
232  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
233  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
234 
235  stepperOSObserver_->observeBeginTakeStep(solutionHistory, *this);
236 
237  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
238 
239  // Create OperatorSplit SolutionHistory to pass to subSteppers.
240  tempState_->copy(solutionHistory->getCurrentState());
241  OpSpSolnHistory_->clear();
242  OpSpSolnHistory_->addState(tempState_);
243  OpSpSolnHistory_->addWorkingState(workingState, false);
244 
245  RCP<SolutionState<Scalar> > currentSubState =
246  OpSpSolnHistory_->getCurrentState();
247  RCP<SolutionState<Scalar> > workingSubState =
248  OpSpSolnHistory_->getWorkingState();
249 
250  bool pass = true;
251  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
252  subStepperIter = subStepperList_.begin();
253  for (; subStepperIter < subStepperList_.end() and pass; subStepperIter++) {
254  int index = subStepperIter - subStepperList_.begin();
255 
256  stepperOSObserver_->observeBeforeStepper(index, solutionHistory, *this);
257 
258  (*subStepperIter)->takeStep(OpSpSolnHistory_);
259 
260  stepperOSObserver_->observeAfterStepper(index, solutionHistory, *this);
261 
262  if (workingSubState->getSolutionStatus() == Status::FAILED) {
263  pass = false;
264  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
265  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::takeStep()");
266  *out << "SubStepper, " << (*subStepperIter)->description()
267  << ", failed!" << std::endl;
268  break;
269  }
270 
271  // "promote" workingSubState
272  currentSubState = OpSpSolnHistory_->getCurrentState();
273  currentSubState->copySolutionData(workingSubState);
274  }
275 
276  if (pass == true) workingState->setSolutionStatus(Status::PASSED);
277  else workingState->setSolutionStatus(Status::FAILED);
278  workingState->setOrder(this->getOrder());
279  OpSpSolnHistory_->clear();
280  stepperOSObserver_->observeEndTakeStep(solutionHistory, *this);
281  }
282  return;
283 }
284 
285 
286 /** \brief Provide a StepperState to the SolutionState.
287  * This Stepper does not have any special state data,
288  * so just provide the base class StepperState with the
289  * Stepper description. This can be checked to ensure
290  * that the input StepperState can be used by this Stepper.
291  */
292 template<class Scalar>
293 Teuchos::RCP<Tempus::StepperState<Scalar> > StepperOperatorSplit<Scalar>::
295 {
296  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
297  rcp(new StepperState<Scalar>(description()));
298  return stepperState;
299 }
300 
301 
302 template<class Scalar>
304 {
305  std::string name = "Operator Split";
306  return(name);
307 }
308 
309 
310 template<class Scalar>
312  Teuchos::FancyOStream &out,
313  const Teuchos::EVerbosityLevel verbLevel) const
314 {
315  out << description() << "::describe:" << std::endl;
316 }
317 
318 
319 template <class Scalar>
321  const Teuchos::RCP<Teuchos::ParameterList> & pList)
322 {
323  Teuchos::RCP<Teuchos::ParameterList> stepperPL = this->stepperPL_;
324  if (pList == Teuchos::null) {
325  // Create default parameters if null, otherwise keep current parameters.
326  if (stepperPL == Teuchos::null) stepperPL = this->getDefaultParameters();
327  } else {
328  stepperPL = pList;
329  }
330  // Can not validate because of optional Parameters, e.g. operators.
331  //stepperPL->validateParametersAndSetDefaults(*this->getValidParameters());
332 
333  std::string stepperType = stepperPL->get<std::string>("Stepper Type");
334  TEUCHOS_TEST_FOR_EXCEPTION( stepperType != "Operator Split", std::logic_error,
335  "Error - Stepper Type is not 'Operator Split'!\n"
336  << " Stepper Type = "<< pList->get<std::string>("Stepper Type") << "\n");
337 
338  this->stepperPL_ = stepperPL;
339 }
340 
341 
342 template<class Scalar>
343 Teuchos::RCP<const Teuchos::ParameterList>
345 {
346  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
347  pl->setName("Default Stepper - " + this->description());
348  pl->set<std::string>("Stepper Type", "Operator Split",
349  "'Stepper Type' must be 'Operator Split'.");
350  pl->set<int> ("Minimum Order", 1,
351  "Minimum Operator-split order. (default = 1)\n");
352  pl->set<int> ("Order", 1,
353  "Operator-split order. (default = 1)\n");
354  pl->set<int> ("Maximum Order", 1,
355  "Maximum Operator-split order. (default = 1)\n");
356 
357  pl->set<std::string>("Stepper List", "",
358  "Comma deliminated list of single quoted Steppers, e.g., \"'Operator 1', 'Operator 2'\".");
359 
360  return pl;
361 }
362 
363 
364 template<class Scalar>
365 Teuchos::RCP<Teuchos::ParameterList>
367 {
368  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
369  *pl = *(this->getValidParameters());
370  return pl;
371 }
372 
373 
374 template <class Scalar>
375 Teuchos::RCP<Teuchos::ParameterList>
377 {
378  return(stepperPL_);
379 }
380 
381 
382 template <class Scalar>
383 Teuchos::RCP<Teuchos::ParameterList>
385 {
386  Teuchos::RCP<Teuchos::ParameterList> temp_plist = stepperPL_;
387  stepperPL_ = Teuchos::null;
388  return(temp_plist);
389 }
390 
391 
392 } // namespace Tempus
393 #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 void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
virtual Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > getModel()
virtual void setObserver(Teuchos::RCP< StepperObserver< Scalar > > obs=Teuchos::null)
Set Observer.
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)
StepperOperatorSplit()
Constructor which is setup except for models and steppers (i.e., addStepper()), and an initialize() b...
StepperState is a simple class to hold state information about the stepper.
StepperOperatorSplitObserver class for StepperOperatorSplit.
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
Keep a fix number of states.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() 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.
Solution state for integrators and steppers. SolutionState contains the metadata for solutions and th...