1#[cfg(feature = "mpi")]
4use crate::{ParallelGridImpl, traits::ParallelBuilder, types::GraphPartitioner};
5use crate::{
6 grid::local_grid::{SingleElementGrid, SingleElementGridBuilder},
7 traits::Builder,
8 types::Scalar,
9};
10#[cfg(feature = "mpi")]
11use mpi::traits::{Communicator, Equivalence};
12use ndelement::{ciarlet::CiarletElement, map::IdentityMap, types::ReferenceCellType};
13
14fn screen_add_points_and_cells<T: Scalar>(
16 b: &mut SingleElementGridBuilder<T>,
17 ncells: usize,
18 cell_type: ReferenceCellType,
19) {
20 let zero = T::from(0.0).unwrap();
21 let n = T::from(ncells).unwrap();
22 for y in 0..ncells + 1 {
23 for x in 0..ncells + 1 {
24 b.add_point(
25 y * (ncells + 1) + x,
26 &[T::from(x).unwrap() / n, T::from(y).unwrap() / n, zero],
27 );
28 }
29 }
30 match cell_type {
31 ReferenceCellType::Triangle => {
32 for y in 0..ncells {
33 for x in 0..ncells {
34 b.add_cell(
35 2 * y * ncells + 2 * x,
36 &[
37 y * (ncells + 1) + x,
38 y * (ncells + 1) + x + 1,
39 y * (ncells + 1) + x + ncells + 2,
40 ],
41 );
42 b.add_cell(
43 2 * y * ncells + 2 * x + 1,
44 &[
45 y * (ncells + 1) + x,
46 y * (ncells + 1) + x + ncells + 2,
47 y * (ncells + 1) + x + ncells + 1,
48 ],
49 );
50 }
51 }
52 }
53 ReferenceCellType::Quadrilateral => {
54 for y in 0..ncells {
55 for x in 0..ncells {
56 b.add_cell(
57 y * ncells + x,
58 &[
59 y * (ncells + 1) + x,
60 y * (ncells + 1) + x + 1,
61 y * (ncells + 1) + x + ncells + 1,
62 y * (ncells + 1) + x + ncells + 2,
63 ],
64 );
65 }
66 }
67 }
68 _ => {
69 panic!("Unsupported cell type: {cell_type:?}");
70 }
71 }
72}
73
74pub fn screen<T: Scalar>(
79 ncells: usize,
80 cell_type: ReferenceCellType,
81) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
82 let mut b = SingleElementGridBuilder::new_with_capacity(
83 3,
84 (ncells + 1) * (ncells + 1),
85 match cell_type {
86 ReferenceCellType::Quadrilateral => ncells * ncells,
87 ReferenceCellType::Triangle => 2 * ncells * ncells,
88 _ => {
89 panic!("Unsupported cell type: {cell_type:?}");
90 }
91 },
92 (cell_type, 1),
93 );
94 screen_add_points_and_cells(&mut b, ncells, cell_type);
95 b.create_grid()
96}
97
98#[cfg(feature = "mpi")]
100pub fn screen_distributed<T: Scalar + Equivalence, C: Communicator>(
101 comm: &C,
102 partitioner: GraphPartitioner,
103 ncells: usize,
104 cell_type: ReferenceCellType,
105) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
106 let mut b = SingleElementGridBuilder::new(3, (cell_type, 1));
107 if comm.rank() == 0 {
108 screen_add_points_and_cells(&mut b, ncells, cell_type);
109 b.create_parallel_grid_root(comm, partitioner)
110 } else {
111 b.create_parallel_grid(comm, 0)
112 }
113}
114
115#[cfg(test)]
116mod test {
117 use super::*;
118 use crate::traits::{GeometryMap, Grid};
119 use approx::assert_relative_eq;
120 use rlst::rlst_dynamic_array;
121
122 #[test]
123 fn test_screen_triangles() {
124 let _g1 = screen::<f64>(1, ReferenceCellType::Triangle);
125 let _g2 = screen::<f64>(2, ReferenceCellType::Triangle);
126 let _g3 = screen::<f64>(3, ReferenceCellType::Triangle);
127 }
128 #[test]
129 fn test_screen_triangles_normals() {
130 for i in 1..5 {
131 let g = screen::<f64>(i, ReferenceCellType::Triangle);
132 let mut points = rlst_dynamic_array!(f64, [2, 1]);
133 points[[0, 0]] = 1.0 / 3.0;
134 points[[1, 0]] = 1.0 / 3.0;
135 let map = g.geometry_map(ReferenceCellType::Triangle, 1, &points);
136 let mut mapped_pt = rlst_dynamic_array!(f64, [3, 1]);
137 let mut j = rlst_dynamic_array!(f64, [3, 2, 1]);
138 let mut jinv = rlst_dynamic_array!(f64, [2, 3, 1]);
139 let mut jdet = vec![0.0];
140 let mut normal = rlst_dynamic_array!(f64, [3, 1]);
141 for i in 0..g.entity_count(ReferenceCellType::Triangle) {
142 map.physical_points(i, &mut mapped_pt);
143 map.jacobians_inverses_dets_normals(i, &mut j, &mut jinv, &mut jdet, &mut normal);
144 assert!(normal[[2, 0]] > 0.0);
145 assert_relative_eq!(normal[[2, 0]], 1.0);
146 }
147 }
148 }
149
150 #[test]
151 fn test_screen_quadrilaterals() {
152 let _g1 = screen::<f64>(1, ReferenceCellType::Quadrilateral);
153 let _g2 = screen::<f64>(2, ReferenceCellType::Quadrilateral);
154 let _g3 = screen::<f64>(3, ReferenceCellType::Quadrilateral);
155 }
156
157 #[test]
158 fn test_screen_quadrilaterals_normals() {
159 for i in 1..5 {
160 let g = screen::<f64>(i, ReferenceCellType::Quadrilateral);
161 let mut points = rlst_dynamic_array!(f64, [2, 1]);
162 points[[0, 0]] = 1.0 / 3.0;
163 points[[1, 0]] = 1.0 / 3.0;
164 let map = g.geometry_map(ReferenceCellType::Quadrilateral, 1, &points);
165 let mut mapped_pt = rlst_dynamic_array!(f64, [3, 1]);
166 let mut j = rlst_dynamic_array!(f64, [3, 2, 1]);
167 let mut jinv = rlst_dynamic_array!(f64, [2, 3, 1]);
168 let mut jdet = vec![0.0];
169 let mut normal = rlst_dynamic_array!(f64, [3, 1]);
170 for i in 0..g.entity_count(ReferenceCellType::Quadrilateral) {
171 map.physical_points(i, &mut mapped_pt);
172 map.jacobians_inverses_dets_normals(i, &mut j, &mut jinv, &mut jdet, &mut normal);
173 assert!(normal[[2, 0]] > 0.0);
174 assert_relative_eq!(normal[[2, 0]], 1.0);
175 }
176 }
177 }
178}