Skip to main content

conspire/geometry/mesh/sets/
mod.rs

1#[cfg(test)]
2mod test;
3
4use std::slice::Iter;
5
6macro_rules! sets {
7    ($set: ident, $sets: ident, $member: ty, $members: ident, $doc: literal, $docs: literal) => {
8        #[doc = $doc]
9        #[derive(Clone, Debug, PartialEq)]
10        pub struct $set {
11            label: Option<usize>,
12            name: Option<String>,
13            $members: Vec<$member>,
14        }
15        impl $set {
16            pub fn new($members: Vec<$member>) -> Self {
17                Self {
18                    label: None,
19                    name: None,
20                    $members,
21                }
22            }
23            pub fn with_label(mut self, label: usize) -> Self {
24                self.label = Some(label);
25                self
26            }
27            pub fn with_name(mut self, name: impl Into<String>) -> Self {
28                self.name = Some(name.into());
29                self
30            }
31            pub fn label(&self) -> Option<usize> {
32                self.label
33            }
34            pub fn name(&self) -> Option<&str> {
35                self.name.as_deref()
36            }
37            pub fn $members(&self) -> &[$member] {
38                &self.$members
39            }
40            pub fn restrict(&self, map: impl Fn($member) -> Option<$member>) -> Option<Self> {
41                let $members: Vec<$member> = self.$members.iter().filter_map(|&m| map(m)).collect();
42                (!$members.is_empty()).then(|| Self {
43                    label: self.label,
44                    name: self.name.clone(),
45                    $members,
46                })
47            }
48        }
49        #[doc = $docs]
50        #[derive(Clone, Debug, Default, PartialEq)]
51        pub struct $sets(Vec<$set>);
52        impl $sets {
53            pub fn new() -> Self {
54                Self::default()
55            }
56            pub fn push(&mut self, set: $set) {
57                self.0.push(set)
58            }
59            pub fn iter(&self) -> Iter<'_, $set> {
60                self.0.iter()
61            }
62            pub fn len(&self) -> usize {
63                self.0.len()
64            }
65            pub fn is_empty(&self) -> bool {
66                self.0.is_empty()
67            }
68            /// The first set with a label.
69            pub fn by_label(&self, label: usize) -> Option<&$set> {
70                self.0.iter().find(|set| set.label == Some(label))
71            }
72            /// The first set with a name.
73            pub fn by_name(&self, name: &str) -> Option<&$set> {
74                self.0.iter().find(|set| set.name.as_deref() == Some(name))
75            }
76            /// The label of each set, giving those without one the smallest label no set has.
77            pub fn resolved_labels(&self) -> Vec<usize> {
78                let mut next = 0;
79                self.0
80                    .iter()
81                    .map(|set| {
82                        set.label.unwrap_or_else(|| {
83                            loop {
84                                next += 1;
85                                if self.by_label(next).is_none() {
86                                    return next;
87                                }
88                            }
89                        })
90                    })
91                    .collect()
92            }
93        }
94        impl<'a> IntoIterator for &'a $sets {
95            type Item = &'a $set;
96            type IntoIter = Iter<'a, $set>;
97            fn into_iter(self) -> Self::IntoIter {
98                self.0.iter()
99            }
100        }
101        impl From<Vec<$set>> for $sets {
102            fn from(sets: Vec<$set>) -> Self {
103                Self(sets)
104            }
105        }
106        impl From<Vec<Vec<$member>>> for $sets {
107            fn from(sets: Vec<Vec<$member>>) -> Self {
108                Self(sets.into_iter().map($set::new).collect())
109            }
110        }
111        impl From<(Vec<Vec<$member>>, Vec<usize>)> for $sets {
112            fn from((sets, labels): (Vec<Vec<$member>>, Vec<usize>)) -> Self {
113                assert_eq!(
114                    sets.len(),
115                    labels.len(),
116                    "There must be exactly one label for each set."
117                );
118                Self(
119                    sets.into_iter()
120                        .zip(labels)
121                        .map(|(members, label)| $set::new(members).with_label(label))
122                        .collect(),
123                )
124            }
125        }
126    };
127}
128
129sets!(
130    NodeSet,
131    NodeSets,
132    usize,
133    nodes,
134    "A set of nodes, optionally labeled and named.",
135    "Sets of nodes."
136);
137sets!(
138    SideSet,
139    SideSets,
140    (usize, usize),
141    sides,
142    "A set of element sides, each an element and the ordinal of one of its faces, optionally labeled and named.",
143    "Sets of element sides."
144);