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