Skip to main content

conspire/geometry/mesh/base/
mod.rs

1#[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}