gizmo_physics_soft/error.rs
1//! Concrete error type for fallible soft-body operations.
2//!
3//! This replaces the previous "swallow + log", `Option`, and silent-clamp
4//! failure surfaces with an explicit, matchable [`SoftBodyError`]. The success
5//! path of every converted function is unchanged; only the failure surface is
6//! now a `Result`.
7
8/// Errors produced by fallible soft-body construction and simulation operations.
9#[derive(Debug, Clone, PartialEq)]
10#[non_exhaustive]
11pub enum SoftBodyError {
12 /// A tetrahedral element referenced a node index that does not exist yet.
13 ///
14 /// `index` is the offending node index and `node_count` is the number of
15 /// nodes currently present in the mesh.
16 NodeIndexOutOfBounds { index: u32, node_count: u32 },
17
18 /// Poisson's ratio was outside the physically valid range `[0.0, 0.5)`.
19 ///
20 /// Values `>= 0.5` produce a singular / negative Lamé `lambda`
21 /// (incompressible limit) and values `< 0.0` are unsupported here.
22 InvalidPoissonsRatio { value: f32 },
23
24 /// Young's modulus was not a finite, strictly-positive value.
25 InvalidYoungsModulus { value: f32 },
26
27 /// A tetrahedral element was (near-)degenerate: its rest volume is not a
28 /// finite, strictly-positive value above the acceptance epsilon.
29 ///
30 /// Such elements have a singular reference shape matrix (`Dm`), so the
31 /// deformation gradient and the derived elastic forces are undefined
32 /// (near-zero stiffness / NaN propagation). `volume` is the offending rest
33 /// volume that was computed.
34 DegenerateTetrahedron { volume: f32 },
35
36 /// The flattened GPU node offset overflowed `u32` (too many nodes across
37 /// all soft bodies in a single step).
38 NodeOffsetOverflow,
39
40 /// No compatible GPU adapter could be acquired.
41 NoCompatibleAdapter,
42
43 /// Requesting a logical GPU device from the adapter failed.
44 DeviceRequestFailed(String),
45}
46
47impl std::fmt::Display for SoftBodyError {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 match self {
50 SoftBodyError::NodeIndexOutOfBounds { index, node_count } => write!(
51 f,
52 "soft body node index {index} out of bounds (node count {node_count})"
53 ),
54 SoftBodyError::InvalidPoissonsRatio { value } => write!(
55 f,
56 "invalid Poisson's ratio {value} (must be in [0.0, 0.5))"
57 ),
58 SoftBodyError::InvalidYoungsModulus { value } => write!(
59 f,
60 "invalid Young's modulus {value} (must be finite and > 0)"
61 ),
62 SoftBodyError::DegenerateTetrahedron { volume } => write!(
63 f,
64 "degenerate tetrahedral element (rest volume {volume} must be finite and > 0)"
65 ),
66 SoftBodyError::NodeOffsetOverflow => {
67 write!(f, "soft body node offset overflowed u32 (too many nodes)")
68 }
69 SoftBodyError::NoCompatibleAdapter => {
70 write!(f, "no compatible GPU adapter available for soft-body compute")
71 }
72 SoftBodyError::DeviceRequestFailed(msg) => {
73 write!(f, "failed to request GPU device for soft-body compute: {msg}")
74 }
75 }
76 }
77}
78
79impl std::error::Error for SoftBodyError {}