conspire/geometry/mesh/base/
mod.rs1#[cfg(test)]
2mod test;
3use crate::math::Reference;
4
5use crate::math::FxHashMap;
6use crate::{
7 geometry::{
8 Coordinate, Coordinates, CoordinatesRef,
9 bbox::{BoundingBox, BoundingBoxes},
10 mesh::{Connectivity, Mesh, NodeSets, SideSets},
11 },
12 math::{CrossProduct, Graph, Scalar, Tensor, TensorRank1Vec2D},
13 units::Dimensionless,
14};
15
16impl Mesh<3> {
17 pub fn normals(&self) -> TensorRank1Vec2D<3, Reference, Dimensionless> {
18 self.iter()
19 .map(|connectivity| match connectivity {
20 Connectivity::Triangular(triangles) => triangles
21 .iter()
22 .map(|&[node_0, node_1, node_2]| {
23 let u = &self.coordinates()[node_1] - &self.coordinates()[node_0];
24 let v = &self.coordinates()[node_2] - &self.coordinates()[node_0];
25 u.cross(v).normalized()
26 })
27 .collect(),
28 _ => panic!(),
29 })
30 .collect()
31 }
32}
33
34impl<const D: usize> Mesh<D> {
35 pub fn exterior_faces(&self) -> Vec<Vec<usize>> {
36 let mut faces = FxHashMap::default();
37 self.iter().for_each(|block| {
38 block.iter().for_each(|element| {
39 block
40 .element_faces(element)
41 .into_iter()
42 .for_each(|oriented| {
43 let mut key = oriented.clone();
44 key.sort_unstable();
45 faces
46 .entry(key)
47 .and_modify(|(_, count)| *count += 1)
48 .or_insert((oriented, 1));
49 })
50 })
51 });
52 faces
53 .into_values()
54 .filter_map(|(face, count)| (count == 1).then_some(face))
55 .collect()
56 }
57 pub fn bounding_boxes(&self) -> BoundingBoxes<D> {
58 self.iter()
59 .flat_map(|block| {
60 block
61 .iter()
62 .map(move |element| block.element_nodes(element))
63 })
64 .map(|nodes| {
65 nodes
66 .iter()
67 .map(|&node| &self.coordinates()[node])
68 .collect::<CoordinatesRef<'_, D>>()
69 .into()
70 })
71 .collect()
72 }
73 pub fn centroids(&self) -> Coordinates<D> {
74 self.iter()
75 .flat_map(|block| {
76 block
77 .iter()
78 .map(move |element| block.element_nodes(element))
79 })
80 .map(|nodes| {
81 let count = nodes.len() as Scalar;
82 nodes
83 .iter()
84 .map(|&node| &self.coordinates()[node])
85 .sum::<Coordinate<D>>()
86 / count
87 })
88 .collect()
89 }
90 pub fn bounding_boxes_and_centroids(
91 &self,
92 ) -> impl Iterator<Item = (BoundingBox<D>, Coordinate<D>)> {
93 self.iter()
94 .flat_map(|block| {
95 block
96 .iter()
97 .map(move |element| block.element_nodes(element))
98 })
99 .map(|nodes| {
100 let count = nodes.len() as Scalar;
101 (
102 nodes
103 .iter()
104 .map(|&node| &self.coordinates()[node])
105 .collect::<CoordinatesRef<'_, D>>()
106 .into(),
107 nodes
108 .iter()
109 .map(|&node| &self.coordinates()[node])
110 .sum::<Coordinate<D>>()
111 / count,
112 )
113 })
114 }
115 pub fn blocks(&self) -> Option<&[usize]> {
116 self.connectivities.numbers()
117 }
118 pub fn connectivities(&self) -> &[Connectivity] {
119 self.connectivities.members()
120 }
121 pub fn node_sets(&self) -> &[Vec<usize>] {
122 self.node_sets.members()
123 }
124 pub fn node_set_numbers(&self) -> Option<&[usize]> {
125 self.node_sets.numbers()
126 }
127 pub fn set_node_sets(&mut self, node_sets: NodeSets) {
128 self.node_sets = node_sets;
129 }
130 pub fn side_sets(&self) -> &[Vec<(usize, usize)>] {
131 self.side_sets.members()
132 }
133 pub fn side_set_numbers(&self) -> Option<&[usize]> {
134 self.side_sets.numbers()
135 }
136 pub fn set_side_sets(&mut self, side_sets: SideSets) {
137 self.side_sets = side_sets;
138 }
139 pub fn iter(&self) -> impl Iterator<Item = &Connectivity> {
140 self.connectivities.members().iter()
141 }
142 pub fn coordinates(&self) -> &Coordinates<D> {
143 self.coordinates.members()
144 }
145 pub fn node_element_connectivity(&self) -> &[Vec<usize>] {
146 self.nodes_elements.get_or_init(|| {
147 let mut nodes_elements = vec![Vec::new(); self.number_of_nodes()];
148 let mut element_offset = 0;
149 for connectivity in self.iter() {
150 let local = connectivity.node_element_connectivity();
151 for (node, elems) in local.iter().enumerate() {
152 nodes_elements[node].extend(elems.iter().map(|&e| e + element_offset))
153 }
154 element_offset += connectivity.number_of_elements();
155 }
156 nodes_elements
157 })
158 }
159 pub fn node_nodes(&self) -> &Graph {
160 self.nodes_nodes.get_or_init(|| {
161 let mut nodes_nodes = vec![Vec::new(); self.number_of_nodes()];
162 for connectivity in self.iter() {
163 connectivity.add_edge_adjacency(&mut nodes_nodes);
164 }
165 for neighbors in &mut nodes_nodes {
166 neighbors.sort_unstable();
167 neighbors.dedup();
168 }
169 nodes_nodes.into()
170 })
171 }
172 pub fn node_node_connectivity(&self) -> &[Vec<usize>] {
173 self.node_nodes().adjacency()
174 }
175 pub fn number_of_element_blocks(&self) -> usize {
176 self.connectivities().len()
177 }
178 pub fn number_of_face_blocks(&self) -> Option<usize> {
179 let number_of_face_blocks = self
180 .iter()
181 .filter(|connectivity| connectivity.number_of_faces().is_some())
182 .count();
183 if number_of_face_blocks > 0 {
184 Some(number_of_face_blocks)
185 } else {
186 None
187 }
188 }
189 pub fn number_of_elements(&self) -> usize {
190 self.iter()
191 .map(|connectivity| connectivity.number_of_elements())
192 .sum()
193 }
194 pub fn number_of_faces(&self) -> Option<usize> {
195 let number_of_faces = self
196 .iter()
197 .filter_map(|connectivity| connectivity.number_of_faces())
198 .sum();
199 if number_of_faces > 0 {
200 Some(number_of_faces)
201 } else {
202 None
203 }
204 }
205 pub fn number_of_nodes(&self) -> usize {
206 self.coordinates().len()
207 }
208}