Closed david-german-tri closed 6 years ago
The fundamental motivation for the discrete return values is to avoid making critical simulation decisions based on unreliable floating point math. This will get much worse with witness functions included since the theory requires a "zero crossing" which must be isolated and in fact never actually gets to zero. The goal is to isolate the floating point nastiness to as small a piece of code as possible, make a discrete decision and then stick with it after that.
The requisite educational requirement is not a PhD -- it's a diploma from the School of Hard Knocks for numerical computation!
Yes - my point in brief is that we're making decisions based on floating point comparison regardless in LeafSystem<T>::DoCalcNextUpdateTimeImpl
(self-explanatory) and IntegratorBase<T>::StepOnceAtMost
(the sort).
Closing this issue as it seems to no longer have an advocate. Feel free to reopen if desired.
StepResult
is the enum return type fromIntegratorBase<T>::StepOnceAtMost
to theSimulator<T>::StepTo
loop. The return value is computed as follows:DoStepOnceAtMost
as a hard limit on step size.kTimeHasAdvanced
.kReachedPublishTime
,kReachedUpdateTime
, orkTimeHasAdvanced
depending on which constraint was active.(#4331 will make the logic a little more complex by "stretching" the max step size, but that's not germane to this issue.)
Then,
StepTo
uses the return type to determine whether to invoke the publish or update handlers on the system being simulated.I believe we could stop returning the enum, and simply check in
StepTo
whether a publish or update time has passed:Reasons I believe this enum-less approach is equally correct:
StepOnceAtMost
will never step past the next discrete event time.context_->get_time()
, so this phrasing makes very clear the Simulator is honoring that request.StepTo
already does a comparison withget_time()
to cope with simultaneous discrete events. If it's legitimate there it's legitimate more generally.(3) in particular is noteworthy, because a direct check of
get_time()
would have prevented a Simulator bug that skipped System-requested discrete updates in #4325. Admittedly, it would have done so at the cost of forcing some epsilon-sized integrator steps, so the #4331 fix is both sufficient and superior - but I claim we can have a belt and suspenders, and delete some lines of code to boot!The dynamics team assures me that actually these enums are vital, but it takes days of painstaking reasoning by a team of Ph.Ds to understand why. They regret not fully capturing this reasoning in comments for the benefit of hapless readers like me. So, I am opening an issue as requested by @SeanCurtis-TRI and @edrumwri, requesting documentation and/or cleanup.