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 // Teuchos
13 #include "Teuchos_Time.hpp"
14 
15 // Tempus
16 #include "Tempus_config.hpp"
17 #include "Tempus_TimeEventBase.hpp"
18 
19 
20 namespace Tempus {
21 
22 
28 template<class Scalar>
29 class TimeEventComposite : virtual public TimeEventBase<Scalar>
30 {
31 public:
32 
35  {
36  this->setName("TimeEventComposite");
37  }
38 
40  virtual ~TimeEventComposite() {}
41 
43 
44  virtual bool isTime(Scalar time) const
46  {
47  bool is_time = false;
48  for(auto& e : timeEvents_) {
49  if (e->isTime(time)) {
50  is_time = true;
51  break;
52  }
53  }
54  return is_time;
55  }
56 
58  virtual Scalar timeToNextEvent(Scalar time) const
59  {
60  return timeOfNextEvent(time) - time;
61  }
62 
64  virtual Scalar timeOfNextEvent(Scalar time) const
65  {
66  std::vector< std::pair<Scalar, Scalar> > timeAbs;
67  for(auto& e : timeEvents_)
68  timeAbs.push_back(std::make_pair(e->timeOfNextEvent(time), e->getAbsTol()));
69  std::sort(timeAbs.begin(), timeAbs.end());
70 
71  if (timeAbs.size() == 0) return this->getDefaultTime();
72 
73  // Check if before or close to first event.
74  if (timeAbs.front().first >= time-timeAbs.front().second)
75  return timeAbs.front().first;
76 
77  // Check if after or close to last event.
78  if (timeAbs.back().first <= time+timeAbs.front().second)
79  return timeAbs.back().first;
80 
81  typename std::vector< std::pair<Scalar, Scalar> >::const_iterator it =
82  std::upper_bound(timeAbs.begin(), timeAbs.end(), std::make_pair(time, 0.0));
83 
84  // Check if close to left-side time event
85  const Scalar timeOfLeftEvent = (*(it-1)).first;
86  const Scalar absTolOfLeftEvent = (*(it-1)).second;
87  if (timeOfLeftEvent > time - absTolOfLeftEvent &&
88  timeOfLeftEvent < time + absTolOfLeftEvent)
89  return timeOfLeftEvent;
90 
91  // Otherwise it is the next event.
92  return (*it).first;
93  }
94 
96  virtual bool eventInRange(Scalar time1, Scalar time2) const
97  {
98  bool inRange = false;
99  for(auto& e : timeEvents_) {
100  if (e->eventInRange(time1, time2)) {
101  inRange = true;
102  break;
103  }
104  }
105  return inRange;
106  }
107 
109  virtual bool isIndex(int index) const
110  {
111  bool is_index = false;
112  for(auto& e : timeEvents_) {
113  if (e->isIndex(index)) {
114  is_index = true;
115  break;
116  }
117  }
118  return is_index;
119  }
120 
122  virtual int indexToNextEvent(int index) const
123  {
124  return indexOfNextEvent(index) - index;
125  }
126 
128  virtual int indexOfNextEvent(int index) const
129  {
130  std::vector<int> indexList;
131  for(auto& e : timeEvents_)
132  indexList.push_back(e->indexOfNextEvent(index));
133 
134  std::sort(indexList.begin(), indexList.end());
135  indexList.erase(std::unique(
136  indexList.begin(), indexList.end()), indexList.end());
137 
138  if (indexList.size() == 0) return this->getDefaultIndex();
139 
140  // Check if before first event.
141  if (indexList.front() >= index) return indexList.front();
142 
143  // Check if after last event.
144  if (indexList.back() <= index) return indexList.back();
145 
146  std::vector<int>::const_iterator it =
147  std::upper_bound(indexList.begin(), indexList.end(), index);
148 
149  // Check if left-side index event
150  const Scalar indexOfLeftEvent = *(it-1);
151  if (indexOfLeftEvent == index) return indexOfLeftEvent;
152 
153  // Otherwise it is the next event.
154  return *it;
155 
156  }
157 
159  virtual bool eventInRangeIndex(int index1, int index2) const
160  {
161  bool inRange = false;
162  for(auto& e : timeEvents_) {
163  if (e->eventInRangeIndex(index1, index2)) {
164  inRange = true;
165  break;
166  }
167  }
168  return inRange;
169  }
171 
172 
173  // Add TimeEvent to the TimeEvent vector.
175  {
176  timeEvents_.push_back(timeEvent);
177  }
178 
179  // Clear the TimeEvent vector.
181  { timeEvents_.clear(); }
182 
183  // Return the size of the TimeEvent vector.
184  std::size_t getSize() const { return timeEvents_.size(); }
185 
187  virtual void describe() const
188  {
191  *out << "TimeEventComposite:" << "\n"
192  << "name = " << this->getName() << "\n"
193  << "Number of TimeEvents = " << timeEvents_.size() << std::endl;
194  *out << "--------------------------------------------" << std::endl;
195  for(auto& e : timeEvents_) {
196  (*e).describe();
197  *out << "--------------------------------------------" << std::endl;
198  }
199  }
200 
201 
202 protected:
203 
204  std::vector<Teuchos::RCP<TimeEventBase<Scalar > > > timeEvents_;
205 
206 };
207 
208 
209 } // namespace Tempus
210 
211 #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.
static RCP< FancyOStream > getDefaultOStream()
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)