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