Skip to main content

cmtool_core/model/
vectors.rs

1// SPDX-License-Identifier: GPL-3.0-or-later
2
3use crate::{
4    CoreError,
5    ensight_gold::{self, types::ElementsType},
6    model::{CMGeometry, Scalar},
7};
8
9pub struct Vector {
10    value_in_vo: Vec<cmtool_data::ScalarValueType>,
11}
12
13impl Vector {
14    pub fn get_slice_xyz(&self, global_id: usize) -> &[f64; 3] {
15        let offset = global_id * 3;
16        self.value_in_vo[offset..offset + 3]
17            .try_into()
18            .expect("Slice with exactly 3 elements")
19    }
20
21    pub fn scale_by(self, a: Scalar) -> Result<Self, CoreError> {
22        // if self.value_in_vo.len() != a.value_in_vo.len() {
23        //     return Err(CoreError::Custom(format!(
24        //         "Bad size for vector scaling {} vs {} ",
25        //         self.value_in_vo.len(),
26        //         a.value_in_vo.len()
27        //     )));
28        // }
29
30        let values: Vec<cmtool_data::ScalarValueType> = self
31            .value_in_vo
32            .chunks(3)
33            .zip(&a.value_in_vo)
34            .flat_map(|(triplet, &s)| triplet.iter().map(move |&v| v * s))
35            .collect();
36        Ok(Self {
37            value_in_vo: values,
38        })
39    }
40
41    pub(crate) fn from_scalar(
42        scalars: [ensight_gold::scalar::ScalarField; 3],
43        geometry: &CMGeometry,
44        eg_geometry: &ensight_gold::Geometry,
45    ) -> Result<Self, CoreError> {
46        let functor = |i_part, i_e, volume_element_id| {
47            [
48                scalars[0].get_value(i_part, i_e, volume_element_id) as f64,
49                scalars[1].get_value(i_part, i_e, volume_element_id) as f64,
50                scalars[2].get_value(i_part, i_e, volume_element_id) as f64,
51            ]
52        };
53        Ok(Self::from_xyz(geometry, eg_geometry, functor))
54    }
55
56    fn from_xyz(
57        geometry: &CMGeometry,
58        eg_geometry: &ensight_gold::Geometry,
59        f: impl Fn(usize, usize, usize) -> [cmtool_data::ScalarValueType; 3],
60    ) -> Self {
61        let mut value_in_vo: Vec<cmtool_data::ScalarValueType> =
62            vec![0.; 3 * geometry.volume_elements.n_element()];
63        for (i_part, part) in eg_geometry.parts.iter().enumerate() {
64            for (i_e, element) in part.elements.iter().enumerate() {
65                if let ElementsType::VolumeElementType(vetype) = element.etype {
66                    let element_index = vetype.to_index();
67
68                    for volume_element_id in 0..element.n_elements {
69                        let volume_element_global_id = geometry.volume_elements.get_global_id(
70                            i_part,
71                            element_index,
72                            volume_element_id,
73                        );
74                        let offset = 3 * volume_element_global_id;
75                        value_in_vo[offset..offset + 3].copy_from_slice(&f(
76                            i_part,
77                            i_e,
78                            volume_element_id,
79                        ));
80                    }
81                }
82            }
83        }
84
85        Self { value_in_vo }
86    }
87
88    ////
89
90    pub(crate) fn new(
91        eg_vector: ensight_gold::vectors::VectorField,
92        geometry: &CMGeometry,
93        eg_geometry: &ensight_gold::Geometry,
94    ) -> Self {
95        let functor =
96            |i_part, i_e, volume_element_id| eg_vector.get_xyz(i_part, i_e, volume_element_id);
97        Self::from_xyz(geometry, eg_geometry, functor)
98    }
99}
100
101//impl Index<usize> for Vector {
102//type Output = cmtool_data::ScalarValueType;
103//
104//fn index(&self, index: usize) -> &Self::Output {
105//#[cfg(debug_assertions)]
106//{
107//// Debug mode: safe indexing with bounds check
108//&self.value_in_vo[index]
109//}
110//
111//#[cfg(not(debug_assertions))]
112//unsafe {
113//// Release mode: unchecked access (unsafe but fast)
114//self.value_in_vo.get_unchecked(index)
115//}
116//}
117//}
118
119// impl IndexMut<usize> for Scalar {
120//     fn index_mut(&mut self, index: usize) -> &mut Self::Output {
121//         let (part, mesh_element_type, mesh_cell) = index;
122//         let flat_index = part * (self.mesh_element_types * self.mesh_cells)
123//             + mesh_element_type * self.mesh_cells
124//             + mesh_cell;
125//         &mut self.data[flat_index]
126//     }
127// }