Skip to main content

conspire/geometry/mesh/base/
mod.rs

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