10#ifndef Tempus_TimeEventRange_impl_hpp
11#define Tempus_TimeEventRange_impl_hpp
17template <
class Scalar>
24 relTol_(this->getDefaultTol()),
25 absTol_(this->getDefaultTol()),
31 std::ostringstream oss;
37template <
class Scalar>
39 std::string name,
bool landOnExactly,
45 timeScale_(std::max(std::abs(start_), std::abs(stop_))),
47 absTol_(relTol_ * timeScale_),
48 landOnExactly_(landOnExactly)
52 std::ostringstream oss;
53 oss <<
"TimeEventRange (" << start <<
"; " << stop <<
"; " << stride <<
")";
64template <
class Scalar>
66 std::string name,
bool landOnExactly,
71 numEvents_(numEvents),
72 timeScale_(std::max(std::abs(start_), std::abs(stop_))),
74 absTol_(relTol_ * timeScale_),
75 landOnExactly_(landOnExactly)
78 std::ostringstream oss;
79 oss <<
"TimeEventRange (" << start <<
"; " << stop <<
"; " << numEvents
91template <
class Scalar>
103 setTimeStride(stride);
106template <
class Scalar>
112 if (stop_ < start_) {
118 setNumEvents(numEvents);
121template <
class Scalar>
125 if (stop_ < start_) stop_ = start_;
127 setTimeStride(stride_);
130template <
class Scalar>
134 if (start_ > stop_) start_ = stop_;
136 setTimeStride(stride_);
139template <
class Scalar>
142 timeScale_ = std::max(std::abs(start_), std::abs(stop_));
143 absTol_ = relTol_ * timeScale_;
148 absTol_ = relTol_ * timeScale_;
152template <
class Scalar>
155 stride_ = Teuchos::ScalarTraits<Scalar>::magnitude(stride);
162 if ((stride_ > stop_ - start_) || (stride_ < 2 * absTol_)) {
163 stride_ = stop_ - start_;
166 numEvents_ = int((stop_ + absTol_ - start_) / stride_) + 1;
169template <
class Scalar>
174 if (stride_ < 2 * absTol_) stride_ = 2 * absTol_;
175 numEvents_ = int((stop_ + absTol_ - start_) / stride_) + 1;
180 stride_ = stop_ - start_;
183 numEvents_ = numEvents;
184 if (numEvents_ < 2) numEvents_ = 2;
185 stride_ = (stop_ - start_) / Scalar(numEvents_ - 1);
190 if (stride_ <= 2 * absTol_) setTimeStride(2 * absTol_);
193template <
class Scalar>
196 relTol_ = std::abs(relTol);
200template <
class Scalar>
204 if (time < start_ - absTol_)
return false;
207 const Scalar timeOfLast = start_ + (numEvents_ - 1) * stride_;
208 if (time > timeOfLast + absTol_)
return false;
211 if (!
approxZero(stride_, 2 * absTol_)) numStrides = (time - start_) / stride_;
213 numStrides = std::min(std::max(0, numStrides),
int(numEvents_ - 1));
214 const Scalar leftBracket = start_ + numStrides * stride_;
220 const Scalar rightBracket = leftBracket + stride_;
226template <
class Scalar>
229 return timeOfNextEvent(time) - time;
232template <
class Scalar>
236 if (time < start_ - absTol_)
return start_;
238 const Scalar timeOfLast = start_ + (numEvents_ - 1) * stride_;
240 if (time > timeOfLast - absTol_)
return std::numeric_limits<Scalar>::max();
244 numStrides = int((time - start_) / stride_) + 1;
245 const Scalar timeEvent = start_ + numStrides * stride_;
253template <
class Scalar>
263 const Scalar timeOfLast = start_ + (numEvents_ - 1) * stride_;
264 if (time2 < start_ - absTol_ || timeOfLast + absTol_ < time1)
return false;
267 return (time1 < start_ - absTol_ && start_ - absTol_ <= time2);
269 const int strideJustBeforeTime1 = std::min(
271 std::max(
int(0),
int((time1 - start_ + absTol_) / stride_ - 0.5)));
273 const int strideJustAfterTime2 = std::max(
274 int(0), std::min(
int(numEvents_ - 1),
275 int((time2 - start_ + absTol_) / stride_ + 0.5)));
277 for (
int i = strideJustBeforeTime1; i <= strideJustAfterTime2; i++) {
278 const Scalar timeEvent = start_ + i * stride_;
279 if (time1 < timeEvent - absTol_ && timeEvent - absTol_ <= time2)
286template <
class Scalar>
288 Teuchos::FancyOStream &out,
const Teuchos::EVerbosityLevel verbLevel)
const
290 auto l_out = Teuchos::fancyOStream(out.getOStream());
291 Teuchos::OSTab ostab(*l_out, 2,
"TimeEventRange");
292 l_out->setOutputToRootOnly(0);
294 *l_out <<
"TimeEventRange:"
296 <<
" name = " << this->getName() <<
"\n"
297 <<
" Type = " << this->getType() <<
"\n"
298 <<
" start_ = " << start_ <<
"\n"
299 <<
" stop_ = " << stop_ <<
"\n"
300 <<
" stride_ = " << stride_ <<
"\n"
301 <<
" numEvents_ = " << numEvents_ <<
"\n"
302 <<
" timeScale_ = " << timeScale_ <<
"\n"
303 <<
" relTol_ = " << relTol_ <<
"\n"
304 <<
" absTol_ = " << absTol_ <<
"\n"
305 <<
" landOnExactly_ = " << landOnExactly_ << std::endl;
308template <
class Scalar>
309Teuchos::RCP<const Teuchos::ParameterList>
312 Teuchos::RCP<Teuchos::ParameterList> pl =
313 Teuchos::parameterList(
"Time Event Range");
315 pl->setName(this->getName());
316 pl->set(
"Name", this->getName());
317 pl->set(
"Type", this->getType());
319 pl->set(
"Start Time", getTimeStart(),
"Start of time range");
320 pl->set(
"Stop Time", getTimeStop(),
"Stop of time range");
321 pl->set(
"Stride Time", getTimeStride(),
"Stride of time range");
323 if (getTimeStride() * Scalar(getNumEvents() - 1) -
324 (getTimeStop() - getTimeStart()) <
326 pl->set(
"Number of Events", getNumEvents(),
327 "Number of events in time range. If specified, 'Stride Time' is "
330 pl->set(
"Relative Tolerance", getRelTol(),
331 "Relative time tolerance for matching time events.");
333 pl->set(
"Land On Exactly", getLandOnExactly(),
334 "Should these time events be landed on exactly, i.e, adjust the "
335 "timestep to hit time event, versus stepping over and keeping the "
336 "time step unchanged.");
344template <
class Scalar>
346 Teuchos::RCP<Teuchos::ParameterList> pl)
349 if (pl == Teuchos::null)
return ter;
351 TEUCHOS_TEST_FOR_EXCEPTION(pl->get<std::string>(
"Type",
"Range") !=
"Range",
353 "Error - Time Event Type != 'Range'. (='" +
354 pl->get<std::string>(
"Type") +
"')\n");
356 auto validPL = *ter->getValidParameters();
357 bool numEventsFound = pl->isParameter(
"Number of Events");
358 if (!numEventsFound) validPL.remove(
"Number of Events");
360 pl->validateParametersAndSetDefaults(validPL);
362 ter->setName(pl->get(
"Name",
"From createTimeEventRange"));
363 ter->setTimeStart(pl->get(
"Start Time", ter->getTimeStart()));
364 ter->setTimeStop(pl->get(
"Stop Time", ter->getTimeStop()));
365 ter->setTimeStride(pl->get(
"Stride Time", ter->getTimeStride()));
367 ter->setNumEvents(pl->get(
"Number of Events", ter->getNumEvents()));
368 ter->setRelTol(pl->get(
"Relative Tolerance", ter->getRelTol()));
369 ter->setLandOnExactly(pl->get(
"Land On Exactly", ter->getLandOnExactly()));
virtual void setType(std::string s)
virtual void setName(std::string name)
Set the name of the TimeEvent.
virtual Scalar getDefaultTol() const
Return the default tolerance used by TimeEvents.
TimeEventRange specifies a start, stop and stride time.
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
Return a valid ParameterList with current settings.
virtual void setRelTol(Scalar relTol)
Set the relative tolerance.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel) const
Describe member data.
virtual void setNumEvents(int numEvents)
Set the number of time events.
virtual void setTimeScale()
Set the time scale for the time events.
virtual void setLandOnExactly(bool LOE)
Set if the time event should be landed on exactly.
virtual void setTimeStop(Scalar stop)
Set the stop of the time range.
virtual void setTimeStride(Scalar stride)
Set the stride of the time range.
Scalar stride_
Stride of time range.
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.
Scalar start_
Start of time range.
TimeEventRange()
Default constructor.
virtual void setTimeStart(Scalar start)
Set the start of the time range.
virtual void setTimeRange(Scalar start, Scalar stop, Scalar stride)
Set the range of time events from start, stop and stride.
virtual bool isTime(Scalar time) const
Test if time is near an event (within tolerance).
Scalar stop_
Stop of time range.
virtual Scalar timeToNextEvent(Scalar time) const
How much time until the next event.
bool approxZero(Scalar value, Scalar tol=Teuchos::ScalarTraits< Scalar >::sfmin())
Test if value is approximately zero within tolerance.
Teuchos::RCP< TimeEventRange< Scalar > > createTimeEventRange(Teuchos::RCP< Teuchos::ParameterList > pList)
Nonmember Constructor via ParameterList.
bool approxEqualAbsTol(Scalar a, Scalar b, Scalar absTol)
Test if values are approximately equal within the absolute tolerance.