bcore/
api.rs

1use crate::datamodel::{Weight,tallies::Tallies};
2
3use crate::error::ApiError;
4use ndarray::{Array1, Array2, ArrayView2, ArrayView3};
5
6/// `Phase` enum represents different states or phases of a substance.
7#[derive(Clone, PartialEq, Copy)]
8pub enum Phase {
9    Liquid,
10    Gas,
11}
12
13/// Type of estimator to retrieve data from MC Particle
14#[derive(Copy, Clone)]
15pub enum Estimator {
16    MonteCarlo,
17    Weighted,
18}
19
20/// A trait for postprocessing operations on simulation results.
21///
22/// This trait defines various methods for analyzing and retrieving data from simulation results.
23pub trait PostProcessReader {
24    /// Returns a reference to the time data from the simulation results.
25    ///
26    /// # Returns
27    /// * `&[f64]` - A slice containing the time data.
28    fn time(&self) -> &[f64];
29
30    fn v_liquid(&self) -> ArrayView2<'_, f64>;
31
32    /// Returns a weight chosen for simulation 
33    ///
34    /// # Returns
35    /// * `Weight object: Can contain either float (unique weight) or vector of weight (non implemented yet)
36    fn weight(&self) -> &Weight;
37
38    // Returns tallies if exported during simulation 
39    ///
40    /// # Returns
41    /// * `Option<&Tallies>: Some if tallies exported 
42    fn tallies(&self) -> Option<&Tallies>;
43
44    /// Returns a 1D array view of the time data from the simulation results.
45    ///
46    /// # Returns
47    /// * `ArrayView1<f64>` - A 1D array view containing the time data.
48    fn time_array(&self) -> Array1<f64>;
49
50    /// Retrieves the maximum number of biological export events.
51    ///
52    /// This method determines the maximum number of export events specifically related
53    /// to biological data dumps.
54    ///
55    /// # Returns
56    /// * `usize` - The number of biological export events, or `0` if no events are found.
57    fn get_max_n_export_bio(&self) -> usize;
58
59    /// Retrieves the total number of export events from the simulation results.
60    ///
61    /// This count includes all types of export actions.
62    ///
63    /// # Returns
64    /// * `usize` - The total number of export events.
65    fn n_export(&self) -> usize;
66    
67    /// Returns model's property names  
68    ///
69    /// # Returns
70    /// * `Vec<String>: Names, empty if no exported names  
71    fn get_property_names(&self) -> Vec<String>;
72
73    /// Computes the spatial average concentration for a specific species and phase.
74    ///
75    /// # Arguments
76    /// * `species` - The index of the species for which to calculate the average.
77    /// * `phase` - The phase (e.g., liquid or gas) to consider.
78    ///
79    /// # Returns
80    /// * `Array1<f64>` - A 1D array containing the spatial average concentrations over time.
81    fn get_spatial_average_concentration(&self, species: usize, phase: Phase) -> Array1<f64>;
82
83    fn get_spatial_average_property(&self, key:&str) ->  Result<Array2<f64>, ApiError>;
84
85    fn get_spatial_average_biomass_concentration(&self) -> Result<Array1<f64>, ApiError>;
86
87    fn get_concentrations(&self, phase: Phase) -> ArrayView3<f64>;
88
89    fn get_spatial_average_mtr(&self, species: usize) -> Result<Array1<f64>, ApiError>;
90
91    fn get_variance_concentration(&self,species:usize,phase:Phase)-> Result<Array1<f64>, ApiError>;
92
93    
94    
95
96    /// Computes the time average concentration for a specific species, position, and phase.
97    ///
98    /// # Arguments
99    /// * `species` - The index of the species for which to calculate the average.
100    /// * `position` - The position in the simulation domain to consider.
101    /// * `phase` - The phase (e.g., liquid or gas) to consider.
102    ///
103    /// # Returns
104    /// * `Result<Array1<f64>, String>` - A 1D array containing the time average concentrations,
105    ///   or an error message if the calculation fails.
106    fn get_time_average_concentration(
107        &self,
108        species: usize,
109        position: usize,
110        phase: Phase,
111    ) -> Result<Array1<f64>, ApiError>;
112
113    /// Calculates the biomass concentration over time.
114    ///
115    /// # Returns
116    /// * `Result<Array2<f64>, String>` - A 2D array containing biomass concentrations over time,
117    ///   or an error message if the calculation fails.
118    fn get_biomass_concentration(&self) -> Result<Array2<f64>, ApiError>;
119
120    fn get_probes(&self) -> Result<Array1<f64>, ApiError>;
121    
122
123    /// Calculates the total growth in number.
124    ///
125    /// # Returns
126    /// * `Array1<f64>` - A 1D array containing the summed growth numbers over time.
127    fn get_growth_in_number(&self) -> Array1<f64>;
128
129    /// Retrieves a reference to the 2D array of particle numbers.
130    ///
131    /// # Returns
132    /// * `&Array2<f64>` - A reference to the 2D array of particle numbers.
133    fn get_number_particle(&self) -> &Array2<f64>;
134
135    /// Fetches specific properties of the model at a given export index.
136    ///
137    /// # Arguments
138    /// * `key` - The key identifying the property to retrieve.
139    /// * `i_export` - The export index for which to retrieve the property.
140    ///
141    /// # Returns
142    /// * `Result<Array1<f64>, String>` - A 1D array of property values,
143    ///   or an error message if the retrieval fails.
144    fn get_properties(&self, key: &str, i_export: usize) -> Result<Array1<f64>, ApiError>;
145
146    /// Calculates the time-averaged population mean for a specific property key.
147    ///
148    /// # Arguments
149    /// * `key` - The key identifying the property to average.
150    ///
151    /// # Returns
152    /// * `Result<Array1<f64>, String>` - A 1D array of mean values over time,
153    ///   or an error message if the calculation fails.
154    fn get_time_population_mean(&self, key: &str) -> Result<Array1<f64>, ApiError>;
155
156    /// Retrieves histogram data for a specific property key at a given export index.
157    ///
158    /// # Arguments
159    /// * `n_bins` - The number of bins to use in the histogram.
160    /// * `i_export` - The export index for which to retrieve the histogram.
161    /// * `key` - The key identifying the property to calculate the histogram for.
162    ///
163    /// # Returns
164    /// * `Result<(Array1<f64>, Array1<f64>), String>` - The histogram bins and counts,
165    ///   or an error message if the calculation fails.
166    fn get_histogram_array(
167        &self,
168        n_bins: usize,
169        i_export: usize,
170        key: &str,
171    ) -> Result<(Array1<f64>, Array1<f64>), ApiError>;
172
173    /// Retrieves histogram data for a specific property key at a given export index.
174    ///
175    /// # Arguments
176    /// * `n_bins` - The number of bins to use in the histogram.
177    /// * `i_export` - The export index for which to retrieve the histogram.
178    /// * `key` - The key identifying the property to calculate the histogram for.
179    ///
180    /// # Returns
181    /// * `Result<(Vec<f64>, Vec<f64>), String>` - The histogram bins and counts as vectors,
182    ///   or an error message if the calculation fails.
183    fn get_histogram(
184        &self,
185        n_bins: usize,
186        i_export: usize,
187        key: &str,
188    ) -> Result<(Vec<f64>, Vec<f64>), ApiError>;
189
190    /// Retrieves the population mean for a specific property key at a given export index.
191    ///
192    /// # Arguments
193    /// * `key` - The key identifying the property to calculate the mean for.
194    /// * `i_export` - The export index for which to calculate the mean.
195    ///
196    /// # Returns
197    /// * `Result<f64, String>` - The population mean, or an error message if the calculation fails.
198    fn get_population_mean(&self, key: &str, i_export: usize) -> Result<f64, ApiError>;
199}
200
201pub trait ModelEstimator {
202    fn mu_direct(&self) -> Result<Array1<f64>, ApiError>;
203
204    fn estimate(&self, etype: Estimator, key: &str, i_export: usize) -> Result<f64, ApiError>;
205
206    fn estimate_time(&self, etype: Estimator, key: &str) -> Result<Array1<f64>, ApiError>;
207}
208
209#[cfg(test)]
210mod tests {
211    use super::*;
212    use ndarray::Array1;
213
214    #[test]
215    fn test_monte_carlo_estimate() {
216        let rx = Array1::from(vec![2.0, 4.0, 6.0]);
217        let weight = 2.0;
218
219        let result =
220            crate::process::estimate(Estimator::MonteCarlo, &Weight::Single(weight), &rx).unwrap();
221        let dim = rx.dim();
222        let weighted_estimator: f64 = (rx * weight).sum(); // (2.0*2.0 + 4.0*2.0 + 6.0*2.0) = 24.0
223        let normalization_factor = (0..dim).map(|_| weight).sum::<f64>(); // 2.0 * 3 = 6.0
224        let expected_result = weighted_estimator / normalization_factor; // 24.0 / 6.0 = 4.0
225        assert_eq!(result, expected_result);
226    }
227
228    #[test]
229    fn test_weighted_estimate() {
230        let rx = Array1::from(vec![2.0, 4.0, 6.0]);
231        let weight = 2.0;
232
233        let result =
234            crate::process::estimate(Estimator::Weighted, &Weight::Single(weight), &rx).unwrap();
235
236        let weighted_estimator: f64 = (rx * weight).sum(); // (2.0*2.0 + 4.0*2.0 + 6.0*2.0) = 24.0
237        let expected_result = weighted_estimator; // Since it's weighted, it should return the weighted sum.
238        assert_eq!(result, expected_result);
239    }
240
241    #[test]
242    fn test_zero_weight() {
243        let rx = Array1::from(vec![2.0, 4.0, 6.0]);
244        let weight = 0.0;
245
246        let result =
247            crate::process::estimate(Estimator::MonteCarlo, &Weight::Single(weight), &rx).unwrap();
248        assert_eq!(result, 0.0);
249    }
250
251    #[test]
252    fn test_empty_array() {
253        let rx = Array1::from(vec![]);
254        let weight = 2.0;
255        let result =
256            crate::process::estimate(Estimator::Weighted, &Weight::Single(weight), &rx).unwrap();
257
258        // With an empty array, the result should be zero
259        assert_eq!(result, 0.0);
260    }
261}