Skip to content

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 },
}

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.

t: f64

A NaN or Inf was detected in the state after a step.


t: f64 dt: f64

Step size became smaller than minimum threshold.


dt: f64

The requested step size is zero, negative, or non-finite, so the integration could never reach t_end.


t0: f64 t_end: f64

t_end lies before t0. Backward integration is not supported; the loops advance time monotonically upward.


atol: f64 rtol: f64

Tolerances cannot drive adaptive error control (see Tolerances::validate).


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.


t: f64 dt: f64

t + dt rounded back to t in f64, so time stopped advancing even though dt itself is positive.


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.


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.


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), 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.