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: Copyright (2017) Sandia Corporation
4//
5// Distributed under BSD 3-clause license (See accompanying file Copyright.txt)
6// ****************************************************************************
7// @HEADER
8
9#ifndef Tempus_TimeEventComposite_decl_hpp
10#define Tempus_TimeEventComposite_decl_hpp
11
12#include "Teuchos_Time.hpp"
13#include "Teuchos_ParameterList.hpp"
14
15#include "Tempus_config.hpp"
18#include "Tempus_TimeEventRange.hpp"
19#include "Tempus_TimeEventRangeIndex.hpp"
20#include "Tempus_TimeEventList.hpp"
21#include "Tempus_TimeEventListIndex.hpp"
22
23
24namespace Tempus {
25
26
32template<class Scalar>
33class TimeEventComposite : virtual public TimeEventBase<Scalar>
34{
35public:
36
39 {
40 this->setType("Composite");
41 this->setName("TimeEventComposite");
42 }
43
46 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > te,
47 std::string name = "TimeEventComposite")
48 {
49 this->setType("Composite");
50 this->setName(name);
51 this->setTimeEvents(te);
52 }
53
56
58
59
60 virtual std::vector<Teuchos::RCP<TimeEventBase<Scalar > > > getTimeEvents() const
61 {
62 std::vector<Teuchos::RCP<TimeEventBase<Scalar > > > te = timeEvents_;
63 return te;
64 }
65
73 virtual void setTimeEvents(
74 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > te)
75 { timeEvents_ = te; }
76
85 virtual bool isTime(Scalar time) const
86 {
87 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
88 return isTime(time, timeEvents);
89 }
90
101 virtual bool isTime(Scalar time,
102 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
103 {
104 timeEvents.clear();
105 for(auto& e : timeEvents_) {
106 if (e->isTime(time)) timeEvents.push_back(e);
107 }
108 return (!timeEvents.empty());
109 }
110
119 virtual Scalar timeToNextEvent(Scalar time) const
120 { return timeOfNextEvent(time) - time; }
121
132 virtual Scalar timeToNextEvent(Scalar time,
133 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
134 { return timeOfNextEvent(time, timeEvents) - time; }
135
143 virtual Scalar timeOfNextEvent(Scalar time) const
144 {
145 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
146 return timeOfNextEvent(time, timeEvents);
147 }
148
167 virtual Scalar timeOfNextEvent(Scalar time,
168 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
169 {
170 timeEvents.clear();
171 typedef std::pair<Scalar, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
172 std::vector<TEPAIR> timeEventPair;
173 for(auto& e : timeEvents_)
174 timeEventPair.push_back(std::make_pair(e->timeOfNextEvent(time), e));
175
176 if (timeEventPair.empty()) return this->getDefaultTime();
177
178 auto compare=[](TEPAIR a, TEPAIR b) { return a.first < b.first; };
179 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
180
181 // The first one is the "time of next event".
182 Scalar tone = timeEventPair.front().first;
183
184 // Check if there are multiple events that match "time of next event".
185 for (auto it = timeEventPair.begin(); it != timeEventPair.end(); ++it) {
186 if ((*it).second->isTime(tone)) timeEvents.push_back((*it).second);
187 }
188
189 return tone;
190 }
191
205 virtual bool eventInRange(Scalar time1, Scalar time2) const
206 {
207 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
208 return eventInRange(time1, time2, timeEvents);
209 }
210
229 virtual bool eventInRange(Scalar time1, Scalar time2,
230 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
231 {
232 typedef std::pair<Scalar, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
233 std::vector<TEPAIR> timeEventPair;
234 for(auto& e : timeEvents_) {
235 if (e->eventInRange(time1, time2))
236 timeEventPair.push_back(std::make_pair(e->timeOfNextEvent(time1), e));
237 }
238
239 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
240 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
241
242 timeEvents.clear();
243 for(auto& e : timeEventPair) timeEvents.push_back(e.second);
244
245 return (!timeEvents.empty());
246 }
247
256 virtual bool isIndex(int index) const
257 {
258 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
259 return isIndex(index, timeEvents);
260 }
261
272 virtual bool isIndex(int index,
273 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
274 {
275 timeEvents.clear();
276 for(auto& e : timeEvents_) {
277 if (e->isIndex(index)) timeEvents.push_back(e);
278 }
279 return (!timeEvents.empty());
280 }
281
287 virtual int indexToNextEvent(int index) const
288 {
289 return indexOfNextEvent(index) - index;
290 }
291
298 virtual int indexToNextEvent(int index,
299 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
300 { return indexOfNextEvent(index, timeEvents) - index; }
301
313 virtual int indexOfNextEvent(int index) const
314 {
315 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
316 return indexOfNextEvent(index, timeEvents);
317 }
318
331 virtual int indexOfNextEvent(int index,
332 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
333 {
334 timeEvents.clear();
335 typedef std::pair<int, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
336 std::vector<TEPAIR> timeEventPair;
337 for(auto& e : timeEvents_)
338 timeEventPair.push_back(std::make_pair(e->indexOfNextEvent(index), e));
339
340 if (timeEventPair.size() == 0) return this->getDefaultIndex();
341
342 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
343 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
344
345 // The first one is the "index of next event".
346 int ione = timeEventPair.front().first;
347
348 // Check if there are multiple events that match "index of next event".
349 for (auto it = timeEventPair.begin(); it != timeEventPair.end(); ++it) {
350 if ((*it).second->isIndex(ione)) timeEvents.push_back((*it).second);
351 }
352
353 return ione;
354 }
355
367 virtual bool eventInRangeIndex(int index1, int index2) const
368 {
369 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
370 return eventInRangeIndex(index1, index2, timeEvents);
371 }
372
389 virtual bool eventInRangeIndex(int index1, int index2,
390 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
391 {
392 typedef std::pair<int, Teuchos::RCP<TimeEventBase<Scalar> > > TEPAIR;
393 std::vector<TEPAIR> timeEventPair;
394 for(auto& e : timeEvents_) {
395 if (e->eventInRangeIndex(index1, index2))
396 timeEventPair.push_back(std::make_pair(e->indexOfNextEvent(index1), e));
397 }
398
399 auto compare = [](TEPAIR a, TEPAIR b) { return a.first < b.first; };
400 std::stable_sort(timeEventPair.begin(), timeEventPair.end(), compare);
401
402 timeEvents.clear();
403 for(auto& e : timeEventPair) timeEvents.push_back(e.second);
404
405 return (!timeEvents.empty());
406 }
407
412 virtual Scalar getAbsTol() const
413 {
414 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
415 return getAbsTol(timeEvents);
416 }
417
426 virtual Scalar getAbsTol(
427 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
428 {
429 timeEvents.clear();
430 Scalar largestAbsTol = timeEvents_.front()->getAbsTol();
431 timeEvents.push_back(timeEvents_.front());
432 for(auto& e : timeEvents_)
433 if (e->getAbsTol() > largestAbsTol) largestAbsTol = e->getAbsTol();
434
435 for(auto& e : timeEvents_)
436 if (e->getAbsTol()-largestAbsTol < largestAbsTol * 1.0e-14)
437 timeEvents.push_back(e);
438
439 return largestAbsTol;
440 }
441
448 virtual bool getLandOnExactly() const
449 {
450 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents;
451 return getLandOnExactly(timeEvents);
452 }
453
463 virtual bool getLandOnExactly(
464 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > & timeEvents) const
465 {
466 timeEvents.clear();
467 for(auto& e : timeEvents_)
468 if (e->getLandOnExactly()) timeEvents.push_back(e);
469
470 return (!timeEvents.empty());
471 }
473
474
484 void add(Teuchos::RCP<TimeEventBase<Scalar> > timeEvent)
485 {
486 std::string name = timeEvent->getName();
487 Teuchos::RCP<TimeEventBase<Scalar> > te = find(name);
488 if (!te.is_null()) {
489 //auto l_out = Teuchos::fancyOStream( Teuchos::rcpFromRef(std::cout) );
490 //Teuchos::OSTab ostab(*l_out, 2, "TimeEventComposite::add");
491 //l_out->setOutputToRootOnly(0);
492
493 //*l_out << "TimeEventComposite::add: Replacing Time Event, "
494 // << name << "." << "\n";
495 remove(name);
496 }
497 timeEvents_.push_back(timeEvent);
498 }
499
507 void remove(std::string name)
508 {
509 for (std::size_t i = 0; i < timeEvents_.size(); ++i) {
510 if (timeEvents_[i]->getName() == name) {
511 timeEvents_.erase(timeEvents_.begin()+i);
512 break;
513 }
514 }
515 // Did not find 'name', so did nothing.
516 }
517
525 Teuchos::RCP<TimeEventBase<Scalar> > find(std::string name)
526 {
527 for (std::size_t i = 0; i < timeEvents_.size(); ++i)
528 if (timeEvents_[i]->getName() == name) return timeEvents_[i];
529
530 return Teuchos::null;
531 }
532
534 void clear() { timeEvents_.clear(); }
535
537 std::size_t getSize() const { return timeEvents_.size(); }
538
540 std::string getTimeEventNames() const
541 {
542 std::stringstream tecList;
543 for(std::size_t i = 0; i < timeEvents_.size(); ++i) {
544 tecList << timeEvents_[i]->getName();
545 if (i < timeEvents_.size()-1) tecList << ", ";
546 }
547 return tecList.str();
548 }
549
551 virtual void describe(Teuchos::FancyOStream &out,
552 const Teuchos::EVerbosityLevel verbLevel) const
553 {
554 auto l_out = Teuchos::fancyOStream( out.getOStream() );
555 Teuchos::OSTab ostab(*l_out, 2, "TimeEventComposite");
556 l_out->setOutputToRootOnly(0);
557
558 *l_out << "TimeEventComposite:" << "\n"
559 << " name = " << this->getName() << "\n"
560 << " Type = " << this->getType() << "\n"
561 << " Number of TimeEvents = " << this->getSize() << "\n"
562 << " Time Events = " << this->getTimeEventNames()<<std::endl;
563 *l_out << "--------------------------------------------" << std::endl;
564 for(auto& e : timeEvents_) {
565 (*e).describe(*l_out, verbLevel);
566 *l_out << "--------------------------------------------" << std::endl;
567 }
568 }
569
570
581 virtual Teuchos::RCP<const Teuchos::ParameterList> getValidParameters() const
582 {
583 Teuchos::RCP<Teuchos::ParameterList> pl =
584 Teuchos::parameterList("Time Event Composite");
585
586 pl->setName(this->getName());
587 pl->set("Name", this->getName());
588 pl->set("Type", this->getType());
589 pl->set<std::string>("Time Events", this->getTimeEventNames());
590
591 for(auto& s : timeEvents_)
592 pl->set(s->getName(), *s->getValidParameters());
593
594 return pl;
595 }
596
597
598protected:
599
600 std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents_;
601
602};
603
604
605// Nonmember constructor - ParameterList
606// ------------------------------------------------------------------------
607
622template<class Scalar>
623Teuchos::RCP<TimeEventComposite<Scalar> >
624createTimeEventComposite(Teuchos::RCP<Teuchos::ParameterList> const& pList)
625{
626 using Teuchos::RCP;
627 using Teuchos::ParameterList;
628
629 auto tec = Teuchos::rcp(new TimeEventComposite<Scalar>());
630 if (pList == Teuchos::null || pList->numParams() == 0) return tec;
631
632 TEUCHOS_TEST_FOR_EXCEPTION(
633 pList->get<std::string>("Type", "Composite") != "Composite",
634 std::logic_error,
635 "Error - Time Event Type != 'Composite'. (='"
636 + pList->get<std::string>("Type")+"')\n");
637
638 tec->setName(pList->get("Name", "From createTimeEventComposite"));
639
640 // string tokenizer
641 std::vector<std::string> teList;
642 teList.clear();
643 std::string str = pList->get<std::string>("Time Events");
644 std::string delimiters(",");
645 const char* WhiteSpace = " \t\v\r\n";
646 // Skip delimiters at the beginning
647 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
648 // Find the first delimiter
649 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
650 while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
651 // Found a token, add it to the vector
652 std::string token = str.substr(lastPos,pos-lastPos);
653
654 std::size_t start = token.find_first_not_of(WhiteSpace);
655 std::size_t end = token.find_last_not_of(WhiteSpace);
656 token = (start == end ? std::string() : token.substr(start, end-start+1));
657
658 teList.push_back(token);
659 if(pos==std::string::npos) break;
660
661 lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
662 pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
663 }
664
665 // For each sublist name tokenized, add the TimeEvent.
666 for ( auto teName: teList) {
667 RCP<ParameterList> pl =
668 Teuchos::rcp(new ParameterList(pList->sublist(teName)));
669
670 auto timeEventType = pl->get<std::string>("Type", "Unknown");
671 if (timeEventType == "Range") {
672 tec->add(createTimeEventRange<Scalar>(pl));
673 } else if (timeEventType == "Range Index") {
674 tec->add(createTimeEventRangeIndex<Scalar>(pl));
675 } else if (timeEventType == "List") {
676 tec->add(createTimeEventList<Scalar>(pl));
677 } else if (timeEventType == "List Index") {
678 tec->add(createTimeEventListIndex<Scalar>(pl));
679 } else {
680 RCP<Teuchos::FancyOStream> out =
681 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
682 out->setOutputToRootOnly(0);
683 Teuchos::OSTab ostab(out,1, "createTimeEventComposite()");
684 *out << "Warning -- createTimeEventComposite() - Unknown Time Event Type!\n"
685 << "'Type' = '" << timeEventType << "'\n"
686 << "Should call add() with this "
687 << "(app-specific?) Time Event.\n" << std::endl;
688 }
689 }
690
691 if (tec->getSize() == 0) {
692 RCP<Teuchos::FancyOStream> out =
693 Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
694 out->setOutputToRootOnly(0);
695 Teuchos::OSTab ostab(out,1, "createTimeEventComposite()");
696 *out << "Warning -- createTimeEventComposite() - Did not\n"
697 << " find/recognize any TimeEvents to create!\n"
698 << " If there is a app-specific TimeEvent,\n"
699 << " explicitly add it to this TimeEventComposite.\n"
700 << std::endl;
701 }
702
703 return tec;
704}
705
706
707} // namespace Tempus
708
709#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.