$$ \gdef\pd#1#2{\frac{\partial #1}{\partial #2}} \gdef\d#1{\, \mathrm{d}#1} \gdef\dx{\d{x}} \gdef\tr#1{\operatorname{tr} (#1)} $$ $$ \gdef\norm#1{\left \lVert #1 \right\rVert} \gdef\seminorm#1{| #1 |} $$ $$ \gdef\vec#1{\mathbf{\boldsymbol{#1}}} \gdef\dvec#1{\bar{\vec #1}} $$

fenris/mesh/
refinement.rs

1//! Functionality and abstractions for mesh refinement.
2//!
3//! Currently we only provide uniform refinement for select element types through
4//! [`refine_mesh`] and [`UniformRefinement`].
5use crate::allocators::DimAllocator;
6use crate::connectivity::Connectivity;
7use crate::mesh::Mesh;
8use nalgebra::{DefaultAllocator, DimName, OPoint, RealField};
9use std::collections::HashMap;
10use std::hash::Hash;
11
12pub mod detail;
13
14#[derive(Debug, Clone)]
15pub struct InvalidVertexCount;
16
17pub trait VertexRepresentation: Clone {
18    fn construct_vertex<T, D>(&self, all_vertices: &[OPoint<T, D>]) -> OPoint<T, D>
19    where
20        T: RealField,
21        D: DimName,
22        DefaultAllocator: DimAllocator<T, D>;
23}
24
25/// Defines a refinement scheme for a given connectivity.
26pub trait RefineConnectivity<Connectivity> {
27    /// An intermediate connectivity type that holds the necessary information
28    /// to represent the connectivity in a manner independent of the index labeling of
29    /// new vertices.
30    ///
31    /// This is generally an internal detail.
32    type Intermediate;
33    /// The resulting connectivity type after refinement.
34    type OutputConnectivity;
35    /// The kind of label used to define vertices in a globally consistent fashion.
36    type VertexLabel: VertexRepresentation;
37
38    /// For a given connectivity, produce a set of intermediate connectivities that represent
39    /// refined connectivities.
40    fn populate_refined_connectivity(&self, connectivity: &Connectivity, intermediates: &mut Vec<Self::Intermediate>);
41
42    /// Populate a set of vertex labels associated with an intermediate connectivity.
43    fn populate_vertex_labels(&self, intermediate: &Self::Intermediate, labels: &mut Vec<Self::VertexLabel>);
44
45    /// Construct the final connectivity from an intermediate given final,
46    /// globally consistent vertex indices.
47    ///
48    /// The implementation must succeed if the number of vertex indices is equal to the
49    /// number of vertex labels associated with the intermediate, as defined by
50    /// the number of vertex labels produced by
51    /// [`populate_vertex_labels`](Self::populate_vertex_labels).
52    fn construct_output_connectivity(
53        &self,
54        intermediate: &Self::Intermediate,
55        vertex_indices: &[usize],
56    ) -> Result<Self::OutputConnectivity, InvalidVertexCount>;
57}
58
59pub struct UniformRefinement;
60
61/// Refine a mesh with the provided refinement scheme.
62pub fn refine_mesh<T, D, C, Refinement>(
63    mesh: &Mesh<T, D, C>,
64    refinement_scheme: Refinement,
65) -> Mesh<T, D, Refinement::OutputConnectivity>
66where
67    T: RealField,
68    D: DimName,
69    Refinement: RefineConnectivity<C>,
70    Refinement::VertexLabel: Eq + Hash,
71    DefaultAllocator: DimAllocator<T, D>,
72{
73    let mut label_to_idx_map = HashMap::new();
74    let mut next_vertex_idx = 0;
75
76    let mut new_connectivity = Vec::new();
77
78    // Local buffers
79    let mut intermediates = Vec::new();
80    let mut vertex_labels = Vec::new();
81    let mut new_vertex_indices = Vec::new();
82    for connectivity in mesh.connectivity() {
83        new_vertex_indices.clear();
84        intermediates.clear();
85        refinement_scheme.populate_refined_connectivity(&connectivity, &mut intermediates);
86        for intermediate in &intermediates {
87            vertex_labels.clear();
88            new_vertex_indices.clear();
89            refinement_scheme.populate_vertex_labels(&intermediate, &mut vertex_labels);
90            for label in &vertex_labels {
91                let idx = label_to_idx_map.entry(label.clone()).or_insert_with(|| {
92                    let idx = next_vertex_idx;
93                    next_vertex_idx += 1;
94                    idx
95                });
96                new_vertex_indices.push(*idx);
97            }
98            let new_cell_connectivity = refinement_scheme
99                .construct_output_connectivity(&intermediate, &new_vertex_indices)
100                .expect("Must succeed since vertex label count is consistent with vertex index count");
101            new_connectivity.push(new_cell_connectivity);
102        }
103    }
104
105    let mut new_vertices = vec![Default::default(); next_vertex_idx];
106    for (label, index) in label_to_idx_map {
107        let vertex = label.construct_vertex(mesh.vertices());
108        new_vertices[index] = vertex;
109    }
110    Mesh::from_vertices_and_connectivity(new_vertices, new_connectivity)
111}
112
113/// Apply one round of uniform mesh refinement.
114///
115/// This is a convenience function for `refine_mesh(mesh, UniformRefinement)`.
116pub fn refine_uniformly<T, D, C>(mesh: &Mesh<T, D, C>) -> Mesh<T, D, C>
117where
118    T: RealField,
119    D: DimName,
120    UniformRefinement: RefineConnectivity<C, OutputConnectivity = C>,
121    <UniformRefinement as RefineConnectivity<C>>::VertexLabel: Eq + Hash,
122    DefaultAllocator: DimAllocator<T, D>,
123{
124    refine_mesh(mesh, UniformRefinement)
125}
126
127/// Repeatedly applies uniform mesh refinement to the given mesh.
128pub fn refine_uniformly_repeat<T, D, C>(mesh: &Mesh<T, D, C>, repeat_times: usize) -> Mesh<T, D, C>
129where
130    T: RealField,
131    D: DimName,
132    C: Connectivity,
133    UniformRefinement: RefineConnectivity<C, OutputConnectivity = C>,
134    <UniformRefinement as RefineConnectivity<C>>::VertexLabel: Eq + Hash,
135    DefaultAllocator: DimAllocator<T, D>,
136{
137    let mut mesh: Mesh<_, _, _> = mesh.clone();
138    for _ in 0..repeat_times {
139        mesh = refine_uniformly(&mesh);
140    }
141    mesh
142}