Skip to main content

conspire/geometry/mesh/connectivity/base/
mod.rs

1use crate::geometry::mesh::connectivity::{Connectivities, Connectivity, iter::ElementIter};
2use std::{fmt::Debug, num::TryFromIntError};
3
4pub trait ConnectivityImpl {
5    fn is_empty(&self) -> bool;
6    fn element_numbers(&self) -> Option<&[usize]>;
7    fn node_element_connectivity(&self) -> &[Vec<usize>];
8    fn number_elements(&mut self, numbers: Vec<usize>);
9    fn number_of_elements(&self) -> usize;
10    fn number_of_faces(&self) -> Option<usize>;
11    fn number_of_faces_per_element<I>(&self) -> Option<Vec<I>>
12    where
13        I: Debug + TryFrom<usize, Error = TryFromIntError>;
14    fn number_of_nodes_per_element(&self) -> Option<usize>;
15    fn number_of_nodes_per_face<I>(&self) -> Option<Vec<I>>
16    where
17        I: Debug + TryFrom<usize, Error = TryFromIntError>;
18    #[cfg(feature = "netcdf")]
19    fn exodus_element_type(&self) -> &str;
20    #[cfg(feature = "netcdf")]
21    fn flat_connectivity<I>(&self) -> FlatConnectivity<I>
22    where
23        I: Debug + TryFrom<usize, Error = TryFromIntError>;
24}
25
26#[cfg(feature = "netcdf")]
27pub enum FlatConnectivity<I> {
28    Primitive(Vec<I>),
29    Polytopal(Vec<I>, Vec<I>),
30}
31
32impl Connectivity {
33    pub fn local_faces(&self) -> &'static [&'static [usize]] {
34        match self {
35            Connectivity::Hexahedral(_) => &[
36                &[0, 1, 5, 4],
37                &[1, 2, 6, 5],
38                &[2, 3, 7, 6],
39                &[3, 0, 4, 7],
40                &[0, 3, 2, 1],
41                &[4, 5, 6, 7],
42            ],
43            Connectivity::Tetrahedral(_) => &[&[0, 1, 3], &[1, 2, 3], &[2, 0, 3], &[0, 2, 1]],
44            Connectivity::Pyramidal(_) => &[
45                &[0, 1, 4],
46                &[1, 2, 4],
47                &[2, 3, 4],
48                &[3, 0, 4],
49                &[0, 3, 2, 1],
50            ],
51            Connectivity::Wedge(_) => &[
52                &[0, 1, 4, 3],
53                &[1, 2, 5, 4],
54                &[2, 0, 3, 5],
55                &[0, 2, 1],
56                &[3, 4, 5],
57            ],
58            Connectivity::Quadrilateral(_) => &[&[0, 1], &[1, 2], &[2, 3], &[3, 0]],
59            Connectivity::Triangular(_) => &[&[0, 1], &[1, 2], &[2, 0]],
60            Connectivity::Polygonal(_) | Connectivity::Polyhedral(_) => todo!(),
61        }
62    }
63    pub fn abaqus_side(&self, ordinal: usize) -> usize {
64        match self {
65            Connectivity::Hexahedral(_) => [3, 4, 5, 6, 1, 2][ordinal],
66            Connectivity::Tetrahedral(_) => [2, 3, 4, 1][ordinal],
67            Connectivity::Pyramidal(_) => [2, 3, 4, 5, 1][ordinal],
68            Connectivity::Wedge(_) => [3, 4, 5, 1, 2][ordinal],
69            Connectivity::Quadrilateral(_) => [1, 2, 3, 4][ordinal],
70            Connectivity::Triangular(_) => [1, 2, 3][ordinal],
71            Connectivity::Polygonal(_) | Connectivity::Polyhedral(_) => todo!(),
72        }
73    }
74    pub fn local_face_from_abaqus_side(&self, side: usize) -> usize {
75        (0..self.local_faces().len())
76            .find(|&ordinal| self.abaqus_side(ordinal) == side)
77            .expect("invalid Abaqus side label for this element type")
78    }
79    pub fn add_edge_adjacency(&self, nodes_nodes: &mut [Vec<usize>]) {
80        match self {
81            Connectivity::Triangular(c) => c.add_edge_adjacency_triangular(nodes_nodes),
82            Connectivity::Quadrilateral(c) => c.add_edge_adjacency(nodes_nodes),
83            Connectivity::Tetrahedral(c) => c.add_edge_adjacency(nodes_nodes),
84            Connectivity::Hexahedral(c) => c.add_edge_adjacency(nodes_nodes),
85            Connectivity::Pyramidal(c) => c.add_edge_adjacency(nodes_nodes),
86            Connectivity::Wedge(c) => c.add_edge_adjacency(nodes_nodes),
87            Connectivity::Polygonal(_) => todo!(),
88            Connectivity::Polyhedral(_) => todo!(),
89        }
90    }
91    pub fn is_empty(&self) -> bool {
92        match self {
93            Connectivity::Hexahedral(c) => c.is_empty(),
94            Connectivity::Pyramidal(c) => c.is_empty(),
95            Connectivity::Wedge(c) => c.is_empty(),
96            Connectivity::Polyhedral(c) => c.is_empty(),
97            Connectivity::Polygonal(c) => c.is_empty(),
98            Connectivity::Quadrilateral(c) => c.is_empty(),
99            Connectivity::Tetrahedral(c) => c.is_empty(),
100            Connectivity::Triangular(c) => c.is_empty(),
101        }
102    }
103    pub fn iter(&self) -> ElementIter<'_> {
104        self.into_iter()
105    }
106    pub fn element_numbers(&self) -> Option<&[usize]> {
107        match self {
108            Connectivity::Hexahedral(c) => c.element_numbers(),
109            Connectivity::Pyramidal(c) => c.element_numbers(),
110            Connectivity::Wedge(c) => c.element_numbers(),
111            Connectivity::Polyhedral(c) => c.element_numbers(),
112            Connectivity::Polygonal(c) => c.element_numbers(),
113            Connectivity::Quadrilateral(c) => c.element_numbers(),
114            Connectivity::Tetrahedral(c) => c.element_numbers(),
115            Connectivity::Triangular(c) => c.element_numbers(),
116        }
117    }
118    pub fn node_element_connectivity(&self) -> &[Vec<usize>] {
119        match self {
120            Connectivity::Hexahedral(c) => c.node_element_connectivity(),
121            Connectivity::Pyramidal(c) => c.node_element_connectivity(),
122            Connectivity::Wedge(c) => c.node_element_connectivity(),
123            Connectivity::Polyhedral(c) => c.node_element_connectivity(),
124            Connectivity::Polygonal(c) => c.node_element_connectivity(),
125            Connectivity::Quadrilateral(c) => c.node_element_connectivity(),
126            Connectivity::Tetrahedral(c) => c.node_element_connectivity(),
127            Connectivity::Triangular(c) => c.node_element_connectivity(),
128        }
129    }
130    pub fn number_elements(&mut self, numbers: Vec<usize>) {
131        match self {
132            Connectivity::Hexahedral(c) => c.number_elements(numbers),
133            Connectivity::Pyramidal(c) => c.number_elements(numbers),
134            Connectivity::Wedge(c) => c.number_elements(numbers),
135            Connectivity::Polyhedral(c) => c.number_elements(numbers),
136            Connectivity::Polygonal(c) => c.number_elements(numbers),
137            Connectivity::Quadrilateral(c) => c.number_elements(numbers),
138            Connectivity::Tetrahedral(c) => c.number_elements(numbers),
139            Connectivity::Triangular(c) => c.number_elements(numbers),
140        }
141    }
142    pub fn number_of_elements(&self) -> usize {
143        match self {
144            Connectivity::Hexahedral(c) => c.number_of_elements(),
145            Connectivity::Pyramidal(c) => c.number_of_elements(),
146            Connectivity::Wedge(c) => c.number_of_elements(),
147            Connectivity::Polyhedral(c) => c.number_of_elements(),
148            Connectivity::Polygonal(c) => c.number_of_elements(),
149            Connectivity::Quadrilateral(c) => c.number_of_elements(),
150            Connectivity::Tetrahedral(c) => c.number_of_elements(),
151            Connectivity::Triangular(c) => c.number_of_elements(),
152        }
153    }
154    pub fn number_of_faces(&self) -> Option<usize> {
155        match self {
156            Connectivity::Hexahedral(c) => c.number_of_faces(),
157            Connectivity::Pyramidal(c) => c.number_of_faces(),
158            Connectivity::Wedge(c) => c.number_of_faces(),
159            Connectivity::Polyhedral(c) => c.number_of_faces(),
160            Connectivity::Polygonal(c) => c.number_of_faces(),
161            Connectivity::Quadrilateral(c) => c.number_of_faces(),
162            Connectivity::Tetrahedral(c) => c.number_of_faces(),
163            Connectivity::Triangular(c) => c.number_of_faces(),
164        }
165    }
166    pub fn number_of_faces_per_element<I>(&self) -> Option<Vec<I>>
167    where
168        I: Debug + TryFrom<usize, Error = TryFromIntError>,
169    {
170        match self {
171            Connectivity::Hexahedral(c) => c.number_of_faces_per_element(),
172            Connectivity::Pyramidal(c) => c.number_of_faces_per_element(),
173            Connectivity::Wedge(c) => c.number_of_faces_per_element(),
174            Connectivity::Polyhedral(c) => c.number_of_faces_per_element(),
175            Connectivity::Polygonal(c) => c.number_of_faces_per_element(),
176            Connectivity::Quadrilateral(c) => c.number_of_faces_per_element(),
177            Connectivity::Tetrahedral(c) => c.number_of_faces_per_element(),
178            Connectivity::Triangular(c) => c.number_of_faces_per_element(),
179        }
180    }
181    pub fn number_of_nodes_per_element(&self) -> Option<usize> {
182        match self {
183            Connectivity::Hexahedral(c) => c.number_of_nodes_per_element(),
184            Connectivity::Pyramidal(c) => c.number_of_nodes_per_element(),
185            Connectivity::Wedge(c) => c.number_of_nodes_per_element(),
186            Connectivity::Polyhedral(c) => c.number_of_nodes_per_element(),
187            Connectivity::Polygonal(c) => c.number_of_nodes_per_element(),
188            Connectivity::Quadrilateral(c) => c.number_of_nodes_per_element(),
189            Connectivity::Tetrahedral(c) => c.number_of_nodes_per_element(),
190            Connectivity::Triangular(c) => c.number_of_nodes_per_element(),
191        }
192    }
193    pub fn number_of_nodes_per_face<I>(&self) -> Option<Vec<I>>
194    where
195        I: Debug + TryFrom<usize, Error = TryFromIntError>,
196    {
197        match self {
198            Connectivity::Hexahedral(c) => c.number_of_nodes_per_face(),
199            Connectivity::Pyramidal(c) => c.number_of_nodes_per_face(),
200            Connectivity::Wedge(c) => c.number_of_nodes_per_face(),
201            Connectivity::Polyhedral(c) => c.number_of_nodes_per_face(),
202            Connectivity::Polygonal(c) => c.number_of_nodes_per_face(),
203            Connectivity::Quadrilateral(c) => c.number_of_nodes_per_face(),
204            Connectivity::Tetrahedral(c) => c.number_of_nodes_per_face(),
205            Connectivity::Triangular(c) => c.number_of_nodes_per_face(),
206        }
207    }
208    #[cfg(feature = "netcdf")]
209    pub fn exodus_element_type(&self) -> &str {
210        match self {
211            Connectivity::Hexahedral(c) => c.exodus_element_type(),
212            Connectivity::Pyramidal(c) => c.exodus_element_type(),
213            Connectivity::Wedge(c) => c.exodus_element_type(),
214            Connectivity::Polyhedral(c) => c.exodus_element_type(),
215            Connectivity::Polygonal(c) => c.exodus_element_type(),
216            Connectivity::Quadrilateral(c) => c.exodus_element_type(),
217            Connectivity::Tetrahedral(c) => c.exodus_element_type(),
218            Connectivity::Triangular(c) => c.exodus_element_type(),
219        }
220    }
221    #[cfg(feature = "netcdf")]
222    pub fn flat_connectivity<I>(&self) -> FlatConnectivity<I>
223    where
224        I: Debug + TryFrom<usize, Error = TryFromIntError>,
225    {
226        match self {
227            Connectivity::Hexahedral(c) => c.flat_connectivity(),
228            Connectivity::Pyramidal(c) => c.flat_connectivity(),
229            Connectivity::Wedge(c) => c.flat_connectivity(),
230            Connectivity::Polyhedral(c) => c.flat_connectivity(),
231            Connectivity::Polygonal(c) => c.flat_connectivity(),
232            Connectivity::Quadrilateral(c) => c.flat_connectivity(),
233            Connectivity::Tetrahedral(c) => c.flat_connectivity(),
234            Connectivity::Triangular(c) => c.flat_connectivity(),
235        }
236    }
237}
238
239impl TryFrom<Connectivities> for Vec<[usize; 3]> {
240    type Error = &'static str;
241    fn try_from(connectivities: Connectivities) -> Result<Self, Self::Error> {
242        let mut triangles = Self::new();
243        for block in connectivities.into_members() {
244            match block {
245                Connectivity::Triangular(block) if triangles.is_empty() => {
246                    triangles = block.into_iter().collect()
247                }
248                Connectivity::Triangular(block) => triangles.extend(block),
249                _ => return Err("connectivity contains a non-triangular block"),
250            }
251        }
252        Ok(triangles)
253    }
254}
255
256impl TryFrom<Connectivities> for Vec<[usize; 8]> {
257    type Error = &'static str;
258    fn try_from(connectivities: Connectivities) -> Result<Self, Self::Error> {
259        let mut hexes = Self::new();
260        for block in connectivities.into_members() {
261            match block {
262                Connectivity::Hexahedral(block) if hexes.is_empty() => {
263                    hexes = block.into_iter().collect()
264                }
265                Connectivity::Hexahedral(block) => hexes.extend(block),
266                _ => return Err("connectivity contains a non-hexahedral block"),
267            }
268        }
269        Ok(hexes)
270    }
271}
272
273impl From<Vec<[usize; 3]>> for Connectivity {
274    fn from(connectivity: Vec<[usize; 3]>) -> Self {
275        Connectivity::Triangular(connectivity.into())
276    }
277}