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 
24 namespace Tempus {
25 
26 
32 template<class Scalar>
33 class TimeEventComposite : virtual public TimeEventBase<Scalar>
34 {
35 public:
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 
55  virtual ~TimeEventComposite() {}
56 
58 
59  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 
485  {
486  std::string name = timeEvent->getName();
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 
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 
582  {
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 
598 protected:
599 
600  std::vector<Teuchos::RCP<TimeEventBase<Scalar> > > timeEvents_;
601 
602 };
603 
604 
605 // Nonmember constructor - ParameterList
606 // ------------------------------------------------------------------------
607 
622 template<class Scalar>
625 {
626  using Teuchos::RCP;
628 
629  auto tec = Teuchos::rcp(new TimeEventComposite<Scalar>());
630  if (pList == Teuchos::null || pList->numParams() == 0) return tec;
631 
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
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 std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > getTimeEvents() const
Get a copy of the current set of TimeEvents.
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 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