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}