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 unit_interval_add_points_and_cells<T: Scalar>(b: &mut SingleElementGridBuilder<T>, nx: usize) {
16 for i in 0..nx + 1 {
17 b.add_point(i, &[T::from(i).unwrap() / T::from(nx).unwrap()]);
18 }
19
20 for i in 0..nx {
21 b.add_cell(i, &[i, i + 1]);
22 }
23}
24
25fn unit_square_add_points_and_cells<T: Scalar>(
27 b: &mut SingleElementGridBuilder<T>,
28 nx: usize,
29 ny: usize,
30 cell_type: ReferenceCellType,
31) {
32 for i in 0..nx + 1 {
33 for j in 0..ny + 1 {
34 b.add_point(
35 i * (ny + 1) + j,
36 &[
37 T::from(i).unwrap() / T::from(nx).unwrap(),
38 T::from(j).unwrap() / T::from(ny).unwrap(),
39 ],
40 );
41 }
42 }
43
44 let dx = ny + 1;
45 let dy = 1;
46 match cell_type {
47 ReferenceCellType::Triangle => {
48 for i in 0..nx {
49 for j in 0..ny {
50 let origin = i * dx + j * dy;
51 b.add_cell(2 * (j * nx + i), &[origin, origin + dx, origin + dx + dy]);
52 b.add_cell(
53 2 * (j * nx + i) + 1,
54 &[origin, origin + dx + dy, origin + dy],
55 );
56 }
57 }
58 }
59 ReferenceCellType::Quadrilateral => {
60 for i in 0..nx {
61 for j in 0..ny {
62 let origin = i * dx + j * dy;
63 b.add_cell(
64 j * nx + i,
65 &[origin, origin + dx, origin + dy, origin + dx + dy],
66 );
67 }
68 }
69 }
70 _ => {
71 panic!("Unsupported cell type: {cell_type:?}")
72 }
73 }
74}
75
76fn unit_square_boundary_add_points_and_cells<T: Scalar>(
78 b: &mut SingleElementGridBuilder<T>,
79 nx: usize,
80 ny: usize,
81) {
82 let dx = ny + 1;
83 let dy = 1;
84
85 for i in 0..nx + 1 {
86 b.add_point(
87 i * dx,
88 &[T::from(i).unwrap() / T::from(nx).unwrap(), T::zero()],
89 );
90 b.add_point(
91 i * dx + ny * dy,
92 &[T::from(i).unwrap() / T::from(nx).unwrap(), T::one()],
93 );
94 }
95 for j in 1..ny {
96 b.add_point(
97 j * dy,
98 &[T::zero(), T::from(j).unwrap() / T::from(ny).unwrap()],
99 );
100 b.add_point(
101 nx * dx + j * dy,
102 &[T::one(), T::from(j).unwrap() / T::from(ny).unwrap()],
103 );
104 }
105
106 for i in 0..nx {
107 let origin = i * dx;
108 b.add_cell(2 * i, &[origin, origin + dx]);
109 let origin = i * dx + ny * dy;
110 b.add_cell(2 * i + 1, &[origin, origin + dx]);
111 }
112 for j in 0..ny {
113 let origin = j * dy;
114 b.add_cell(2 * nx + 2 * j, &[origin, origin + dy]);
115 let origin = nx * dx + j * dy;
116 b.add_cell(2 * nx + 2 * j + 1, &[origin, origin + dy]);
117 }
118}
119
120fn unit_cube_add_points_and_cells<T: Scalar>(
122 b: &mut SingleElementGridBuilder<T>,
123 nx: usize,
124 ny: usize,
125 nz: usize,
126 cell_type: ReferenceCellType,
127) {
128 for i in 0..nx + 1 {
129 for j in 0..ny + 1 {
130 for k in 0..nz + 1 {
131 b.add_point(
132 (i * (ny + 1) + j) * (nz + 1) + k,
133 &[
134 T::from(i).unwrap() / T::from(nx).unwrap(),
135 T::from(j).unwrap() / T::from(ny).unwrap(),
136 T::from(k).unwrap() / T::from(nz).unwrap(),
137 ],
138 );
139 }
140 }
141 }
142
143 let dx = (ny + 1) * (nz + 1);
144 let dy = nz + 1;
145 let dz = 1;
146 match cell_type {
147 ReferenceCellType::Tetrahedron => {
148 for i in 0..nx {
149 for j in 0..ny {
150 for k in 0..nz {
151 let origin = i * dx + j * dy + k * dz;
152 b.add_cell(
153 6 * ((j * nx + i) * ny + k),
154 &[origin, origin + dx, origin + dx + dy, origin + dx + dy + dz],
155 );
156 b.add_cell(
157 6 * ((j * nx + i) * ny + k) + 1,
158 &[origin, origin + dy, origin + dx + dy, origin + dx + dy + dz],
159 );
160 b.add_cell(
161 6 * ((j * nx + i) * ny + k) + 2,
162 &[origin, origin + dx, origin + dx + dz, origin + dx + dy + dz],
163 );
164 b.add_cell(
165 6 * ((j * nx + i) * ny + k) + 3,
166 &[origin, origin + dz, origin + dx + dz, origin + dx + dy + dz],
167 );
168 b.add_cell(
169 6 * ((j * nx + i) * ny + k) + 4,
170 &[origin, origin + dy, origin + dy + dz, origin + dx + dy + dz],
171 );
172 b.add_cell(
173 6 * ((j * nx + i) * ny + k) + 5,
174 &[origin, origin + dz, origin + dy + dz, origin + dx + dy + dz],
175 );
176 }
177 }
178 }
179 }
180 ReferenceCellType::Hexahedron => {
181 for i in 0..nx {
182 for j in 0..ny {
183 for k in 0..nz {
184 let origin = i * dx + j * dy + k * dz;
185 b.add_cell(
186 (j * nx + i) * ny + k,
187 &[
188 origin,
189 origin + dx,
190 origin + dy,
191 origin + dy,
192 origin + dz,
193 origin + dx + dz,
194 origin + dy + dz,
195 origin + dy + dz,
196 ],
197 );
198 }
199 }
200 }
201 }
202 _ => {
203 panic!("Unsupported cell type: {cell_type:?}")
204 }
205 }
206}
207
208fn unit_cube_boundary_add_points_and_cells<T: Scalar>(
210 b: &mut SingleElementGridBuilder<T>,
211 nx: usize,
212 ny: usize,
213 nz: usize,
214 cell_type: ReferenceCellType,
215) {
216 for i in 0..nx + 1 {
217 for j in 0..ny + 1 {
218 for k in if i == 0 || i == nx || j == 0 || j == ny {
219 (0..nz + 1).collect::<Vec<_>>()
220 } else {
221 vec![0, nz]
222 } {
223 b.add_point(
224 (i * (ny + 1) + j) * (nz + 1) + k,
225 &[
226 T::from(i).unwrap() / T::from(nx).unwrap(),
227 T::from(j).unwrap() / T::from(ny).unwrap(),
228 T::from(k).unwrap() / T::from(nz).unwrap(),
229 ],
230 );
231 }
232 }
233 }
234
235 let dx = (ny + 1) * (nz + 1);
236 let dy = nz + 1;
237 let dz = 1;
238 match cell_type {
239 ReferenceCellType::Triangle => {
240 let mut cell_n = 0;
241 for i in 0..nx {
242 for j in 0..ny {
243 let origin = i * dx + j * dy;
244 b.add_cell(cell_n, &[origin, origin + dx, origin + dx + dy]);
245 b.add_cell(cell_n + 1, &[origin, origin + dx + dy, origin + dy]);
246 let origin = i * dx + j * dy + nz * dz;
247 b.add_cell(cell_n + 2, &[origin, origin + dx, origin + dx + dy]);
248 b.add_cell(cell_n + 3, &[origin, origin + dx + dy, origin + dy]);
249 cell_n += 4;
250 }
251 }
252 for i in 0..nx {
253 for k in 0..nz {
254 let origin = i * dx + k * dz;
255 b.add_cell(cell_n, &[origin, origin + dx, origin + dx + dz]);
256 b.add_cell(cell_n + 1, &[origin, origin + dx + dz, origin + dz]);
257 let origin = i * dx + ny * dy + k * dz;
258 b.add_cell(cell_n + 2, &[origin, origin + dx, origin + dx + dz]);
259 b.add_cell(cell_n + 3, &[origin, origin + dx + dz, origin + dz]);
260 cell_n += 4;
261 }
262 }
263 for j in 0..ny {
264 for k in 0..nz {
265 let origin = j * dy + k * dz;
266 b.add_cell(cell_n, &[origin, origin + dy, origin + dy + dz]);
267 b.add_cell(cell_n + 1, &[origin, origin + dy + dz, origin + dz]);
268 let origin = nx * dx + j * dy + k * dz;
269 b.add_cell(cell_n + 2, &[origin, origin + dy, origin + dy + dz]);
270 b.add_cell(cell_n + 3, &[origin, origin + dy + dz, origin + dz]);
271 cell_n += 4;
272 }
273 }
274 }
275 ReferenceCellType::Quadrilateral => {
276 let mut cell_n = 0;
277 for i in 0..nx {
278 for j in 0..ny {
279 let origin = i * dx + j * dy;
280 b.add_cell(
281 cell_n,
282 &[origin, origin + dx, origin + dy, origin + dx + dy],
283 );
284 let origin = i * dx + j * dy + nz * dz;
285 b.add_cell(
286 cell_n + 1,
287 &[origin, origin + dx, origin + dy, origin + dx + dy],
288 );
289 cell_n += 2;
290 }
291 }
292 for i in 0..nx {
293 for k in 0..nz {
294 let origin = i * dx + k * dz;
295 b.add_cell(
296 cell_n,
297 &[origin, origin + dx, origin + dz, origin + dx + dz],
298 );
299 let origin = i * dx + ny * dy + k * dz;
300 b.add_cell(
301 cell_n + 1,
302 &[origin, origin + dx, origin + dz, origin + dx + dz],
303 );
304 cell_n += 2;
305 }
306 }
307 for j in 0..ny {
308 for k in 0..nz {
309 let origin = j * dy + k * dz;
310 b.add_cell(
311 cell_n,
312 &[origin, origin + dy, origin + dz, origin + dy + dz],
313 );
314 let origin = nx * dx + j * dy + k * dz;
315 b.add_cell(
316 cell_n + 1,
317 &[origin, origin + dy, origin + dz, origin + dy + dz],
318 );
319 cell_n += 2;
320 }
321 }
322 }
323 _ => {
324 panic!("Unsupported cell type: {cell_type:?}")
325 }
326 }
327}
328
329fn unit_cube_edges_add_points_and_cells<T: Scalar>(
331 b: &mut SingleElementGridBuilder<T>,
332 nx: usize,
333 ny: usize,
334 nz: usize,
335) {
336 for i in 0..nx + 1 {
337 for j in if i == 0 || i == nx {
338 (0..ny + 1).collect::<Vec<_>>()
339 } else {
340 vec![0, ny]
341 } {
342 for k in if (i == 0 || i == nx) && (j == 0 || j == ny) {
343 (0..nz + 1).collect::<Vec<_>>()
344 } else {
345 vec![0, nz]
346 } {
347 b.add_point(
348 (i * (ny + 1) + j) * (nz + 1) + k,
349 &[
350 T::from(i).unwrap() / T::from(nx).unwrap(),
351 T::from(j).unwrap() / T::from(ny).unwrap(),
352 T::from(k).unwrap() / T::from(nz).unwrap(),
353 ],
354 );
355 }
356 }
357 }
358
359 let dx = (ny + 1) * (nz + 1);
360 let dy = nz + 1;
361 let dz = 1;
362 let mut cell_n = 0;
363 for i in 0..nx {
364 for origin in [
365 i * dx,
366 i * dx + ny * dy,
367 i * dx + nz * dz,
368 i * dx + ny * dy + nz * dz,
369 ] {
370 b.add_cell(cell_n, &[origin, origin + dx]);
371 cell_n += 1;
372 }
373 }
374 for j in 0..ny {
375 for origin in [
376 j * dy,
377 j * dy + nx * dx,
378 j * dy + nz * dz,
379 j * dy + nx * dx + nz * dz,
380 ] {
381 b.add_cell(cell_n, &[origin, origin + dy]);
382 cell_n += 1;
383 }
384 }
385 for k in 0..nz {
386 for origin in [
387 k * dz,
388 k * dz + nx * dx,
389 k * dz + ny * dy,
390 k * dz + nx * dx + ny * dy,
391 ] {
392 b.add_cell(cell_n, &[origin, origin + dz]);
393 cell_n += 1;
394 }
395 }
396}
397
398pub fn unit_interval<T: Scalar>(
402 nx: usize,
403) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
404 let mut b = SingleElementGridBuilder::new_with_capacity(
405 1,
406 nx + 1,
407 nx,
408 (ReferenceCellType::Interval, 1),
409 );
410 unit_interval_add_points_and_cells(&mut b, nx);
411 b.create_grid()
412}
413
414#[cfg(feature = "mpi")]
416pub fn unit_interval_distributed<T: Scalar + Equivalence, C: Communicator>(
417 comm: &C,
418 partitioner: GraphPartitioner,
419 nx: usize,
420) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
421 let mut b = SingleElementGridBuilder::new(1, (ReferenceCellType::Interval, 1));
422 if comm.rank() == 0 {
423 unit_interval_add_points_and_cells(&mut b, nx);
424 b.create_parallel_grid_root(comm, partitioner)
425 } else {
426 b.create_parallel_grid(comm, 0)
427 }
428}
429
430pub fn unit_square<T: Scalar>(
434 nx: usize,
435 ny: usize,
436 cell_type: ReferenceCellType,
437) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
438 let mut b = SingleElementGridBuilder::new_with_capacity(
439 2,
440 (nx + 1) * (ny + 1),
441 match cell_type {
442 ReferenceCellType::Triangle => 2 * nx * ny,
443 ReferenceCellType::Quadrilateral => 2 * nx * ny,
444 _ => {
445 panic!("Unsupported cell type: {cell_type:?}")
446 }
447 },
448 (cell_type, 1),
449 );
450 unit_square_add_points_and_cells(&mut b, nx, ny, cell_type);
451 b.create_grid()
452}
453
454#[cfg(feature = "mpi")]
456pub fn unit_square_distributed<T: Scalar + Equivalence, C: Communicator>(
457 comm: &C,
458 partitioner: GraphPartitioner,
459 nx: usize,
460 ny: usize,
461 cell_type: ReferenceCellType,
462) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
463 let mut b = SingleElementGridBuilder::new(1, (cell_type, 1));
464 if comm.rank() == 0 {
465 unit_square_add_points_and_cells(&mut b, nx, ny, cell_type);
466 b.create_parallel_grid_root(comm, partitioner)
467 } else {
468 b.create_parallel_grid(comm, 0)
469 }
470}
471
472pub fn unit_square_boundary<T: Scalar>(
476 nx: usize,
477 ny: usize,
478) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
479 let mut b = SingleElementGridBuilder::new_with_capacity(
480 2,
481 2 * (nx + ny),
482 2 * (nx + ny),
483 (ReferenceCellType::Interval, 1),
484 );
485 unit_square_boundary_add_points_and_cells(&mut b, nx, ny);
486 b.create_grid()
487}
488
489#[cfg(feature = "mpi")]
491pub fn unit_square_boundary_distributed<T: Scalar + Equivalence, C: Communicator>(
492 comm: &C,
493 partitioner: GraphPartitioner,
494 nx: usize,
495 ny: usize,
496 cell_type: ReferenceCellType,
497) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
498 let mut b = SingleElementGridBuilder::new(1, (cell_type, 1));
499 if comm.rank() == 0 {
500 unit_square_boundary_add_points_and_cells(&mut b, nx, ny);
501 b.create_parallel_grid_root(comm, partitioner)
502 } else {
503 b.create_parallel_grid(comm, 0)
504 }
505}
506
507pub fn unit_cube<T: Scalar>(
512 nx: usize,
513 ny: usize,
514 nz: usize,
515 cell_type: ReferenceCellType,
516) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
517 let mut b = SingleElementGridBuilder::new_with_capacity(
518 3,
519 (nx + 1) * (ny + 1) * (nz + 1),
520 match cell_type {
521 ReferenceCellType::Tetrahedron => 6 * nx * ny * nz,
522 ReferenceCellType::Hexahedron => 2 * nx * ny * nz,
523 _ => {
524 panic!("Unsupported cell type: {cell_type:?}")
525 }
526 },
527 (cell_type, 1),
528 );
529
530 unit_cube_add_points_and_cells(&mut b, nx, ny, nz, cell_type);
531 b.create_grid()
532}
533
534#[cfg(feature = "mpi")]
536pub fn unit_cube_distributed<T: Scalar + Equivalence, C: Communicator>(
537 comm: &C,
538 partitioner: GraphPartitioner,
539 nx: usize,
540 ny: usize,
541 nz: usize,
542 cell_type: ReferenceCellType,
543) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
544 let mut b = SingleElementGridBuilder::new(3, (cell_type, 1));
545 if comm.rank() == 0 {
546 unit_cube_add_points_and_cells(&mut b, nx, ny, nz, cell_type);
547 b.create_parallel_grid_root(comm, partitioner)
548 } else {
549 b.create_parallel_grid(comm, 0)
550 }
551}
552
553pub fn unit_cube_boundary<T: Scalar>(
558 nx: usize,
559 ny: usize,
560 nz: usize,
561 cell_type: ReferenceCellType,
562) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
563 let mut b = SingleElementGridBuilder::new_with_capacity(
564 3,
565 (nx + 1) * (ny + 1) * (nz + 1) - (nx - 1) * (ny - 1) * (nz - 1),
566 match cell_type {
567 ReferenceCellType::Triangle => 4 * (nx * ny + nx * nz + ny * nz),
568 ReferenceCellType::Quadrilateral => 2 * (nx * ny + nx * nz + ny * nz),
569 _ => {
570 panic!("Unsupported cell type: {cell_type:?}")
571 }
572 },
573 (cell_type, 1),
574 );
575 unit_cube_boundary_add_points_and_cells(&mut b, nx, ny, nz, cell_type);
576 b.create_grid()
577}
578
579#[cfg(feature = "mpi")]
581pub fn unit_cube_boundary_distributed<T: Scalar + Equivalence, C: Communicator>(
582 comm: &C,
583 partitioner: GraphPartitioner,
584 nx: usize,
585 ny: usize,
586 nz: usize,
587 cell_type: ReferenceCellType,
588) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
589 let mut b = SingleElementGridBuilder::new(3, (cell_type, 1));
590 if comm.rank() == 0 {
591 unit_cube_boundary_add_points_and_cells(&mut b, nx, ny, nz, cell_type);
592 b.create_parallel_grid_root(comm, partitioner)
593 } else {
594 b.create_parallel_grid(comm, 0)
595 }
596}
597
598pub fn unit_cube_edges<T: Scalar>(
603 nx: usize,
604 ny: usize,
605 nz: usize,
606) -> SingleElementGrid<T, CiarletElement<T, IdentityMap, T>> {
607 let mut b = SingleElementGridBuilder::new_with_capacity(
608 3,
609 4 * (nx + ny + nz + 1),
610 4 * (nx + ny + nz),
611 (ReferenceCellType::Interval, 1),
612 );
613 unit_cube_edges_add_points_and_cells(&mut b, nx, ny, nz);
614 b.create_grid()
615}
616
617#[cfg(feature = "mpi")]
619pub fn unit_cube_edges_distributed<T: Scalar + Equivalence, C: Communicator>(
620 comm: &C,
621 partitioner: GraphPartitioner,
622 nx: usize,
623 ny: usize,
624 nz: usize,
625) -> ParallelGridImpl<'_, C, SingleElementGrid<T, CiarletElement<T, IdentityMap, T>>> {
626 let mut b = SingleElementGridBuilder::new(3, (ReferenceCellType::Interval, 1));
627 if comm.rank() == 0 {
628 unit_cube_edges_add_points_and_cells(&mut b, nx, ny, nz);
629 b.create_parallel_grid_root(comm, partitioner)
630 } else {
631 b.create_parallel_grid(comm, 0)
632 }
633}
634
635#[cfg(test)]
636mod test {
637 use super::*;
638 use crate::traits::{Entity, Geometry, Grid, Point};
639 use approx::*;
640 use itertools::izip;
641
642 fn max(values: &[f64]) -> f64 {
643 let mut out = values[0];
644 for i in &values[1..] {
645 if *i > out {
646 out = *i;
647 }
648 }
649 out
650 }
651
652 fn check_volume(
653 grid: &impl Grid<T = f64, EntityDescriptor = ReferenceCellType>,
654 expected_volume: f64,
655 ) {
656 let mut volume = 0.0;
657 let gdim = grid.geometry_dim();
658 for t in grid.cell_types() {
659 for cell in grid.entity_iter(*t) {
660 let g = cell.geometry();
661 let mut point = vec![0.0; gdim];
662 let mut min_p = vec![10.0; gdim];
663 let mut max_p = vec![-10.0; gdim];
664 for p in g.points() {
665 p.coords(&mut point);
666 for (j, v) in point.iter().enumerate() {
667 if *v < min_p[j] {
668 min_p[j] = *v;
669 }
670 if *v > max_p[j] {
671 max_p[j] = *v;
672 }
673 }
674 }
675 volume += match cell.entity_type() {
676 ReferenceCellType::Interval => {
677 max(&izip!(min_p, max_p).map(|(i, j)| j - i).collect::<Vec<_>>())
678 }
679 ReferenceCellType::Triangle => match gdim {
680 2 => (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]) / 2.0,
681 3 => max(&[
682 (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]) / 2.0,
683 (max_p[0] - min_p[0]) * (max_p[2] - min_p[2]) / 2.0,
684 (max_p[1] - min_p[1]) * (max_p[2] - min_p[2]) / 2.0,
685 ]),
686 _ => {
687 panic!("Unsupported dimension");
688 }
689 },
690 ReferenceCellType::Quadrilateral => match gdim {
691 2 => (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]),
692 3 => max(&[
693 (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]),
694 (max_p[0] - min_p[0]) * (max_p[2] - min_p[2]),
695 (max_p[1] - min_p[1]) * (max_p[2] - min_p[2]),
696 ]),
697 _ => {
698 panic!("Unsupported dimension");
699 }
700 },
701 ReferenceCellType::Tetrahedron => {
702 (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]) * (max_p[2] - min_p[2]) / 6.0
703 }
704 ReferenceCellType::Hexahedron => {
705 (max_p[0] - min_p[0]) * (max_p[1] - min_p[1]) * (max_p[2] - min_p[2])
706 }
707 _ => {
708 panic!("Unsupported cell");
709 }
710 };
711 }
712 }
713 assert_relative_eq!(volume, expected_volume, epsilon = 1e-10);
714 }
715
716 #[test]
717 fn test_unit_interval() {
718 check_volume(&unit_interval::<f64>(1), 1.0);
719 check_volume(&unit_interval::<f64>(2), 1.0);
720 check_volume(&unit_interval::<f64>(4), 1.0);
721 check_volume(&unit_interval::<f64>(7), 1.0);
722 }
723
724 #[test]
725 fn test_unit_square_triangle() {
726 check_volume(&unit_square::<f64>(1, 1, ReferenceCellType::Triangle), 1.0);
727 check_volume(&unit_square::<f64>(2, 2, ReferenceCellType::Triangle), 1.0);
728 check_volume(&unit_square::<f64>(4, 5, ReferenceCellType::Triangle), 1.0);
729 check_volume(&unit_square::<f64>(7, 6, ReferenceCellType::Triangle), 1.0);
730 }
731
732 #[test]
733 fn test_unit_square_quadrilateral() {
734 check_volume(
735 &unit_square::<f64>(1, 1, ReferenceCellType::Quadrilateral),
736 1.0,
737 );
738 check_volume(
739 &unit_square::<f64>(2, 2, ReferenceCellType::Quadrilateral),
740 1.0,
741 );
742 check_volume(
743 &unit_square::<f64>(4, 5, ReferenceCellType::Quadrilateral),
744 1.0,
745 );
746 check_volume(
747 &unit_square::<f64>(7, 6, ReferenceCellType::Quadrilateral),
748 1.0,
749 );
750 }
751
752 #[test]
753 fn test_unit_square_boundary() {
754 check_volume(&unit_square_boundary::<f64>(1, 1), 4.0);
755 check_volume(&unit_square_boundary::<f64>(2, 2), 4.0);
756 check_volume(&unit_square_boundary::<f64>(4, 5), 4.0);
757 check_volume(&unit_square_boundary::<f64>(7, 6), 4.0);
758 }
759
760 #[test]
761 fn test_unit_cube_boundary_triangle() {
762 check_volume(
763 &unit_cube_boundary::<f64>(1, 1, 1, ReferenceCellType::Triangle),
764 6.0,
765 );
766 check_volume(
767 &unit_cube_boundary::<f64>(2, 2, 2, ReferenceCellType::Triangle),
768 6.0,
769 );
770 check_volume(
771 &unit_cube_boundary::<f64>(4, 5, 5, ReferenceCellType::Triangle),
772 6.0,
773 );
774 check_volume(
775 &unit_cube_boundary::<f64>(7, 6, 4, ReferenceCellType::Triangle),
776 6.0,
777 );
778 }
779
780 #[test]
781 fn test_unit_cube_boundary_quadrilateral() {
782 check_volume(
783 &unit_cube_boundary::<f64>(1, 1, 1, ReferenceCellType::Quadrilateral),
784 6.0,
785 );
786 check_volume(
787 &unit_cube_boundary::<f64>(2, 2, 2, ReferenceCellType::Quadrilateral),
788 6.0,
789 );
790 check_volume(
791 &unit_cube_boundary::<f64>(4, 5, 5, ReferenceCellType::Quadrilateral),
792 6.0,
793 );
794 check_volume(
795 &unit_cube_boundary::<f64>(7, 6, 4, ReferenceCellType::Quadrilateral),
796 6.0,
797 );
798 }
799
800 #[test]
801 fn test_unit_cube_tetrahedron() {
802 check_volume(
803 &unit_cube::<f64>(1, 1, 1, ReferenceCellType::Tetrahedron),
804 1.0,
805 );
806 check_volume(
807 &unit_cube::<f64>(2, 2, 2, ReferenceCellType::Tetrahedron),
808 1.0,
809 );
810 check_volume(
811 &unit_cube::<f64>(4, 5, 5, ReferenceCellType::Tetrahedron),
812 1.0,
813 );
814 check_volume(
815 &unit_cube::<f64>(7, 6, 4, ReferenceCellType::Tetrahedron),
816 1.0,
817 );
818 }
819 #[test]
820 fn test_unit_cube_hexahedron() {
821 check_volume(
822 &unit_cube::<f64>(1, 1, 1, ReferenceCellType::Hexahedron),
823 1.0,
824 );
825 check_volume(
826 &unit_cube::<f64>(2, 2, 2, ReferenceCellType::Hexahedron),
827 1.0,
828 );
829 check_volume(
830 &unit_cube::<f64>(4, 5, 5, ReferenceCellType::Hexahedron),
831 1.0,
832 );
833 check_volume(
834 &unit_cube::<f64>(7, 6, 4, ReferenceCellType::Hexahedron),
835 1.0,
836 );
837 }
838
839 #[test]
840 fn test_unit_cube_edges() {
841 check_volume(&unit_cube_edges::<f64>(1, 1, 1), 12.0);
842 check_volume(&unit_cube_edges::<f64>(2, 2, 2), 12.0);
843 check_volume(&unit_cube_edges::<f64>(4, 5, 5), 12.0);
844 check_volume(&unit_cube_edges::<f64>(7, 6, 4), 12.0);
845 }
846}