//! Errors raised when an interface or a transfer cannot be formed. use thiserror::Error; /// Why a coupling operation was refused. #[derive(Debug, Clone, PartialEq, Error)] pub enum FsiError { /// One side of the interface was empty. #[error("empty interface: {side} has no entries")] EmptyInterface { /// Which side was empty. side: &'static str, }, /// Too few structure nodes to reproduce a face centroid exactly. /// /// Linear reproduction in three dimensions imposes four constraints, /// so at least four independent nodes are needed. Falling back to a /// weaker interpolation would conserve force and silently corrupt /// moment, which is worse than refusing. #[error("interface needs at least {needed} structure nodes for linear reproduction, got {got}")] InsufficientNodes { /// Nodes supplied. got: usize, /// Nodes required. needed: usize, }, /// A field had a different length from the mesh it belongs to. #[error("{field}: expected {expected} values, got {got}")] CountMismatch { /// Which field. field: &'static str, /// Length supplied. got: usize, /// Length required. expected: usize, }, /// A field value was NaN or infinite. #[error("non-finite value in {field} at index {index}")] NonFinite { /// Which field. field: &'static str, /// Where. index: usize, }, /// A parameter given to a coupling scheme was outside its valid /// range. #[error("invalid coupling parameter {parameter}: {value}")] InvalidParameter { /// Which parameter. parameter: &'static str, /// The value supplied. value: f64, }, /// The interface iteration ran away. /// /// In partitioned coupling this is almost always the added-mass /// effect: once the fluid's added mass exceeds the structural mass the /// fixed point becomes repulsive, and a fixed relaxation factor cannot /// recover it. Dynamic relaxation can. #[error("coupling diverged after {iterations} iterations (residual {residual})")] CouplingDiverged { /// Iterations completed before divergence was detected. iterations: usize, /// Residual at that point. residual: f64, }, /// The iteration budget ran out before the interface agreed. #[error( "coupling did not converge in {iterations} iterations (residual {residual}, tolerance {tolerance})" )] CouplingNotConverged { /// Iterations performed. iterations: usize, /// Residual reached. residual: f64, /// Tolerance required. tolerance: f64, }, /// The interpolation system was singular — the selected nodes are /// degenerate, for example all collinear. #[error("degenerate node neighbourhood for face {face}: cannot reproduce its centroid")] DegenerateNeighbourhood { /// Which face. face: usize, }, }