Tempus  Version of the Day
Time Integration
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Tempus_TimeEventList_impl.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_TimeEventList_impl_hpp
10 #define Tempus_TimeEventList_impl_hpp
11 
12 
13 namespace Tempus {
14 
15 template<class Scalar>
17 {
18  this->setName("TimeEventList");
19  setRelTol(1.0e-14);
20  setTimeScale();
21  setLandOnExactly(true);
22 }
23 
24 
25 template<class Scalar>
27  std::string name, std::vector<Scalar> timeList,
28  Scalar relTol, bool landOnExactly)
29 {
30  this->setName(name);
31  setRelTol(relTol);
32  setTimeScale();
33  setLandOnExactly(landOnExactly);
34  setTimeList(timeList);
35 }
36 
37 
38 template<class Scalar>
40 {
41  if (timeList_.size() == 0) {
42  timeScale_ = std::abs(this->getDefaultTime());
43  absTol_ = relTol_*timeScale_;
44  return;
45  }
46 
47  timeScale_ = std::max(std::abs(timeList_.front()),
48  std::abs(timeList_.back()));
49  absTol_ = relTol_*timeScale_;
50 
51  // Check if timeScale is near zero.
52  if ((-absTol_ <= timeScale_ ) && (timeScale_ <= absTol_)) {
53  timeScale_ = 1.0;
54  absTol_ = relTol_*timeScale_;
55  }
56 }
57 
58 
59 template<class Scalar>
60 void TimeEventList<Scalar>::setTimeList(std::vector<Scalar> timeList)
61 {
62  for(auto it = std::begin(timeList); it != std::end(timeList); ++it)
63  addTime(*it);
64 }
65 
66 
67 template<class Scalar>
69 {
70  if (timeList_.size() == 0) {
71  timeList_.push_back(time);
72  setTimeScale();
73  return;
74  }
75 
76  auto it = std::upper_bound(timeList_.begin(), timeList_.end(), time);
77  if (timeList_.size() == 1) {
78  // Only add if a "different" time.
79  if (std::abs(timeList_.front()-time) >= absTol_)
80  timeList_.insert(it, time);
81  setTimeScale();
82  return;
83  }
84 
85  // Don't add if already in list. Check both ends.
86  if (it == timeList_.begin()) {
87  if (std::abs(timeList_.front()-time) >= absTol_)
88  timeList_.insert(it, time);
89  } else if (it == timeList_.end()) {
90  if (std::abs(timeList_.back()-time) >= absTol_)
91  timeList_.insert(it, time);
92  } else if (std::abs(*(it-1) - time) >= absTol_ &&
93  std::abs(*(it ) - time) >= absTol_) {
94  timeList_.insert(it, time);
95  }
96  setTimeScale();
97 }
98 
99 
100 template<class Scalar>
102 {
103  relTol_ = std::abs(relTol);
104  setTimeScale();
105 }
106 
107 
108 template<class Scalar>
109 bool TimeEventList<Scalar>::isTime(Scalar time) const
110 {
111  return (std::abs(timeToNextEvent(time)) <= absTol_);
112 }
113 
114 
115 template<class Scalar>
116 Scalar TimeEventList<Scalar>::timeToNextEvent(Scalar time) const
117 {
118  return timeOfNextEvent(time) - time; // Neg. indicating in the past.
119 }
120 
121 
122 template<class Scalar>
123 Scalar TimeEventList<Scalar>::timeOfNextEvent(Scalar time) const
124 {
125  if (timeList_.size() == 0) return this->getDefaultTime();
126 
127  // Check if before or close to first event.
128  if (timeList_.front() >= time-absTol_) return timeList_.front();
129 
130  // Check if after or close to last event.
131  if (timeList_.back() <= time+absTol_) return timeList_.back();
132 
133  typename std::vector<Scalar>::const_iterator it =
134  std::upper_bound(timeList_.begin(), timeList_.end(), time);
135 
136  // Check if close to left-side time event
137  const Scalar timeOfLeftEvent = *(it-1);
138  if (timeOfLeftEvent > time-absTol_ &&
139  timeOfLeftEvent < time+absTol_) return timeOfLeftEvent;
140 
141  // Otherwise it is the next event.
142  return *it;
143 }
144 
145 
146 template<class Scalar>
148  Scalar time1, Scalar time2) const
149 {
150  if (time1 > time2) {
151  Scalar tmp = time1;
152  time1 = time2;
153  time2 = tmp;
154  }
155 
156  if (timeList_.size() == 0) return false;
157 
158  // Check if range is completely outside time events.
159  if (time2+absTol_ < timeList_.front() ||
160  timeList_.back() < time1-absTol_) return false;
161 
162  Scalar timeEvent1 = timeOfNextEvent(time1);
163  Scalar timeEvent2 = timeOfNextEvent(time2);
164  // Check if the next time event is different for the two times.
165  if (timeEvent1 != timeEvent2) return true;
166 
167  // Check if times bracket time event.
168  if (time1-absTol_ <= timeEvent1 && timeEvent1 <= time2+absTol_) return true;
169 
170  return false;
171 }
172 
173 
174 template<class Scalar>
176 {
179  *out << "TimeEventList:" << "\n"
180  << "name = " << this->getName() << "\n"
181  << "timeScale_ = " << timeScale_ << "\n"
182  << "relTol_ = " << relTol_ << "\n"
183  << "absTol_ = " << absTol_ << "\n"
184  << "landOnExactly_ = " << landOnExactly_ << "\n"
185  << "timeList_ = " << std::endl;
186  for (auto it = timeList_.begin(); it != timeList_.end()-1; ++it)
187  *out << *it << ", ";
188  *out << *(timeList_.end()-1) << "\n";
189 }
190 
191 
192 } // namespace Tempus
193 #endif // Tempus_TimeEventList_impl_hpp
virtual void setTimeList(std::vector< Scalar > timeList)
virtual bool isTime(Scalar time) const
Test if time is near a TimeEvent (within tolerance).
virtual void addTime(Scalar time)
virtual Scalar timeOfNextEvent(Scalar time) const
Time of the next event. Negative indicating the last event is in the past.
virtual bool eventInRange(Scalar time1, Scalar time2) const
Test if an event occurs within the time range.
virtual void describe() const
Describe member data.
static RCP< FancyOStream > getDefaultOStream()
virtual void setRelTol(Scalar relTol)
TimeEventList()
Default constructor.
virtual Scalar timeToNextEvent(Scalar time) const
How much time until the next event. Negative indicating the last event is in the past.