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