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