cmtool_core/model/
compartments.rs1use crate::{
4 model::{CMGeometry, interfaces::AInterfacesInfo},
5 utils::compute_volume,
6};
7
8#[derive(Clone, Copy)]
9pub struct ElementVolumeInfo {
10 pub global_id: usize,
11 pub volume: f64,
12}
13
14impl Default for ElementVolumeInfo {
15 fn default() -> Self {
16 ElementVolumeInfo {
17 global_id: 0,
18 volume: 0.,
19 }
20 }
21}
22
23pub struct CompartmentInfo {
24 pub n_volumes: Vec<usize>,
25 pub volumes: Vec<Vec<ElementVolumeInfo>>,
26}
27
28impl CompartmentInfo {
29 fn new(volume_per_compartment: Vec<usize>) -> Self {
31 let volumes: Vec<Vec<ElementVolumeInfo>> = volume_per_compartment
32 .iter()
33 .map(|n_volume| vec![ElementVolumeInfo::default(); *n_volume])
34 .collect();
35
36 Self {
37 n_volumes: volume_per_compartment,
38 volumes,
39 }
40 }
41
42 pub fn fill(&mut self, geometry: &CMGeometry) {
43 let mut local_vertices = Vec::new();
44
45 let mut tmp_count_k_element: Vec<usize> = vec![0; geometry.n_zone()];
46
47 for (volume_element_global_id, &n_compartment_in_velem) in
48 geometry.volume_elements.enumerate_number_id()
49 {
50 let (elem_type, n_vertex) = geometry
51 .volume_elements
52 .get_element_and_nvertex(volume_element_global_id);
53
54 local_vertices.clear();
55 local_vertices.resize(n_vertex, Default::default());
56 for i_compartment_in_velem in 0..n_compartment_in_velem {
57 let compartment_id = geometry
58 .volume_elements
59 .get_list_compartment_id(volume_element_global_id, i_compartment_in_velem);
60
61 let k_element = tmp_count_k_element[compartment_id];
62 tmp_count_k_element[compartment_id] += 1;
63
64 geometry.fill_vertices(volume_element_global_id, n_vertex, &mut local_vertices);
65 let volume = compute_volume(&local_vertices, elem_type).unwrap()
66 / (n_compartment_in_velem as f64);
67
68 assert!(volume >= 0., "CMTOOL(\"fill\"): Negative volume");
69 self.volumes[compartment_id][k_element] = ElementVolumeInfo {
70 global_id: volume_element_global_id,
71 volume,
72 };
73 }
74 }
75 }
76}
77
78pub struct CountVolumeElement {
79 pub per_compartment: Vec<usize>,
80 pub at_interface: Vec<usize>,
81}
82
83impl CountVolumeElement {
84 pub fn new(n_zone: usize) -> Self {
85 CountVolumeElement {
86 per_compartment: vec![0; n_zone],
87 at_interface: vec![0; n_zone * n_zone],
90 }
91 }
92
93 pub fn into_reduce(self) -> (CompartmentInfo, AInterfacesInfo) {
94 let at_interface: Vec<usize> = self.at_interface.into_iter().filter(|&v| v != 0).collect();
95
96 let per_compartment: Vec<usize> = self
97 .per_compartment
98 .into_iter()
99 .filter(|&v| v != 0)
100 .collect();
101
102 (
103 CompartmentInfo::new(per_compartment),
104 AInterfacesInfo::new(at_interface),
105 )
106 }
107
108 pub fn incr_compartment(&mut self, compartment_id: usize) {
109 self.per_compartment[compartment_id] += 1;
110 }
111 pub fn incr_interface(&mut self, compartment_id_0: usize, compartment_id_k: usize) {
112 self.at_interface[compartment_id_0 * self.per_compartment.len() + compartment_id_k] += 1;
113 }
114
115 pub fn n_interfaces(&self) -> usize {
116 self.at_interface.iter().filter(|&&v| v > 0).count()
117 }
118
119 pub fn n_zone_with_volume_element(&self) -> usize {
120 self.per_compartment.iter().filter(|v| **v != 0).count()
121 }
122}