cellular_raza_core/backend/cpu_os_threads/
errors.rs

1use crate::storage::StorageError;
2use cellular_raza_concepts::*;
3use core::any::type_name;
4use core::fmt::{Debug, Display};
5
6use std::error::Error; // TODO in the future use core::error::Error (unstable right now)
7
8use crossbeam_channel::{RecvError, SendError};
9
10macro_rules! impl_error_variant {
11    ($name: ident, $($err_var: ident),+) => {
12        // Implement Display for ErrorVariant
13        impl Display for $name {
14            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
15                match self {
16                    $(
17                        $name::$err_var(message) => write!(f, "{}", message),
18                    )+
19                }
20            }
21        }
22    }
23}
24
25macro_rules! impl_from_error {
26    ($name: ident, $(($err_var: ident, $err_type: ty)),+) => {
27        $(
28            // Implement conversion from error to errorvariant
29            impl From<$err_type> for $name {
30                fn from(err: $err_type) -> Self {
31                    $name::$err_var(err)
32                }
33            }
34        )+
35    }
36}
37
38/// Covers all errors that can occur in this Simulation
39///
40/// This main error type should be derivable from errors arising during the simulation process.
41/// It is required for custom error types `MyCustomError` of the engine to implement the
42/// `From<MyCustomError> for SimulationError`.
43///
44/// Errors are separated by their ability to be recovered, ignored or handled otherwise.
45/// Since this crate aims to provide an adaptive solving approach, it is desired to have a fallback
46/// mechanism which can be called for errors which may arise due to precision problems.
47#[derive(Debug)]
48pub enum SimulationError {
49    // Very likely to be user errors
50    /// Occurs during calculations of any mathematical update steps such as
51    /// [Interaction](cellular_raza_concepts::Interaction) between cells.
52    CalcError(CalcError),
53    /// Related to time-stepping events. See [crate::time].
54    TimeError(TimeError),
55    /// Error-type specifically related to the
56    /// [Controller](cellular_raza_concepts::domain_old::Controller) trait.
57    ControllerError(ControllerError),
58    /// An error specific to cell-division events by the
59    ///
60    /// [Cycle](cellular_raza_concepts::Cycle) trait.
61    DivisionError(DivisionError),
62    /// Related to the [PhasedDeath](cellular_raza_concepts::CycleEvent::PhasedDeath) event.
63    /// This error can only occur during the
64    /// [update_conditional_phased_death](cellular_raza_concepts::Cycle::update_conditional_phased_death)
65    /// method.
66    DeathError(DeathError),
67    /// Enforcing boundary conditions on cells can exhibhit this boundary error.
68    BoundaryError(BoundaryError),
69    /// Plotting results. See also [cellular_raza_concepts::PlotSelf] and [cellular_raza_concepts::CreatePlottingRoot].
70    DrawingError(DrawingError),
71    /// Mostly caused by trying to find a voxel by its index.
72    /// This error can also occur when applying too large simulation-steps.
73    IndexError(IndexError),
74
75    // Less likely but possible to be user errors
76    /// Sending information between threads fails
77    SendError(String),
78    /// Receiving information from another thread fails
79    ReceiveError(RecvError),
80    /// Storing results fails
81    StorageError(StorageError),
82
83    // Highly unlikely to be user errors
84    /// When writing to output files or reading from them.
85    /// See [std::io::Error]
86    IoError(std::io::Error),
87    /// Occurs when requested data could not be returned
88    RequestError(RequestError),
89    /// Errors related to [rand] and its functionalities
90    RngError(RngError),
91
92    // Highly unlikely to be user errors
93    /// Errors surrounding construction of [rayon::ThreadPool].
94    ThreadingError(rayon::ThreadPoolBuildError),
95}
96
97impl_from_error! {SimulationError,
98    (ReceiveError, RecvError),
99    (CalcError, CalcError),
100    (ControllerError, ControllerError),
101    (RequestError, RequestError),
102    (TimeError, TimeError),
103    (DivisionError, DivisionError),
104    (DeathError, DeathError),
105    (BoundaryError, BoundaryError),
106    (IndexError, IndexError),
107    (IoError, std::io::Error),
108    (DrawingError, DrawingError),
109    (RngError, RngError),
110    (StorageError, StorageError),
111    (ThreadingError, rayon::ThreadPoolBuildError)
112}
113
114impl_error_variant! {SimulationError,
115    SendError,
116    ReceiveError,
117    RequestError,
118    CalcError,
119    ControllerError,
120    TimeError,
121    DivisionError,
122    DeathError,
123    BoundaryError,
124    IndexError,
125    IoError,
126    DrawingError,
127    RngError,
128    StorageError,
129    ThreadingError
130}
131
132// Implement the general error property
133impl std::error::Error for SimulationError {}
134
135// Implement conversion from Sending error manually
136impl<T> From<SendError<T>> for SimulationError {
137    fn from(_err: SendError<T>) -> Self {
138        SimulationError::SendError(format!(
139            "Error receiving object of type {}",
140            type_name::<SendError<T>>()
141        ))
142    }
143}
144
145impl<E> From<plotters::drawing::DrawingAreaErrorKind<E>> for SimulationError
146where
147    E: Error + Send + Sync,
148{
149    fn from(drawing_error: plotters::drawing::DrawingAreaErrorKind<E>) -> SimulationError {
150        SimulationError::DrawingError(DrawingError::from(drawing_error))
151    }
152}