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}