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