Skip to main content

cmtool_core/model/
data.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3use crate::{
4    coordinates::CartesianCoordinates,
5    ensight_gold::{
6        Part,
7        types::{ElementsType, VolumeElementTypes},
8    },
9};
10const C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM: usize = 20;
11
12#[derive(Default, Debug)]
13pub struct VolumeElementData {
14    global_id: Vec<Vec<usize>>,
15    // part_global_id: Vec<usize>,         // Part GID accessed via voGID
16    vtype: Vec<VolumeElementTypes>, // Volume element type accessed via voGID
17    ids: Vec<usize>,                // Volume element ID accessed via voGID
18    vertices: Vec<usize>,           // List of vertices attached to volume element
19    pub xyz: Vec<CartesianCoordinates>, // Coordinates of center of volume element
20    // raz: Vec<f64>,                // Additional coordinates or metadata
21
22    // cell_id: Vec<usize>,          // cID accessed via voGID
23    vertices_cell_id: Vec<usize>, // cID associated with each vertex of volume element
24    nc_id: Vec<usize>,            // Number of cID per volume element
25    compartment_ids: Vec<usize>,  // List of cID in which vertices are
26}
27
28impl VolumeElementData {
29    pub fn get_vertex_per_element(&self, global_id: usize) -> usize {
30        ElementsType::VolumeElementType(self.vtype[global_id])
31            .node_count()
32            .try_into()
33            .unwrap()
34    }
35
36    pub fn get_element_and_nvertex(&self, global_id: usize) -> (VolumeElementTypes, usize) {
37        let element = self.vtype[global_id];
38        (
39            element,
40            ElementsType::VolumeElementType(element)
41                .node_count()
42                .try_into()
43                .unwrap(),
44        )
45    }
46
47    pub fn set_number_cid(&mut self, global_id: usize, n_cid: usize) {
48        self.nc_id[global_id] = n_cid;
49    }
50    pub fn get_number_cid(&self, global_id: usize) -> usize {
51        self.nc_id[global_id]
52    }
53
54    pub fn enumerate_number_id(&self) -> std::iter::Enumerate<std::slice::Iter<'_, usize>> {
55        self.nc_id.iter().enumerate()
56    }
57
58    pub fn resize(&mut self, n_part: usize, n_velement: usize, velement_detail: &[usize]) {
59        self.global_id
60            .resize(n_part * VolumeElementTypes::NUMBER_OF_TYPES, Vec::new());
61
62        for (vec, &new_len) in self.global_id.iter_mut().zip(velement_detail.iter()) {
63            vec.resize(new_len, 0);
64        }
65        //Use with_capacity because volument_element
66        //doesn't provide default value.
67        self.vtype = Vec::with_capacity(n_velement);
68        self.ids.resize(n_velement, 0);
69        self.nc_id.resize(n_velement, 0);
70        self.vertices
71            .resize(n_velement * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM, 0);
72        self.compartment_ids
73            .resize(n_velement * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM, 0);
74        self.xyz.resize(n_velement, Default::default());
75        // self.raz.resize(n_velement * 3, 0.);
76        self.vertices_cell_id
77            .resize(n_velement * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM, 0);
78    }
79
80    pub fn n_element(&self) -> usize {
81        self.ids.len()
82    }
83
84    pub fn set_list_compartment_id(&mut self, global_id: usize, k_vertex: usize, val: usize) {
85        self.compartment_ids[global_id * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM + k_vertex] = val;
86    }
87
88    pub fn get_list_compartment_id(&self, global_id: usize, k_vertex: usize) -> usize {
89        self.compartment_ids[global_id * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM + k_vertex]
90    }
91
92    pub fn set_global_id(
93        &mut self,
94        i_part: usize,
95        element_index: usize,
96        volume_element_id: usize,
97        val: usize,
98    ) {
99        self.global_id[VolumeElementTypes::NUMBER_OF_TYPES * i_part + element_index]
100            [volume_element_id] = val;
101    }
102
103    pub fn get_global_id(
104        &self,
105        i_part: usize,
106        element_index: usize,
107        volume_element_id: usize,
108    ) -> usize {
109        self.global_id[VolumeElementTypes::NUMBER_OF_TYPES * i_part + element_index]
110            [volume_element_id]
111    }
112
113    pub fn get_vertex_from_vol_global_id(
114        &self,
115        vol_element_global_id: usize,
116        k_vertex: usize,
117    ) -> usize {
118        self.vertices[vol_element_global_id * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM + k_vertex]
119    }
120
121    fn set_vertex_from_vol_global_id(
122        &mut self,
123        vol_element_global_id: usize,
124        k_vertex: usize,
125        val: usize,
126    ) {
127        self.vertices[vol_element_global_id * C_MAX_NUMBER_VERTEX_PER_VOLUME_ELEM + k_vertex] = val;
128    }
129
130    pub fn fill_from_part(
131        &mut self,
132        global_volume_element_counter: usize,
133        part_it: (usize, &Part),
134        velem_detail: &[usize],
135        vertices: &VerticesData,
136    ) -> usize {
137        const N_NUMBER_TYPE: usize = VolumeElementTypes::NUMBER_OF_TYPES;
138        let (i_part, part) = part_it;
139
140        //local_vec_counter is the sum of n_element for eaach element in part.
141        //Actually can be computed with the iter below
142        // let result :usize= part.elements.iter()
143        // .filter(|e| matches!(e.etype, ElementsType::VolumeElementType(_)))
144        // .map(|vol_element| vol_element.n_elements).sum();
145
146        //But as we perform different operation during the loop it's better to just iterate once.
147
148        //Vec counter logic is not the same as vertice becuase we can't predict the number of itertion
149        // inner loop bound si not trividl
150        //To return number of volument_element
151        //Start from count=n, during loop , count +=m, so return count-n
152        let mut local_vec_counter = global_volume_element_counter;
153
154        //mutable state, loop counters, nested loops, and side-effecting methods (self.set_*)
155        //the for loop + if let version is better than filter().for_each
156
157        let i_part_base_index = i_part * N_NUMBER_TYPE;
158
159        for element in part.elements.iter() {
160            if let ElementsType::VolumeElementType(vol_elem) = element.etype {
161                let n_vertex = element.etype.node_count() as usize;
162                let element_index = vol_elem.to_index();
163                let n_volume_element = velem_detail[i_part_base_index + element_index];
164
165                let current_vertex_in_part = vertices.get_current_vertex_from_part(i_part);
166
167                for ve_id in 0..n_volume_element {
168                    let ve_global_id = local_vec_counter;
169
170                    local_vec_counter += 1;
171
172                    self.set_global_id(i_part, element_index, ve_id, ve_global_id);
173
174                    self.vtype.push(vol_elem);
175                    self.ids[ve_global_id] = ve_id;
176
177                    for k_vertex in 0..n_vertex {
178                        let vtx = element.get_vertex(ve_id, k_vertex);
179                        self.set_vertex_from_vol_global_id(
180                            ve_global_id,
181                            k_vertex,
182                            current_vertex_in_part[vtx - 1],
183                        );
184                    }
185                }
186            }
187        }
188
189        local_vec_counter - global_volume_element_counter
190    }
191}
192
193//TODO: Remove this and merge with volume ?
194#[derive(Default)]
195pub struct VerticesData {
196    //Actually only used to construct volume data
197    //TODO: Make this temp varialbe ?
198    ve_gid: Vec<Vec<usize>>, // Access to veGID by part and vertex
199
200    // part_id: Vec<usize>,     // Access to vertex partID from veGID
201    // ve_id: Vec<usize>,   // Access to vertex veID from veGID
202    xyz: Vec<f64>, // Vertices coordinates
203                   // vertex_c_id: Vec<usize>, // Access to vertex cID from veGID
204}
205
206impl VerticesData {
207    pub fn fill_from_part(
208        &mut self,
209        vertex_counter: usize,
210        vertex_detail: &[usize],
211        part_it: (usize, &Part),
212    ) -> usize {
213        let (i_part, part) = part_it;
214
215        let mut vertex_global_identifier = vertex_counter;
216        #[allow(clippy::explicit_counter_loop)]
217        for ve_id in 0..vertex_detail[i_part] {
218            self.ve_gid[i_part][ve_id] = vertex_global_identifier;
219            let offset = vertex_global_identifier * 3;
220            self.xyz[offset..offset + 3].copy_from_slice(part.get_vertex_coordinates_slice(ve_id));
221            vertex_global_identifier += 1;
222        }
223        vertex_detail[i_part]
224    }
225    pub fn resize(&mut self, n_vertices: usize, vertex_detail: &[usize]) {
226        self.ve_gid = vertex_detail
227            .iter()
228            .map(|n_vertex_p_part| vec![0; *n_vertex_p_part])
229            .collect();
230
231        // self.part_id.resize(n_vertices, 0);
232        // self.ve_id.resize(n_vertices, 0);
233
234        self.xyz.resize(n_vertices * 3, 0.);
235        // self.vertex_c_id.resize(n_vertices, 0);
236    }
237
238    pub fn n_vertex(&self) -> usize {
239        self.xyz.len() / 3
240    }
241
242    fn get_current_vertex_from_part(&self, part_id: usize) -> &[usize] {
243        &self.ve_gid[part_id]
244    }
245
246    pub fn get_slice_xyz(&self, global_id: usize) -> &[f64; 3] {
247        let offset = global_id * 3;
248        self.xyz[offset..offset + 3]
249            .try_into()
250            .expect("Slice with exactly 3 elements")
251    }
252    pub fn get_radius_from_global_id(&self, vertex_global_id: usize) -> f64 {
253        let offset = vertex_global_id * 3;
254        self.xyz[offset].hypot(self.xyz[offset + 1])
255    }
256}