IntegrationError
Defined in: error.rs:52
pub enum IntegrationError { NonFiniteState { t: f64 }, StepSizeTooSmall { t: f64, dt: f64 }, InvalidStepSize { dt: f64 }, InvalidTimeSpan { t0: f64, t_end: f64 }, InvalidTolerances { atol: f64, rtol: f64 }, IndeterminateErrorNorm { t: f64 }, TimeStagnated { t: f64, dt: f64 }, StepBelowSpacing { t: f64, dt: f64, spacing: f64 }, LandingUnreachable { t: f64, h: f64, landing: f64 }, NonFiniteRootValue { t: f64, event: usize }, InvalidRootSearch { t_tolerance: f64, max_iterations: u32 }, RootNotLocalized { t: f64, bracket: f64 }, RootStillCrossed { t: f64, event: usize }, RootTrialRejected { t: f64, h: f64, err: f64 }, InvalidBoundaryTolerance { event: usize, tolerance: f64 }, RootSlotCount { events: usize, slots: usize },}Reason the integration was stopped by the integrator itself.
#[non_exhaustive]: adding a variant here previously broke every downstream
exhaustive match. Consumers should use a wildcard arm, or
IntegrationError::time() when all they need is the failure time.
Variants
Section titled “Variants”NonFiniteState
Section titled “NonFiniteState”t: f64
A NaN or Inf was detected in the state after a step.
StepSizeTooSmall
Section titled “StepSizeTooSmall”t: f64 dt: f64
Step size became smaller than minimum threshold.
InvalidStepSize
Section titled “InvalidStepSize”dt: f64
The requested step size is zero, negative, or non-finite, so the
integration could never reach t_end.
InvalidTimeSpan
Section titled “InvalidTimeSpan”t0: f64 t_end: f64
t_end lies before t0. Backward integration is not supported; the
loops advance time monotonically upward.
InvalidTolerances
Section titled “InvalidTolerances”atol: f64 rtol: f64
Tolerances cannot drive adaptive error control (see
Tolerances::validate).
IndeterminateErrorNorm
Section titled “IndeterminateErrorNorm”t: f64
The error norm evaluated to NaN (an indeterminate 0 / 0), so the step
could neither be accepted nor usefully retried. +Inf is not an error:
it shrinks the step and recovers or ends in Self::StepSizeTooSmall.
TimeStagnated
Section titled “TimeStagnated”t: f64 dt: f64
t + dt rounded back to t in f64, so time stopped advancing even
though dt itself is positive.
StepBelowSpacing
Section titled “StepBelowSpacing”t: f64 dt: f64 spacing: f64
dt is narrower than the spacing of f64 at t, so no grid can carry
it: the clock still advances, but by spacing rather than by the dt
asked for. Distinct from Self::TimeStagnated, where the clock does
not advance at all — that happens once dt falls below half the
spacing.
LandingUnreachable
Section titled “LandingUnreachable”t: f64 h: f64 landing: f64
A fixed-step walk decided a step from t should land on landing, and
the width between the two does not carry the clock there: t + h falls
short of landing, or past it.
The last step of a span is assigned the span’s end rather than reaching
it by arithmetic, so its width has to resolve both its start and its
end. Where |t| is large enough relative to the resolution the end
needs, one f64 cannot: from -1e16 the distance to 1.0 rounds to
1e16, and -1e16 + 1e16 is 0.0. Publishing such a step would name a
time the solver’s own stages never saw. Measured across 408 spans, the
walk refuses only where the span crosses zero from 1e14 or further
away in a single step.
NonFiniteRootValue
Section titled “NonFiniteRootValue”t: f64 event: usize
A RootEvent(crate::RootEvent) reported a non-finite value at t.
The sign of such a value says nothing about which side of the boundary
the state is on, so neither the detection nor the search that follows it
would mean anything.
InvalidRootSearch
Section titled “InvalidRootSearch”t_tolerance: f64 max_iterations: u32
A RootSearch(crate::RootSearch) cannot narrow a bracket: the
tolerance is not positive and finite, or no iteration is allowed.
RootNotLocalized
Section titled “RootNotLocalized”t: f64 bracket: f64
The bisection ran out of iterations with the bracket still wider than
the tolerance, so the crossing was never pinned down. A value that
changes sign without being continuous in t does this.
RootStillCrossed
Section titled “RootStillCrossed”t: f64 event: usize
A RootEvent(crate::RootEvent) whose value is still on its crossed
side after the caller was given every chance to move the state off it.
The search locates a crossing from a change of sign, so a value that
already starts on the crossed side has none left to give. A caller
driving a RootSet(crate::RootSet) itself is the one that moves the
state off such an event before walking on; where its own handling
leaves the value where it was — or puts it past another event — there
is nothing left for the walk to search for.
RootTrialRejected
Section titled “RootTrialRejected”t: f64 h: f64 err: f64
A step of width h taken while narrowing a bracket failed the adaptive
solver’s own error control, with error norm err.
The step is narrower than the one already accepted from the same start, so its local error should be the smaller of the two. Where it is not, the state the search would read its value at is not on a trajectory the solver can represent there, and a crossing time derived from it would name nothing. The search does not subdivide further: it has no step-size control of its own, by design, so that the trials cannot move the one the walk uses.
InvalidBoundaryTolerance
Section titled “InvalidBoundaryTolerance”event: usize tolerance: f64
A RootEvent(crate::RootEvent) reported a boundary tolerance that is
negative or non-finite.
The width is what re-arms an event’s guard after a root. A negative one re-arms it at once, so the boundary the state is still on is reported again; a non-finite one never re-arms it, so the event fires once and then never again.
RootSlotCount
Section titled “RootSlotCount”events: usize slots: usize
A root set was built from an event slice and a slot slice of different lengths.
One slot carries one event’s search state across steps, so the pairing is by index and a mismatch would leave an event without one.
Methods
Section titled “Methods”time()
Section titled “time()”fn time(&self) -> Option<f64>
The simulation time the failure is attributed to, when the variant carries one.
None for the pre-flight argument checks (Self::InvalidStepSize,
Self::InvalidTolerances, Self::InvalidRootSearch), which reject
before any step runs — the caller’s start time is the meaningful
timestamp there. Callers that need a f64 unconditionally should use
err.time().unwrap_or(start_t), which also keeps them compiling as new
variants are added.