Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros 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 // Teuchos
13 #include "Teuchos_Time.hpp"
14 
15 // Tempus
16 #include "Tempus_TimeEventBase.hpp"
17 
18 
19 namespace Tempus {
20 
21 
22 /** \brief This composite TimeEvent loops over added TimeEvents.
23  *
24  * Individual TimeEvents are executed in the order in which they
25  * were added.
26  */
27 template<class Scalar>
28 class TimeEventComposite : virtual public TimeEventBase<Scalar>
29 {
30 public:
31 
32  /// Constructor
34  {
35  this->setName("TimeEventComposite");
36  }
37 
38  /// Destructor
39  virtual ~TimeEventComposite() {}
40 
41  /// \name Basic methods
42  //@{
43  /// Test if time is near a TimeEvent (within tolerance).
44  virtual bool isTime(Scalar time) const
45  {
46  bool is_time = false;
47  for(auto& e : timeEvents_) {
48  if (e->isTime(time)) {
49  is_time = true;
50  break;
51  }
52  }
53  return is_time;
54  }
55 
56  /// How much time until the next event. Negative indicating the last event is in the past.
57  virtual Scalar timeToNextEvent(Scalar time) const
58  {
59  return timeOfNextEvent(time) - time;
60  }
61 
62  /// Time of the next event. Negative indicating the last event is in the past.
63  virtual Scalar timeOfNextEvent(Scalar time) const
64  {
65  std::vector< std::pair<Scalar, Scalar> > timeAbs;
66  for(auto& e : timeEvents_)
67  timeAbs.push_back(std::make_pair(e->timeOfNextEvent(time), e->getAbsTol()));
68  std::sort(timeAbs.begin(), timeAbs.end());
69 
70  if (timeAbs.size() == 0) return this->getDefaultTime();
71 
72  // Check if before or close to first event.
73  if (timeAbs.front().first >= time-timeAbs.front().second)
74  return timeAbs.front().first;
75 
76  // Check if after or close to last event.
77  if (timeAbs.back().first <= time+timeAbs.front().second)
78  return timeAbs.back().first;
79 
80  typename std::vector< std::pair<Scalar, Scalar> >::const_iterator it =
81  std::upper_bound(timeAbs.begin(), timeAbs.end(), std::make_pair(time, 0.0));
82 
83  // Check if close to left-side time event
84  const Scalar timeOfLeftEvent = (*(it-1)).first;
85  const Scalar absTolOfLeftEvent = (*(it-1)).second;
86  if (timeOfLeftEvent > time - absTolOfLeftEvent &&
87  timeOfLeftEvent < time + absTolOfLeftEvent)
88  return timeOfLeftEvent;
89 
90  // Otherwise it is the next event.
91  return (*it).first;
92  }
93 
94  /// Test if an event occurs within the time range.
95  virtual bool eventInRange(Scalar time1, Scalar time2) const
96  {
97  bool inRange = false;
98  for(auto& e : timeEvents_) {
99  if (e->eventInRange(time1, time2)) {
100  inRange = true;
101  break;
102  }
103  }
104  return inRange;
105  }
106 
107  /// Test if index is a time event.TimeEventBase
108  virtual bool isIndex(int index) const
109  {
110  bool is_index = false;
111  for(auto& e : timeEvents_) {
112  if (e->isIndex(index)) {
113  is_index = true;
114  break;
115  }
116  }
117  return is_index;
118  }
119 
120  /// How many indices until the next event. Negative indicating the last event is in the past.
121  virtual int indexToNextEvent(int index) const
122  {
123  return indexOfNextEvent(index) - index;
124  }
125 
126  /// Index of the next event. Negative indicating the last event is in the past.
127  virtual int indexOfNextEvent(int index) const
128  {
129  std::vector<int> indexList;
130  for(auto& e : timeEvents_)
131  indexList.push_back(e->indexOfNextEvent(index));
132 
133  std::sort(indexList.begin(), indexList.end());
134  indexList.erase(std::unique(
135  indexList.begin(), indexList.end()), indexList.end());
136 
137  if (indexList.size() == 0) return this->getDefaultIndex();
138 
139  // Check if before first event.
140  if (indexList.front() >= index) return indexList.front();
141 
142  // Check if after last event.
143  if (indexList.back() <= index) return indexList.back();
144 
145  std::vector<int>::const_iterator it =
146  std::upper_bound(indexList.begin(), indexList.end(), index);
147 
148  // Check if left-side index event
149  const Scalar indexOfLeftEvent = *(it-1);
150  if (indexOfLeftEvent == index) return indexOfLeftEvent;
151 
152  // Otherwise it is the next event.
153  return *it;
154 
155  }
156 
157  /// Test if an event occurs within the time range.
158  virtual bool eventInRangeIndex(int index1, int index2) const
159  {
160  bool inRange = false;
161  for(auto& e : timeEvents_) {
162  if (e->eventInRangeIndex(index1, index2)) {
163  inRange = true;
164  break;
165  }
166  }
167  return inRange;
168  }
169  //@}
170 
171 
172  // Add TimeEvent to the TimeEvent vector.
173  void addTimeEvent(Teuchos::RCP<TimeEventBase<Scalar> > timeEvent)
174  {
175  timeEvents_.push_back(timeEvent);
176  }
177 
178  // Clear the TimeEvent vector.
180  { timeEvents_.clear(); }
181 
182  // Return the size of the TimeEvent vector.
183  std::size_t getSize() const { return timeEvents_.size(); }
184 
185  /// Describe member data.
186  virtual void describe() const
187  {
188  Teuchos::RCP<Teuchos::FancyOStream> out =
189  Teuchos::VerboseObjectBase::getDefaultOStream();
190  *out << "TimeEventComposite:" << "\n"
191  << "name = " << this->getName() << "\n"
192  << "Number of TimeEvents = " << timeEvents_.size() << std::endl;
193  *out << "--------------------------------------------" << std::endl;
194  for(auto& e : timeEvents_) {
195  (*e).describe();
196  *out << "--------------------------------------------" << std::endl;
197  }
198  }
199 
200 
201 protected:
202 
203  std::vector<Teuchos::RCP<TimeEventBase<Scalar > > > timeEvents_;
204 
205 };
206 
207 
208 } // namespace Tempus
209 
210 #endif // Tempus_TimeEventComposite_decl_hpp
virtual Scalar getDefaultTime() const
virtual bool isIndex(int index) const
Test if index is a time event.TimeEventBase.
virtual void setName(std::string name)
virtual bool isTime(Scalar time) const
Test if time is near a TimeEvent (within tolerance).
std::vector< Teuchos::RCP< TimeEventBase< Scalar > > > timeEvents_
virtual int getDefaultIndex() const
virtual bool eventInRange(Scalar time1, Scalar time2) const
Test if an event occurs within the time range.
virtual void describe() const
Describe member data.
virtual Scalar timeToNextEvent(Scalar time) const
How much time until the next event. Negative indicating the last event is in the past.
This composite TimeEvent loops over added TimeEvents.
virtual bool eventInRangeIndex(int index1, int index2) const
Test if an event occurs within the time range.
virtual int indexToNextEvent(int index) const
How many indices until the next event. Negative indicating the last event is in the past...
virtual int indexOfNextEvent(int index) const
Index of the next event. Negative indicating the last event is in the past.
This class defines time events which can be used to &quot;trigger&quot; an action. Time events are points in ti...
virtual std::string getName() const
virtual Scalar timeOfNextEvent(Scalar time) const
Time of the next event. Negative indicating the last event is in the past.
virtual ~TimeEventComposite()
Destructor.
void addTimeEvent(Teuchos::RCP< TimeEventBase< Scalar > > timeEvent)