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}