1use super::SingleElementMesh;
4use crate::{
5 geometry::SingleElementGeometry,
6 topology::single_type::SingleTypeTopology,
7 traits::{Builder, GeometryBuilder, MeshBuilder, TopologyBuilder},
8 types::Scalar,
9};
10use ndelement::{
11 ciarlet::{CiarletElement, LagrangeElementFamily, LagrangeVariant, lagrange},
12 map::IdentityMap,
13 reference_cell,
14 traits::FiniteElement,
15 types::{Continuity, ReferenceCellType},
16};
17use rlst::rlst_dynamic_array;
18use std::collections::{HashMap, HashSet};
19
20#[derive(Debug)]
44pub struct SingleElementMeshBuilder<T: Scalar> {
45 gdim: usize,
46 element_data: (ReferenceCellType, usize),
47 element: CiarletElement<T, IdentityMap, T>,
48 points_per_cell: usize,
49 pub(crate) points: Vec<T>,
50 cells: Vec<usize>,
51 point_indices_to_ids: Vec<usize>,
52 point_ids_to_indices: HashMap<usize, usize>,
53 cell_indices_to_ids: Vec<usize>,
54 cell_ids_to_indices: HashMap<usize, usize>,
55 point_indices: HashSet<usize>,
56 cell_indices: HashSet<usize>,
57 parametric_coords: HashMap<usize, (usize, Vec<T>)>,
58}
59
60impl<T: Scalar> SingleElementMeshBuilder<T> {
61 pub fn new(gdim: usize, data: (ReferenceCellType, usize)) -> Self {
63 Self::new_with_capacity(gdim, 0, 0, data)
64 }
65
66 pub fn new_with_capacity(
68 gdim: usize,
69 npoints: usize,
70 ncells: usize,
71 data: (ReferenceCellType, usize),
72 ) -> Self {
73 let element = lagrange::create::<T, T>(
74 data.0,
75 data.1,
76 Continuity::Standard,
77 LagrangeVariant::Equispaced,
78 );
79 let points_per_cell = element.dim();
80 Self {
81 gdim,
82 element_data: data,
83 element,
84 points_per_cell,
85 points: Vec::with_capacity(npoints * gdim),
86 cells: Vec::with_capacity(ncells * points_per_cell),
87 point_indices_to_ids: Vec::with_capacity(npoints),
88 point_ids_to_indices: HashMap::new(),
89 cell_indices_to_ids: Vec::with_capacity(ncells),
90 cell_ids_to_indices: HashMap::new(),
91 point_indices: HashSet::new(),
92 cell_indices: HashSet::new(),
93 parametric_coords: HashMap::new(),
94 }
95 }
96}
97
98impl<T: Scalar> Builder for SingleElementMeshBuilder<T> {
99 type Mesh = SingleElementMesh<T, CiarletElement<T, IdentityMap, T>>;
100 type T = T;
101 type CellData<'a> = &'a [usize];
102 type EntityDescriptor = ReferenceCellType;
103
104 fn add_point(&mut self, id: usize, data: &[T]) {
105 if data.len() != self.gdim {
106 panic!("Point has wrong number of coordinates");
107 }
108 if self.point_indices.contains(&id) {
109 panic!("Cannot add point with duplicate id.");
110 }
111 self.point_ids_to_indices
112 .insert(id, self.point_indices_to_ids.len());
113 self.point_indices.insert(id);
114 self.point_indices_to_ids.push(id);
115 self.points.extend_from_slice(data);
116 }
117
118 fn add_cell(&mut self, id: usize, cell_data: &[usize]) {
119 if self.cell_indices.contains(&id) {
120 panic!("Cannot add cell with duplicate id.");
121 }
122 assert_eq!(cell_data.len(), self.points_per_cell);
123 self.cell_ids_to_indices
124 .insert(id, self.cell_indices_to_ids.len());
125 self.cell_indices.insert(id);
126 self.cell_indices_to_ids.push(id);
127 for id in cell_data {
128 self.cells.push(self.point_ids_to_indices[id]);
129 }
130 }
131
132 fn add_cell_from_nodes_and_type(
133 &mut self,
134 id: usize,
135 nodes: &[usize],
136 cell_type: ReferenceCellType,
137 cell_degree: usize,
138 ) {
139 if (cell_type, cell_degree) != self.element_data {
140 panic!("Invalid cell type.");
141 }
142 self.add_cell(id, nodes);
143 }
144
145 fn create_mesh(&self) -> SingleElementMesh<T, CiarletElement<T, IdentityMap, T>> {
146 let cell_vertices =
147 self.extract_vertices(&self.cells, &[self.element_data.0], &[self.element_data.1]);
148
149 let mut vertex_ids = HashSet::<usize>::new();
154 for v in &cell_vertices {
155 vertex_ids.insert(*v);
156 }
157
158 let vertex_ids = {
159 let mut tmp = Vec::<usize>::with_capacity(vertex_ids.len());
160 tmp.extend(vertex_ids.iter());
161 tmp.sort();
162 tmp
163 };
164
165 let geometry = self.create_geometry(
166 &self.point_indices_to_ids,
167 &self.points,
168 &self.cells,
169 &[self.element_data.0],
170 &[self.element_data.1],
171 );
172
173 let topology = self.create_topology(
174 vertex_ids,
175 (0..self.cell_count()).collect::<Vec<_>>(),
176 &cell_vertices,
177 &[self.element_data.0],
178 );
179
180 self.create_mesh_from_topology_geometry(topology, geometry)
181 }
182
183 fn point_count(&self) -> usize {
184 self.point_indices_to_ids.len()
185 }
186 fn cell_count(&self) -> usize {
187 self.cell_indices_to_ids.len()
188 }
189 fn point_indices_to_ids(&self) -> &[usize] {
190 &self.point_indices_to_ids
191 }
192 fn cell_indices_to_ids(&self) -> &[usize] {
193 &self.cell_indices_to_ids
194 }
195 fn cell_points(&self, index: usize) -> &[usize] {
196 &self.cells[self.points_per_cell * index..self.points_per_cell * (index + 1)]
197 }
198 fn cell_vertices(&self, index: usize) -> &[usize] {
199 &self.cells[self.points_per_cell * index
200 ..self.points_per_cell * index + reference_cell::entity_counts(self.element_data.0)[0]]
201 }
202 fn point(&self, index: usize) -> &[T] {
203 &self.points[self.gdim * index..self.gdim * (index + 1)]
204 }
205 fn points(&self) -> &[T] {
206 &self.points
207 }
208 fn cell_type(&self, _index: usize) -> ReferenceCellType {
209 self.element_data.0
210 }
211 fn cell_degree(&self, _index: usize) -> usize {
212 self.element_data.1
213 }
214 fn gdim(&self) -> usize {
215 self.gdim
216 }
217 fn tdim(&self) -> usize {
218 reference_cell::dim(self.element_data.0)
219 }
220
221 fn npts(&self, _cell_type: Self::EntityDescriptor, _degree: usize) -> usize {
222 self.points_per_cell
223 }
224
225 fn add_point_parametric_coords(&mut self, id: usize, entity_dim: usize, coords: &[T]) {
226 if let Some(&index) = self.point_ids_to_indices.get(&id) {
227 self.parametric_coords
228 .insert(index, (entity_dim, coords.to_vec()));
229 }
230 }
231
232 fn point_parametric_coords(&self, index: usize) -> Option<(usize, &[T])> {
233 self.parametric_coords
234 .get(&index)
235 .map(|(dim, coords)| (*dim, coords.as_slice()))
236 }
237}
238
239impl<T: Scalar> GeometryBuilder for SingleElementMeshBuilder<T> {
240 type MeshGeometry = SingleElementGeometry<T, CiarletElement<T, IdentityMap, T>>;
241 fn create_geometry(
242 &self,
243 point_ids: &[usize],
244 coordinates: &[Self::T],
245 cell_points: &[usize],
246 _cell_types: &[ReferenceCellType],
247 _cell_degrees: &[usize],
248 ) -> SingleElementGeometry<T, CiarletElement<T, IdentityMap, T>> {
249 let npts = point_ids.len();
250 let mut points = rlst_dynamic_array!(T, [self.gdim(), npts]);
251 points.data_mut().unwrap().copy_from_slice(coordinates);
252
253 let family = LagrangeElementFamily::<T, T>::new(
254 self.element_data.1,
255 Continuity::Standard,
256 LagrangeVariant::Equispaced,
257 );
258
259 SingleElementGeometry::<T, CiarletElement<T, IdentityMap, T>>::new(
260 self.element_data.0,
261 points,
262 cell_points,
263 &family,
264 )
265 }
266}
267
268impl<T: Scalar> TopologyBuilder for SingleElementMeshBuilder<T> {
269 type MeshTopology = SingleTypeTopology;
270 fn create_topology(
271 &self,
272 vertex_ids: Vec<usize>,
273 cell_ids: Vec<usize>,
274 cells: &[usize],
275 _cell_types: &[ReferenceCellType],
276 ) -> SingleTypeTopology {
277 let vertex_ids_to_pos = {
279 let mut tmp = HashMap::<usize, usize>::new();
280 for (i, id) in vertex_ids.iter().enumerate() {
281 tmp.insert(*id, i);
282 }
283 tmp
284 };
285
286 let cells = {
288 let mut new_cells = Vec::<usize>::with_capacity(cells.len());
289 for id in cells {
290 new_cells.push(vertex_ids_to_pos[id]);
291 }
292 new_cells
293 };
294
295 SingleTypeTopology::new(
296 &cells,
297 self.element_data.0,
298 Some(vertex_ids),
299 Some(cell_ids),
300 )
301 }
302
303 fn extract_vertices(
304 &self,
305 cell_points: &[usize],
306 _cell_types: &[Self::EntityDescriptor],
307 _cell_degrees: &[usize],
308 ) -> Vec<usize> {
309 let mut vertices = vec![];
310 for v in 0..reference_cell::entity_counts(self.element_data.0)[0] {
311 for d in self.element.entity_dofs(0, v).unwrap() {
312 vertices.push(*d);
313 }
314 }
315 let mut cell_vertices = vec![];
316 let mut start = 0;
317 let npoints = self.element.dim();
318 while start < cell_points.len() {
319 for v in &vertices {
320 cell_vertices.push(cell_points[start + v])
321 }
322 start += npoints;
323 }
324 cell_vertices
325 }
326}
327
328impl<T: Scalar> MeshBuilder for SingleElementMeshBuilder<T> {
329 fn create_mesh_from_topology_geometry(
330 &self,
331 topology: <Self as TopologyBuilder>::MeshTopology,
332 geometry: <Self as GeometryBuilder>::MeshGeometry,
333 ) -> <Self as Builder>::Mesh {
334 SingleElementMesh::new(topology, geometry)
335 }
336}
337
338#[cfg(test)]
339mod test {
340 use super::*;
341
342 #[test]
343 #[should_panic]
344 fn test_duplicate_point_id() {
345 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
346
347 b.add_point(2, &[0.0, 0.0, 0.0]);
348 b.add_point(0, &[1.0, 0.0, 0.0]);
349 b.add_point(1, &[0.0, 1.0, 0.0]);
350 b.add_point(2, &[1.0, 1.0, 0.0]);
351 }
352
353 #[test]
354 #[should_panic]
355 fn test_duplicate_cell_id() {
356 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
357
358 b.add_point(0, &[0.0, 0.0, 0.0]);
359 b.add_point(1, &[1.0, 0.0, 0.0]);
360 b.add_point(2, &[0.0, 1.0, 0.0]);
361 b.add_point(3, &[1.0, 1.0, 0.0]);
362
363 b.add_cell(0, &[0, 1, 2]);
364 b.add_cell(0, &[1, 2, 3]);
365 }
366
367 #[test]
368 fn test_non_contiguous_ids() {
369 let mut b = SingleElementMeshBuilder::<f64>::new(3, (ReferenceCellType::Triangle, 1));
370
371 b.add_point(0, &[0.0, 0.0, 0.0]);
372 b.add_point(1, &[1.0, 0.0, 0.0]);
373 b.add_point(2, &[0.0, 1.0, 0.0]);
374 b.add_point(4, &[1.0, 1.0, 0.0]);
375
376 b.add_cell(0, &[0, 1, 2]);
377 b.add_cell(2, &[1, 2, 4]);
378
379 b.create_mesh();
380 }
381}