Skip to main content

cmtool_data/
lib.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3mod case;
4mod descriptors;
5mod flowmap;
6mod rawdata;
7mod states;
8#[cfg(test)]
9mod test_utils;
10mod transitioner;
11pub use case::{
12    CCMCaseInfo, CMCase, CMCaseJson, CMCaseReader, CMCaseWriter, DEFAULT_CASE_FILE_NAME, read_case,
13};
14use core::f64;
15pub use descriptors::{CMAExportType, CMExportType, PhaseCM};
16pub use flowmap::FlowMapDescriptor;
17pub use rawdata::{
18    FluxFileHeader, RawData, RawDataFlux, RawDataScalar, RawFlux, RawPhase, RawScalar,
19    ScalarFileHeader, ScalarValueType,
20};
21pub use states::*;
22use std::io;
23use thiserror::Error;
24pub use transitioner::*;
25
26/// Errors that can occur during data operations.
27///
28/// This enum encapsulates various error conditions that might arise during
29/// data reading, writing, and serialization operations.
30#[derive(Error, Debug)]
31pub enum DataError {
32    /// I/O error variant that occurs during file reading or writing operations.
33    ///
34    /// # Arguments
35    ///
36    /// * `source` - The underlying IO error that triggered this error.
37    #[error("I/O error occurred while handling the file: {0}")]
38    IO(#[from] io::Error),
39
40    /// Serialization or deserialization error variant.
41    ///
42    /// This error occurs when there is a failure during the serialization
43    /// or deserialization of data.
44    #[error("Serialization/Deserialization error occurred")]
45    Serde,
46
47    /// An unexpected or unknown error occurred during data operations.
48    ///
49    /// This variant serves as a catch-all for errors not explicitly covered
50    /// by other variants.
51    #[error("An unknown error occurred during data operation")]
52    Unknown,
53
54    #[error("Data is illed-format")]
55    BadData,
56
57    /// An index does not address any element of the accessed collection.
58    #[error("Index {index} is out of range, {size} element(s) available")]
59    OutOfRange { index: usize, size: usize },
60}
61
62#[inline(always)]
63#[allow(unused)]
64fn linear_index_row_major(_n_row: usize, n_col: usize, i: usize, j: usize) -> usize {
65    i * n_col + j
66}
67
68#[inline(always)]
69#[allow(unused)]
70fn linear_index_col_major(n_row: usize, _n_col: usize, i: usize, j: usize) -> usize {
71    j * n_row + i
72}
73
74///Create transitioner
75pub fn get_transitioner<T: FlowMapTransitioner>(root: &str) -> Result<T, DataError> {
76    let case_path = format!("{}/{}", root, DEFAULT_CASE_FILE_NAME);
77    let p = std::path::Path::new(&case_path);
78    let case = read_case(p)?;
79
80    //Load all the case information into the iterator
81    T::from_case(root, &case)
82}
83
84///Compute the smallest average residence time in compartment
85pub fn get_min_residence_time<T: FlowMapTransitioner>(fmt: &T) -> f64 {
86    let n_states = fmt.size();
87    let mut min_all = f64::MAX;
88
89    for i_state in 0..n_states {
90        let state = fmt
91            .get_at(i_state)
92            .expect("Transitioner error: n_state != real stored states");
93
94        if state.liquid.out_flows.len() != state.liquid.volumes.len() {
95            panic!("Mismatched lengths between out_flows and volumes.");
96        }
97
98        let min_i = state
99            .liquid
100            .out_flows
101            .iter()
102            .zip(state.liquid.volumes.iter())
103            .map(|(&f, &v)| f / v)
104            .filter(|&x| x.is_finite())
105            .min_by(|a, b| a.partial_cmp(b).unwrap_or(std::cmp::Ordering::Greater))
106            .expect("Should exist a minimum for the state");
107
108        min_all = f64::min(min_all, min_i);
109    }
110
111    min_all
112}