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 
13 
14 namespace Tempus {
15 
16 template <class Scalar>
18  : timeScale_(1.0),
19  relTol_(this->getDefaultTol()),
20  absTol_(this->getDefaultTol()),
21  landOnExactly_(true)
22 {
23  this->setType("List");
24  this->setName("TimeEventList");
25  setRelTol(this->getDefaultTol());
26  setTimeScale();
27  setLandOnExactly(true);
28 }
29 
30 template <class Scalar>
31 TimeEventList<Scalar>::TimeEventList(std::vector<Scalar> timeList,
32  std::string name, bool landOnExactly,
33  Scalar relTol)
34  : timeScale_(1.0),
35  relTol_(this->getDefaultTol()),
36  absTol_(this->getDefaultTol()),
37  landOnExactly_(true)
38 {
39  this->setType("List");
40  this->setName(name);
41  setRelTol(relTol);
42  setTimeScale();
43  setLandOnExactly(landOnExactly);
44  setTimeList(timeList);
45 }
46 
47 template <class Scalar>
49 {
50  if (timeList_.size() == 0) {
51  timeScale_ = 1.0;
52  absTol_ = relTol_ * timeScale_;
53  return;
54  }
55 
56  timeScale_ =
57  std::max(std::abs(timeList_.front()), std::abs(timeList_.back()));
58  absTol_ = relTol_ * timeScale_;
59 
60  // Check if timeScale is near zero.
61  if (approxZero(timeScale_, absTol_)) {
62  timeScale_ = 1.0;
63  absTol_ = relTol_ * timeScale_;
64  }
65 }
66 
67 template <class Scalar>
68 void TimeEventList<Scalar>::setTimeList(std::vector<Scalar> timeList, bool sort)
69 {
70  timeList_ = timeList;
71  if (sort) {
72  std::sort(timeList_.begin(), timeList_.end());
73  timeList_.erase(std::unique(timeList_.begin(), timeList_.end()),
74  timeList_.end());
75  }
76 }
77 
78 template <class Scalar>
80 {
81  if (timeList_.size() == 0) {
82  timeList_.push_back(time);
83  setTimeScale();
84  return;
85  }
86 
87  auto it = std::upper_bound(timeList_.begin(), timeList_.end(), time);
88  if (timeList_.size() == 1) {
89  // Only add if a "different" time.
90  if (std::abs(timeList_.front() - time) >= absTol_)
91  timeList_.insert(it, time);
92  setTimeScale();
93  return;
94  }
95 
96  // Don't add if already in list. Check both ends.
97  if (it == timeList_.begin()) {
98  if (std::abs(timeList_.front() - time) >= absTol_)
99  timeList_.insert(it, time);
100  }
101  else if (it == timeList_.end()) {
102  if (std::abs(timeList_.back() - time) >= absTol_)
103  timeList_.insert(it, time);
104  }
105  else if (std::abs(*(it - 1) - time) >= absTol_ &&
106  std::abs(*(it)-time) >= absTol_) {
107  timeList_.insert(it, time);
108  }
109  setTimeScale();
110 }
111 
112 template <class Scalar>
114 {
115  relTol_ = std::abs(relTol);
116  setTimeScale();
117 }
118 
119 template <class Scalar>
120 bool TimeEventList<Scalar>::isTime(Scalar time) const
121 {
122  for (auto it = timeList_.begin(); it != timeList_.end(); ++it)
123  if (approxEqualAbsTol(time, *it, absTol_)) return true;
124 
125  return false;
126 }
127 
128 template <class Scalar>
129 Scalar TimeEventList<Scalar>::timeToNextEvent(Scalar time) const
130 {
131  return timeOfNextEvent(time) - time; // Neg. indicating in the past.
132 }
133 
134 template <class Scalar>
135 Scalar TimeEventList<Scalar>::timeOfNextEvent(Scalar time) const
136 {
137  if (timeList_.size() == 0) return this->getDefaultTime();
138 
139  // Check if before first event.
140  if (time < timeList_.front() - absTol_) return timeList_.front();
141 
142  // Check if after or close to last event.
143  if (time > timeList_.back() - absTol_)
144  return std::numeric_limits<Scalar>::max();
145 
146  typename std::vector<Scalar>::const_iterator it =
147  std::upper_bound(timeList_.begin(), timeList_.end(), time);
148  const Scalar timeEvent = *it;
149 
150  // Check timeEvent is near time. If so, return the next event.
151  if (approxEqualAbsTol(time, timeEvent, absTol_)) return *(it + 1);
152 
153  return timeEvent;
154 }
155 
156 template <class Scalar>
157 bool TimeEventList<Scalar>::eventInRange(Scalar time1, Scalar time2) const
158 {
159  if (time1 > time2) {
160  Scalar tmp = time1;
161  time1 = time2;
162  time2 = tmp;
163  }
164 
165  if (timeList_.size() == 0) return false;
166 
167  for (auto it = timeList_.begin(); it != timeList_.end(); ++it)
168  if (time1 + absTol_ < *it && *it < time2 + absTol_) return true;
169 
170  return false;
171 }
172 
173 template <class Scalar>
175  Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
176 {
177  auto l_out = Teuchos::fancyOStream(out.getOStream());
178  Teuchos::OSTab ostab(*l_out, 2, "TimeEventList");
179  l_out->setOutputToRootOnly(0);
180 
181  *l_out << "TimeEventList:"
182  << "\n"
183  << " name = " << this->getName() << "\n"
184  << " Type = " << this->getType() << "\n"
185  << " timeScale_ = " << timeScale_ << "\n"
186  << " relTol_ = " << relTol_ << "\n"
187  << " absTol_ = " << absTol_ << "\n"
188  << " landOnExactly_ = " << landOnExactly_ << "\n"
189  << " timeList_ = ";
190  if (!timeList_.empty()) {
191  for (auto it = timeList_.begin(); it != timeList_.end() - 1; ++it)
192  *l_out << *it << ", ";
193  *l_out << *(timeList_.end() - 1) << std::endl;
194  }
195  else {
196  *l_out << "<empty>" << std::endl;
197  }
198 }
199 
200 template <class Scalar>
203 {
205  Teuchos::parameterList("Time Event List");
206 
207  pl->setName(this->getName());
208  pl->set("Name", this->getName());
209  pl->set("Type", this->getType());
210 
211  pl->set("Relative Tolerance", this->getRelTol(),
212  "Relative time tolerance for matching time events.");
213 
214  pl->set("Land On Exactly", this->getLandOnExactly(),
215  "Should these time events be landed on exactly, i.e, adjust the "
216  "timestep to hit time event, versus stepping over and keeping the "
217  "time step unchanged.");
218 
219  std::vector<Scalar> times = this->getTimeList();
220  std::ostringstream list;
221  if (!times.empty()) {
222  for (std::size_t i = 0; i < times.size() - 1; ++i) list << times[i] << ", ";
223  list << times[times.size() - 1];
224  }
225  pl->set<std::string>("Time List", list.str(),
226  "Comma deliminated list of times");
227 
228  return pl;
229 }
230 
231 // Nonmember constructors.
232 // ------------------------------------------------------------------------
233 
234 template <class Scalar>
237 {
238  auto tel = Teuchos::rcp(new TimeEventList<Scalar>());
239  if (pl == Teuchos::null) return tel; // Return default TimeEventList.
240 
241  TEUCHOS_TEST_FOR_EXCEPTION(pl->get<std::string>("Type", "List") != "List",
242  std::logic_error,
243  "Error - Time Event Type != 'List'. (='" +
244  pl->get<std::string>("Type") + "')\n");
245 
246  pl->validateParametersAndSetDefaults(*tel->getValidParameters());
247 
248  tel->setName(pl->get("Name", "From createTimeEventList"));
249  tel->setRelTol(pl->get("Relative Tolerance", tel->getRelTol()));
250  tel->setLandOnExactly(pl->get("Land On Exactly", tel->getLandOnExactly()));
251 
252  std::vector<Scalar> timeList;
253  std::string str = pl->get<std::string>("Time List");
254  std::string delimiters(",");
255  // Skip delimiters at the beginning
256  std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
257  // Find the first delimiter
258  std::string::size_type pos = str.find_first_of(delimiters, lastPos);
259  while ((pos != std::string::npos) || (lastPos != std::string::npos)) {
260  // Found a token, add it to the vector
261  std::string token = str.substr(lastPos, pos - lastPos);
262  timeList.push_back(Scalar(std::stod(token)));
263  if (pos == std::string::npos) break;
264 
265  lastPos = str.find_first_not_of(delimiters, pos); // Skip delimiters
266  pos = str.find_first_of(delimiters, lastPos); // Find next delimiter
267  }
268  tel->setTimeList(timeList);
269 
270  return tel;
271 }
272 
273 } // namespace Tempus
274 #endif // Tempus_TimeEventList_impl_hpp
virtual bool isTime(Scalar time) const
Test if time is near an event (within tolerance).
virtual void setType(std::string s)
virtual void setName(std::string name)
Set the name of the TimeEvent.
T & get(const std::string &name, T def_value)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a valid ParameterList with current settings.
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 void addTime(Scalar time)
Add the time to event vector.
virtual Scalar timeOfNextEvent(Scalar time) const
Return the time of the next event following the input time.
virtual bool eventInRange(Scalar time1, Scalar time2) const
Test if an event occurs within the time range.
virtual Scalar getDefaultTol() const
Return the default tolerance used by TimeEvents.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
virtual void setTimeScale()
Set the time scale for the time events.
void validateParametersAndSetDefaults(ParameterList const &validParamList, int const depth=1000)
virtual void setRelTol(Scalar relTol)
Set the relative tolerance.
virtual void setTimeList(std::vector< Scalar > timeList, bool sort=true)
Set the list of time events.
TimeEventList()
Default constructor.
RCP< std::basic_ostream< char_type, traits_type > > getOStream()
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Describe member data.
bool approxEqualAbsTol(Scalar a, Scalar b, Scalar absTol)
Test if values are approximately equal within the absolute tolerance.
bool approxZero(Scalar value, Scalar tol=Teuchos::ScalarTraits< Scalar >::sfmin())
Test if value is approximately zero within tolerance.
virtual Scalar timeToNextEvent(Scalar time) const
How much time until the next event.
ParameterList & setName(const std::string &name)
virtual void setLandOnExactly(bool LOE)
Set if the time event should be landed on exactly.
TimeEventList specifies a list of time events.
Teuchos::RCP< TimeEventList< Scalar > > createTimeEventList(Teuchos::RCP< Teuchos::ParameterList > pList)
Nonmember Constructor via ParameterList.