489 lines
14 KiB
Rust
489 lines
14 KiB
Rust
//! Error handling for RTX Science
|
|
//!
|
|
//! Provides comprehensive error types for scientific computing operations,
|
|
//! physics simulations, and domain-specific applications.
|
|
|
|
use thiserror::Error;
|
|
|
|
/// Result type alias for RTX Science operations
|
|
pub type Result<T> = std::result::Result<T, ScienceError>;
|
|
|
|
/// Comprehensive error types for scientific computing operations
|
|
#[derive(Error, Debug)]
|
|
pub enum ScienceError {
|
|
/// Tensor operation errors
|
|
#[error("Tensor error: {0}")]
|
|
Tensor(#[from] crate::TensorError),
|
|
|
|
/// Autograd computation errors
|
|
#[error("Autograd error: {0}")]
|
|
Autograd(#[from] crate::AutogradError),
|
|
|
|
/// Physics simulation errors
|
|
#[error("Physics simulation error: {message}")]
|
|
Physics {
|
|
/// Error message
|
|
message: String,
|
|
/// Physics domain context
|
|
domain: PhysicsDomain,
|
|
},
|
|
|
|
/// Numerical computation errors
|
|
#[error("Numerical error: {message} (method: {method})")]
|
|
Numerical {
|
|
/// Error description
|
|
message: String,
|
|
/// Numerical method that failed
|
|
method: String,
|
|
/// Convergence information if applicable
|
|
convergence_info: Option<ConvergenceInfo>,
|
|
},
|
|
|
|
/// Chemistry-specific errors
|
|
#[cfg(feature = "chemistry")]
|
|
#[error("Chemistry error: {message}")]
|
|
Chemistry {
|
|
/// Error message
|
|
message: String,
|
|
/// Molecular context if available
|
|
molecule_context: Option<String>,
|
|
},
|
|
|
|
/// Biology-specific errors
|
|
#[cfg(feature = "biology")]
|
|
#[error("Biology error: {message}")]
|
|
Biology {
|
|
/// Error message
|
|
message: String,
|
|
/// Biological context
|
|
bio_context: BiologyContext,
|
|
},
|
|
|
|
/// Materials science errors
|
|
#[cfg(feature = "materials")]
|
|
#[error("Materials science error: {message}")]
|
|
Materials {
|
|
/// Error message
|
|
message: String,
|
|
/// Material system context
|
|
material_system: Option<String>,
|
|
},
|
|
|
|
/// Scientific data validation errors
|
|
#[error("Data validation error: {message}")]
|
|
DataValidation {
|
|
/// Error message
|
|
message: String,
|
|
/// Field that failed validation
|
|
field: String,
|
|
/// Expected range or constraint
|
|
expected: String,
|
|
/// Actual value received
|
|
actual: String,
|
|
},
|
|
|
|
/// Conservation law violation errors
|
|
#[error("Conservation law violation: {law} (error: {magnitude:.2e})")]
|
|
ConservationViolation {
|
|
/// Conservation law that was violated
|
|
law: ConservationLaw,
|
|
/// Magnitude of the violation
|
|
magnitude: f64,
|
|
/// Tolerance that was exceeded
|
|
tolerance: f64,
|
|
},
|
|
|
|
/// Boundary condition specification errors
|
|
#[error("Boundary condition error: {message}")]
|
|
BoundaryCondition {
|
|
/// Error message
|
|
message: String,
|
|
/// Boundary type
|
|
boundary_type: BoundaryType,
|
|
},
|
|
|
|
/// Convergence failure errors
|
|
#[error("Convergence failure: {algorithm} failed to converge after {iterations} iterations")]
|
|
ConvergenceFailure {
|
|
/// Algorithm that failed to converge
|
|
algorithm: String,
|
|
/// Number of iterations attempted
|
|
iterations: usize,
|
|
/// Final residual or error measure
|
|
final_residual: f64,
|
|
/// Target tolerance
|
|
tolerance: f64,
|
|
},
|
|
|
|
/// Invalid physics model parameters
|
|
#[error(
|
|
"Invalid model parameters: {parameter} = {value} is outside valid range [{min}, {max}]"
|
|
)]
|
|
InvalidParameters {
|
|
/// Parameter name
|
|
parameter: String,
|
|
/// Invalid value
|
|
value: f64,
|
|
/// Minimum valid value
|
|
min: f64,
|
|
/// Maximum valid value
|
|
max: f64,
|
|
},
|
|
|
|
/// GPU/CUDA computation errors
|
|
#[error("GPU computation error: {message}")]
|
|
GpuComputation {
|
|
/// Error message
|
|
message: String,
|
|
/// CUDA device ID if applicable
|
|
device_id: Option<i32>,
|
|
},
|
|
|
|
/// Distributed computing errors
|
|
#[cfg(feature = "distributed-sci")]
|
|
#[error("Distributed computing error: {message}")]
|
|
DistributedComputing {
|
|
/// Error message
|
|
message: String,
|
|
/// Node/rank information
|
|
node_info: Option<String>,
|
|
},
|
|
|
|
/// I/O errors for scientific data
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
/// Serialization/deserialization errors
|
|
#[error("Serialization error: {0}")]
|
|
Serialization(#[from] serde_json::Error),
|
|
|
|
/// Generic anyhow errors for complex cases
|
|
#[error(transparent)]
|
|
Other(#[from] anyhow::Error),
|
|
}
|
|
|
|
/// Physics domain context for error reporting
|
|
#[derive(Debug, Clone)]
|
|
pub enum PhysicsDomain {
|
|
/// Fluid dynamics
|
|
FluidDynamics,
|
|
/// Heat transfer
|
|
HeatTransfer,
|
|
/// Electromagnetics
|
|
Electromagnetics,
|
|
/// Quantum mechanics
|
|
QuantumMechanics,
|
|
/// Molecular dynamics
|
|
MolecularDynamics,
|
|
/// Continuum mechanics
|
|
ContinuumMechanics,
|
|
/// Statistical mechanics
|
|
StatisticalMechanics,
|
|
/// Thermodynamics
|
|
Thermodynamics,
|
|
}
|
|
|
|
/// Conservation laws that can be violated
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum ConservationLaw {
|
|
/// Conservation of mass
|
|
Mass,
|
|
/// Conservation of momentum
|
|
Momentum,
|
|
/// Conservation of energy
|
|
Energy,
|
|
/// Conservation of angular momentum
|
|
AngularMomentum,
|
|
/// Conservation of charge
|
|
Charge,
|
|
/// Conservation of probability (quantum)
|
|
Probability,
|
|
}
|
|
|
|
/// Boundary condition types
|
|
#[derive(Debug, Clone)]
|
|
pub enum BoundaryType {
|
|
/// Dirichlet (fixed value)
|
|
Dirichlet,
|
|
/// Neumann (fixed derivative)
|
|
Neumann,
|
|
/// Robin (mixed)
|
|
Robin,
|
|
/// Periodic
|
|
Periodic,
|
|
/// No-slip
|
|
NoSlip,
|
|
/// Free-slip
|
|
FreeSlip,
|
|
}
|
|
|
|
/// Convergence information for numerical methods
|
|
#[derive(Debug, Clone)]
|
|
pub struct ConvergenceInfo {
|
|
/// Number of iterations completed
|
|
pub iterations: usize,
|
|
/// Final residual or error norm
|
|
pub final_residual: f64,
|
|
/// Target tolerance
|
|
pub tolerance: f64,
|
|
/// Convergence rate if computed
|
|
pub convergence_rate: Option<f64>,
|
|
/// Additional diagnostic information
|
|
pub diagnostics: Vec<String>,
|
|
}
|
|
|
|
/// Biology-specific context for errors
|
|
#[cfg(feature = "biology")]
|
|
#[derive(Debug, Clone)]
|
|
pub enum BiologyContext {
|
|
/// Protein structure
|
|
ProteinStructure,
|
|
/// DNA/RNA sequence
|
|
NucleicAcid,
|
|
/// Metabolic pathway
|
|
MetabolicPathway,
|
|
/// Gene expression
|
|
GeneExpression,
|
|
/// Cell signaling
|
|
CellSignaling,
|
|
/// Population dynamics
|
|
PopulationDynamics,
|
|
}
|
|
|
|
impl ScienceError {
|
|
/// Create a physics error with domain context
|
|
pub fn physics(message: impl Into<String>, domain: PhysicsDomain) -> Self {
|
|
Self::Physics {
|
|
message: message.into(),
|
|
domain,
|
|
}
|
|
}
|
|
|
|
/// Create a numerical error with method context
|
|
pub fn numerical(
|
|
message: impl Into<String>,
|
|
method: impl Into<String>,
|
|
convergence_info: Option<ConvergenceInfo>,
|
|
) -> Self {
|
|
Self::Numerical {
|
|
message: message.into(),
|
|
method: method.into(),
|
|
convergence_info,
|
|
}
|
|
}
|
|
|
|
/// Create a chemistry error with molecular context
|
|
#[cfg(feature = "chemistry")]
|
|
pub fn chemistry(message: impl Into<String>, molecule_context: Option<String>) -> Self {
|
|
Self::Chemistry {
|
|
message: message.into(),
|
|
molecule_context,
|
|
}
|
|
}
|
|
|
|
/// Create a biology error with biological context
|
|
#[cfg(feature = "biology")]
|
|
pub fn biology(message: impl Into<String>, bio_context: BiologyContext) -> Self {
|
|
Self::Biology {
|
|
message: message.into(),
|
|
bio_context,
|
|
}
|
|
}
|
|
|
|
/// Create a materials science error
|
|
#[cfg(feature = "materials")]
|
|
pub fn materials(message: impl Into<String>, material_system: Option<String>) -> Self {
|
|
Self::Materials {
|
|
message: message.into(),
|
|
material_system,
|
|
}
|
|
}
|
|
|
|
/// Create a data validation error
|
|
pub fn data_validation(
|
|
message: impl Into<String>,
|
|
field: impl Into<String>,
|
|
expected: impl Into<String>,
|
|
actual: impl Into<String>,
|
|
) -> Self {
|
|
Self::DataValidation {
|
|
message: message.into(),
|
|
field: field.into(),
|
|
expected: expected.into(),
|
|
actual: actual.into(),
|
|
}
|
|
}
|
|
|
|
/// Create a conservation law violation error
|
|
#[must_use]
|
|
pub fn conservation_violation(law: ConservationLaw, magnitude: f64, tolerance: f64) -> Self {
|
|
Self::ConservationViolation {
|
|
law,
|
|
magnitude,
|
|
tolerance,
|
|
}
|
|
}
|
|
|
|
/// Create a convergence failure error
|
|
pub fn convergence_failure(
|
|
algorithm: impl Into<String>,
|
|
iterations: usize,
|
|
final_residual: f64,
|
|
tolerance: f64,
|
|
) -> Self {
|
|
Self::ConvergenceFailure {
|
|
algorithm: algorithm.into(),
|
|
iterations,
|
|
final_residual,
|
|
tolerance,
|
|
}
|
|
}
|
|
|
|
/// Check if the error is recoverable
|
|
#[must_use]
|
|
pub fn is_recoverable(&self) -> bool {
|
|
match self {
|
|
Self::ConvergenceFailure { .. } => true,
|
|
Self::InvalidParameters { .. } => true,
|
|
Self::DataValidation { .. } => true,
|
|
Self::Numerical { .. } => true,
|
|
_ => false,
|
|
}
|
|
}
|
|
|
|
/// Create an I/O error with context
|
|
pub fn io_error(message: impl Into<String>, context: impl Into<String>) -> Self {
|
|
let msg = format!("{}: {}", message.into(), context.into());
|
|
Self::Io(std::io::Error::other(msg))
|
|
}
|
|
|
|
/// Get error severity level
|
|
#[must_use]
|
|
pub fn severity(&self) -> ErrorSeverity {
|
|
match self {
|
|
Self::ConservationViolation {
|
|
magnitude,
|
|
tolerance,
|
|
..
|
|
} => {
|
|
if magnitude / tolerance > 100.0 {
|
|
ErrorSeverity::Critical
|
|
} else if magnitude / tolerance > 10.0 {
|
|
ErrorSeverity::High
|
|
} else {
|
|
ErrorSeverity::Medium
|
|
}
|
|
}
|
|
Self::Physics { .. } => ErrorSeverity::High,
|
|
Self::ConvergenceFailure { .. } => ErrorSeverity::Medium,
|
|
Self::GpuComputation { .. } => ErrorSeverity::High,
|
|
Self::Tensor(_) | Self::Autograd(_) => ErrorSeverity::High,
|
|
_ => ErrorSeverity::Low,
|
|
}
|
|
}
|
|
|
|
/// Create a generic computation error
|
|
pub fn computation(message: impl Into<String>) -> Self {
|
|
Self::Numerical {
|
|
message: message.into(),
|
|
method: "general computation".to_string(),
|
|
convergence_info: None,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Error severity levels for logging and handling
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum ErrorSeverity {
|
|
/// Low severity - warnings, minor issues
|
|
Low,
|
|
/// Medium severity - computational issues, convergence problems
|
|
Medium,
|
|
/// High severity - physics violations, computation failures
|
|
High,
|
|
/// Critical severity - system failures, severe physics violations
|
|
Critical,
|
|
}
|
|
|
|
impl std::fmt::Display for PhysicsDomain {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let name = match self {
|
|
Self::FluidDynamics => "Fluid Dynamics",
|
|
Self::HeatTransfer => "Heat Transfer",
|
|
Self::Electromagnetics => "Electromagnetics",
|
|
Self::QuantumMechanics => "Quantum Mechanics",
|
|
Self::MolecularDynamics => "Molecular Dynamics",
|
|
Self::ContinuumMechanics => "Continuum Mechanics",
|
|
Self::StatisticalMechanics => "Statistical Mechanics",
|
|
Self::Thermodynamics => "Thermodynamics",
|
|
};
|
|
write!(f, "{name}")
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for ConservationLaw {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let name = match self {
|
|
Self::Mass => "Mass",
|
|
Self::Momentum => "Momentum",
|
|
Self::Energy => "Energy",
|
|
Self::AngularMomentum => "Angular Momentum",
|
|
Self::Charge => "Charge",
|
|
Self::Probability => "Probability",
|
|
};
|
|
write!(f, "{name}")
|
|
}
|
|
}
|
|
|
|
impl std::fmt::Display for BoundaryType {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let name = match self {
|
|
Self::Dirichlet => "Dirichlet",
|
|
Self::Neumann => "Neumann",
|
|
Self::Robin => "Robin",
|
|
Self::Periodic => "Periodic",
|
|
Self::NoSlip => "No-slip",
|
|
Self::FreeSlip => "Free-slip",
|
|
};
|
|
write!(f, "{name}")
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "biology")]
|
|
impl std::fmt::Display for BiologyContext {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
let name = match self {
|
|
Self::ProteinStructure => "Protein Structure",
|
|
Self::NucleicAcid => "Nucleic Acid",
|
|
Self::MetabolicPathway => "Metabolic Pathway",
|
|
Self::GeneExpression => "Gene Expression",
|
|
Self::CellSignaling => "Cell Signaling",
|
|
Self::PopulationDynamics => "Population Dynamics",
|
|
};
|
|
write!(f, "{name}")
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_error_creation() {
|
|
let err = ScienceError::physics("Test error", PhysicsDomain::FluidDynamics);
|
|
assert!(matches!(err, ScienceError::Physics { .. }));
|
|
}
|
|
|
|
#[test]
|
|
fn test_error_severity() {
|
|
let err = ScienceError::conservation_violation(ConservationLaw::Energy, 1e-2, 1e-6);
|
|
assert_eq!(err.severity(), ErrorSeverity::Critical);
|
|
}
|
|
|
|
#[test]
|
|
fn test_recoverable_errors() {
|
|
let err = ScienceError::convergence_failure("Newton", 100, 1e-3, 1e-6);
|
|
assert!(err.is_recoverable());
|
|
}
|
|
}
|