Skip to main content

conspire/geometry/mesh/connectivity/polytopal/
mod.rs

1use crate::geometry::mesh::connectivity::base::FlatConnectivity;
2use crate::{geometry::mesh::connectivity::base::ConnectivityImpl, math::Set};
3use std::{cell::OnceCell, fmt::Debug, num::TryFromIntError, slice::Iter, vec::IntoIter};
4
5pub struct PolytopalConnectivity<const M: usize>(
6    Set<Vec<Vec<usize>>>,
7    Vec<Vec<usize>>,
8    OnceCell<Vec<Vec<usize>>>,
9);
10
11impl<const M: usize> From<(Vec<Vec<usize>>, Vec<Vec<usize>>)> for PolytopalConnectivity<M> {
12    fn from((elements_faces, faces_nodes): (Vec<Vec<usize>>, Vec<Vec<usize>>)) -> Self {
13        PolytopalConnectivity(Set::from(elements_faces), faces_nodes, OnceCell::new())
14    }
15}
16
17impl<const M: usize> PolytopalConnectivity<M> {
18    pub fn add_edge_adjacency(&self, nodes_nodes: &mut [Vec<usize>]) {
19        for faces in self.0.members() {
20            for &face in faces {
21                let nodes = &self.1[face];
22                for (index, &u) in nodes.iter().enumerate() {
23                    let v = nodes[(index + 1) % nodes.len()];
24                    if u != v {
25                        nodes_nodes[u].push(v);
26                        nodes_nodes[v].push(u);
27                    }
28                }
29            }
30        }
31    }
32    pub fn elements_faces(&self) -> &[Vec<usize>] {
33        self.0.members()
34    }
35    pub fn faces_nodes(&self) -> &[Vec<usize>] {
36        &self.1
37    }
38    pub fn iter(&self) -> Iter<'_, Vec<usize>> {
39        self.0.members().iter()
40    }
41}
42
43impl<'a, const M: usize> IntoIterator for &'a PolytopalConnectivity<M> {
44    type Item = &'a Vec<usize>;
45    type IntoIter = Iter<'a, Vec<usize>>;
46    fn into_iter(self) -> Self::IntoIter {
47        self.0.members().iter()
48    }
49}
50
51impl<const M: usize> IntoIterator for PolytopalConnectivity<M> {
52    type Item = Vec<usize>;
53    type IntoIter = IntoIter<Vec<usize>>;
54    fn into_iter(self) -> Self::IntoIter {
55        self.0.into_members().into_iter()
56    }
57}
58
59impl<const M: usize> ConnectivityImpl for PolytopalConnectivity<M> {
60    fn is_empty(&self) -> bool {
61        self.0.members().is_empty()
62    }
63    fn element_numbers(&self) -> Option<&[usize]> {
64        self.0.numbers()
65    }
66    fn node_element_connectivity(&self) -> &[Vec<usize>] {
67        self.2.get_or_init(|| {
68            let number_of_nodes = self.1.iter().flatten().max().map_or(0, |&node| node + 1);
69            let mut nodes_elements = vec![Vec::new(); number_of_nodes];
70            for (element, faces) in self.0.members().iter().enumerate() {
71                let mut nodes: Vec<usize> = faces
72                    .iter()
73                    .flat_map(|&face| self.1[face].iter().copied())
74                    .collect();
75                nodes.sort_unstable();
76                nodes.dedup();
77                for node in nodes {
78                    nodes_elements[node].push(element)
79                }
80            }
81            nodes_elements
82        })
83    }
84    fn number_elements(&mut self, numbers: Vec<usize>) {
85        self.0.set_numbers(numbers)
86    }
87    fn number_of_elements(&self) -> usize {
88        self.0.members().len()
89    }
90    fn number_of_faces(&self) -> Option<usize> {
91        Some(self.1.len())
92    }
93    fn number_of_faces_per_element<I>(&self) -> Option<Vec<I>>
94    where
95        I: Debug + TryFrom<usize, Error = TryFromIntError>,
96    {
97        if let Ok(num) = self
98            .0
99            .members()
100            .iter()
101            .map(|faces| faces.len().try_into())
102            .collect()
103        {
104            Some(num)
105        } else {
106            panic!()
107        }
108    }
109    fn number_of_nodes_per_element(&self) -> Option<usize> {
110        None
111    }
112    fn number_of_nodes_per_face<I>(&self) -> Option<Vec<I>>
113    where
114        I: Debug + TryFrom<usize, Error = TryFromIntError>,
115    {
116        if let Ok(num) = self.1.iter().map(|nodes| nodes.len().try_into()).collect() {
117            Some(num)
118        } else {
119            panic!()
120        }
121    }
122    fn exodus_element_type(&self) -> &str {
123        match M {
124            2 => "nsided",
125            3 => "nfaced",
126            _ => panic!(),
127        }
128    }
129    fn flat_connectivity<I>(&self) -> FlatConnectivity<I>
130    where
131        I: Debug + TryFrom<usize, Error = TryFromIntError>,
132    {
133        let elements_faces = self
134            .0
135            .members()
136            .iter()
137            .flat_map(|faces| faces.iter().map(|&f| (f + 1).try_into()))
138            .collect();
139        let faces_nodes = self
140            .1
141            .iter()
142            .flat_map(|nodes| nodes.iter().map(|&n| (n + 1).try_into()))
143            .collect();
144        match (elements_faces, faces_nodes) {
145            (Ok(elements_faces), Ok(faces_nodes)) => {
146                FlatConnectivity::Polytopal(elements_faces, faces_nodes)
147            }
148            _ => panic!(),
149        }
150    }
151}