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: 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"
15 
16 #include "Tempus_config.hpp"
17 #include "Tempus_TimeEventBase.hpp"
19 #include "Tempus_TimeEventRange.hpp"
20 #include "Tempus_TimeEventRangeIndex.hpp"
21 #include "Tempus_TimeEventList.hpp"
22 #include "Tempus_TimeEventListIndex.hpp"
23 
24 namespace Tempus {
25 
31 template <class Scalar>
32 class TimeEventComposite : virtual public TimeEventBase<Scalar> {
33  public:
36  {
37  this->setType("Composite");
38  this->setName("TimeEventComposite");
39  }
40 
43  std::string name = "TimeEventComposite")
44  {
45  this->setType("Composite");
46  this->setName(name);
47  this->setTimeEvents(te);
48  }
49 
51  virtual ~TimeEventComposite() {}
52 
54 
55  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 
506  {
507  std::string name = timeEvent->getName();
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 
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 
604  {
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 
639 template <class Scalar>
642 {
644  using Teuchos::RCP;
645 
646  auto tec = Teuchos::rcp(new TimeEventComposite<Scalar>());
647  if (pList == Teuchos::null || pList->numParams() == 0) return tec;
648 
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
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)
#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
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
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