Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Tempus_SolutionHistory_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_SolutionHistory_impl_hpp
11#define Tempus_SolutionHistory_impl_hpp
12
13#include "Teuchos_StandardParameterEntryValidators.hpp"
14#include "Teuchos_TimeMonitor.hpp"
15
16#include "Thyra_VectorStdOps.hpp"
17
20
21namespace Tempus {
22
23template <class Scalar>
25 : name_("Solution History"), storageType_(STORAGE_TYPE_UNDO), storageLimit_(2)
26{
27 using Teuchos::RCP;
28 // Create history, a vector of solution states.
29 history_ = rcp(new std::vector<RCP<SolutionState<Scalar> > >);
31 isInitialized_ = false;
32}
33
34template <class Scalar>
36 std::string name,
37 Teuchos::RCP<std::vector<Teuchos::RCP<SolutionState<Scalar> > > > history,
38 Teuchos::RCP<Interpolator<Scalar> > interpolator, StorageType storageType,
39 int storageLimit)
40{
41 setName(name);
42 setHistory(history);
43 setInterpolator(interpolator);
44 setStorageType(storageType);
45 setStorageLimit(storageLimit);
46
47 isInitialized_ = false;
48 if (getNumStates() > 0) isInitialized_ = true;
49}
50
51template <class Scalar>
53 const Teuchos::RCP<SolutionState<Scalar> >& state, bool doChecks)
54{
55 // Check that we're not going to exceed our storage limit:
56 if (Teuchos::as<int>(history_->size() + 1) > storageLimit_) {
57 switch (storageType_) {
59 TEUCHOS_TEST_FOR_EXCEPTION(
60 true, std::logic_error,
61 "Error - Storage type is STORAGE_TYPE_INVALID.\n");
62 break;
63 }
66 case STORAGE_TYPE_UNDO: {
67 if (state->getTime() >= history_->front()->getTime()) {
68 // Case: State is younger than the oldest state in history.
69 // Remove state from the beginning of history, then add new state.
70 history_->erase(history_->begin());
71 }
72 else {
73 // Case: State is older than the oldest state in history.
74 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
75 Teuchos::OSTab ostab(out, 1, "SolutionHistory::addState");
76 *out << "Warning, state is older than oldest state in history. "
77 << "State not added!" << std::endl;
78 return;
79 }
80 break;
81 }
82 case STORAGE_TYPE_UNLIMITED: break;
83 default:
84 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error,
85 "Error - unknown storage type.\n");
86 }
87 }
88
89 // Add new state in chronological order.
90 if (history_->size() == 0) {
91 history_->push_back(state);
92 }
93 else {
94 typename std::vector<Teuchos::RCP<SolutionState<Scalar> > >::iterator
95 state_it = history_->begin();
96 bool equal = false;
97 const Scalar newTime = state->getTime();
98 for (; state_it < history_->end(); state_it++) {
99 const Scalar shTime = (*state_it)->getTime();
100 if (doChecks) {
101 const Scalar denom = std::max(std::fabs(shTime), std::fabs(newTime));
102 if (std::fabs(newTime - shTime) < 1.0e-14 * denom) {
103 equal = true;
104 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
105 Teuchos::OSTab ostab(out, 1, "SolutionHistory::addState");
106 *out << "Warning, state to be added matches state in history. "
107 << "State not added!" << std::endl;
108
109 *out << "===============" << std::endl;
110 *out << "Added SolutionState -- ";
111 (*state_it)->describe(*out, Teuchos::VERB_MEDIUM);
112 *out << "===============" << std::endl;
113 this->describe(*out, Teuchos::VERB_MEDIUM);
114
115 std::exit(-1);
116 break;
117 }
118 }
119 if (newTime < shTime) break;
120 }
121 if (!equal) history_->insert(state_it, state);
122 }
123
124 TEUCHOS_TEST_FOR_EXCEPTION(
125 getNumStates() <= 0, std::logic_error,
126 "Error - SolutionHistory::addState() Invalid history size!\n");
127
128 return;
129}
130
131template <class Scalar>
133 const Teuchos::RCP<SolutionState<Scalar> >& state, const bool updateTime)
134{
135 using Teuchos::RCP;
136
137 auto cs = getCurrentState();
138 state->setSolutionStatus(Status::WORKING);
139 state->setIndex(cs->getIndex() + 1);
140 if (updateTime) {
141 state->setTime(cs->getTime() + cs->getTimeStep());
142 state->setTimeStep(cs->getTimeStep());
143 }
144
145 addState(state);
146 workingState_ = (*history_)[getNumStates() - 1];
147}
148
149template <class Scalar>
151 const Teuchos::RCP<SolutionState<Scalar> >& state)
152{
153 if (history_->size() != 0) {
154 auto state_it = history_->rbegin();
155 for (; state_it < history_->rend(); state_it++) {
156 if (state->getTime() == (*state_it)->getTime()) break;
157 }
158
159 TEUCHOS_TEST_FOR_EXCEPTION(state_it == history_->rend(), std::logic_error,
160 "Error - removeState() Could not remove state = "
161 << (*state_it)->description());
162
163 // Need to be careful when erasing a reverse iterator.
164 history_->erase(std::next(state_it).base());
165 }
166 return;
167}
168
169template <class Scalar>
171{
172 Teuchos::RCP<SolutionState<Scalar> > tmpState = findState(time);
173 removeState(tmpState);
174}
175
176template <class Scalar>
177Teuchos::RCP<SolutionState<Scalar> > SolutionHistory<Scalar>::findState(
178 const Scalar time) const
179{
180 // Use last step in solution history as the scale for comparing times
181 Scalar scale = 1.0;
182 if (history_->size() > 0)
183 scale = (*history_)[history_->size() - 1]->getTime();
184 if (approxZero(scale)) scale = Scalar(1.0);
185
186 const Scalar absTol = scale * numericalTol<Scalar>();
187 TEUCHOS_TEST_FOR_EXCEPTION(
188 !(minTime() - absTol <= time && time <= maxTime() + absTol),
189 std::logic_error,
190 "Error - SolutionHistory::findState() Requested time out of range!\n"
191 << " [Min, Max] = ["
192 << minTime() << ", " << maxTime()
193 << "]\n time = "
194 << time << "\n");
195
196 // Linear search
197 auto state_it = history_->begin();
198 for (; state_it < history_->end(); ++state_it) {
199 if (approxEqualAbsTol(time, (*state_it)->getTime(), absTol)) break;
200 }
201
202 TEUCHOS_TEST_FOR_EXCEPTION(state_it == history_->end(), std::logic_error,
203 "Error - SolutionHistory::findState()!\n"
204 " Did not find a SolutionState with time = "
205 << time << std::endl);
206
207 return *state_it;
208}
209
210template <class Scalar>
211Teuchos::RCP<SolutionState<Scalar> > SolutionHistory<Scalar>::interpolateState(
212 const Scalar time) const
213{
214 Teuchos::RCP<SolutionState<Scalar> > state_out = getCurrentState()->clone();
215 interpolate<Scalar>(*interpolator_, history_, time, state_out.get());
216 return state_out;
217}
218
219template <class Scalar>
221 const Scalar time, SolutionState<Scalar>* state_out) const
222{
223 interpolate<Scalar>(*interpolator_, history_, time, state_out);
224}
225
227template <class Scalar>
229{
230 TEMPUS_FUNC_TIME_MONITOR("Tempus::SolutionHistory::initWorkingState()");
231 {
232 TEUCHOS_TEST_FOR_EXCEPTION(
233 getCurrentState() == Teuchos::null, std::logic_error,
234 "Error - SolutionHistory::initWorkingState()\n"
235 "Can not initialize working state without a current state!\n");
236
237 // If workingState_ has a valid pointer, we are still working on it,
238 // i.e., step failed and trying again. There are a couple options:
239 // 1. Reuse the workingState as it might be a good guess. This
240 // could help with performance. This was the initial implementation.
241 // 2. Reset the workingState to the last time step. This could
242 // be more robust in the case of the workingState failing with nans.
243 // This is the current implementation.
244 if (getWorkingState(false) != Teuchos::null) {
245 Thyra::V_V(getWorkingState()->getX().ptr(), *(getCurrentState()->getX()));
246 return;
247 }
248
249 Teuchos::RCP<SolutionState<Scalar> > newState;
250 if (getNumStates() < storageLimit_) {
251 // Create newState which is duplicate of currentState
252 newState = getCurrentState()->clone();
253 }
254 else {
255 // Recycle old state and copy currentState
256 newState = (*history_)[0];
257 history_->erase(history_->begin());
258 if (getNumStates() > 0) newState->copy(getCurrentState());
259 // When using the Griewank algorithm, we will want to select which
260 // older state to recycle.
261 }
262
263 addWorkingState(newState);
264 }
265 return;
266}
267
268template <class Scalar>
270{
271 auto ws = getWorkingState();
272
273 if (ws->getSolutionStatus() == Status::PASSED) {
274 ws->setNFailures(std::max(0, ws->getNFailures() - 1));
275 ws->setNConsecutiveFailures(0);
276 ws->setSolutionStatus(Status::PASSED);
277 // ws->setIsSynced(true);
278 ws->setIsInterpolated(false);
279 workingState_ = Teuchos::null;
280 }
281 else {
282 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
283 Teuchos::OSTab ostab(out, 1, "SolutionHistory::promoteWorkingState()");
284 *out << "Warning - WorkingState is not passing, so not promoted!\n"
285 << std::endl;
286 }
287}
288
289template <class Scalar>
291 Teuchos::RCP<const SolutionHistory<Scalar> > sh)
292{
293 this->setName(sh->getName());
294
295 this->clear();
296 auto sh_history = sh->getHistory();
297 typename std::vector<Teuchos::RCP<SolutionState<Scalar> > >::iterator
298 state_it = sh_history->begin();
299 for (; state_it < sh_history->end(); state_it++) this->addState(*state_it);
300
301 auto interpolator =
302 Teuchos::rcp_const_cast<Interpolator<Scalar> >(sh->getInterpolator());
303 this->setInterpolator(interpolator);
304
305 this->setStorageType(sh->getStorageType());
306 this->setStorageLimit(sh->getStorageLimit());
307}
308
309template <class Scalar>
311{
312 storageLimit_ = std::max(1, storage_limit);
313
314 if (storageType_ == STORAGE_TYPE_INVALID ||
315 storageType_ == STORAGE_TYPE_KEEP_NEWEST) {
316 if (storage_limit != 1) {
317 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
318 Teuchos::OSTab ostab(out, 1, "SolutionHistory::setStorageLimit");
319 *out << "Warning - 'Storage Limit' for 'Keep Newest' is 1.\n"
320 << " (Storage Limit = " << storage_limit << "). Resetting to 1."
321 << std::endl;
322 storageLimit_ = 1;
323 }
324 }
325 else if (storageType_ == STORAGE_TYPE_UNDO) {
326 if (storage_limit != 2) {
327 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
328 Teuchos::OSTab ostab(out, 1, "SolutionHistory::setStorageLimit");
329 *out << "Warning - 'Storage Limit' for 'Undo' is 2.\n"
330 << " (Storage Limit = " << storage_limit << "). Resetting to 2."
331 << std::endl;
332 storageLimit_ = 2;
333 }
334 }
335 else if (storageType_ == STORAGE_TYPE_STATIC) {
336 storageLimit_ = storage_limit;
337 }
338 else if (storageType_ == STORAGE_TYPE_UNLIMITED) {
339 storageLimit_ = std::numeric_limits<int>::max();
340 }
341
342 TEUCHOS_TEST_FOR_EXCEPTION(
343 (Teuchos::as<int>(history_->size()) > storageLimit_), std::logic_error,
344 "Error - requested storage limit = "
345 << storageLimit_
346 << " is smaller than the current number of states stored = "
347 << history_->size() << "!\n");
348
349 isInitialized_ = false;
350}
351
352template <class Scalar>
354{
355 storageType_ = st;
356 if (storageType_ == STORAGE_TYPE_KEEP_NEWEST)
357 setStorageLimit(1);
358 else if (storageType_ == STORAGE_TYPE_UNDO)
359 setStorageLimit(2);
360 else if (storageType_ == STORAGE_TYPE_UNLIMITED)
361 setStorageLimit(std::numeric_limits<int>::max());
362 isInitialized_ = false;
363}
364
365template <class Scalar>
367{
368 if (s == "Keep Newest") { // Keep the single newest state
369 storageType_ = STORAGE_TYPE_KEEP_NEWEST;
370 storageLimit_ = 1;
371 }
372 else if (s == "Undo") { // Keep the 2 newest states for undo
373 storageType_ = STORAGE_TYPE_UNDO;
374 storageLimit_ = 2;
375 }
376 else if (s == "Static") { // Keep a fix number of states
377 storageType_ = STORAGE_TYPE_STATIC;
378 }
379 else if (s == "Unlimited") { // Grow the history as needed
380 storageType_ = STORAGE_TYPE_UNLIMITED;
381 }
382 else {
383 TEUCHOS_TEST_FOR_EXCEPTION(
384 true, std::logic_error,
385 "Error - Unknown 'Storage Type' = '" << s << "'\n");
386 }
387 isInitialized_ = false;
388}
389
390template <class Scalar>
392{
393 std::string s = "Invalid";
394 if (storageType_ == STORAGE_TYPE_KEEP_NEWEST)
395 s = "Keep Newest";
396 else if (storageType_ == STORAGE_TYPE_UNDO)
397 s = "Undo";
398 else if (storageType_ == STORAGE_TYPE_STATIC)
399 s = "Static";
400 else if (storageType_ == STORAGE_TYPE_UNLIMITED)
401 s = "Unlimited";
402 return s;
403}
404
405template <class Scalar>
406Teuchos::RCP<SolutionState<Scalar> >
408{
409 Teuchos::RCP<SolutionState<Scalar> > state = Teuchos::null;
410 const int m = history_->size();
411 if (m < 1) {
412 if (warn) {
413 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
414 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndexN");
415 *out << "Warning - getStateTimeIndexN() No states in SolutionHistory!"
416 << std::endl;
417 }
418 }
419 else {
420 state = (*history_)[m - 1];
421 }
422 return state;
423}
424
425template <class Scalar>
426Teuchos::RCP<SolutionState<Scalar> >
428{
429 Teuchos::RCP<SolutionState<Scalar> > state = Teuchos::null;
430 const int m = history_->size();
431 if (m < 2) {
432 if (warn) {
433 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
434 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndexNM1");
435 *out << "Warning - getStateTimeIndexNM1() Not enough states in "
436 << "SolutionHistory! Size of history = " << getNumStates()
437 << std::endl;
438 }
439 }
440 else {
441 const int n = (*history_)[m - 1]->getIndex();
442 const int nm1 = (*history_)[m - 2]->getIndex();
443
444 // No need to search SolutionHistory as states n and nm1 should be
445 // next to each other.
446 if (nm1 != n - 1) {
447 if (warn) {
448 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
449 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndexNM1");
450 *out << "Warning - getStateTimeIndexNM1() Timestep index n-1 is not in "
451 << "SolutionHistory!\n"
452 << " (n)th index = " << n << "\n"
453 << " (n-1)th index = " << nm1 << std::endl;
454 }
455 }
456 else {
457 state = (*history_)[m - 2];
458 }
459 }
460
461 return state;
462}
463
464template <class Scalar>
465Teuchos::RCP<SolutionState<Scalar> >
467{
468 Teuchos::RCP<SolutionState<Scalar> > state = Teuchos::null;
469 const int m = history_->size();
470 if (m < 3) {
471 if (warn) {
472 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
473 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndexNM2");
474 *out << "Warning - getStateTimeIndexNM2() Not enough states in "
475 << "SolutionHistory! Size of history = " << getNumStates()
476 << std::endl;
477 }
478 }
479 else {
480 const int n = (*history_)[m - 1]->getIndex();
481 const int nm2 = (*history_)[m - 3]->getIndex();
482
483 // Assume states n and nm2 are one away from each other.
484 if (nm2 != n - 2) {
485 // Check if it is at nm1
486 const int nm1 = (*history_)[m - 2]->getIndex();
487 if (nm1 == n - 2) {
488 state = (*history_)[m - 2];
489 }
490 else if (warn) {
491 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
492 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndexNM2");
493 *out << "Warning - getStateTimeIndexNM2() Timestep index n-2 is not in "
494 << "SolutionHistory!\n"
495 << " (n)th index = " << n << "\n"
496 << " (n-2)th index = " << nm2 << std::endl;
497 }
498 }
499 else {
500 state = (*history_)[m - 3];
501 }
502 }
503
504 return state;
505}
506
507template <class Scalar>
508Teuchos::RCP<SolutionState<Scalar> > SolutionHistory<Scalar>::getStateTimeIndex(
509 int index, bool warn) const
510{
511 typename std::vector<Teuchos::RCP<SolutionState<Scalar> > >::iterator
512 state_it = history_->begin();
513 for (; state_it < history_->end(); state_it++) {
514 if ((*state_it)->getIndex() == index) break;
515 }
516
517 Teuchos::RCP<SolutionState<Scalar> > state = Teuchos::null;
518 if (state_it == history_->end()) {
519 if (warn) {
520 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
521 Teuchos::OSTab ostab(out, 1, "SolutionHistory::getStateTimeIndex");
522 *out << "Warning - getStateTimeIndex() Timestep index is not in "
523 << "SolutionHistory!\n"
524 << " index = " << index << std::endl;
525 }
526 }
527 else {
528 state = *state_it;
529 }
530 return state;
531}
532
533template <class Scalar>
535{
536 return ("Tempus::SolutionHistory - '" + name_ + "'");
537}
538
539template <class Scalar>
541 Teuchos::FancyOStream& out, const Teuchos::EVerbosityLevel verbLevel) const
542{
543 auto l_out = Teuchos::fancyOStream(out.getOStream());
544 Teuchos::OSTab ostab(*l_out, 2, this->description());
545 l_out->setOutputToRootOnly(0);
546
547 *l_out << "\n--- " << this->description() << " ---" << std::endl;
548
549 if ((Teuchos::as<int>(verbLevel) ==
550 Teuchos::as<int>(Teuchos::VERB_DEFAULT)) ||
551 (Teuchos::as<int>(verbLevel) >= Teuchos::as<int>(Teuchos::VERB_LOW))) {
552 //*l_out << " interpolator = " << interpolator->description() <<
553 // std::endl;
554 *l_out << " storageLimit = " << storageLimit_ << std::endl;
555 *l_out << " storageType = " << getStorageTypeString() << std::endl;
556 *l_out << " number of states = " << history_->size() << std::endl;
557 if (history_->size() > 0) {
558 *l_out << " time range = (" << history_->front()->getTime() << ", "
559 << history_->back()->getTime() << ")" << std::endl;
560 }
561 }
562
563 if (Teuchos::as<int>(verbLevel) >= Teuchos::as<int>(Teuchos::VERB_MEDIUM)) {
564 for (int i = 0; i < (int)history_->size(); ++i)
565 (*history_)[i]->describe(*l_out, verbLevel);
566 }
567 *l_out << std::string(this->description().length() + 8, '-') << std::endl;
568}
569
570template <class Scalar>
571Teuchos::RCP<const Teuchos::ParameterList>
573{
574 Teuchos::RCP<Teuchos::ParameterList> pl =
575 Teuchos::parameterList("Solution History");
576
577 pl->setName(getName());
578
579 pl->set(
580 "Storage Type", getStorageTypeString(),
581 "'Storage Type' sets the memory storage. "
582 "'Keep Newest' - will retain the single newest solution state. "
583 "'Undo' - will retain two solution states in order to do a single undo. "
584 "'Static' - will retain 'Storage Limit' number of solution states. "
585 "'Unlimited' - will not remove any solution states!");
586
587 pl->set(
588 "Storage Limit", getStorageLimit(),
589 "Limit on the number of SolutionStates that SolutionHistory can have.");
590
591 pl->set("Interpolator", *interpolator_->getNonconstParameterList());
592
593 return pl;
594}
595
596template <class Scalar>
597Teuchos::RCP<Teuchos::ParameterList>
599{
600 return Teuchos::rcp_const_cast<Teuchos::ParameterList>(getValidParameters());
601}
602
603template <class Scalar>
605 const Teuchos::RCP<Interpolator<Scalar> >& interpolator)
606{
607 if (interpolator == Teuchos::null) {
609 }
610 else {
611 interpolator_ = interpolator;
612 }
613 isInitialized_ = false;
614}
615
616template <class Scalar>
617Teuchos::RCP<Interpolator<Scalar> >
619{
620 return interpolator_;
621}
622
623template <class Scalar>
624Teuchos::RCP<const Interpolator<Scalar> >
626{
627 return interpolator_;
628}
629
630template <class Scalar>
631Teuchos::RCP<Interpolator<Scalar> > SolutionHistory<Scalar>::unSetInterpolator()
632{
633 Teuchos::RCP<Interpolator<Scalar> > old_interpolator = interpolator_;
634 interpolator_ = lagrangeInterpolator<Scalar>();
635 return old_interpolator;
636}
637
638template <class Scalar>
639void SolutionHistory<Scalar>::printHistory(std::string verb) const
640{
641 Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream();
642 Teuchos::OSTab ostab(out, 1, "SolutionHistory::printHistory");
643 *out << name_ << " (size=" << history_->size() << ")"
644 << " (w - working; c - current; i - interpolated)" << std::endl;
645 for (int i = 0; i < (int)history_->size(); ++i) {
646 auto state = (*history_)[i];
647 *out << " ";
648 if (state == getWorkingState())
649 *out << "w - ";
650 else if (state == getCurrentState())
651 *out << "c - ";
652 else if (state->getIsInterpolated() == true)
653 *out << "i - ";
654 else
655 *out << " ";
656 *out << "[" << i << "] = " << state << std::endl;
657 if (verb == "medium" || verb == "high") {
658 if (state != Teuchos::null) {
659 auto x = state->getX();
660 *out << " x = " << x << std::endl
661 << " norm(x) = " << Thyra::norm(*x) << std::endl;
662 }
663 }
664 if (verb == "high") {
665 (*history_)[i]->describe(*out, this->getVerbLevel());
666 }
667 }
668}
669
670template <class Scalar>
672{
673 TEUCHOS_TEST_FOR_EXCEPTION(
674 getNumStates() <= 0, std::logic_error,
675 "Error - SolutionHistory::initialize() Invalid history size!\n");
676
677 TEUCHOS_TEST_FOR_EXCEPTION(
678 interpolator_ == Teuchos::null, std::logic_error,
679 "Error - SolutionHistory::initialize() Interpolator is not set!\n");
680
681 TEUCHOS_TEST_FOR_EXCEPTION(storageLimit_ < 1, std::logic_error,
682 "Error - SolutionHistory::initialize() Storage "
683 "Limit needs to a positive integer!\n"
684 << " Storage Limit = " << storageLimit_
685 << "\n");
686
687 TEUCHOS_TEST_FOR_EXCEPTION(
688 (storageType_ == STORAGE_TYPE_INVALID), std::logic_error,
689 "Error - SolutionHistory::initialize() Storage Type is invalid!\n");
690
691 TEUCHOS_TEST_FOR_EXCEPTION(
692 (storageType_ == STORAGE_TYPE_KEEP_NEWEST && storageLimit_ != 1),
693 std::logic_error,
694 "Error - SolutionHistory::initialize() \n"
695 << " For Storage Type = '" << getStorageTypeString()
696 << "', Storage Limit needs to be one.\n"
697 << " Storage Limit = " << storageLimit_ << "\n");
698
699 TEUCHOS_TEST_FOR_EXCEPTION(
700 (storageType_ == STORAGE_TYPE_UNDO && storageLimit_ != 2),
701 std::logic_error,
702 "Error - SolutionHistory::initialize() \n"
703 << " For Storage Type = '" << getStorageTypeString()
704 << "', Storage Limit needs to be two.\n"
705 << " Storage Limit = " << storageLimit_ << "\n");
706
707 isInitialized_ = true; // Only place where this is set to true!
708}
709
710// Nonmember constructors.
711// ------------------------------------------------------------------------
712
713template <class Scalar>
714Teuchos::RCP<SolutionHistory<Scalar> > createSolutionHistory()
715{
716 auto sh = rcp(new SolutionHistory<Scalar>());
717 sh->setName("From createSolutionHistory");
718
719 return sh;
720}
721
722template <class Scalar>
723Teuchos::RCP<SolutionHistory<Scalar> > createSolutionHistoryPL(
724 Teuchos::RCP<Teuchos::ParameterList> pl)
725{
726 auto sh = rcp(new SolutionHistory<Scalar>());
727 sh->setName("From createSolutionHistoryPL");
728
729 if (pl == Teuchos::null || pl->numParams() == 0) return sh;
730
731 pl->validateParametersAndSetDefaults(*sh->getValidParameters());
732
733 sh->setName(pl->name());
734 sh->setStorageTypeString(pl->get("Storage Type", "Undo"));
735 sh->setStorageLimit(pl->get("Storage Limit", 2));
736
738 Teuchos::sublist(pl, "Interpolator")));
739
740 return sh;
741}
742
743template <class Scalar>
744Teuchos::RCP<SolutionHistory<Scalar> > createSolutionHistoryState(
745 const Teuchos::RCP<SolutionState<Scalar> >& state)
746{
747 auto sh = rcp(new SolutionHistory<Scalar>());
748 sh->setName("From createSolutionHistoryState");
749 sh->addState(state);
750 return sh;
751}
752
753template <class Scalar>
754Teuchos::RCP<SolutionHistory<Scalar> > createSolutionHistoryME(
755 const Teuchos::RCP<const Thyra::ModelEvaluator<Scalar> >& model)
756{
757 // Setup initial condition SolutionState --------------------
758 auto state = createSolutionStateME(model);
759 state->setTime(0.0);
760 state->setIndex(0);
761 state->setTimeStep(0.0);
762 state->setOrder(1);
763
764 // Setup SolutionHistory ------------------------------------
765 auto sh = rcp(new SolutionHistory<Scalar>());
766 sh->setName("From createSolutionHistoryME");
767 sh->addState(state);
768
769 return sh;
770}
771
772} // namespace Tempus
773#endif // Tempus_SolutionHistory_impl_hpp
static Teuchos::RCP< Interpolator< Scalar > > createInterpolator(std::string interpolatorType="")
Create default interpolator from interpolator type (e.g., "Linear").
Base strategy class for interpolation functionality.
SolutionHistory is basically a container of SolutionStates. SolutionHistory maintains a collection of...
Teuchos::RCP< SolutionState< Scalar > > getStateTimeIndex(int index, bool warn=true) const
Get the state with timestep index equal to "index".
Teuchos::RCP< SolutionState< Scalar > > getStateTimeIndexNM1(bool warn=true) const
Get the state with timestep index equal to n-1.
void initWorkingState()
Initialize the working state.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a valid ParameterList with current settings.
Teuchos::RCP< const Interpolator< Scalar > > getInterpolator() const
virtual std::string description() const
void addState(const Teuchos::RCP< SolutionState< Scalar > > &state, bool doChecks=true)
Add solution state to history.
Teuchos::RCP< SolutionState< Scalar > > getStateTimeIndexNM2(bool warn=true) const
Get the state with timestep index equal to n-2.
void setStorageType(StorageType st)
Set the storage type via enum.
bool isInitialized_
Bool if SolutionHistory is initialized.
Teuchos::RCP< Teuchos::ParameterList > getNonconstParameterList()
Return a valid non-const ParameterList with current settings.
std::string getStorageTypeString() const
Set the string storage type.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
void copy(Teuchos::RCP< const SolutionHistory< Scalar > > sh)
Teuchos::RCP< Interpolator< Scalar > > unSetInterpolator()
Unset the interpolator for this history.
void initialize() const
Initialize SolutionHistory.
void setStorageLimit(int storage_limit)
Set the maximum storage of this history.
Teuchos::RCP< Interpolator< Scalar > > getNonconstInterpolator()
void setStorageTypeString(std::string st)
Set the storage type via string.
Teuchos::RCP< SolutionState< Scalar > > findState(const Scalar time) const
Find solution state at requested time (no interpolation)
void printHistory(std::string verb="low") const
Print information on States in the SolutionHistory.
Teuchos::RCP< SolutionState< Scalar > > interpolateState(const Scalar time) const
Generate and interpolate a new solution state at requested time.
void removeState(const Teuchos::RCP< SolutionState< Scalar > > &state)
Remove solution state.
void addWorkingState(const Teuchos::RCP< SolutionState< Scalar > > &state, const bool updateTime=true)
Add a working solution state to history.
Teuchos::RCP< SolutionState< Scalar > > getStateTimeIndexN(bool warn=true) const
Get the state with timestep index equal to n.
Teuchos::RCP< std::vector< Teuchos::RCP< SolutionState< Scalar > > > > history_
void setInterpolator(const Teuchos::RCP< Interpolator< Scalar > > &interpolator)
Set the interpolator for this history.
Teuchos::RCP< Interpolator< Scalar > > interpolator_
void promoteWorkingState()
Promote the working state to current state.
Solution state for integrators and steppers.
@ STORAGE_TYPE_STATIC
Keep a fix number of states.
@ STORAGE_TYPE_UNLIMITED
Grow the history as needed.
@ STORAGE_TYPE_INVALID
Invalid storage type.
@ STORAGE_TYPE_UNDO
Keep the 2 newest states for undo.
@ STORAGE_TYPE_KEEP_NEWEST
Keep the single newest state.
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< SolutionHistory< Scalar > > createSolutionHistoryPL(Teuchos::RCP< Teuchos::ParameterList > pList)
Nonmember constructor from a ParameterList.
bool approxZero(Scalar value, Scalar tol=Teuchos::ScalarTraits< Scalar >::sfmin())
Test if value is approximately zero within tolerance.
Teuchos::RCP< SolutionHistory< Scalar > > createSolutionHistoryState(const Teuchos::RCP< SolutionState< Scalar > > &state)
Nonmember contructor from a SolutionState.
bool approxEqualAbsTol(Scalar a, Scalar b, Scalar absTol)
Test if values are approximately equal within the absolute tolerance.
Teuchos::RCP< SolutionHistory< Scalar > > createSolutionHistory()
Nonmember constructor.
Teuchos::RCP< SolutionHistory< Scalar > > createSolutionHistoryME(const Teuchos::RCP< const Thyra::ModelEvaluator< Scalar > > &model)
Nonmember contructor from a Thyra ModelEvaluator.