RustedSciThe 0.4.19

Rust framework for symbolic and numerical computing:BVP ( Newton-Raphson frozen/damped/with collocations ), IVP( BDF, Radau, Backward Euler, LSODE, LSODA, RK45, DoPri), nonlinear equations ( Levenberg, Gavin) and more
Documentation
use std::error::Error;
use std::fmt::{Display, Formatter};

/// Describes why the nonlinear solve stopped.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum TerminationReason {
    /// The residual or method-specific convergence check succeeded.
    Converged,
    /// The maximum number of outer iterations was reached.
    MaxIterations,
    /// The trial step became too small to make progress.
    StepTooSmall,
    /// The method stopped because progress stalled.
    Stagnation,
    /// Too many trial steps were rejected.
    RejectedStepLimit,
}

/// Errors returned by the nonlinear solver pipeline.
#[derive(Debug, Clone, PartialEq)]
pub enum SolveError {
    /// A vector or matrix has an unexpected dimension.
    DimensionMismatch {
        /// Expected dimension.
        expected: usize,
        /// Actual dimension.
        actual: usize,
        /// Short description of the failing context.
        context: &'static str,
    },
    /// Solver configuration is invalid.
    InvalidConfig(String),
    /// The declared symbolic parameter schema is invalid.
    InvalidParameterSchema(String),
    /// Parameter values were created for a different ordered schema.
    ParameterSchemaMismatch(String),
    /// The declared symbolic variable schema is invalid.
    InvalidVariableSchema(String),
    /// An equation references a symbol absent from the declared schema.
    UndeclaredSymbol {
        /// Zero-based equation index.
        equation_index: usize,
        /// Referenced symbol name.
        name: String,
    },
    /// A parameter value is not finite.
    NonFiniteParameterValue {
        /// Index of the invalid parameter.
        index: usize,
        /// Invalid value.
        value: f64,
    },
    /// Initial point violates the provided bounds.
    InfeasibleInitialGuess {
        /// Index of the offending variable.
        index: usize,
        /// Current variable value.
        value: f64,
        /// Lower bound.
        lower: f64,
        /// Upper bound.
        upper: f64,
    },
    /// Residual evaluation failed.
    ResidualEvaluation(String),
    /// Jacobian evaluation failed.
    JacobianEvaluation(String),
    /// Compiled AOT artifact was selected, but no linked in-process runtime was available.
    CompiledAotRuntimeUnavailable(String),
    /// A compiled AOT artifact was required, but no registered artifact exists.
    CompiledAotArtifactMissing(String),
    /// A generated AOT crate is known, but the compiled artifact is not built yet.
    CompiledAotArtifactNotBuilt(String),
    /// Automatic AOT build was requested without an output directory.
    AotBuildOutputDirMissing,
    /// Automatic AOT build failed.
    AotBuildFailed(String),
    /// Linear system solve failed.
    LinearSolveFailure(String),
    /// Jacobian is singular or too ill-conditioned.
    SingularJacobian,
    /// Numerical breakdown such as NaN or Inf.
    NumericalBreakdown(String),
}

impl Display for SolveError {
    /// Formats a human-readable error message.
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            SolveError::DimensionMismatch {
                expected,
                actual,
                context,
            } => {
                write!(
                    f,
                    "dimension mismatch in {context}: expected {expected}, got {actual}"
                )
            }
            SolveError::InvalidConfig(msg) => write!(f, "invalid solver configuration: {msg}"),
            SolveError::InvalidParameterSchema(msg) => {
                write!(f, "invalid nonlinear parameter schema: {msg}")
            }
            SolveError::ParameterSchemaMismatch(msg) => {
                write!(f, "nonlinear parameter schema mismatch: {msg}")
            }
            SolveError::InvalidVariableSchema(msg) => {
                write!(f, "invalid nonlinear variable schema: {msg}")
            }
            SolveError::UndeclaredSymbol {
                equation_index,
                name,
            } => write!(
                f,
                "equation {equation_index} references undeclared symbol '{name}'"
            ),
            SolveError::NonFiniteParameterValue { index, value } => {
                write!(
                    f,
                    "non-finite nonlinear parameter at index {index}: {value}"
                )
            }
            SolveError::InfeasibleInitialGuess {
                index,
                value,
                lower,
                upper,
            } => write!(
                f,
                "initial guess at index {index} = {value} violates bounds [{lower}, {upper}]"
            ),
            SolveError::ResidualEvaluation(msg) => write!(f, "residual evaluation failed: {msg}"),
            SolveError::JacobianEvaluation(msg) => write!(f, "jacobian evaluation failed: {msg}"),
            SolveError::CompiledAotRuntimeUnavailable(msg) => {
                write!(f, "compiled AOT runtime unavailable: {msg}")
            }
            SolveError::CompiledAotArtifactMissing(msg) => {
                write!(f, "compiled AOT artifact missing: {msg}")
            }
            SolveError::CompiledAotArtifactNotBuilt(msg) => {
                write!(f, "compiled AOT artifact not built: {msg}")
            }
            SolveError::AotBuildOutputDirMissing => {
                write!(
                    f,
                    "automatic AOT build requested without an output directory"
                )
            }
            SolveError::AotBuildFailed(msg) => write!(f, "automatic AOT build failed: {msg}"),
            SolveError::LinearSolveFailure(msg) => write!(f, "linear solve failed: {msg}"),
            SolveError::SingularJacobian => write!(f, "jacobian is singular or ill-conditioned"),
            SolveError::NumericalBreakdown(msg) => write!(f, "numerical breakdown: {msg}"),
        }
    }
}

impl Error for SolveError {}