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"
16 
17 namespace Tempus {
18 
19 
20 template<class Scalar>
22 {
23  this->setStepperType( "Operator Split");
24  this->setUseFSAL( this->getUseFSALDefault());
25  this->setICConsistency( this->getICConsistencyDefault());
26  this->setICConsistencyCheck( this->getICConsistencyCheckDefault());
27 
28  this->setOrder (1);
29  this->setOrderMin(1);
30  this->setOrderMax(1);
31 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
32  this->setObserver();
33 #endif
34  this->setAppAction(Teuchos::null);
35 
36  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
37  OpSpSolnHistory_->setStorageLimit(2);
38  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
39 }
40 
41 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
42 template<class Scalar>
44  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
45  std::vector<Teuchos::RCP<Stepper<Scalar> > > subStepperList,
46  const Teuchos::RCP<StepperObserver<Scalar> >& obs,
47  bool useFSAL,
48  std::string ICConsistency,
49  bool ICConsistencyCheck,
50  int order,
51  int orderMin,
52  int orderMax)
53 {
54  this->setStepperType( "Operator Split");
55  this->setUseFSAL( useFSAL);
56  this->setICConsistency( ICConsistency);
57  this->setICConsistencyCheck( ICConsistencyCheck);
58 
59  this->setSubStepperList(subStepperList);
60  this->setOrder (order);
61  this->setOrderMin(orderMin);
62  this->setOrderMax(orderMax);
63 
64  this->setObserver(obs);
65  this->setAppAction(Teuchos::null);
66 
67  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
68  OpSpSolnHistory_->setStorageLimit(2);
69  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
70 
71  if ( !(appModels.empty()) ) {
72  this->setModels(appModels);
73  this->initialize();
74  }
75 }
76 #endif
77 
78 template<class Scalar>
80  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels,
81  std::vector<Teuchos::RCP<Stepper<Scalar> > > subStepperList,
82  bool useFSAL,
83  std::string ICConsistency,
84  bool ICConsistencyCheck,
85  int order,
86  int orderMin,
87  int orderMax,
88  const Teuchos::RCP<StepperOperatorSplitAppAction<Scalar> >& stepperOSAppAction)
89 {
90  this->setStepperType( "Operator Split");
91  this->setUseFSAL( useFSAL);
92  this->setICConsistency( ICConsistency);
93  this->setICConsistencyCheck( ICConsistencyCheck);
94 
95  this->setSubStepperList(subStepperList);
96  this->setOrder (order);
97  this->setOrderMin(orderMin);
98  this->setOrderMax(orderMax);
99 
100 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
101  this->setObserver();
102 #endif
103  this->setAppAction(stepperOSAppAction);
104 
105  OpSpSolnHistory_ = rcp(new SolutionHistory<Scalar>());
106  OpSpSolnHistory_->setStorageLimit(2);
107  OpSpSolnHistory_->setStorageType(Tempus::STORAGE_TYPE_STATIC);
108 
109  if ( !(appModels.empty()) ) {
110  this->setModels(appModels);
111  this->initialize();
112  }
113 }
114 
115 
116 template<class Scalar>
118  const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& appModel)
119 {
120  if (appModel != Teuchos::null) {
121  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
122  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setModel()");
123  *out << "Warning -- No ModelEvaluator to set for StepperOperatorSplit, "
124  << "because it is a Stepper of Steppers.\n" << std::endl;
125  }
126 }
127 
128 template<class Scalar>
129 Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >
131 {
132  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > model;
133  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
134  subStepperIter = subStepperList_.begin();
135  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
136  model = (*subStepperIter)->getModel();
137  if (model != Teuchos::null) break;
138  }
139  if ( model == Teuchos::null ) {
140  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
141  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::getModel()");
142  *out << "Warning -- StepperOperatorSplit::getModel() "
143  << "Could not find a valid model! Returning null!" << std::endl;
144  }
145 
146  return model;
147 }
148 
149 template<class Scalar>
151  Teuchos::RCP<Thyra::NonlinearSolverBase<Scalar> > /* solver */)
152 {
153  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
154  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::setSolver()");
155  *out << "Warning -- No solver to set for StepperOperatorSplit "
156  << "because it is a Stepper of Steppers.\n" << std::endl;
157 
158  this->isInitialized_ = false;
159 }
160 
161 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
162 template<class Scalar>
164  Teuchos::RCP<StepperObserver<Scalar> > obs)
165 {
166  if (obs == Teuchos::null) {
167  // Create default observer, otherwise keep current observer.
168  if (stepperOSObserver_ == Teuchos::null) {
169  stepperOSObserver_ =
170  Teuchos::rcp(new StepperOperatorSplitObserver<Scalar>());
171  }
172  } else {
173  stepperOSObserver_ =
174  Teuchos::rcp_dynamic_cast<StepperOperatorSplitObserver<Scalar> > (obs, true);
175  }
176 
177  this->isInitialized_ = false;
178 }
179 #endif
180 
181 template<class Scalar>
183  Teuchos::RCP<StepperOperatorSplitAppAction<Scalar> > appAction)
184 {
185  if (appAction == Teuchos::null) {
186  // Create default appAction, otherwise keep current.
187  if (stepperOSAppAction_ == Teuchos::null) {
188  stepperOSAppAction_ =
190  }
191  } else {
192  stepperOSAppAction_ =
193  Teuchos::rcp_dynamic_cast<StepperOperatorSplitAppAction<Scalar> > (appAction, true);
194  }
195  this->isInitialized_ = false;
196 }
197 
198 
199 template<class Scalar>
201  Teuchos::RCP<Stepper<Scalar> > stepper, bool useFSAL)
202 {
203  stepper->setUseFSAL(useFSAL);
204  stepper->initialize();
205  subStepperList_.push_back(stepper);
206 }
207 
208 
209 template<class Scalar>
211  std::vector<Teuchos::RCP<Stepper<Scalar> > > subStepperList)
212 {
213  using Teuchos::RCP;
214  using Teuchos::ParameterList;
215 
216  subStepperList_ = subStepperList;
217 
218  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
219  subStepperIter = subStepperList_.begin();
220 
221  for (; subStepperIter<subStepperList_.end(); subStepperIter++) {
222  auto subStepper = *(subStepperIter);
223  bool useFSAL = subStepper->getUseFSAL();
224  if (useFSAL) {
225  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
226  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::createSubSteppers()");
227  *out << "Warning -- subStepper = '"
228  << subStepper->getStepperType() << "' has \n"
229  << " subStepper->getUseFSAL() = " << useFSAL << ".\n"
230  << " subSteppers usually can not use the FSAL priniciple with\n"
231  << " operator splitting. Proceeding with it set to true.\n"
232  << std::endl;
233  }
234  }
235 
236  this->isInitialized_ = false;
237 }
238 
239 template<class Scalar>
241  std::vector<Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> > > appModels)
242 {
243  using Teuchos::RCP;
244  using Teuchos::ParameterList;
245 
246  TEUCHOS_TEST_FOR_EXCEPTION(subStepperList_.size() != appModels.size(),
247  std::logic_error, "Error - Number of models and Steppers do not match!\n"
248  << " There are " << appModels.size() << " models.\n"
249  << " There are " << subStepperList_.size() << " steppers.\n");
250 
251  typename std::vector<RCP<const Thyra::ModelEvaluator<Scalar> > >::iterator
252  appModelIter = appModels.begin();
253 
254  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
255  subStepperIter = subStepperList_.begin();
256 
257  for (; appModelIter<appModels.end() || subStepperIter<subStepperList_.end();
258  appModelIter++, subStepperIter++)
259  {
260  auto appModel = *(appModelIter);
261  auto subStepper = *(subStepperIter);
262  subStepper->setModel(appModel);
263  subStepper->initialize();
264  }
265 
266  this->isInitialized_ = false;
267 }
268 
269 template<class Scalar>
271 {
272  if (tempState_ == Teuchos::null) {
273  Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >model = this->getModel();
274  TEUCHOS_TEST_FOR_EXCEPTION( model == Teuchos::null, std::logic_error,
275  "Error - StepperOperatorSplit::initialize() Could not find "
276  "a valid model!\n");
277  tempState_ = createSolutionStateME(model, this->getDefaultStepperState());
278  }
279 
280  if (!isOneStepMethod() ) {
281  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
282  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::initialize()");
283  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
284  subStepperIter = subStepperList_.begin();
285  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
286  *out << "SubStepper, " << (*subStepperIter)->getStepperType()
287  << ", isOneStepMethod = " << (*subStepperIter)->isOneStepMethod()
288  << std::endl;
289  }
290  TEUCHOS_TEST_FOR_EXCEPTION(!isOneStepMethod(), std::logic_error,
291  "Error - OperatorSplit only works for one-step methods!\n");
292  }
293 
295 }
296 
297 template<class Scalar>
299  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
300 {
301  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
302  subStepperIter = subStepperList_.begin();
303  for (; subStepperIter < subStepperList_.end(); subStepperIter++)
304  (*subStepperIter)->setInitialConditions(solutionHistory);
305 }
306 
307 template<class Scalar>
309  const Teuchos::RCP<SolutionHistory<Scalar> >& solutionHistory)
310 {
311  this->checkInitialized();
312 
313  using Teuchos::RCP;
314 
315  TEMPUS_FUNC_TIME_MONITOR("Tempus::StepperOperatorSplit::takeStep()");
316  {
317  TEUCHOS_TEST_FOR_EXCEPTION(solutionHistory->getNumStates() < 2,
318  std::logic_error,
319  "Error - StepperOperatorSplit<Scalar>::takeStep(...)\n"
320  "Need at least two SolutionStates for OperatorSplit.\n"
321  " Number of States = " << solutionHistory->getNumStates() << "\n"
322  "Try setting in \"Solution History\" \"Storage Type\" = \"Undo\"\n"
323  " or \"Storage Type\" = \"Static\" and \"Storage Limit\" = \"2\"\n");
324 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
325  stepperOSObserver_->observeBeginTakeStep(solutionHistory, *this);
326 #endif
327  RCP<StepperOperatorSplit<Scalar> > thisStepper = Teuchos::rcpFromRef(*this);
328  stepperOSAppAction_->execute(solutionHistory, thisStepper,
330 
331  RCP<SolutionState<Scalar> > workingState=solutionHistory->getWorkingState();
332 
333  // Create OperatorSplit SolutionHistory to pass to subSteppers.
334  tempState_->copy(solutionHistory->getCurrentState());
335  OpSpSolnHistory_->clear();
336  OpSpSolnHistory_->addState(tempState_);
337  OpSpSolnHistory_->addWorkingState(workingState, false);
338 
339  RCP<SolutionState<Scalar> > currentSubState =
340  OpSpSolnHistory_->getCurrentState();
341  RCP<SolutionState<Scalar> > workingSubState =
342  OpSpSolnHistory_->getWorkingState();
343 
344  bool pass = true;
345  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::iterator
346  subStepperIter = subStepperList_.begin();
347  for (; subStepperIter < subStepperList_.end() and pass; subStepperIter++) {
348 
349 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
350  int index = subStepperIter - subStepperList_.begin();
351  stepperOSObserver_->observeBeforeStepper(index, solutionHistory, *this);
352 #endif
353  stepperOSAppAction_->execute(solutionHistory, thisStepper,
355 
356  (*subStepperIter)->takeStep(OpSpSolnHistory_);
357 
358 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
359  stepperOSObserver_->observeAfterStepper(index, solutionHistory, *this);
360 #endif
361  stepperOSAppAction_->execute(solutionHistory, thisStepper,
363 
364  if (workingSubState->getSolutionStatus() == Status::FAILED) {
365  pass = false;
366  Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
367  Teuchos::OSTab ostab(out,1,"StepperOperatorSplit::takeStep()");
368  *out << "SubStepper, " << (*subStepperIter)->getStepperType()
369  << ", failed!" << std::endl;
370  break;
371  }
372 
373  // "promote" workingSubState
374  currentSubState = OpSpSolnHistory_->getCurrentState();
375  currentSubState->copySolutionData(workingSubState);
376  }
377 
378  if (pass == true) workingState->setSolutionStatus(Status::PASSED);
379  else workingState->setSolutionStatus(Status::FAILED);
380  workingState->setOrder(this->getOrder());
381  workingState->computeNorms(solutionHistory->getCurrentState());
382  OpSpSolnHistory_->clear();
383 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
384  stepperOSObserver_->observeEndTakeStep(solutionHistory, *this);
385 #endif
386  stepperOSAppAction_->execute(solutionHistory, thisStepper,
388  }
389  return;
390 }
391 
392 
393 /** \brief Provide a StepperState to the SolutionState.
394  * This Stepper does not have any special state data,
395  * so just provide the base class StepperState with the
396  * Stepper description. This can be checked to ensure
397  * that the input StepperState can be used by this Stepper.
398  */
399 template<class Scalar>
400 Teuchos::RCP<Tempus::StepperState<Scalar> > StepperOperatorSplit<Scalar>::
402 {
403  Teuchos::RCP<Tempus::StepperState<Scalar> > stepperState =
404  rcp(new StepperState<Scalar>(this->getStepperType()));
405  return stepperState;
406 }
407 
408 
409 template<class Scalar>
411  Teuchos::FancyOStream &out,
412  const Teuchos::EVerbosityLevel verbLevel) const
413 {
414  out << std::endl;
415  Stepper<Scalar>::describe(out, verbLevel);
416 
417  out << "--- StepperOperatorSplit ---\n";
418  out << " subStepperList_.size() = " << subStepperList_.size() << std::endl;
419  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
420  subStepperIter = subStepperList_.begin();
421  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
422  out << " SubStepper = " << (*subStepperIter)->getStepperType()<<std::endl;
423  out << " = " << (*subStepperIter)->isInitialized() << std::endl;
424  out << " = " << (*subStepperIter) << std::endl;
425  }
426  out << " OpSpSolnHistory_ = " << OpSpSolnHistory_ << std::endl;
427  out << " tempState_ = " << tempState_ << std::endl;
428 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
429  out << " stepperOSObserver_ = " << stepperOSObserver_ << std::endl;
430 #endif
431  out << " stepperOSAppAction_ = " << stepperOSAppAction_ << std::endl;
432  out << " order_ = " << order_ << std::endl;
433  out << " orderMin_ = " << orderMin_ << std::endl;
434  out << " orderMax_ = " << orderMax_ << std::endl;
435  out << "----------------------------" << std::endl;
436 }
437 
438 
439 template<class Scalar>
440 bool StepperOperatorSplit<Scalar>::isValidSetup(Teuchos::FancyOStream & out) const
441 {
442  bool isValidSetup = true;
443 
444  if ( !Stepper<Scalar>::isValidSetup(out) ) isValidSetup = false;
445 
446  if (subStepperList_.size() == 0) {
447  isValidSetup = false;
448  out << "The substepper list is empty!\n";
449  }
450 
451  typename std::vector<Teuchos::RCP<Stepper<Scalar> > >::const_iterator
452  subStepperIter = subStepperList_.begin();
453 
454  for (; subStepperIter < subStepperList_.end(); subStepperIter++) {
455  auto subStepper = *(subStepperIter);
456  if ( !subStepper->isInitialized() ) {
457  isValidSetup = false;
458  out << "The subStepper, " << subStepper->description()
459  << ", is not initialized!\n";
460  }
461  }
462 #ifndef TEMPUS_HIDE_DEPRECATED_CODE
463  if (stepperOSObserver_ == Teuchos::null) {
464  isValidSetup = false;
465  out << "The Operator-Split observer is not set!\n";
466  }
467 #endif
468  if (stepperOSAppAction_ == Teuchos::null) {
469  isValidSetup = false;
470  out << "The Operator-Split AppAction is not set!\n";
471  }
472 
473  return isValidSetup;
474 }
475 
476 
477 template<class Scalar>
478 Teuchos::RCP<const Teuchos::ParameterList>
480 {
481  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
482  getValidParametersBasic(pl, this->getStepperType());
483  pl->set<int> ("Minimum Order", 1,
484  "Minimum Operator-split order. (default = 1)\n");
485  pl->set<int> ("Order", 1,
486  "Operator-split order. (default = 1)\n");
487  pl->set<int> ("Maximum Order", 1,
488  "Maximum Operator-split order. (default = 1)\n");
489 
490  pl->set<std::string>("Stepper List", "",
491  "Comma deliminated list of single quoted Steppers, e.g., \"'Operator 1', 'Operator 2'\".");
492 
493  return pl;
494 }
495 
496 
497 } // namespace Tempus
498 #endif // Tempus_StepperOperatorSplit_impl_hpp
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()
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 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.
Thyra Base interface for time steppers.
StepperState is a simple class to hold state information about the stepper.
virtual void setAppAction(Teuchos::RCP< StepperOperatorSplitAppAction< Scalar > > appAction)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
StepperOperatorSplitObserver class for StepperOperatorSplit.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
StepperObserver class for Stepper class.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
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.
void getValidParametersBasic(Teuchos::RCP< Teuchos::ParameterList > pl, std::string stepperType)
Provide basic parameters to Steppers.
virtual void initialize()
Initialize during construction and after changing input parameters.
virtual void setSubStepperList(std::vector< Teuchos::RCP< Stepper< Scalar > > > subStepperList)