Tempus Version of the Day
Time Integration
Loading...
Searching...
No Matches
Tempus_TimeEventComposite.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_TimeEventComposite_decl_hpp
11#define Tempus_TimeEventComposite_decl_hpp
12
13#include "Teuchos_Time.hpp"
14#include "Teuchos_ParameterList.hpp"
15
16#include "Tempus_config.hpp"
19#include "Tempus_TimeEventRange.hpp"
20#include "Tempus_TimeEventRangeIndex.hpp"
21#include "Tempus_TimeEventList.hpp"
22#include "Tempus_TimeEventListIndex.hpp"
23
24namespace Tempus {
25
31template <class Scalar>
32class TimeEventComposite : virtual public TimeEventBase<Scalar> {
33 public:
36 {
37 this->setType("Composite");
38 this->setName("TimeEventComposite");
39 }
40
42 TimeEventComposite(std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > te,
43 std::string name = "TimeEventComposite")
44 {
45 this->setType("Composite");
46 this->setName(name);
47 this->setTimeEvents(te);
48 }
49
52
54
55
56 virtual std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > getTimeEvents()
57 const
58 {
59 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > te = timeEvents_;
60 return te;
61 }
62
70 virtual void setTimeEvents(
71 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > te)
72 {
73 timeEvents_ = te;
74 }
75
84 virtual bool isTime(Scalar time) const
85 {
86 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
87 return isTime(time, timeEvents);
88 }
89
101 virtual bool isTime(
102 Scalar time,
103 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
104 {
105 timeEvents.clear();
106 for (auto& e : timeEvents_) {
107 if (e->isTime(time)) timeEvents.push_back(e);
108 }
109 return (!timeEvents.empty());
110 }
111
120 virtual Scalar timeToNextEvent(Scalar time) const
121 {
122 return timeOfNextEvent(time) - time;
123 }
124
136 virtual Scalar timeToNextEvent(
137 Scalar time,
138 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
139 {
140 return timeOfNextEvent(time, timeEvents) - time;
141 }
142
150 virtual Scalar timeOfNextEvent(Scalar time) const
151 {
152 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
153 return timeOfNextEvent(time, timeEvents);
154 }
155
175 virtual Scalar timeOfNextEvent(
176 Scalar time,
177 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
178 {
179 timeEvents.clear();
180 typedef std::pair<Scalar, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
181 std::vector<TEPAIR> timeEventPair;
182 for (auto& e : timeEvents_)
183 timeEventPair.push_back(std::make_pair(e->timeOfNextEvent(time), e));
184
185 if (timeEventPair.empty()) return this->getDefaultTime();
186
187 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
188 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
189
190 // The first one is the "time of next event".
191 Scalar tone = timeEventPair.front().first;
192
193 // Check if there are multiple events that match "time of next event".
194 for (auto it = timeEventPair.begin(); it != timeEventPair.end(); ++it) {
195 if ((*it).second->isTime(tone)) timeEvents.push_back((*it).second);
196 }
197
198 return tone;
199 }
200
214 virtual bool eventInRange(Scalar time1, Scalar time2) const
215 {
216 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
217 return eventInRange(time1, time2, timeEvents);
218 }
219
239 virtual bool eventInRange(
240 Scalar time1, Scalar time2,
241 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
242 {
243 typedef std::pair<Scalar, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
244 std::vector<TEPAIR> timeEventPair;
245 for (auto& e : timeEvents_) {
246 if (e->eventInRange(time1, time2))
247 timeEventPair.push_back(std::make_pair(e->timeOfNextEvent(time1), e));
248 }
249
250 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
251 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
252
253 timeEvents.clear();
254 for (auto& e : timeEventPair) timeEvents.push_back(e.second);
255
256 return (!timeEvents.empty());
257 }
258
267 virtual bool isIndex(int index) const
268 {
269 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
270 return isIndex(index, timeEvents);
271 }
272
283 virtual bool isIndex(
284 int index,
285 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
286 {
287 timeEvents.clear();
288 for (auto& e : timeEvents_) {
289 if (e->isIndex(index)) timeEvents.push_back(e);
290 }
291 return (!timeEvents.empty());
292 }
293
299 virtual int indexToNextEvent(int index) const
300 {
301 return indexOfNextEvent(index) - index;
302 }
303
310 virtual int indexToNextEvent(
311 int index,
312 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
313 {
314 return indexOfNextEvent(index, timeEvents) - index;
315 }
316
328 virtual int indexOfNextEvent(int index) const
329 {
330 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
331 return indexOfNextEvent(index, timeEvents);
332 }
333
347 virtual int indexOfNextEvent(
348 int index,
349 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
350 {
351 timeEvents.clear();
352 typedef std::pair<int, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
353 std::vector<TEPAIR> timeEventPair;
354 for (auto& e : timeEvents_)
355 timeEventPair.push_back(std::make_pair(e->indexOfNextEvent(index), e));
356
357 if (timeEventPair.size() == 0) return this->getDefaultIndex();
358
359 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
360 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
361
362 // The first one is the "index of next event".
363 int ione = timeEventPair.front().first;
364
365 // Check if there are multiple events that match "index of next event".
366 for (auto it = timeEventPair.begin(); it != timeEventPair.end(); ++it) {
367 if ((*it).second->isIndex(ione)) timeEvents.push_back((*it).second);
368 }
369
370 return ione;
371 }
372
384 virtual bool eventInRangeIndex(int index1, int index2) const
385 {
386 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
387 return eventInRangeIndex(index1, index2, timeEvents);
388 }
389
407 virtual bool eventInRangeIndex(
408 int index1, int index2,
409 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
410 {
411 typedef std::pair<int, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
412 std::vector<TEPAIR> timeEventPair;
413 for (auto& e : timeEvents_) {
414 if (e->eventInRangeIndex(index1, index2))
415 timeEventPair.push_back(std::make_pair(e->indexOfNextEvent(index1), e));
416 }
417
418 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
419 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
420
421 timeEvents.clear();
422 for (auto& e : timeEventPair) timeEvents.push_back(e.second);
423
424 return (!timeEvents.empty());
425 }
426
431 virtual Scalar getAbsTol() const
432 {
433 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
434 return getAbsTol(timeEvents);
435 }
436
446 virtual Scalar getAbsTol(
447 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
448 {
449 timeEvents.clear();
450 Scalar largestAbsTol = timeEvents_.front()->getAbsTol();
451 timeEvents.push_back(timeEvents_.front());
452 for (auto& e : timeEvents_)
453 if (e->getAbsTol() > largestAbsTol) largestAbsTol = e->getAbsTol();
454
455 for (auto& e : timeEvents_)
456 if (e->getAbsTol() - largestAbsTol < largestAbsTol * 1.0e-14)
457 timeEvents.push_back(e);
458
459 return largestAbsTol;
460 }
461
469 virtual bool getLandOnExactly() const
470 {
471 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
472 return getLandOnExactly(timeEvents);
473 }
474
485 virtual bool getLandOnExactly(
486 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > >& timeEvents) const
487 {
488 timeEvents.clear();
489 for (auto& e : timeEvents_)
490 if (e->getLandOnExactly()) timeEvents.push_back(e);
491
492 return (!timeEvents.empty());
493 }
495
505 void add(Teuchos::RCP<TimeEventBase<Scalar> > timeEvent)
506 {
507 std::string name = timeEvent->getName();
508 Teuchos::RCP<TimeEventBase<Scalar> > te = find(name);
509 if (!te.is_null()) {
510 // auto l_out = Teuchos::fancyOStream( Teuchos::rcpFromRef(std::cout) );
511 // Teuchos::OSTab ostab(*l_out, 2, "TimeEventComposite::add");
512 // l_out->setOutputToRootOnly(0);
513
514 //*l_out << "TimeEventComposite::add: Replacing Time Event, "
515 // << name << "." << "\n";
516 remove(name);
517 }
518 timeEvents_.push_back(timeEvent);
519 }
520
528 void remove(std::string name)
529 {
530 for (std::size_t i = 0; i < timeEvents_.size(); ++i) {
531 if (timeEvents_[i]->getName() == name) {
532 timeEvents_.erase(timeEvents_.begin() + i);
533 break;
534 }
535 }
536 // Did not find 'name', so did nothing.
537 }
538
546 Teuchos::RCP<TimeEventBase<Scalar> > find(std::string name)
547 {
548 for (std::size_t i = 0; i < timeEvents_.size(); ++i)
549 if (timeEvents_[i]->getName() == name) return timeEvents_[i];
550
551 return Teuchos::null;
552 }
553
555 void clear() { timeEvents_.clear(); }
556
558 std::size_t getSize() const { return timeEvents_.size(); }
559
561 std::string getTimeEventNames() const
562 {
563 std::stringstream tecList;
564 for (std::size_t i = 0; i < timeEvents_.size(); ++i) {
565 tecList << timeEvents_[i]->getName();
566 if (i < timeEvents_.size() - 1) tecList << ", ";
567 }
568 return tecList.str();
569 }
570
572 virtual void describe(Teuchos::FancyOStream& out,
573 const Teuchos::EVerbosityLevel verbLevel) const
574 {
575 auto l_out = Teuchos::fancyOStream(out.getOStream());
576 Teuchos::OSTab ostab(*l_out, 2, "TimeEventComposite");
577 l_out->setOutputToRootOnly(0);
578
579 *l_out << "TimeEventComposite:"
580 << "\n"
581 << " name = " << this->getName() << "\n"
582 << " Type = " << this->getType() << "\n"
583 << " Number of TimeEvents = " << this->getSize() << "\n"
584 << " Time Events = " << this->getTimeEventNames()
585 << std::endl;
586 *l_out << "--------------------------------------------" << std::endl;
587 for (auto& e : timeEvents_) {
588 (*e).describe(*l_out, verbLevel);
589 *l_out << "--------------------------------------------" << std::endl;
590 }
591 }
592
603 virtual Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const
604 {
605 Teuchos::RCP<Teuchos::ParameterList> pl =
606 Teuchos::parameterList("Time Event Composite");
607
608 pl->setName(this->getName());
609 pl->set("Name", this->getName());
610 pl->set("Type", this->getType());
611 pl->set<std::string>("Time Events", this->getTimeEventNames());
612
613 for (auto& s : timeEvents_) pl->set(s->getName(), *s->getValidParameters());
614
615 return pl;
616 }
617
618 protected:
619 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents_;
620};
621
622// Nonmember constructor - ParameterList
623// ------------------------------------------------------------------------
624
639template <class Scalar>
640Teuchos::RCP<TimeEventComposite<Scalar> > createTimeEventComposite(
641 Teuchos::RCP<Teuchos::ParameterList> const& pList)
642{
643 using Teuchos::ParameterList;
644 using Teuchos::RCP;
645
646 auto tec = Teuchos::rcp(new TimeEventComposite<Scalar>());
647 if (pList == Teuchos::null || pList->numParams() == 0) return tec;
648
649 TEUCHOS_TEST_FOR_EXCEPTION(
650 pList->get<std::string>("Type", "Composite") != "Composite",
651 std::logic_error,
652 "Error - Time Event Type != 'Composite'. (='" +
653 pList->get<std::string>("Type") + "')\n");
654
655 tec->setName(pList->get("Name", "From createTimeEventComposite"));
656
657 // string tokenizer
658 std::vector<std::string> teList;
659 teList.clear();
660 std::string str = pList->get<std::string>("Time Events");
661 std::string delimiters(",");
662 const char* WhiteSpace = " \t\v\r\n";
663 // Skip delimiters at the beginning
664 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
665 // Find the first delimiter
666 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
667 while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
668 // Found a token, add it to the vector
669 std::string token = str.substr(lastPos, pos - lastPos);
670
671 std::size_t start = token.find_first_not_of(WhiteSpace);
672 std::size_t end = token.find_last_not_of(WhiteSpace);
673 token =
674 (start == end ? std::string() : token.substr(start, end - start + 1));
675
676 teList.push_back(token);
677 if (pos == std::string::npos) break;
678
679 lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
680 pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
681 }
682
683 // For each sublist name tokenized, add the TimeEvent.
684 for (auto teName : teList) {
685 RCP<ParameterList> pl =
686 Teuchos::rcp(new ParameterList(pList->sublist(teName)));
687
688 auto timeEventType = pl->get<std::string>("Type", "Unknown");
689 if (timeEventType == "Range") {
690 tec->add(createTimeEventRange<Scalar>(pl));
691 }
692 else if (timeEventType == "Range Index") {
693 tec->add(createTimeEventRangeIndex<Scalar>(pl));
694 }
695 else if (timeEventType == "List") {
696 tec->add(createTimeEventList<Scalar>(pl));
697 }
698 else if (timeEventType == "List Index") {
699 tec->add(createTimeEventListIndex<Scalar>(pl));
700 }
701 else {
702 RCP<Teuchos::FancyOStream> out =
703 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
704 out->setOutputToRootOnly(0);
705 Teuchos::OSTab ostab(out, 1, "createTimeEventComposite()");
706 *out << "Warning -- createTimeEventComposite() - Unknown Time Event "
707 "Type!\n"
708 << "'Type' = '" << timeEventType << "'\n"
709 << "Should call add() with this "
710 << "(app-specific?) Time Event.\n"
711 << std::endl;
712 }
713 }
714
715 if (tec->getSize() == 0) {
716 RCP<Teuchos::FancyOStream> out =
717 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
718 out->setOutputToRootOnly(0);
719 Teuchos::OSTab ostab(out, 1, "createTimeEventComposite()");
720 *out << "Warning -- createTimeEventComposite() - Did not\n"
721 << " find/recognize any TimeEvents to create!\n"
722 << " If there is a app-specific TimeEvent,\n"
723 << " explicitly add it to this TimeEventComposite.\n"
724 << std::endl;
725 }
726
727 return tec;
728}
729
730} // namespace Tempus
731
732#endif // Tempus_TimeEventComposite_decl_hpp
This class defines time events which can be used to "trigger" an action.
virtual void setType(std::string s)
virtual std::string getName() const
Return the name of the TimeEvent.
virtual std::string getType() const
Return the type of TimeEvent.
virtual void setName(std::string name)
Set the name of the TimeEvent.
virtual int getDefaultIndex() const
Return the default index used by TimeEvents.
virtual Scalar getDefaultTime() const
Return the default time used for TimeEvents.
This composite TimeEvent loops over added TimeEvents.
virtual int indexOfNextEvent(int index) const
Return the index of the next event following the input index.
virtual Scalar getAbsTol(std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Return the largest absolute tolerance from all the TimeEvents plus the constraining TimeEvent(s).
virtual void setTimeEvents(std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > te)
Set the TimeEvents.
std::size_t getSize() const
Return the size of the TimeEvent vector.
void remove(std::string name)
Remove TimeEvent based on name.
virtual int indexToNextEvent(int index) const
How many indices until the next event.
std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > timeEvents_
virtual Scalar timeOfNextEvent(Scalar time, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Return the time of the next time event and constraining TimeEvent(s).
virtual Scalar timeOfNextEvent(Scalar time) const
Return the time of the next event following the input time.
virtual Scalar timeToNextEvent(Scalar time, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
How much time until the next event plus the constraining TimeEvent(s).
virtual std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > getTimeEvents() const
Get a copy of the current set of TimeEvents.
virtual bool getLandOnExactly(std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Return if the time events need to be landed on exactly plus the constraining TimeEvent(s).
virtual bool eventInRangeIndex(int index1, int index2, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Test if an event occurs within the index range plus the constraining TimeEvent(s).
virtual bool eventInRange(Scalar time1, Scalar time2) const
Test if an event occurs within the time range.
virtual int indexToNextEvent(int index, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
How many indices until the next event.
Teuchos::RCP< TimeEventBase< Scalar > > find(std::string name)
Find TimeEvent based on name.
virtual bool isTime(Scalar time, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Test if time is near a TimeEvent (within tolerance) plus the constraining TimeEvent(s).
void add(Teuchos::RCP< TimeEventBase< Scalar > > timeEvent)
Add TimeEvent to the TimeEvent vector.
std::string getTimeEventNames() const
Return a string of the names of Time Events (comma separated).
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Describe member data.
virtual Scalar getAbsTol() const
Return the largest absolute tolerance from all the TimeEvents.
TimeEventComposite(std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > te, std::string name="TimeEventComposite")
Construct with full argument list of data members.
virtual Scalar timeToNextEvent(Scalar time) const
How much time until the next event.
virtual Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a valid ParameterList with current settings.
void clear()
Clear the TimeEvent vector.
virtual bool getLandOnExactly() const
Return if the time events need to be landed on exactly.
virtual bool isIndex(int index, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Test if index is a time event plus the constraining TimeEvent(s).
virtual bool eventInRangeIndex(int index1, int index2) const
Test if an event occurs within the index range.
virtual bool isTime(Scalar time) const
Test if time is near a TimeEvent (within tolerance).
virtual bool eventInRange(Scalar time1, Scalar time2, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Test if an event occurs within the time range plus the constraining TimeEvent(s).
virtual bool isIndex(int index) const
Test if index is a time event.
virtual int indexOfNextEvent(int index, std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > &timeEvents) const
Return the index of the next event following the input index plus the constraining TimeEvent(s).
Teuchos::RCP< TimeEventComposite< Scalar > > createTimeEventComposite(Teuchos::RCP< Teuchos::ParameterList > const &pList)
TimeEventComposite nonmember constructor via ParameterList.