ndgrid/shapes/screen.rs
1//! Regular sphere grid
2
3use crate::{
4 grid::local_grid::{SingleElementGrid, SingleElementGridBuilder},
5 traits::Builder,
6 types::Scalar,
7};
8use ndelement::{ciarlet::CiarletElement, map::IdentityMap, types::ReferenceCellType};
9/// Create a square grid with triangle cells
10///
11/// Create a grid of the square \[0,1\]^2 with triangle cells. The input ncells is the number of cells
12/// along each side of the square.
13pub fn screen_triangles<T: Scalar>(
14 ncells: usize,
15) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
16 if ncells == 0 {
17 panic!("Cannot create a grid with 0 cells");
18 }
19 let mut b = SingleElementGridBuilder::new_with_capacity(
20 3,
21 (ncells + 1) * (ncells + 1),
22 2 * ncells * ncells,
23 (ReferenceCellType::Triangle, 1),
24 );
25
26 let zero = T::from(0.0).unwrap();
27 let n = T::from(ncells).unwrap();
28 for y in 0..ncells + 1 {
29 for x in 0..ncells + 1 {
30 b.add_point(
31 y * (ncells + 1) + x,
32 &[T::from(x).unwrap() / n, T::from(y).unwrap() / n, zero],
33 );
34 }
35 }
36 for y in 0..ncells {
37 for x in 0..ncells {
38 b.add_cell(
39 2 * y * ncells + 2 * x,
40 &[
41 y * (ncells + 1) + x,
42 y * (ncells + 1) + x + 1,
43 y * (ncells + 1) + x + ncells + 2,
44 ],
45 );
46 b.add_cell(
47 2 * y * ncells + 2 * x + 1,
48 &[
49 y * (ncells + 1) + x,
50 y * (ncells + 1) + x + ncells + 2,
51 y * (ncells + 1) + x + ncells + 1,
52 ],
53 );
54 }
55 }
56
57 b.create_grid()
58}
59
60/// Create a square grid with quadrilateral cells
61///
62/// Create a grid of the square \[0,1\]^2 with quadrilateral cells. The input ncells is the number of
63/// cells along each side of the square.
64pub fn screen_quadrilaterals<T: Scalar>(
65 ncells: usize,
66) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
67 if ncells == 0 {
68 panic!("Cannot create a grid with 0 cells");
69 }
70 let mut b = SingleElementGridBuilder::new_with_capacity(
71 3,
72 (ncells + 1) * (ncells + 1),
73 ncells * ncells,
74 (ReferenceCellType::Quadrilateral, 1),
75 );
76
77 let zero = T::from(0.0).unwrap();
78 let n = T::from(ncells).unwrap();
79 for y in 0..ncells + 1 {
80 for x in 0..ncells + 1 {
81 b.add_point(
82 y * (ncells + 1) + x,
83 &[T::from(x).unwrap() / n, T::from(y).unwrap() / n, zero],
84 );
85 }
86 }
87 for y in 0..ncells {
88 for x in 0..ncells {
89 b.add_cell(
90 y * ncells + x,
91 &[
92 y * (ncells + 1) + x,
93 y * (ncells + 1) + x + 1,
94 y * (ncells + 1) + x + ncells + 1,
95 y * (ncells + 1) + x + ncells + 2,
96 ],
97 );
98 }
99 }
100
101 b.create_grid()
102}
103
104/*
105/// Create a rectangular grid with quadrilateral cells
106///
107/// Create a grid of the square \[0,2\]x\[0,1\] with triangle cells on the left half and quadrilateral
108/// cells on the right half. The input ncells is the number of cells along each side of the unit
109/// square.
110pub fn screen_mixed<T: Float + Scalar>(ncells: usize) -> MixedGrid<T>
111{
112 if ncells == 0 {
113 panic!("Cannot create a grid with 0 cells");
114 }
115 let mut b = MixedGridBuilder::new_with_capacity(
116 2 * (ncells + 1) * (ncells + 1),
117 3 * ncells * ncells,
118 (),
119 );
120
121 let zero = T::from(0.0).unwrap();
122 let n = T::from(ncells + 1).unwrap();
123 for y in 0..ncells + 1 {
124 for x in 0..2 * (ncells + 1) {
125 b.add_point(
126 2 * y * (ncells + 1) + x,
127 [T::from(x).unwrap() / n, T::from(y).unwrap() / n, zero],
128 );
129 }
130 }
131 for y in 0..ncells {
132 for x in 0..ncells {
133 b.add_cell(
134 2 * y * ncells + 2 * x,
135 (
136 vec![
137 2 * y * (ncells + 1) + x,
138 2 * y * (ncells + 1) + x + 1,
139 2 * y * (ncells + 1) + x + 2 * ncells + 3,
140 ],
141 ReferenceCellType::Triangle,
142 1,
143 ),
144 );
145 b.add_cell(
146 2 * y * ncells + 2 * x + 1,
147 (
148 vec![
149 2 * y * (ncells + 1) + x,
150 2 * y * (ncells + 1) + x + 2 * ncells + 3,
151 2 * y * (ncells + 1) + x + 2 * ncells + 2,
152 ],
153 ReferenceCellType::Triangle,
154 1,
155 ),
156 );
157 b.add_cell(
158 2 * ncells * ncells + y * ncells + x,
159 (
160 vec![
161 (ncells + 1) + 2 * y * (ncells + 1) + x,
162 (ncells + 1) + 2 * y * (ncells + 1) + x + 1,
163 (ncells + 1) + 2 * y * (ncells + 1) + x + 2 * ncells + 3,
164 (ncells + 1) + 2 * y * (ncells + 1) + x + 2 * ncells + 2,
165 ],
166 ReferenceCellType::Quadrilateral,
167 1,
168 ),
169 );
170 }
171 }
172 b.create_grid()
173}
174*/
175
176#[cfg(test)]
177mod test {
178 use super::*;
179 use crate::traits::{GeometryMap, Grid};
180 use approx::assert_relative_eq;
181
182 #[test]
183 fn test_screen_triangles() {
184 let _g1 = screen_triangles::<f64>(1);
185 let _g2 = screen_triangles::<f64>(2);
186 let _g3 = screen_triangles::<f64>(3);
187 }
188 #[test]
189 fn test_screen_triangles_normals() {
190 for i in 1..5 {
191 let g = screen_triangles::<f64>(i);
192 let points = vec![1.0 / 3.0, 1.0 / 3.0];
193 let map = g.geometry_map(ReferenceCellType::Triangle, 1, &points);
194 let mut mapped_pt = vec![0.0; 3];
195 let mut j = vec![0.0; 6];
196 let mut jdet = vec![0.0];
197 let mut normal = vec![0.0; 3];
198 for i in 0..g.entity_count(ReferenceCellType::Triangle) {
199 map.physical_points(i, &mut mapped_pt);
200 map.jacobians_dets_normals(i, &mut j, &mut jdet, &mut normal);
201 assert!(normal[2] > 0.0);
202 assert_relative_eq!(normal[2], 1.0);
203 }
204 }
205 }
206
207 #[test]
208 fn test_screen_quadrilaterals() {
209 let _g1 = screen_quadrilaterals::<f64>(1);
210 let _g2 = screen_quadrilaterals::<f64>(2);
211 let _g3 = screen_quadrilaterals::<f64>(3);
212 }
213
214 #[test]
215 fn test_screen_quadrilaterals_normals() {
216 for i in 1..5 {
217 let g = screen_quadrilaterals::<f64>(i);
218 let points = vec![1.0 / 3.0, 1.0 / 3.0];
219 let map = g.geometry_map(ReferenceCellType::Quadrilateral, 1, &points);
220 let mut mapped_pt = vec![0.0; 3];
221 let mut j = vec![0.0; 6];
222 let mut jdet = vec![0.0];
223 let mut normal = vec![0.0; 3];
224 for i in 0..g.entity_count(ReferenceCellType::Quadrilateral) {
225 map.physical_points(i, &mut mapped_pt);
226 map.jacobians_dets_normals(i, &mut j, &mut jdet, &mut normal);
227 assert!(normal[2] > 0.0);
228 assert_relative_eq!(normal[2], 1.0);
229 }
230 }
231 }
232
233 /*
234 #[test]
235 fn test_screen_mixed() {
236 let _g1 = screen_mixed::<f64>(1);
237 let _g2 = screen_mixed::<f64>(2);
238 let _g3 = screen_mixed::<f64>(3);
239 }
240
241 #[test]
242 fn test_screen_mixed_normal() {
243 for i in 1..5 {
244 let g = screen_mixed::<f64>(i);
245 let points = vec![1.0 / 3.0, 1.0 / 3.0];
246 let map = g.reference_to_physical_map(&points);
247 let mut mapped_pt = vec![0.0; 3];
248 let mut normal = vec![0.0; 3];
249 for i in 0..g.number_of_cells() {
250 map.reference_to_physical(i, &mut mapped_pt);
251 map.normal(i, &mut normal);
252 assert!(normal[2] > 0.0);
253 }
254 }
255 }
256 */
257}