use std::collections::HashSet;
#[derive(Clone, Copy)]
pub struct QuadMeshView2d<'a, F: Copy, const NODES_PER_ELEMENT: usize> {
pub nodes_rz: &'a [[F; 2]],
pub elements: &'a [[usize; NODES_PER_ELEMENT]],
}
impl<'a, F: Copy, const NODES_PER_ELEMENT: usize> QuadMeshView2d<'a, F, NODES_PER_ELEMENT> {
pub fn num_nodes(&self) -> usize {
self.nodes_rz.len()
}
pub fn num_elements(&self) -> usize {
self.elements.len()
}
pub fn validate_connectivity(&self) -> Result<(), String> {
let node_count = self.num_nodes();
for (element_index, element) in self.elements.iter().enumerate() {
let mut unique_nodes = HashSet::with_capacity(NODES_PER_ELEMENT);
for &node in element {
if node >= node_count {
return Err(format!(
"element {element_index} references node {node}, but mesh has only {node_count} nodes"
));
}
unique_nodes.insert(node);
}
if unique_nodes.len() != NODES_PER_ELEMENT {
eprintln!(
"warning: element {element_index} contains duplicate node indices: {element:?}"
);
}
}
Ok(())
}
pub fn element_nodes(
&self,
element_index: usize,
) -> Result<[usize; NODES_PER_ELEMENT], String> {
self.elements
.get(element_index)
.copied()
.ok_or_else(|| format!("element index {element_index} out of bounds"))
}
pub fn element_coords(
&self,
element_index: usize,
) -> Result<[[F; 2]; NODES_PER_ELEMENT], String> {
let nodes = self.element_nodes(element_index)?;
Ok(std::array::from_fn(|local_index| {
self.nodes_rz[nodes[local_index]]
}))
}
}