1#[cfg(feature = "mpi")]
3use crate::ParallelGridImpl;
4#[cfg(feature = "mpi")]
5use crate::{
6 SingleElementGridBuilder,
7 traits::{Builder, DistributableGrid, ParallelBuilder},
8 types::GraphPartitioner,
9};
10#[cfg(feature = "serde")]
11use crate::{
12 geometry::single_element::SerializableGeometry, topology::single_type::SerializableTopology,
13 traits::ConvertToSerializable,
14};
15use crate::{
16 geometry::{GeometryMap, SingleElementEntityGeometry, SingleElementGeometry},
17 topology::single_type::{SingleTypeEntityTopology, SingleTypeTopology},
18 traits::{Entity, Grid},
19 types::{Ownership, Scalar},
20};
21#[cfg(feature = "mpi")]
22use mpi::traits::{Communicator, Equivalence};
23use ndelement::{
24 ciarlet::{CiarletElement, LagrangeElementFamily},
25 map::IdentityMap,
26 reference_cell,
27 traits::{ElementFamily, FiniteElement, MappedFiniteElement},
28 types::{Continuity, ReferenceCellType},
29};
30use rlst::{
31 Array, ValueArrayImpl,
32 dense::{base_array::BaseArray, data_container::VectorContainer},
33 rlst_dynamic_array,
34};
35
36#[derive(Debug)]
38pub struct SingleElementGridEntity<
39 'a,
40 T: Scalar,
41 E: MappedFiniteElement<CellType = ReferenceCellType, T = T>,
42> {
43 grid: &'a SingleElementGrid<T, E>,
44 cell_index: usize,
45 entity_dim: usize,
46 entity_index: usize,
47}
48
49impl<'e, T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>>
50 SingleElementGridEntity<'e, T, E>
51{
52 pub fn new(
54 grid: &'e SingleElementGrid<T, E>,
55 cell_index: usize,
56 entity_dim: usize,
57 entity_index: usize,
58 ) -> Self {
59 Self {
60 grid,
61 cell_index,
62 entity_dim,
63 entity_index,
64 }
65 }
66}
67impl<T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>> Entity
68 for SingleElementGridEntity<'_, T, E>
69{
70 type T = T;
71 type EntityDescriptor = ReferenceCellType;
72 type Topology<'a>
73 = SingleTypeEntityTopology<'a>
74 where
75 Self: 'a;
76 type Geometry<'a>
77 = SingleElementEntityGeometry<'a, T, E>
78 where
79 Self: 'a;
80 fn entity_type(&self) -> ReferenceCellType {
81 self.grid.topology.entity_types()[self.entity_dim]
82 }
83 fn local_index(&self) -> usize {
84 self.grid
85 .topology
86 .cell_entity_index(self.cell_index, self.entity_dim, self.entity_index)
87 }
88 fn global_index(&self) -> usize {
89 self.local_index()
90 }
91 fn geometry(&self) -> Self::Geometry<'_> {
92 SingleElementEntityGeometry::new(
93 &self.grid.geometry,
94 self.cell_index,
95 self.entity_dim,
96 self.entity_index,
97 )
98 }
99 fn topology(&self) -> Self::Topology<'_> {
100 SingleTypeEntityTopology::new(&self.grid.topology, self.entity_type(), self.local_index())
101 }
102 fn ownership(&self) -> Ownership {
103 Ownership::Owned
104 }
105 fn id(&self) -> Option<usize> {
106 self.grid
107 .topology
108 .entity_id(self.entity_dim, self.local_index())
109 }
110}
111
112#[derive(Debug)]
114pub struct SingleElementGridEntityIter<
115 'a,
116 T: Scalar,
117 E: MappedFiniteElement<CellType = ReferenceCellType, T = T>,
118> {
119 grid: &'a SingleElementGrid<T, E>,
120 entity_type: ReferenceCellType,
121 index: usize,
122}
123
124impl<'a, T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>>
125 SingleElementGridEntityIter<'a, T, E>
126{
127 pub fn new(grid: &'a SingleElementGrid<T, E>, entity_type: ReferenceCellType) -> Self {
129 Self {
130 grid,
131 entity_type,
132 index: 0,
133 }
134 }
135}
136impl<'a, T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>> Iterator
137 for SingleElementGridEntityIter<'a, T, E>
138{
139 type Item = SingleElementGridEntity<'a, T, E>;
140
141 fn next(&mut self) -> Option<SingleElementGridEntity<'a, T, E>> {
142 self.index += 1;
143 self.grid.entity(self.entity_type, self.index - 1)
144 }
145}
146
147#[derive(Debug)]
149pub struct SingleElementGrid<T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>>
150{
151 topology: SingleTypeTopology,
152 geometry: SingleElementGeometry<T, E>,
153}
154
155#[cfg(feature = "serde")]
156#[derive(serde::Serialize, Debug, serde::Deserialize)]
157#[serde(bound = "for<'de2> T: serde::Deserialize<'de2>")]
158pub struct SerializableGrid<T: Scalar + serde::Serialize>
159where
160 for<'de2> T: serde::Deserialize<'de2>,
161{
162 topology: SerializableTopology,
163 geometry: SerializableGeometry<T>,
164}
165
166#[cfg(feature = "serde")]
167impl<T: Scalar + serde::Serialize> ConvertToSerializable
168 for SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>
169{
170 type SerializableType = SerializableGrid<T>;
171 fn to_serializable(&self) -> SerializableGrid<T> {
172 SerializableGrid {
173 topology: self.topology.to_serializable(),
174 geometry: self.geometry.to_serializable(),
175 }
176 }
177 fn from_serializable(s: SerializableGrid<T>) -> Self {
178 Self {
179 topology: SingleTypeTopology::from_serializable(s.topology),
180 geometry: SingleElementGeometry::from_serializable(s.geometry),
181 }
182 }
183}
184
185impl<T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>>
186 SingleElementGrid<T, E>
187{
188 pub fn new(topology: SingleTypeTopology, geometry: SingleElementGeometry<T, E>) -> Self {
190 Self { topology, geometry }
191 }
192}
193
194impl<T: Scalar> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
195 pub fn new_from_raw_data(
197 coordinates: &[T],
198 gdim: usize,
199 cells: &[usize],
200 cell_type: ReferenceCellType,
201 geometry_degree: usize,
202 ) -> Self {
203 let npts = coordinates.len() / gdim;
204 let mut points = rlst_dynamic_array!(T, [gdim, npts]);
205 points.data_mut().unwrap().copy_from_slice(coordinates);
206
207 let family = LagrangeElementFamily::<T, T>::new(geometry_degree, Continuity::Standard);
208
209 let geometry = SingleElementGeometry::<T, CiarletElement<T, IdentityMap, T>>::new(
210 cell_type, points, cells, &family,
211 );
212
213 let points_per_cell = family.element(cell_type).dim();
214 let tpoints_per_cell = reference_cell::entity_counts(cell_type)[0];
215 let ncells = cells.len() / points_per_cell;
216
217 let mut tcells = vec![0; tpoints_per_cell * ncells];
218 for c in 0..ncells {
219 tcells[c * tpoints_per_cell..(c + 1) * tpoints_per_cell].copy_from_slice(
220 &cells[c * points_per_cell..c * points_per_cell + tpoints_per_cell],
221 );
222 }
223
224 let topology = SingleTypeTopology::new(&tcells, cell_type, None, None);
225
226 Self { topology, geometry }
227 }
228}
229
230impl<T: Scalar, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>> Grid
231 for SingleElementGrid<T, E>
232{
233 type T = T;
234 type Entity<'a>
235 = SingleElementGridEntity<'a, T, E>
236 where
237 Self: 'a;
238 type GeometryMap<'a>
239 = GeometryMap<'a, T, BaseArray<VectorContainer<T>, 2>, BaseArray<VectorContainer<usize>, 2>>
240 where
241 Self: 'a;
242 type EntityDescriptor = ReferenceCellType;
243 type EntityIter<'a>
244 = SingleElementGridEntityIter<'a, T, E>
245 where
246 Self: 'a;
247
248 fn geometry_dim(&self) -> usize {
249 self.geometry.dim()
250 }
251 fn topology_dim(&self) -> usize {
252 self.topology.dim()
253 }
254
255 fn entity(
256 &self,
257 entity_type: ReferenceCellType,
258 local_index: usize,
259 ) -> Option<Self::Entity<'_>> {
260 let dim = reference_cell::dim(entity_type);
261 if local_index < self.topology.entity_count(entity_type) {
262 if dim == self.topology_dim() {
263 Some(SingleElementGridEntity::new(self, local_index, dim, 0))
264 } else {
265 let cell = self.topology.upward_connectivity[dim][self.topology_dim() - dim - 1]
266 [local_index][0];
267 let dc = &self.topology.downward_connectivity[self.topology_dim()][dim];
268 let index = (0..dc.shape()[0])
269 .position(|i| dc[[i, cell]] == local_index)
270 .unwrap();
271 Some(SingleElementGridEntity::new(self, cell, dim, index))
272 }
273 } else {
274 None
275 }
276 }
277
278 fn entity_types(&self, dim: usize) -> &[ReferenceCellType] {
279 &self.topology.entity_types()[dim..dim + 1]
280 }
281
282 fn entity_count(&self, entity_type: ReferenceCellType) -> usize {
283 self.topology.entity_count(entity_type)
284 }
285
286 fn entity_iter(&self, entity_type: ReferenceCellType) -> Self::EntityIter<'_> {
287 SingleElementGridEntityIter::new(self, entity_type)
288 }
289
290 fn entity_from_id(
291 &self,
292 entity_type: ReferenceCellType,
293 id: usize,
294 ) -> Option<Self::Entity<'_>> {
295 let entity_dim = reference_cell::dim(entity_type);
296 self.topology.ids_to_indices[entity_dim]
297 .get(&id)
298 .map(|i| self.entity(entity_type, *i))?
299 }
300
301 fn geometry_map<Array2Impl: ValueArrayImpl<T, 2>>(
302 &self,
303 entity_type: ReferenceCellType,
304 geometry_degree: usize,
305 points: &Array<Array2Impl, 2>,
306 ) -> GeometryMap<'_, T, BaseArray<VectorContainer<T>, 2>, BaseArray<VectorContainer<usize>, 2>>
307 {
308 debug_assert!(points.shape()[0] == reference_cell::dim(entity_type));
309 debug_assert!(geometry_degree == self.geometry.element().lagrange_superdegree());
310 if entity_type == self.topology.entity_types()[self.topology_dim()] {
311 GeometryMap::new(
312 self.geometry.element(),
313 points,
314 self.geometry.points(),
315 self.geometry.cells(),
316 )
317 } else {
318 unimplemented!();
319 }
320 }
321}
322
323#[cfg(feature = "mpi")]
324impl<T: Scalar + Equivalence, E: MappedFiniteElement<CellType = ReferenceCellType, T = T>>
325 DistributableGrid for SingleElementGrid<T, E>
326{
327 type ParallelGrid<'a, C: Communicator + 'a> =
328 ParallelGridImpl<'a, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>>;
329
330 fn distribute<'a, C: Communicator>(
331 &self,
332 comm: &'a C,
333 partitioner: GraphPartitioner,
334 ) -> Self::ParallelGrid<'a, C> {
335 let e = self.geometry.element();
336 let pts = self.geometry.points();
337 let cells = self.geometry.cells();
338 let mut b = SingleElementGridBuilder::<T>::new_with_capacity(
339 self.geometry.dim(),
340 pts.shape()[1],
341 cells.shape()[1],
342 (e.cell_type(), e.lagrange_superdegree()),
343 );
344 for p in 0..pts.shape()[1] {
345 b.add_point(
346 p,
347 &pts.data().unwrap()[p * pts.shape()[0]..(p + 1) * pts.shape()[0]],
348 );
349 }
350 for c in 0..cells.shape()[1] {
351 b.add_cell(
352 c,
353 &cells.data().unwrap()[c * cells.shape()[0]..(c + 1) * cells.shape()[0]],
354 );
355 }
356 b.create_parallel_grid_root(comm, partitioner)
357 }
358}
359
360#[cfg(test)]
361mod test {
362 use super::*;
363 use crate::traits::Topology;
364 use itertools::izip;
365 use ndelement::{
366 ciarlet::{CiarletElement, LagrangeElementFamily},
367 reference_cell,
368 types::Continuity,
369 };
370 use rlst::rlst_dynamic_array;
371
372 fn example_grid_triangle() -> SingleElementGrid<f64, CiarletElement<f64, IdentityMap, f64>> {
373 let mut points = rlst_dynamic_array!(f64, [3, 4]);
374 *points.get_mut([0, 0]).unwrap() = 0.0;
375 *points.get_mut([1, 0]).unwrap() = 0.0;
376 *points.get_mut([2, 0]).unwrap() = 1.0;
377 *points.get_mut([0, 1]).unwrap() = 1.0;
378 *points.get_mut([1, 1]).unwrap() = 0.0;
379 *points.get_mut([2, 1]).unwrap() = 0.0;
380 *points.get_mut([0, 2]).unwrap() = 0.0;
381 *points.get_mut([1, 2]).unwrap() = 1.0;
382 *points.get_mut([2, 2]).unwrap() = 0.0;
383 *points.get_mut([0, 3]).unwrap() = 2.0;
384 *points.get_mut([1, 3]).unwrap() = 1.0;
385 *points.get_mut([2, 3]).unwrap() = 0.0;
386 let family = LagrangeElementFamily::<f64>::new(1, Continuity::Standard);
387 SingleElementGrid::new(
388 SingleTypeTopology::new(&[0, 1, 2, 2, 1, 3], ReferenceCellType::Triangle, None, None),
389 SingleElementGeometry::<f64, CiarletElement<f64, IdentityMap, f64>>::new(
390 ReferenceCellType::Triangle,
391 points,
392 &[0, 1, 2, 2, 1, 3],
393 &family,
394 ),
395 )
396 }
397
398 #[test]
399 fn test_edges_triangle() {
400 let grid = example_grid_triangle();
401 let conn = reference_cell::connectivity(ReferenceCellType::Triangle);
402 for edge in grid.entity_iter(ReferenceCellType::Interval) {
403 let cell = grid
404 .entity(ReferenceCellType::Triangle, edge.cell_index)
405 .unwrap();
406 for (i, v) in izip!(
407 &conn[1][edge.entity_index][0],
408 edge.topology().sub_entity_iter(ReferenceCellType::Point)
409 ) {
410 assert_eq!(v, cell.topology().sub_entity(ReferenceCellType::Point, *i));
411 }
412 }
413 }
414}